Statistics
| Branch: | Tag: | Revision:

root / src / main / scala / gr / grnet / aquarium / Aquarium.scala @ 7dbaeb04

History | View | Annotate | Download (15.3 kB)

1 12a4f3c9 Christos KK Loverdos
/*
2 04b151ba Christos KK Loverdos
 * Copyright 2011-2012 GRNET S.A. All rights reserved.
3 12a4f3c9 Christos KK Loverdos
 *
4 12a4f3c9 Christos KK Loverdos
 * Redistribution and use in source and binary forms, with or
5 12a4f3c9 Christos KK Loverdos
 * without modification, are permitted provided that the following
6 12a4f3c9 Christos KK Loverdos
 * conditions are met:
7 12a4f3c9 Christos KK Loverdos
 *
8 12a4f3c9 Christos KK Loverdos
 *   1. Redistributions of source code must retain the above
9 12a4f3c9 Christos KK Loverdos
 *      copyright notice, this list of conditions and the following
10 12a4f3c9 Christos KK Loverdos
 *      disclaimer.
11 12a4f3c9 Christos KK Loverdos
 *
12 12a4f3c9 Christos KK Loverdos
 *   2. Redistributions in binary form must reproduce the above
13 12a4f3c9 Christos KK Loverdos
 *      copyright notice, this list of conditions and the following
14 12a4f3c9 Christos KK Loverdos
 *      disclaimer in the documentation and/or other materials
15 12a4f3c9 Christos KK Loverdos
 *      provided with the distribution.
16 12a4f3c9 Christos KK Loverdos
 *
17 12a4f3c9 Christos KK Loverdos
 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18 12a4f3c9 Christos KK Loverdos
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 12a4f3c9 Christos KK Loverdos
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 12a4f3c9 Christos KK Loverdos
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21 12a4f3c9 Christos KK Loverdos
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 12a4f3c9 Christos KK Loverdos
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 12a4f3c9 Christos KK Loverdos
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24 12a4f3c9 Christos KK Loverdos
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 12a4f3c9 Christos KK Loverdos
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 12a4f3c9 Christos KK Loverdos
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 12a4f3c9 Christos KK Loverdos
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 12a4f3c9 Christos KK Loverdos
 * POSSIBILITY OF SUCH DAMAGE.
29 12a4f3c9 Christos KK Loverdos
 *
30 12a4f3c9 Christos KK Loverdos
 * The views and conclusions contained in the software and
31 12a4f3c9 Christos KK Loverdos
 * documentation are those of the authors and should not be
32 12a4f3c9 Christos KK Loverdos
 * interpreted as representing official policies, either expressed
33 12a4f3c9 Christos KK Loverdos
 * or implied, of GRNET S.A.
34 12a4f3c9 Christos KK Loverdos
 */
35 12a4f3c9 Christos KK Loverdos
36 12a4f3c9 Christos KK Loverdos
package gr.grnet.aquarium
37 12a4f3c9 Christos KK Loverdos
38 695c71e2 Christos KK Loverdos
import com.ckkloverdos.env.Env
39 695c71e2 Christos KK Loverdos
import com.ckkloverdos.key.{IntKey, StringKey, LongKey, TypedKeySkeleton, TypedKey, BooleanKey}
40 ba69480b Christos KK Loverdos
import com.ckkloverdos.props.Props
41 7dbaeb04 Christos KK Loverdos
import gr.grnet.aquarium.store.{PolicyStore, StoreProvider}
42 695c71e2 Christos KK Loverdos
import java.io.File
43 695c71e2 Christos KK Loverdos
import gr.grnet.aquarium.util.{Loggable, Lifecycle}
44 6ad32d72 Christos KK Loverdos
import gr.grnet.aquarium.service.{StoreWatcherService, RabbitMQService, TimerService, EventBusService, AkkaService}
45 695c71e2 Christos KK Loverdos
import com.ckkloverdos.convert.Converters
46 b30e5a44 Christos KK Loverdos
import java.util.concurrent.atomic.AtomicBoolean
47 695c71e2 Christos KK Loverdos
import org.slf4j.{LoggerFactory, Logger}
48 695c71e2 Christos KK Loverdos
import com.ckkloverdos.maybe._
49 695c71e2 Christos KK Loverdos
import com.ckkloverdos.sys.SysProp
50 7de7765f Christos KK Loverdos
import gr.grnet.aquarium.service.event.AquariumCreatedEvent
51 7dbaeb04 Christos KK Loverdos
import gr.grnet.aquarium.policy.{FullPriceTable, PolicyModel, CachingPolicyStore, PolicyDefinedFullPriceTableRef, StdUserAgreement, UserAgreementModel, ResourceType}
52 2a29acf9 Christos KK Loverdos
import gr.grnet.aquarium.charging.{ChargingService, ChargingBehavior}
53 2a29acf9 Christos KK Loverdos
import gr.grnet.aquarium.util.date.TimeHelpers
54 12a4f3c9 Christos KK Loverdos
55 12a4f3c9 Christos KK Loverdos
/**
56 12a4f3c9 Christos KK Loverdos
 *
57 695c71e2 Christos KK Loverdos
 * @author Christos KK Loverdos <loverdos@gmail.com>
58 12a4f3c9 Christos KK Loverdos
 */
