WIP: Remodeling events
[aquarium] / src / main / scala / gr / grnet / aquarium / ResourceLocator.scala
1 /*
2  * Copyright 2011-2012 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *
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.
16  *
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.
29  *
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.
34  */
35
36 package gr.grnet.aquarium
37
38 import com.ckkloverdos.resource.{StreamResource, CompositeStreamResourceContext, ClassLoaderStreamResourceContext, FileStreamResourceContext}
39 import com.ckkloverdos.maybe.{Failed, Just, Maybe, NoVal}
40 import com.ckkloverdos.sys.{SysEnv, SysProp}
41 import java.io.File
42
43 import gr.grnet.aquarium.util.justForSure
44
45 /**
46  * Used to locate configuration files.
47  *
48  * This code was initially in [[gr.grnet.aquarium.Configurator]].
49  *
50  * @author Christos KK Loverdos <loverdos@gmail.com>
51  */
52
53 object ResourceLocator {
54   final object Names {
55     final val LOGBACK_XML = "logback.xml"
56   }
57
58   final val AKKA_HOME = SysEnv("AKKA_HOME")
59
60   /**
61    * This is normally exported from the shell script that starts Aquarium.
62    *
63    * TODO: Make this searchable for resources (ie put it in the resource context)
64    */
65   final val AQUARIUM_HOME = SysEnv("AQUARIUM_HOME")
66
67   final lazy val AQUARIUM_HOME_FOLDER: File = {
68     AQUARIUM_HOME.value match {
69       case Just(home) ⇒
70         val file = new File(home)
71         if(!file.isDirectory) {
72           throw new AquariumException("%s (%s) is not a folder".format(AQUARIUM_HOME.name, home))
73         }
74         file.getCanonicalFile()
75       case _ ⇒
76         throw new AquariumException("%s is not set".format(AQUARIUM_HOME.name))
77     }
78   }
79
80   final lazy val AQUARIUM_HOME_CONF_FOLDER = new File(AQUARIUM_HOME_FOLDER, "conf")
81
82   final lazy val LOGBACK_XML_FILE = new File(AQUARIUM_HOME_CONF_FOLDER, Names.LOGBACK_XML)
83
84   /**
85    * This exists in order to have a feeling of where we are.
86    */
87   final lazy val CONF_HERE = justForSure(getResource(".")).get.url.toExternalForm
88
89   /**
90    * AQUARIUM_HOME/conf resource context.
91    */
92   private[this] final lazy val HomeConfResourceContext = new FileStreamResourceContext(AQUARIUM_HOME_CONF_FOLDER)
93
94   /**
95    * The venerable /etc resource context. Applicable in Unix environments
96    */
97   private[this] final lazy val SlashEtcResourceContext = new FileStreamResourceContext("/etc/aquarium")
98
99   /**
100    * Class loader resource context.
101    * This has the lowest priority.
102    */
103   private[this] final lazy val ClasspathBaseResourceContext = new ClassLoaderStreamResourceContext(Thread
104     .currentThread().getContextClassLoader)
105
106   /**
107    * Use this property to override the place where aquarium configuration resides.
108    *
109    * The value of this property is a folder that defines the highest-priority resource context.
110    */
111   private[this] final lazy val ConfBaseFolderSysProp = SysProp("aquarium.conf.base.folder")
112
113   private[this] final lazy val BasicResourceContext = new CompositeStreamResourceContext(
114     NoVal,
115     SlashEtcResourceContext,
116     HomeConfResourceContext,
117     ClasspathBaseResourceContext)
118
119   /**
120    * The resource context used in the application.
121    */
122   private[this] final lazy val MasterResourceContext = {
123     ConfBaseFolderSysProp.value match {
124       case Just(value) ⇒
125         // We have a system override for the configuration location
126         new CompositeStreamResourceContext(Just(BasicResourceContext), new FileStreamResourceContext(value))
127       case NoVal ⇒
128         BasicResourceContext
129       case Failed(e) ⇒
130         throw new AquariumException(e)
131     }
132   }
133
134   def getResource(what: String): Maybe[StreamResource] =
135     MasterResourceContext.getResource(what)
136 }