package gr.grnet.aquarium
-import actor.{ActorProvider}
-import com.ckkloverdos.resource._
-import com.ckkloverdos.sys.SysProp
+import events.im.IMEventModel
+import java.io.File
+
+import com.ckkloverdos.maybe._
import com.ckkloverdos.props.Props
-import com.ckkloverdos.maybe.{Maybe, Failed, Just, NoVal}
import com.ckkloverdos.convert.Converters.{DefaultConverters => TheDefaultConverters}
-import processor.actor.{UserEventProcessorService, ResourceEventProcessorService}
-import store._
-import util.{Lifecycle, Loggable}
-import java.io.File
+
+import gr.grnet.aquarium.service._
+import gr.grnet.aquarium.util.{Lifecycle, Loggable}
+import gr.grnet.aquarium.store._
/**
* The master configurator. Responsible to load all of application configuration and provide the relevant services.
Maybe(configurable configure props) match {
case Just(_) ⇒
instance
- case Failed(e, _) ⇒
- throw new Exception("Could not configure instance of %s".format(className), e)
+ case Failed(e) ⇒
+ throw new AquariumException("Could not configure instance of %s".format(className), e)
case NoVal ⇒
- throw new Exception("Could not configure instance of %s".format(className))
+ throw new AquariumException("Could not configure instance of %s".format(className))
}
case _ ⇒
instance
}
- case Failed(e, _) ⇒
- throw new Exception("Could not instantiate %s".format(className), e)
+ case Failed(e) ⇒
+ throw new AquariumException("Could not instantiate %s".format(className), e)
case NoVal ⇒
- throw new Exception("Could not instantiate %s".format(className))
+ throw new AquariumException("Could not instantiate %s".format(className))
}
}
- private[this] lazy val _actorProvider: ActorProvider = {
- val instance = newInstance[ActorProvider](props.getEx(Keys.actor_provider_class))
- logger.info("Loaded ActorProvider: %s".format(instance.getClass))
+ private[this] lazy val _actorProvider: ActorProviderService = {
+ val instance = newInstance[ActorProviderService](props.getEx(Keys.actor_provider_class))
+ logger.info("Loaded ActorProviderService: %s".format(instance.getClass))
instance
}
}
}
- private[this] lazy val _userEventStoreM: Maybe[UserEventStore] = {
+ private[this] lazy val _imEventStoreM: Maybe[IMEventStore] = {
props.get(Keys.user_event_store_class) map { className ⇒
- val instance = newInstance[UserEventStore](className)
- logger.info("Overriding UserEventStore provisioning. Implementation given by: %s".format(instance.getClass))
+ val instance = newInstance[IMEventStore](className)
+ logger.info("Overriding IMEventStore provisioning. Implementation given by: %s".format(instance.getClass))
instance
}
}
}
}
- private[this] lazy val _resEventProc: ResourceEventProcessorService = new ResourceEventProcessorService
+ private[this] lazy val _eventsStoreFolder: Maybe[File] = {
+ props.get(Keys.events_store_folder) map {
+ folderName ⇒
+ val canonicalFolder = {
+ val folder = new File(folderName)
+ if(folder.isAbsolute) {
+ folder.getCanonicalFile
+ } else {
+ logger.info("{} is not absolute, making it relative to AQUARIUM_HOME", Keys.events_store_folder)
+ new File(ResourceLocator.AQUARIUM_HOME_FOLDER, folderName).getCanonicalFile
+ }
+ }
+
+ val canonicalPath = canonicalFolder.getCanonicalPath
+
+ logger.info("{} = {}", Keys.events_store_folder, canonicalPath)
+
+ if(canonicalFolder.exists() && !canonicalFolder.isDirectory) {
+ throw new AquariumException("%s = %s is not a folder".format(Keys.events_store_folder, canonicalFolder))
+ }
+
+ // Now, events folder must be outside AQUARIUM_HOME, since AQUARIUM_HOME can be wiped out for an upgrade but
+ // we still want to keep the events.
+ val ahCanonicalPath = ResourceLocator.AQUARIUM_HOME_FOLDER.getCanonicalPath
+ if(canonicalPath.startsWith(ahCanonicalPath)) {
+ throw new AquariumException(
+ "%s = %s is under %s = %s".format(
+ Keys.events_store_folder, canonicalFolder,
+ ResourceLocator.AQUARIUM_HOME.name, ahCanonicalPath
+ ))
+ }
+
+ canonicalFolder.mkdirs()
+
+ canonicalFolder
+ }
+ }
+
+ private[this] lazy val _resEventProc = new ResourceEventProcessorService
- private[this] lazy val _imEventProc: UserEventProcessorService = new UserEventProcessorService
+ private[this] lazy val _imEventProc = new IMEventProcessorService
+
+ private[this] lazy val _lifecycleServices = List(AkkaService, _restService, _actorProvider, _resEventProc, _imEventProc)
def get(key: String, default: String = ""): String = props.getOr(key, default)
def defaultClassLoader = Thread.currentThread().getContextClassLoader
/**
+ * FIXME: This must be ditched.
+ *
* Find a file whose location can be overiden in
* the configuration file (e.g. policy.yaml)
*
}
def startServices(): Unit = {
- _restService.start()
- _actorProvider.start()
- _resEventProc.start()
- _imEventProc.start()
+ _lifecycleServices.foreach(_.start())
}
def stopServices(): Unit = {
- _imEventProc.stop()
- _resEventProc.stop()
- _restService.stop()
- _actorProvider.stop()
-
+ _lifecycleServices.reverse.foreach(_.stop())
// akka.actor.Actor.registry.shutdownAll()
}
}
}
- def userEventStore = {
- _userEventStoreM match {
+ def imEventStore = {
+ _imEventStoreM match {
case Just(es) ⇒ es
- case _ ⇒ storeProvider.userEventStore
+ case _ ⇒ storeProvider.imEventStore
}
}
new Configurator(newProps)
}
- // FIXME: This is instead of props.getInt which currently contains a bug.
- // FIXME: Fix the original bug and delete this method
- def getInt(name: String): Maybe[Int] = {
- props.get(name).map(_.toInt)
+ def eventsStoreFolder = _eventsStoreFolder
+
+ def adminCookie: MaybeOption[String] = props.get(Configurator.Keys.admin_cookie) match {
+ case just @ Just(_) ⇒ just
+ case _ ⇒ NoVal
}
}
case Just(masterConfResource) ⇒
masterConfResource
case NoVal ⇒
- throw new RuntimeException("Could not find master configuration file: %s".format(MasterConfName))
- case Failed(e, m) ⇒
- throw new RuntimeException(m, e)
+ throw new AquariumException("Could not find master configuration file: %s".format(MasterConfName))
+ case Failed(e) ⇒
+ throw new AquariumException(e, "Could not find master configuration file: %s".format(MasterConfName))
}
}
case Just(props) ⇒
props
case NoVal ⇒
- throw new RuntimeException("Could not load master configuration file: %s".format(MasterConfName))
- case Failed(e, m) ⇒
- throw new RuntimeException(m, e)
+ throw new AquariumException("Could not load master configuration file: %s".format(MasterConfName))
+ case Failed(e) ⇒
+ throw new AquariumException(e, "Could not load master configuration file: %s".format(MasterConfName))
}
}
case Just(masterConf) ⇒
masterConf
case NoVal ⇒
- throw new RuntimeException("Could not initialize master configuration file: %s".format(MasterConfName))
- case Failed(e, m) ⇒
- throw new RuntimeException(m, e)
+ throw new AquariumException("Could not initialize master configuration file: %s".format(MasterConfName))
+ case Failed(e) ⇒
+ throw new AquariumException(e, "Could not initialize master configuration file: %s".format(MasterConfName))
}
}
final val version = "version"
/**
- * The fully qualified name of the class that implements the `ActorProvider`.
+ * The fully qualified name of the class that implements the `ActorProviderService`.
* Will be instantiated reflectively and should have a public default constructor.
*/
final val actor_provider_class = "actor.provider.class"
*/
final val time_unit_in_millis = "time.unit.in.seconds"
- final val message_queues_store_folder = "messages"
+ /**
+ * If a value is given to this property, then it represents a folder where all events coming to aquarium are
+ * stored.
+ */
+ final val events_store_folder = "events.store.folder"
+
+ /**
+ * If set to `true`, then an IM event that cannot be parsed to [[gr.grnet.aquarium.events.im.IMEventModel]] is
+ * saved to the [[gr.grnet.aquarium.store.IMEventStore]].
+ */
+ final val save_unparsed_event_im = "save.unparsed.event.im"
+
+ /**
+ * A cookie used in every administrative REST API call, so that Aquarium knows it comes from
+ * an authorised client.
+ */
+ final val admin_cookie = "admin.cookie"
+ }
+
+ object HTTP {
+ final val RESTAdminHeaderName = "X-Aquarium-Admin-Cookie"
+ final val RESTAdminHeaderNameLowerCase = RESTAdminHeaderName.toLowerCase
}
}