59 695c71e2 Christos KK Loverdos
60 695c71e2 Christos KK Loverdos
final class Aquarium(env: Env) extends Lifecycle with Loggable {
61 695c71e2 Christos KK Loverdos
  import Aquarium.EnvKeys
62 9ce8385e Christos KK Loverdos
63 b7b59f6f Christos KK Loverdos
  @volatile private[this] var _chargingBehaviorMap = Map[String, ChargingBehavior]()
64 b7b59f6f Christos KK Loverdos
65 7dbaeb04 Christos KK Loverdos
  private[this] lazy val cachingPolicyStore = new CachingPolicyStore(
66 7dbaeb04 Christos KK Loverdos
    apply(EnvKeys.defaultPolicyModel),
67 7dbaeb04 Christos KK Loverdos
    apply(EnvKeys.storeProvider).policyStore
68 7dbaeb04 Christos KK Loverdos
  )
69 7dbaeb04 Christos KK Loverdos
70 b30e5a44 Christos KK Loverdos
  private[this] val _isStopping = new AtomicBoolean(false)
71 b30e5a44 Christos KK Loverdos
72 5e4d8d64 Christos KK Loverdos
  override def toString = "%s/v%s".format(getClass.getName, version)
73 5e4d8d64 Christos KK Loverdos
74 b30e5a44 Christos KK Loverdos
  def isStopping() = _isStopping.get()
75 b30e5a44 Christos KK Loverdos
76 6453d1cf Christos KK Loverdos
  @inline
77 6453d1cf Christos KK Loverdos
  def getClientLogger(client: AnyRef): Logger = {
78 6453d1cf Christos KK Loverdos
    client match {
79 6453d1cf Christos KK Loverdos
      case null ⇒
80 6453d1cf Christos KK Loverdos
        this.logger
81 6453d1cf Christos KK Loverdos
82 6453d1cf Christos KK Loverdos
      case _ ⇒
83 6453d1cf Christos KK Loverdos
        LoggerFactory.getLogger(client.getClass)
84 6453d1cf Christos KK Loverdos
    }
85 6453d1cf Christos KK Loverdos
  }
86 6453d1cf Christos KK Loverdos
87 3004b61c Christos KK Loverdos
  def debug(client: AnyRef, fmt: String, args: Any*) = {
88 6453d1cf Christos KK Loverdos
    getClientLogger(client).debug(fmt.format(args: _*))
89 3004b61c Christos KK Loverdos
  }
90 3004b61c Christos KK Loverdos
91 3004b61c Christos KK Loverdos
  def info(client: AnyRef, fmt: String, args: Any*) = {
92 6453d1cf Christos KK Loverdos
    getClientLogger(client).info(fmt.format(args: _*))
93 3004b61c Christos KK Loverdos
  }
94 3004b61c Christos KK Loverdos
95 3004b61c Christos KK Loverdos
  def warn(client: AnyRef, fmt: String, args: Any*) = {
96 6453d1cf Christos KK Loverdos
    getClientLogger(client).warn(fmt.format(args: _*))
97 3004b61c Christos KK Loverdos
  }
98 3004b61c Christos KK Loverdos
99 695c71e2 Christos KK Loverdos
  @throws(classOf[AquariumInternalError])
100 695c71e2 Christos KK Loverdos
  def apply[T: Manifest](key: TypedKey[T]): T = {
101 695c71e2 Christos KK Loverdos
    try {
102 695c71e2 Christos KK Loverdos
     env.getEx(key)
103 695c71e2 Christos KK Loverdos
    } catch {
104 695c71e2 Christos KK Loverdos
      case e: Exception ⇒
105 695c71e2 Christos KK Loverdos
        throw new AquariumInternalError("Could not locate %s in Aquarium environment".format(key))
106 03046173 Christos KK Loverdos
    }
107 03046173 Christos KK Loverdos
  }
108 03046173 Christos KK Loverdos
109 b7b59f6f Christos KK Loverdos
  private[this] lazy val _allServices = Aquarium.ServiceKeys.map(this.apply(_))
110 af872cfe Georgios Gousios
111 b30e5a44 Christos KK Loverdos
  private[this] def startServices(): Unit = {
112 6107e07c Christos KK Loverdos
    for(service ← _allServices) {
113 6a8f1284 Christos KK Loverdos
      logStartingF(service.toString) {
114 6a8f1284 Christos KK Loverdos
        service.start()
115 6a8f1284 Christos KK Loverdos
      } {}
116 6107e07c Christos KK Loverdos
    }
117 6adaafb6 Christos KK Loverdos
  }
118 6adaafb6 Christos KK Loverdos
119 b30e5a44 Christos KK Loverdos
  private[this] def stopServices(): Unit = {
120 6a8f1284 Christos KK Loverdos
    val services = _allServices.reverse
121 6a8f1284 Christos KK Loverdos
122 6a8f1284 Christos KK Loverdos
    for(service ← services) {
123 6a8f1284 Christos KK Loverdos
      logStoppingF(service.toString) {
124 6a8f1284 Christos KK Loverdos
        safeUnit(service.stop())
125 6a8f1284 Christos KK Loverdos
      } {}
126 6a8f1284 Christos KK Loverdos
    }
127 6adaafb6 Christos KK Loverdos
  }
128 6adaafb6 Christos KK Loverdos
129 695c71e2 Christos KK Loverdos
  private[this] def showBasicConfiguration(): Unit = {
130 b30e5a44 Christos KK Loverdos
    for(folder ← this.eventsStoreFolder) {
131 695c71e2 Christos KK Loverdos
      logger.info("{} = {}", EnvKeys.eventsStoreFolder.name, folder)
132 b30e5a44 Christos KK Loverdos
    }
133 b30e5a44 Christos KK Loverdos
    this.eventsStoreFolder.throwMe // on error
134 758f18b8 Christos KK Loverdos
  }
135 b30e5a44 Christos KK Loverdos
136 758f18b8 Christos KK Loverdos
  private[this] def addShutdownHooks(): Unit = {
137 b30e5a44 Christos KK Loverdos
    Runtime.getRuntime.addShutdownHook(new Thread(new Runnable {
138 b30e5a44 Christos KK Loverdos
      def run = {
139 cbd58d68 Christos KK Loverdos
        if(!_isStopping.get()) {
140 cbd58d68 Christos KK Loverdos
          logStoppingF("Aquarium") {
141 cbd58d68 Christos KK Loverdos
            stop()
142 cbd58d68 Christos KK Loverdos
          } {}
143 b30e5a44 Christos KK Loverdos
        }
144 b30e5a44 Christos KK Loverdos
      }
145 b30e5a44 Christos KK Loverdos
    }))
146 b30e5a44 Christos KK Loverdos
  }
147 b30e5a44 Christos KK Loverdos
148 695c71e2 Christos KK Loverdos
  def start(): Unit = {
149 cbd58d68 Christos KK Loverdos
    this._isStopping.set(false)
150 695c71e2 Christos KK Loverdos
    showBasicConfiguration()
151 758f18b8 Christos KK Loverdos
    addShutdownHooks()
152 cbd58d68 Christos KK Loverdos
    startServices()
153 758f18b8 Christos KK Loverdos
  }
154 758f18b8 Christos KK Loverdos
155 695c71e2 Christos KK Loverdos
  def stop(): Unit = {
156 b30e5a44 Christos KK Loverdos
    this._isStopping.set(true)
157 6adaafb6 Christos KK Loverdos
    stopServices()
158 6adaafb6 Christos KK Loverdos
  }
159 199695ce Christos KK Loverdos
160 695c71e2 Christos KK Loverdos
  /**
161 695c71e2 Christos KK Loverdos
   * Stops Aquarium after the given millis. Used during testing.
162 695c71e2 Christos KK Loverdos
   */
163 695c71e2 Christos KK Loverdos
  def stopAfterMillis(millis: Long) {
164 695c71e2 Christos KK Loverdos
    Thread sleep millis
165 695c71e2 Christos KK Loverdos
    stop()
166 119e4381 Christos KK Loverdos
  }
167 119e4381 Christos KK Loverdos
168 695c71e2 Christos KK Loverdos
  /**
169 695c71e2 Christos KK Loverdos
   * Reflectively provide a new instance of a class and configure it appropriately.
170 695c71e2 Christos KK Loverdos
   */
171 b7b59f6f Christos KK Loverdos
  def newInstance[C <: AnyRef](_class: Class[C]): C = {
172 b7b59f6f Christos KK Loverdos
    newInstance(_class.getName)
173 b7b59f6f Christos KK Loverdos
  }
174 b7b59f6f Christos KK Loverdos
175 b7b59f6f Christos KK Loverdos
  /**
176 b7b59f6f Christos KK Loverdos
   * Reflectively provide a new instance of a class and configure it appropriately.
177 b7b59f6f Christos KK Loverdos
   */
178 b7b59f6f Christos KK Loverdos
  def newInstance[C <: AnyRef](className: String): C = {
179 695c71e2 Christos KK Loverdos
    val originalProps = apply(EnvKeys.originalProps)
180 2ffb577f Christos KK Loverdos
181 695c71e2 Christos KK Loverdos
    val instanceM = MaybeEither(defaultClassLoader.loadClass(className).newInstance().asInstanceOf[C])
182 695c71e2 Christos KK Loverdos
    instanceM match {
183 695c71e2 Christos KK Loverdos
      case Just(instance) ⇒
184 7de7765f Christos KK Loverdos
//        eventBus.addSubscriber[C](instance)
185 7de7765f Christos KK Loverdos
        instance match {
186 7de7765f Christos KK Loverdos
          case aquariumAware: AquariumAware ⇒
187 7de7765f Christos KK Loverdos
            aquariumAware.awareOfAquarium(AquariumCreatedEvent(this))
188 7de7765f Christos KK Loverdos
189 7de7765f Christos KK Loverdos
          case _ ⇒
190 7de7765f Christos KK Loverdos
        }
191 695c71e2 Christos KK Loverdos
192 695c71e2 Christos KK Loverdos
        instance match {
193 695c71e2 Christos KK Loverdos
          case configurable: Configurable if (originalProps ne null) ⇒
194 695c71e2 Christos KK Loverdos
            val localProps = configurable.propertyPrefix match {
195 695c71e2 Christos KK Loverdos
              case somePrefix @ Some(prefix) ⇒
196 695c71e2 Christos KK Loverdos
                if(prefix.length == 0) {
197 695c71e2 Christos KK Loverdos
                  logger.warn(
198 695c71e2 Christos KK Loverdos
                    "Property prefix for %s is %s. Consider using None".format(instance, somePrefix))
199 695c71e2 Christos KK Loverdos
                }
200 695c71e2 Christos KK Loverdos
201 695c71e2 Christos KK Loverdos
                originalProps.subsetForKeyPrefix(prefix)
202 695c71e2 Christos KK Loverdos
203 695c71e2 Christos KK Loverdos
              case None ⇒
204 695c71e2 Christos KK Loverdos
                originalProps
205 695c71e2 Christos KK Loverdos
            }
206 695c71e2 Christos KK Loverdos
207 7de7765f Christos KK Loverdos
            logger.debug("Configuring {} with props (prefix={})", configurable.getClass.getName, configurable.propertyPrefix)
208 695c71e2 Christos KK Loverdos
            MaybeEither(configurable configure localProps) match {
209 695c71e2 Christos KK Loverdos
              case Just(_) ⇒
210 7de7765f Christos KK Loverdos
                logger.info("Configured {} with props (prefix={})", configurable.getClass.getName, configurable.propertyPrefix)
211 695c71e2 Christos KK Loverdos
212 695c71e2 Christos KK Loverdos
              case Failed(e) ⇒
213 695c71e2 Christos KK Loverdos
                throw new AquariumInternalError("Could not configure instance of %s".format(className), e)
214 695c71e2 Christos KK Loverdos
            }
215 695c71e2 Christos KK Loverdos
216 695c71e2 Christos KK Loverdos
          case _ ⇒
217 695c71e2 Christos KK Loverdos
        }
218 ee343d66 Georgios Gousios
219 7de7765f Christos KK Loverdos
        instance
220 7de7765f Christos KK Loverdos
221 695c71e2 Christos KK Loverdos
      case Failed(e) ⇒
222 695c71e2 Christos KK Loverdos
        throw new AquariumInternalError("Could not instantiate %s".format(className), e)
223 489d6802 Georgios Gousios
    }
224 489d6802 Georgios Gousios
225 695c71e2 Christos KK Loverdos
  }
226 0e00e810 Christos KK Loverdos
227 6ad32d72 Christos KK Loverdos
  def currentResourceTypesMap: Map[String, ResourceType] = {
228 2a29acf9 Christos KK Loverdos
    val policyOpt = policyStore.loadValidPolicyAt(TimeHelpers.nowMillis())
229 2a29acf9 Christos KK Loverdos
    if(policyOpt.isEmpty) {
230 2a29acf9 Christos KK Loverdos
      throw new AquariumInternalError("Not even the default policy found")
231 2a29acf9 Christos KK Loverdos
    }
232 2a29acf9 Christos KK Loverdos
233 2a29acf9 Christos KK Loverdos
    policyOpt.get.resourceTypesMap
234 0e00e810 Christos KK Loverdos
  }
235 0e00e810 Christos KK Loverdos
236 2a29acf9 Christos KK Loverdos
  def unsafeValidPolicyAt(referenceTimeMillis: Long): PolicyModel = {
237 2a29acf9 Christos KK Loverdos
    policyStore.loadValidPolicyAt(referenceTimeMillis) match {
238 2a29acf9 Christos KK Loverdos
      case None ⇒
239 2a29acf9 Christos KK Loverdos
        throw new AquariumInternalError(
240 2a29acf9 Christos KK Loverdos
          "No policy found at %s".format(TimeHelpers.toYYYYMMDDHHMMSSSSS(referenceTimeMillis))
241 2a29acf9 Christos KK Loverdos
        )
242 2a29acf9 Christos KK Loverdos
243 2a29acf9 Christos KK Loverdos
      case Some(policy) ⇒
244 2a29acf9 Christos KK Loverdos
        policy
245 2a29acf9 Christos KK Loverdos
    }
246 0e00e810 Christos KK Loverdos
  }
247 0e00e810 Christos KK Loverdos
248 2a29acf9 Christos KK Loverdos
  def unsafePriceTableForRoleAt(role: String, referenceTimeMillis: Long): FullPriceTable = {
249 2a29acf9 Christos KK Loverdos
    val policyAtReferenceTime = unsafeValidPolicyAt(referenceTimeMillis)
250 2a29acf9 Christos KK Loverdos
    policyAtReferenceTime.roleMapping.get(role) match {
251 2a29acf9 Christos KK Loverdos
      case None ⇒
252 2a29acf9 Christos KK Loverdos
        throw new AquariumInternalError("Unknown price table for role %s at %s".format(
253 2a29acf9 Christos KK Loverdos
          role,
254 2a29acf9 Christos KK Loverdos
          TimeHelpers.toYYYYMMDDHHMMSSSSS(referenceTimeMillis)
255 2a29acf9 Christos KK Loverdos
        ))
256 2a29acf9 Christos KK Loverdos
257 2a29acf9 Christos KK Loverdos
      case Some(fullPriceTable) ⇒
258 2a29acf9 Christos KK Loverdos
        fullPriceTable
259 2a29acf9 Christos KK Loverdos
    }
260 0e00e810 Christos KK Loverdos
  }
261 b33dcda7 Christos KK Loverdos
262 2a29acf9 Christos KK Loverdos
  /**
263 2a29acf9 Christos KK Loverdos
   * Computes the initial user agreement for the given role and reference time. Also,
264 2a29acf9 Christos KK Loverdos
   * records the ID from a potential related IMEvent.
265 2a29acf9 Christos KK Loverdos
   *
266 2a29acf9 Christos KK Loverdos
   * @param role                The role in the agreement
267 2a29acf9 Christos KK Loverdos
   * @param referenceTimeMillis The reference time to consider for the agreement
268 2a29acf9 Christos KK Loverdos
   */
269 2a29acf9 Christos KK Loverdos
  def initialUserAgreement(
270 2a29acf9 Christos KK Loverdos
      role: String,
271 2a29acf9 Christos KK Loverdos
      referenceTimeMillis: Long,
272 2a29acf9 Christos KK Loverdos
      relatedIMEventID: Option[String]
273 2a29acf9 Christos KK Loverdos
  ): UserAgreementModel = {
274 2a29acf9 Christos KK Loverdos
275 2a29acf9 Christos KK Loverdos
    // Just checking
276 2a29acf9 Christos KK Loverdos
    assert(null ne unsafePriceTableForRoleAt(role, referenceTimeMillis))
277 2a29acf9 Christos KK Loverdos
278 2a29acf9 Christos KK Loverdos
    StdUserAgreement(
279 2a29acf9 Christos KK Loverdos
      "<StandardUserAgreement>",
280 2a29acf9 Christos KK Loverdos
      relatedIMEventID,
281 2a29acf9 Christos KK Loverdos
      0,
282 2a29acf9 Christos KK Loverdos
      Long.MaxValue,
283 2a29acf9 Christos KK Loverdos
      role,
284 2a29acf9 Christos KK Loverdos
      PolicyDefinedFullPriceTableRef
285 2a29acf9 Christos KK Loverdos
    )
286 2a29acf9 Christos KK Loverdos
  }
287 2a29acf9 Christos KK Loverdos
288 2a29acf9 Christos KK Loverdos
  def initialUserBalance(role: String, referenceTimeMillis: Long): Double = {
289 2a29acf9 Christos KK Loverdos
    // FIXME: Where is the mapping?
290 2a29acf9 Christos KK Loverdos
    1000.0
291 b33dcda7 Christos KK Loverdos
  }
292 1a5a2e04 Christos KK Loverdos
293 b7b59f6f Christos KK Loverdos
  def chargingBehaviorOf(resourceType: ResourceType): ChargingBehavior = {
294 b7b59f6f Christos KK Loverdos
    val className = resourceType.chargingBehavior
295 b7b59f6f Christos KK Loverdos
    _chargingBehaviorMap.get(className) match {
296 b7b59f6f Christos KK Loverdos
      case Some(chargingBehavior) ⇒
297 b7b59f6f Christos KK Loverdos
        chargingBehavior
298 b7b59f6f Christos KK Loverdos
299 b7b59f6f Christos KK Loverdos
      case _ ⇒
300 b7b59f6f Christos KK Loverdos
        // It does not matter if this is entered by multiple threads and more than one instance of the same class
301 b7b59f6f Christos KK Loverdos
        // is created. The returned instance is not meant to be cached.
302 2a29acf9 Christos KK Loverdos
        try {
303 2a29acf9 Christos KK Loverdos
          val chargingBehavior = newInstance[ChargingBehavior](className)
304 2a29acf9 Christos KK Loverdos
          _chargingBehaviorMap synchronized {
305 2a29acf9 Christos KK Loverdos
            _chargingBehaviorMap = _chargingBehaviorMap.updated(className, chargingBehavior)
306 2a29acf9 Christos KK Loverdos
          }
307 b7b59f6f Christos KK Loverdos
308 2a29acf9 Christos KK Loverdos
          chargingBehavior
309 2a29acf9 Christos KK Loverdos
        }
310 2a29acf9 Christos KK Loverdos
        catch {
311 2a29acf9 Christos KK Loverdos
          case e: Exception ⇒
312 2a29acf9 Christos KK Loverdos
            throw new AquariumInternalError("Could not load charging behavior %s".format(className), e)
313 2a29acf9 Christos KK Loverdos
        }
314 b7b59f6f Christos KK Loverdos
    }
315 b7b59f6f Christos KK Loverdos
  }
316 b7b59f6f Christos KK Loverdos
317 7dbaeb04 Christos KK Loverdos
  def defaultPolicyModel = apply(EnvKeys.defaultPolicyModel)
318 7dbaeb04 Christos KK Loverdos
319 695c71e2 Christos KK Loverdos
  def defaultClassLoader = apply(EnvKeys.defaultClassLoader)
320 3a9638eb Christos KK Loverdos
321 b7b59f6f Christos KK Loverdos
  def resourceEventStore = apply(EnvKeys.storeProvider).resourceEventStore
322 07322062 Christos KK Loverdos
323 b7b59f6f Christos KK Loverdos
  def imEventStore = apply(EnvKeys.storeProvider).imEventStore
324 07322062 Christos KK Loverdos
325 b7b59f6f Christos KK Loverdos
  def userStateStore = apply(EnvKeys.storeProvider).userStateStore
326 695c71e2 Christos KK Loverdos
327 7dbaeb04 Christos KK Loverdos
  def policyStore = this.cachingPolicyStore
328 695c71e2 Christos KK Loverdos
329 695c71e2 Christos KK Loverdos
  def eventsStoreFolder = apply(EnvKeys.eventsStoreFolder)
330 695c71e2 Christos KK Loverdos
331 695c71e2 Christos KK Loverdos
  def eventBus = apply(EnvKeys.eventBus)
332 695c71e2 Christos KK Loverdos
333 2a29acf9 Christos KK Loverdos
  def chargingService = apply(EnvKeys.chargingService)
334 695c71e2 Christos KK Loverdos
335 695c71e2 Christos KK Loverdos
  def userStateTimestampThreshold = apply(EnvKeys.userStateTimestampThreshold)
336 695c71e2 Christos KK Loverdos
337 695c71e2 Christos KK Loverdos
  def adminCookie = apply(EnvKeys.adminCookie)
338 695c71e2 Christos KK Loverdos
339 695c71e2 Christos KK Loverdos
  def converters = apply(EnvKeys.converters)
340 695c71e2 Christos KK Loverdos
341 695c71e2 Christos KK Loverdos
  def saveResourceEventsToEventsStoreFolder = apply(EnvKeys.eventsStoreSaveRCEvents)
342 695c71e2 Christos KK Loverdos
343 695c71e2 Christos KK Loverdos
  def saveIMEventsToEventsStoreFolder = apply(EnvKeys.eventsStoreSaveIMEvents)
344 695c71e2 Christos KK Loverdos
345 695c71e2 Christos KK Loverdos
  def timerService = apply(EnvKeys.timerService)
346 695c71e2 Christos KK Loverdos
347 695c71e2 Christos KK Loverdos
  def restPort = apply(EnvKeys.restPort)
348 695c71e2 Christos KK Loverdos
349 153e9cb9 Christos KK Loverdos
  def akkaService = apply(EnvKeys.akkaService)
350 153e9cb9 Christos KK Loverdos
351 695c71e2 Christos KK Loverdos
  def version = apply(EnvKeys.version)
352 12a4f3c9 Christos KK Loverdos
}
353 12a4f3c9 Christos KK Loverdos
354 70111c64 Christos KK Loverdos
object Aquarium {
355 b30e5a44 Christos KK Loverdos
  final val PropsToShow = List(
356 b30e5a44 Christos KK Loverdos
    SysProp.JavaVMName,
357 b30e5a44 Christos KK Loverdos
    SysProp.JavaVersion,
358 b30e5a44 Christos KK Loverdos
    SysProp.JavaHome,
359 b30e5a44 Christos KK Loverdos
    SysProp.JavaClassVersion,
360 b30e5a44 Christos KK Loverdos
    SysProp.JavaLibraryPath,
361 b30e5a44 Christos KK Loverdos
    SysProp.JavaClassPath,
362 b30e5a44 Christos KK Loverdos
    SysProp.JavaIOTmpDir,
363 b30e5a44 Christos KK Loverdos
    SysProp.UserName,
364 b30e5a44 Christos KK Loverdos
    SysProp.UserHome,
365 b30e5a44 Christos KK Loverdos
    SysProp.UserDir,
366 b30e5a44 Christos KK Loverdos
    SysProp.FileEncoding
367 b30e5a44 Christos KK Loverdos
  )
368 b30e5a44 Christos KK Loverdos
369 695c71e2 Christos KK Loverdos
  object HTTP {
370 695c71e2 Christos KK Loverdos
   final val RESTAdminHeaderName = "X-Aquarium-Admin-Cookie"
371 695c71e2 Christos KK Loverdos
   final val RESTAdminHeaderNameLowerCase = RESTAdminHeaderName.toLowerCase
372 695c71e2 Christos KK Loverdos
 }
373 695c71e2 Christos KK Loverdos
374 695c71e2 Christos KK Loverdos
  final class AquariumEnvKey[T: Manifest](override val name: String) extends TypedKeySkeleton[T](name) {
375 b7b59f6f Christos KK Loverdos
    override def toString = "%s(%s)".format(manifest[T], name)
376 695c71e2 Christos KK Loverdos
  }
377 695c71e2 Christos KK Loverdos
378 695c71e2 Christos KK Loverdos
  final val ServiceKeys: List[TypedKey[_ <: Lifecycle]] = List(
379 695c71e2 Christos KK Loverdos
    EnvKeys.timerService,
380 695c71e2 Christos KK Loverdos
    EnvKeys.akkaService,
381 695c71e2 Christos KK Loverdos
    EnvKeys.eventBus,
382 695c71e2 Christos KK Loverdos
    EnvKeys.restService,
383 695c71e2 Christos KK Loverdos
    EnvKeys.rabbitMQService,
384 695c71e2 Christos KK Loverdos
    EnvKeys.storeWatcherService
385 695c71e2 Christos KK Loverdos
  )
386 49054030 Georgios Gousios
387 695c71e2 Christos KK Loverdos
  object EnvKeys {
388 9ce8385e Christos KK Loverdos
    /**
389 9ce8385e Christos KK Loverdos
     * The Aquarium version. Will be reported in any due occasion.
390 9ce8385e Christos KK Loverdos
     */
391 695c71e2 Christos KK Loverdos
    final val version = StringKey("version")
392 9ce8385e Christos KK Loverdos
393 695c71e2 Christos KK Loverdos
    final val originalProps: TypedKey[Props] =
394 695c71e2 Christos KK Loverdos
      new AquariumEnvKey[Props]("originalProps")
395 6adaafb6 Christos KK Loverdos
396 6adaafb6 Christos KK Loverdos
    /**
397 119e4381 Christos KK Loverdos
     * The fully qualified name of the class that implements the `StoreProvider`.
398 119e4381 Christos KK Loverdos
     * Will be instantiated reflectively and should have a public default constructor.
399 119e4381 Christos KK Loverdos
     */
400 695c71e2 Christos KK Loverdos
    final val storeProvider: TypedKey[StoreProvider] =
401 695c71e2 Christos KK Loverdos
      new AquariumEnvKey[StoreProvider]("store.provider.class")
402 aef7611f Christos KK Loverdos
403 aef7611f Christos KK Loverdos
    /**
404 695c71e2 Christos KK Loverdos
     * If a value is given to this property, then it represents a folder where all events coming to aquarium are
405 695c71e2 Christos KK Loverdos
     * saved.
406 158cbc5b Christos KK Loverdos
     *
407 695c71e2 Christos KK Loverdos
     * This is for debugging purposes.
408 158cbc5b Christos KK Loverdos
     */
409 695c71e2 Christos KK Loverdos
    final val eventsStoreFolder: TypedKey[Option[File]] =
410 695c71e2 Christos KK Loverdos
      new AquariumEnvKey[Option[File]]("events.store.folder")
411 158cbc5b Christos KK Loverdos
412 158cbc5b Christos KK Loverdos
    /**
413 695c71e2 Christos KK Loverdos
     * If this is `true` and `events.store.folder` is defined, then all resource events are
414 695c71e2 Christos KK Loverdos
     * also stored in `events.store.folder`.
415 158cbc5b Christos KK Loverdos
     *
416 695c71e2 Christos KK Loverdos
     * This is for debugging purposes.
417 158cbc5b Christos KK Loverdos
     */
418 158cbc5b Christos KK Loverdos
419 695c71e2 Christos KK Loverdos
    final val eventsStoreSaveRCEvents = BooleanKey("events.store.save.rc.events")
420 58be4efe Georgios Gousios
421 58be4efe Georgios Gousios
    /**
422 695c71e2 Christos KK Loverdos
     * If this is `true` and `events.store.folder` is defined, then all IM events are
423 695c71e2 Christos KK Loverdos
     * also stored in `events.store.folder`.
424 695c71e2 Christos KK Loverdos
     *
425 695c71e2 Christos KK Loverdos
     * This is for debugging purposes.
426 ad8d8db2 Georgios Gousios
     */
427 695c71e2 Christos KK Loverdos
    final val eventsStoreSaveIMEvents = BooleanKey("events.store.save.im.events")
428 ad8d8db2 Georgios Gousios
429 ad8d8db2 Georgios Gousios
    /**
430 6453d1cf Christos KK Loverdos
     * A time period in milliseconds for which we can tolerate stale parts regarding user state.
431 863efd17 Christos KK Loverdos
     *
432 6453d1cf Christos KK Loverdos
     * The smaller the value, the more accurate the user credits and other state parts are.
433 863efd17 Christos KK Loverdos
     *
434 863efd17 Christos KK Loverdos
     * If a request for user state (e.g. balance) is received and the request timestamp exceeds
435 863efd17 Christos KK Loverdos
     * the timestamp of the last known balance amount by this value, then a re-computation for
436 863efd17 Christos KK Loverdos
     * the balance is triggered.
437 863efd17 Christos KK Loverdos
     */
438 695c71e2 Christos KK Loverdos
    final val userStateTimestampThreshold = LongKey("user.state.timestamp.threshold")
439 4050a3c9 Christos KK Loverdos
440 4050a3c9 Christos KK Loverdos
    /**
441 695c71e2 Christos KK Loverdos
     * REST service listening port.
442 4050a3c9 Christos KK Loverdos
     */
443 695c71e2 Christos KK Loverdos
    final val restPort = IntKey("rest.port")
444 313f6c96 Christos KK Loverdos
445 5e4d8d64 Christos KK Loverdos
    final val restShutdownTimeoutMillis = LongKey("rest.shutdown.timeout.millis")
446 5e4d8d64 Christos KK Loverdos
447 03046173 Christos KK Loverdos
    /**
448 695c71e2 Christos KK Loverdos
     * A cookie used in every administrative REST API call, so that Aquarium knows it comes from
449 695c71e2 Christos KK Loverdos
     * an authorised client.
450 03046173 Christos KK Loverdos
     */
451 695c71e2 Christos KK Loverdos
    final val adminCookie: TypedKey[Option[String]] =
452 695c71e2 Christos KK Loverdos
      new AquariumEnvKey[Option[String]]("admin.cookie")
453 6bac5d11 Christos KK Loverdos
454 07322062 Christos KK Loverdos
    /**
455 695c71e2 Christos KK Loverdos
     * The class that initializes the REST service
456 6bac5d11 Christos KK Loverdos
     */
457 695c71e2 Christos KK Loverdos
    final val restService: TypedKey[Lifecycle] =
458 695c71e2 Christos KK Loverdos
      new AquariumEnvKey[Lifecycle]("rest.service.class")
459 3a9638eb Christos KK Loverdos
460 695c71e2 Christos KK Loverdos
    final val akkaService: TypedKey[AkkaService] =
461 695c71e2 Christos KK Loverdos
      new AquariumEnvKey[AkkaService]("akka.service")
462 695c71e2 Christos KK Loverdos
463 695c71e2 Christos KK Loverdos
    final val eventBus: TypedKey[EventBusService] =
464 695c71e2 Christos KK Loverdos
      new AquariumEnvKey[EventBusService]("event.bus.service")
465 695c71e2 Christos KK Loverdos
466 695c71e2 Christos KK Loverdos
    final val timerService: TypedKey[TimerService] =
467 695c71e2 Christos KK Loverdos
      new AquariumEnvKey[TimerService]("timer.service")
468 695c71e2 Christos KK Loverdos
469 695c71e2 Christos KK Loverdos
    final val rabbitMQService: TypedKey[RabbitMQService] =
470 695c71e2 Christos KK Loverdos
      new AquariumEnvKey[RabbitMQService]("rabbitmq.service")
471 695c71e2 Christos KK Loverdos
472 695c71e2 Christos KK Loverdos
    final val storeWatcherService: TypedKey[StoreWatcherService] =
473 695c71e2 Christos KK Loverdos
      new AquariumEnvKey[StoreWatcherService]("store.watcher.service")
474 695c71e2 Christos KK Loverdos
475 695c71e2 Christos KK Loverdos
    final val converters: TypedKey[Converters] =
476 695c71e2 Christos KK Loverdos
      new AquariumEnvKey[Converters]("converters")
477 695c71e2 Christos KK Loverdos
478 2a29acf9 Christos KK Loverdos
    final val chargingService: TypedKey[ChargingService] =
479 2a29acf9 Christos KK Loverdos
      new AquariumEnvKey[ChargingService]("charging.service")
480 695c71e2 Christos KK Loverdos
481 695c71e2 Christos KK Loverdos
    final val defaultClassLoader: TypedKey[ClassLoader] =
482 695c71e2 Christos KK Loverdos
      new AquariumEnvKey[ClassLoader]("default.class.loader")
483 7ef5958a Christos KK Loverdos
484 7dbaeb04 Christos KK Loverdos
    final val defaultPolicyModel: TypedKey[PolicyModel] =
485 7dbaeb04 Christos KK Loverdos
      new AquariumEnvKey[PolicyModel]("default.policy.model")
486 7ef5958a Christos KK Loverdos
  }
487 49054030 Georgios Gousios
}