Refactor Aquarium to make it more configurable
[aquarium] / src / main / scala / gr / grnet / aquarium / logic / accounting / Policy.scala
index 79d2bb5..deee38f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011 GRNET S.A. All rights reserved.
+ * Copyright 2011-2012 GRNET S.A. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or
  * without modification, are permitted provided that the following
 package gr.grnet.aquarium.logic.accounting
 
 import dsl.{Timeslot, DSLPolicy, DSL}
-import gr.grnet.aquarium.Configurator._
 import java.io.{InputStream, FileInputStream, File}
 import java.util.Date
-import gr.grnet.aquarium.util.date.TimeHelpers
 import gr.grnet.aquarium.util.Loggable
 import java.util.concurrent.atomic.AtomicReference
-import gr.grnet.aquarium.Configurator
-import com.ckkloverdos.maybe.{Failed, NoVal, Maybe, Just}
 import collection.immutable.{TreeMap, SortedMap}
+import gr.grnet.aquarium.{ResourceLocator, AquariumAwareSkeleton, AquariumException, Aquarium}
+import gr.grnet.aquarium.util.date.{MutableDateCalc, TimeHelpers}
+import com.ckkloverdos.maybe.{Failed, Just}
 
 /**
  * Searches for and loads the applicable accounting policy
  *
  * @author Georgios Gousios <gousiosg@gmail.com>
  */
-object Policy extends DSL with Loggable {
+object Policy extends DSL with Loggable with AquariumAwareSkeleton {
 
   /* Pointer to the latest policy */
   private[logic] lazy val policies = {
@@ -61,8 +60,8 @@ object Policy extends DSL with Loggable {
   /* Pointer to the latest policy */
   private lazy val currentPolicy = {new AtomicReference[DSLPolicy](latestPolicy)}
 
-  /* Configurator to use for loading information about the policy store */
-  private var config: Configurator = _
+  /* Aquarium to use for loading information about the policy store */
+  private var config: Aquarium = _
 
   /**
    * Get the latest defined policy.
@@ -79,7 +78,7 @@ object Policy extends DSL with Loggable {
     } match {
       case Some(x) => x._2
       case None =>
-        throw new AccountingException("No valid policy for date: %s".format(at))
+        throw new AquariumException("No valid policy for date: %s".format(new MutableDateCalc(at)))
     }
   }
 
@@ -152,66 +151,51 @@ object Policy extends DSL with Loggable {
    * Set the configurator to use for loading policy stores. Should only
    * used for unit testing.
    */
-  /*private[logic] */def withConfigurator(config: Configurator): Unit =
+  def withConfigurator(config: Aquarium): Unit =
     this.config = config
 
   /**
-   * Search default locations for a policy file and provide an
-   * arbitrary default if this cannot be found.
-   */
-   private[logic] def policyFile = {
-    BasicResourceContext.getResource(PolicyConfName) match {
-      case Just(policyResource) ⇒
-        val path = policyResource.url.getPath
-        new File(path)
-      case _ ⇒
-        new File("policy.yaml")
-    }
-  }
-
-  /**
    * Check whether the policy definition file (in whichever path) is
    * newer than the latest stored policy, reload and set it as current.
    * This method has side-effects to this object's state.
    */
   private[logic] def reloadPolicies: SortedMap[Timeslot, DSLPolicy] =
     if (config == null)
-      reloadPolicies(MasterConfigurator)
+      reloadPolicies(aquarium)
     else
       reloadPolicies(config)
 
-  private def reloadPolicies(config: Configurator):
+  private def reloadPolicies(config: Aquarium):
   SortedMap[Timeslot, DSLPolicy] = {
     //1. Load policies from db
     val pol = config.policyStore.loadPolicyEntriesAfter(0)
 
     //2. Check whether policy file has been updated
     val latestPolicyChange = if (pol.isEmpty) 0 else pol.last.validFrom
-    val policyf = policyFile
+
+    val policyf = ResourceLocator.Resources.PolicyYAMLResource
     var updated = false
 
     if (policyf.exists) {
-      if (policyf.lastModified > latestPolicyChange) {
-        logger.info("Policy file updated since last check, reloading")
         updated = true
-      } else {
-        logger.info("Policy file not changed since last check")
-      }
-    } else {
+     } else {
       logger.warn("User specified policy file %s does not exist, " +
-        "using stored policy information".format(policyf.getAbsolutePath))
+        "using stored policy information".format(policyf.url))
     }
 
     if (updated) {
-      val ts = TimeHelpers.nowMillis
-      val parsedNew = loadPolicyFromFile(policyf)
-      val newPolicy = parsedNew.toPolicyEntry.copy(occurredMillis = ts,
-        receivedMillis = ts, validFrom = ts)
+      val ts = TimeHelpers.nowMillis()
+      val parsedNewM = policyf.mapInputStream(parse).toMaybeEither
+      val parsedNew = parsedNewM match {
+        case Just(parsedNew) ⇒ parsedNew
+        case Failed(e)       ⇒ throw e
+      }
+      val newPolicy = parsedNew.toPolicyEntry
 
       config.policyStore.findPolicyEntry(newPolicy.id) match {
-        case Just(x) =>
+        case Some(x) =>
           logger.warn("Policy file contents not modified")
-        case NoVal =>
+        case None =>
           if (!pol.isEmpty) {
             val toUpdate = pol.last.copy(validTo = ts - 1)
             config.policyStore.updatePolicyEntry(toUpdate)
@@ -219,14 +203,14 @@ object Policy extends DSL with Loggable {
           } else {
             config.policyStore.storePolicyEntry(newPolicy)
           }
-        case Failed(e, expl) =>
-          throw e
       }
     }
 
     config.policyStore.loadPolicyEntriesAfter(0).foldLeft(new TreeMap[Timeslot, DSLPolicy]()){
       (acc, p) =>
-        acc ++ Map(Timeslot(new Date(p.validFrom), new Date(p.validTo)) -> parse(p.policyYAML))
+        acc ++ Map(Timeslot(p.validFrom, p.validTo) -> parse(p.policyYAML))
     }
   }
+
+  Policy.policy
 }
\ No newline at end of file