WIP: IMEventModel end-to-end chain
[aquarium] / src / main / scala / gr / grnet / aquarium / Main.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 akka.actor.Actor
39 import com.ckkloverdos.sys.SysProp
40 import org.slf4j.LoggerFactory
41 import ch.qos.logback.classic.LoggerContext
42 import ch.qos.logback.classic.joran.JoranConfigurator
43 import ch.qos.logback.core.util.StatusPrinter
44 import com.ckkloverdos.maybe.{NoVal, Maybe, Failed, Just}
45 import util.date.TimeHelpers
46 import util.{LazyLoggable, Loggable}
47
48 /**
49  * Main method for Aquarium
50  *
51  * @author Georgios Gousios <gousiosg@gmail.com>
52  * @author Christos KK Loverdos <loverdos@gmail.com>
53  */
54 object Main extends LazyLoggable {
55   private[this] final val PropsToShow = List(
56     SysProp.JavaVMName,
57     SysProp.JavaVersion,
58     SysProp.JavaHome,
59     SysProp.JavaClassVersion,
60     SysProp.JavaLibraryPath,
61     SysProp.JavaClassPath,
62     SysProp.JavaIOTmpDir,
63     SysProp.UserName,
64     SysProp.UserHome,
65     SysProp.UserDir,
66     SysProp("file.encoding")
67   )
68
69   private[this] def configureLogging(): Unit = {
70     // http://logback.qos.ch/manual/joran.html
71     LoggerFactory.getILoggerFactory match {
72       case context: LoggerContext ⇒
73         Maybe {
74           val joran = new JoranConfigurator
75           joran.setContext(context)
76           context.reset()
77           joran.doConfigure(ResourceLocator.LOGBACK_XML_FILE)
78           logger.info("Logging subsystem configured from {}", ResourceLocator.LOGBACK_XML_FILE)
79         } forJust {
80           case _ ⇒
81             StatusPrinter.printInCaseOfErrorsOrWarnings(context)
82         } forFailed {
83           case failed @ Failed(e) ⇒
84             StatusPrinter.print(context)
85             throw new AquariumException(e, "Could not configure logging from %s".format(ResourceLocator.LOGBACK_XML_FILE))
86         }
87       case _ ⇒
88     }
89   }
90
91   def doStart(): Unit = {
92     import ResourceLocator.{AQUARIUM_HOME, AQUARIUM_HOME_FOLDER, CONF_HERE, AKKA_HOME}
93     // We have AKKA builtin, so no need to mess with pre-existing installation.
94     if(AKKA_HOME.value.isJust) {
95       val error = new AquariumException("%s is set. Please unset and restart Aquarium".format(AKKA_HOME.name))
96       logger.error("%s is set".format(AKKA_HOME.name), error)
97       throw error
98     }
99
100     val mc = Configurator.MasterConfigurator
101
102     mc.eventsStoreFolder match {
103       case Just(folder) ⇒
104         logger.info("{} = {}", Configurator.Keys.events_store_folder, folder)
105
106       case failed @ Failed(e) ⇒
107         throw e
108
109       case _ ⇒
110     }
111
112     for {
113       prop <- PropsToShow
114     } {
115       logger.info("{} = {}", prop.name, prop.rawValue)
116     }
117     logger.info("{} = {}", AQUARIUM_HOME.name, AQUARIUM_HOME_FOLDER)
118     logger.info("CONF_HERE = {}", CONF_HERE)
119
120     mc.startServices()
121
122     Runtime.getRuntime.addShutdownHook(new Thread(new Runnable {
123       def run = {
124         logStopping()
125         val (ms0, ms1, _) = TimeHelpers.timed {
126           mc.stopServices()
127         }
128         logStopped(ms0, ms1)
129       }
130     }))
131   }
132
133   def main(args: Array[String]) = {
134     configureLogging()
135
136     logStarting("Aquarium from %s", ResourceLocator.AQUARIUM_HOME_FOLDER)
137     val (ms0, ms1, _) = TimeHelpers.timed {
138       doStart()
139     }
140     logStarted(ms0, ms1, "Aquarium")
141   }
142 }