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}
45 import com.ckkloverdos.props.Props
46 import com.ckkloverdos.convert.Converters._
47 import com.ckkloverdos.maybe.Just
48 import com.ckkloverdos.maybe.Failed
49 import com.ckkloverdos.convert.Converters
54 * This code was initially in [[gr.grnet.aquarium.Aquarium]].
56 * @author Christos KK Loverdos <loverdos@gmail.com>
59 object ResourceLocator {
60 final object ResourceNames {
61 final val CONF_FODLER = "conf"
62 final val SLASH_ETC_AQUARIUM_FOLDER = "/etc/aquarium"
64 final val LOGBACK_XML = "logback.xml"
65 final val AQUARIUM_PROPERTIES = "aquarium.properties"
66 final val POLICY_YAML = "policy.yaml"
67 final val ROLE_AGREEMENTS_MAP = "roles-agreements.map"
72 final val AKKA_HOME = "AKKA_HOME"
73 // final val AQUARIUM_HOME = "AQUARIUM_HOME"
76 final object Folders {
77 private[this] def checkFolder(name: String, file: File): File = {
78 if(!file.isDirectory) {
79 throw new AquariumInternalError(
80 "%s=%s is not a folder".format(
85 "%s [=%s]".format(file, file.getCanonicalFile)
93 * This is normally exported from the shell script (AQUARIUM_HOME) that starts Aquarium or given in the command
94 * line (aquarium.home).
96 * TODO: Make this searchable for resources (ie put it in the resource context)
98 final lazy val AquariumHome = {
99 SysProps.AquariumHome.value match {
100 case Just(aquariumHome) ⇒
101 checkFolder(SysProps.Names.AquariumHome, new File(aquariumHome))
104 throw new AquariumInternalError("Error regarding %s".format(SysProps.Names.AquariumHome), e)
107 SysEnvs.AQUARIUM_HOME.value match {
108 case Just(aquarium_home) ⇒
109 val folder = new File(aquarium_home)
110 checkFolder(SysEnvs.Names.AQUARIUM_HOME, folder)
111 SysProps.AquariumHome.update(folder.getPath) // needed for logback configuration
115 throw new AquariumInternalError("Error regarding %s".format(SysEnvs.Names.AQUARIUM_HOME), e)
118 val folder = new File(".")
119 SysProps.AquariumHome.update(folder.getPath) // needed for logback configuration
127 final object SysEnvs {
129 final val AKKA_HOME = Homes.Names.AKKA_HOME
130 final val AQUARIUM_HOME = "AQUARIUM_HOME"
133 final val AKKA_HOME = SysEnv(Names.AKKA_HOME)
134 final val AQUARIUM_HOME = SysEnv(Names.AQUARIUM_HOME)
137 final object SysProps {
139 final val AquariumHome = "aquarium.home"
140 final val AquariumPropertiesPath = "aquarium.properties.path"
141 final val AquariumConfFolder = "aquarium.conf.folder"
144 final val AquariumHome = SysProp(Names.AquariumHome)
147 * Use this property to override the place of aquarium.properties.
148 * If this is set, then it override any other way to specify the aquarium.properties location.
150 final val AquariumPropertiesPath = SysProp(Names.AquariumPropertiesPath)
153 * Use this property to override the place where aquarium configuration resides.
155 * The value of this property is a folder that defines the highest-priority resource context.
157 final val AquariumConfFolder = SysProp(Names.AquariumConfFolder)
160 final object ResourceContexts {
162 * AQUARIUM_HOME/conf resource context.
164 private[this] final lazy val HomeConfResourceContext = new FileStreamResourceContext(AQUARIUM_HOME_CONF_FOLDER)
167 * The venerable /etc resource context. Applicable in Unix environments
169 private[this] final lazy val SlashEtcResourceContext = new FileStreamResourceContext(ResourceNames.SLASH_ETC_AQUARIUM_FOLDER)
172 * Class loader resource context.
173 * This has the lowest priority.
175 private[this] final lazy val ClasspathBaseResourceContext = new ClassLoaderStreamResourceContext(
176 Thread.currentThread().getContextClassLoader)
178 private[this] final lazy val BasicResourceContext = new CompositeStreamResourceContext(
180 SlashEtcResourceContext,
181 HomeConfResourceContext,
182 ClasspathBaseResourceContext)
185 * The resource context used in the application.
187 final lazy val MasterResourceContext = {
188 SysProps.AquariumConfFolder.value match {
190 // We have a system override for the configuration location
191 new CompositeStreamResourceContext(
192 Just(BasicResourceContext),
193 new FileStreamResourceContext(value))
199 throw new AquariumInternalError(e)
204 final lazy val AQUARIUM_HOME_CONF_FOLDER = new File(Homes.Folders.AquariumHome, ResourceNames.CONF_FODLER)
207 * This exists in order to have a feeling of where we are.
209 final lazy val HERE = justForSure(getResource(".")).get.url.toExternalForm
211 final object Resources {
212 final lazy val AquariumPropertiesResource = {
213 ResourceLocator.SysProps.AquariumPropertiesPath.value match {
214 case Just(aquariumPropertiesPath) ⇒
215 // If we have a command-line override, prefer that
216 new FileStreamResource(new File(aquariumPropertiesPath))
220 throw new AquariumInternalError(
221 "Could not find %s".format(ResourceLocator.SysProps.Names.AquariumPropertiesPath), e)
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)
243 final lazy val LogbackXMLResource = {
244 getResource(ResourceNames.LOGBACK_XML) match {
245 case Just(logbackXML) ⇒
249 throw new AquariumInternalError(
250 "Could not find %s".format(ResourceLocator.ResourceNames.LOGBACK_XML))
253 throw new AquariumInternalError(
254 "Could not find %s".format(ResourceLocator.ResourceNames.LOGBACK_XML), e)
259 final lazy val PolicyYAMLResource = {
260 ResourceLocator.getResource(ResourceLocator.ResourceNames.POLICY_YAML) match {
261 case Just(policyYAML) ⇒
265 throw new AquariumInternalError(
266 "Could not find %s".format(ResourceLocator.ResourceNames.POLICY_YAML))
269 throw new AquariumInternalError(
270 "Could not find %s".format(ResourceLocator.ResourceNames.POLICY_YAML), e)
275 final lazy val AquariumProperties = {
276 implicit val DefaultConverters = Converters.DefaultConverters
277 val maybeProps = Props(Resources.AquariumPropertiesResource)
283 throw new AquariumInternalError(
284 "Could not load %s from %s".format(
285 ResourceLocator.ResourceNames.AQUARIUM_PROPERTIES,
286 Resources.AquariumPropertiesResource))
290 throw new AquariumInternalError(
291 "Could not load %s from %s".format(
292 ResourceLocator.ResourceNames.AQUARIUM_PROPERTIES,
293 Resources.AquariumPropertiesResource),
299 def getResource(what: String): Maybe[StreamResource] = {
300 ResourceContexts.MasterResourceContext.getResource(what)