2 * Copyright 2011-2012 GRNET S.A. All rights reserved.
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the following
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
30 * The views and conclusions contained in the software and
31 * documentation are those of the authors and should not be
32 * interpreted as representing official policies, either expressed
33 * or implied, of GRNET S.A.
36 package gr.grnet.aquarium
38 import com.ckkloverdos.maybe.{Failed, Just, Maybe, NoVal}
39 import com.ckkloverdos.sys.{SysEnv, SysProp}
42 import gr.grnet.aquarium.util.justForSure
43 import gr.grnet.aquarium.util.isRunningTests
44 import com.ckkloverdos.resource.{FileStreamResource, StreamResource, CompositeStreamResourceContext, ClassLoaderStreamResourceContext, FileStreamResourceContext}
49 * This code was initially in [[gr.grnet.aquarium.Configurator]].
51 * @author Christos KK Loverdos <loverdos@gmail.com>
54 object ResourceLocator {
55 final object ResourceNames {
56 final val CONF_FODLER = "conf"
57 final val SLASH_ETC_AQUARIUM_FOLDER = "/etc/aquarium"
59 final val LOGBACK_XML = "logback.xml"
60 final val AQUARIUM_PROPERTIES = "aquarium.properties"
61 final val POLICY_YAML = "policy.yaml"
62 final val ROLE_AGREEMENTS_MAP = "roles-agreements.map"
67 final val AKKA_HOME = "AKKA_HOME"
68 // final val AQUARIUM_HOME = "AQUARIUM_HOME"
71 final object Folders {
72 private[this] def checkFolder(name: String, file: File): File = {
73 if(!file.isDirectory) {
74 throw new AquariumInternalError(
75 "%s=%s is not a folder".format(
80 "%s [=%s]".format(file, file.getCanonicalFile)
88 * This is normally exported from the shell script (AQUARIUM_HOME) that starts Aquarium or given in the command
89 * line (aquarium.home).
91 * TODO: Make this searchable for resources (ie put it in the resource context)
93 final lazy val AquariumHome = {
94 SysProps.AquariumHome.value match {
95 case Just(aquariumHome) ⇒
96 checkFolder(SysProps.Names.AquariumHome, new File(aquariumHome))
99 throw new AquariumInternalError("Error regarding %s".format(SysProps.Names.AquariumHome), e)
102 SysEnvs.AQUARIUM_HOME.value match {
103 case Just(aquarium_home) ⇒
104 val folder = new File(aquarium_home)
105 checkFolder(SysEnvs.Names.AQUARIUM_HOME, folder)
106 SysProps.AquariumHome.update(folder.getPath) // needed for logback configuration
110 throw new AquariumInternalError("Error regarding %s".format(SysEnvs.Names.AQUARIUM_HOME), e)
113 val folder = new File(".")
114 SysProps.AquariumHome.update(folder.getPath) // needed for logback configuration
122 final object SysEnvs {
124 final val AKKA_HOME = Homes.Names.AKKA_HOME
125 final val AQUARIUM_HOME = "AQUARIUM_HOME"
128 final val AKKA_HOME = SysEnv(Names.AKKA_HOME)
129 final val AQUARIUM_HOME = SysEnv(Names.AQUARIUM_HOME)
132 final object SysProps {
134 final val AquariumHome = "aquarium.home"
135 final val AquariumPropertiesPath = "aquarium.properties.path"
136 final val AquariumConfFolder = "aquarium.conf.folder"
139 final val AquariumHome = SysProp(Names.AquariumHome)
142 * Use this property to override the place of aquarium.properties.
143 * If this is set, then it override any other way to specify the aquarium.properties location.
145 final val AquariumPropertiesPath = SysProp(Names.AquariumPropertiesPath)
148 * Use this property to override the place where aquarium configuration resides.
150 * The value of this property is a folder that defines the highest-priority resource context.
152 final val AquariumConfFolder = SysProp(Names.AquariumConfFolder)
155 final object ResourceContexts {
157 * AQUARIUM_HOME/conf resource context.
159 private[this] final lazy val HomeConfResourceContext = new FileStreamResourceContext(AQUARIUM_HOME_CONF_FOLDER)
162 * The venerable /etc resource context. Applicable in Unix environments
164 private[this] final lazy val SlashEtcResourceContext = new FileStreamResourceContext(ResourceNames.SLASH_ETC_AQUARIUM_FOLDER)
167 * Class loader resource context.
168 * This has the lowest priority.
170 private[this] final lazy val ClasspathBaseResourceContext = new ClassLoaderStreamResourceContext(
171 Thread.currentThread().getContextClassLoader)
173 private[this] final lazy val BasicResourceContext = new CompositeStreamResourceContext(
175 SlashEtcResourceContext,
176 HomeConfResourceContext,
177 ClasspathBaseResourceContext)
180 * The resource context used in the application.
182 final lazy val MasterResourceContext = {
183 SysProps.AquariumConfFolder.value match {
185 // We have a system override for the configuration location
186 new CompositeStreamResourceContext(
187 Just(BasicResourceContext),
188 new FileStreamResourceContext(value))
194 throw new AquariumInternalError(e)
199 final lazy val AQUARIUM_HOME_CONF_FOLDER = new File(Homes.Folders.AquariumHome, ResourceNames.CONF_FODLER)
201 final lazy val LOGBACK_XML_FILE = new File(AQUARIUM_HOME_CONF_FOLDER, ResourceNames.LOGBACK_XML)
204 * This exists in order to have a feeling of where we are.
206 final lazy val CONF_HERE = justForSure(getResource(".")).get.url.toExternalForm
208 final object Resources {
209 final lazy val AquariumPropertiesResource = {
210 ResourceLocator.SysProps.AquariumPropertiesPath.value match {
211 case Just(aquariumPropertiesPath) ⇒
212 // If we have a command-line override, prefer that
213 new FileStreamResource(new File(aquariumPropertiesPath))
217 throw new AquariumInternalError(
218 "Could not find %s=%s".format(
219 ResourceLocator.SysProps.Names.AquariumPropertiesPath,
220 ResourceLocator.SysProps.Names.AquariumPropertiesPath),
224 // Otherwise try other locations
225 val aquariumPropertiesRCM = ResourceLocator getResource ResourceLocator.ResourceNames.AQUARIUM_PROPERTIES
226 aquariumPropertiesRCM match {
227 case Just(aquariumProperties) ⇒
232 throw new AquariumInternalError(
233 "Could not find %s".format(ResourceLocator.ResourceNames.AQUARIUM_PROPERTIES))
237 throw new AquariumInternalError(
238 "Could not find %s".format(ResourceLocator.ResourceNames.AQUARIUM_PROPERTIES), e)
245 def getResource(what: String): Maybe[StreamResource] = {
246 ResourceContexts.MasterResourceContext.getResource(what)