diff --git a/proxy/src/main/java/org/fedoraproject/candlepin/controller/Entitler.java b/proxy/src/main/java/org/fedoraproject/candlepin/controller/Entitler.java
index 5f5a060..19264b3 100644
--- a/proxy/src/main/java/org/fedoraproject/candlepin/controller/Entitler.java
+++ b/proxy/src/main/java/org/fedoraproject/candlepin/controller/Entitler.java
@@ -37,17 +37,17 @@ import java.util.Date;
* Entitler
*/
public class Entitler {
-
+
private PoolCurator epCurator;
private EntitlementCurator entitlementCurator;
private ConsumerCurator consumerCurator;
private Enforcer enforcer;
private static Logger log = Logger.getLogger(Entitler.class);
-
+
@Inject
protected Entitler(PoolCurator epCurator,
- EntitlementCurator entitlementCurator, ConsumerCurator consumerCurator,
- Enforcer enforcer) {
+ EntitlementCurator entitlementCurator, ConsumerCurator consumerCurator,
+ Enforcer enforcer) {
this.epCurator = epCurator;
this.entitlementCurator = entitlementCurator;
this.consumerCurator = consumerCurator;
@@ -60,39 +60,47 @@ public class Entitler {
* If the entitlement cannot be granted, null will be returned.
*
* TODO: Throw exception if entitlement not granted. Report why.
- *
- * @param consumer consumer requesting to be entitled
- * @param product product to be entitled.
+ *
+ * @param consumer
+ * consumer requesting to be entitled
+ * @param product
+ * product to be entitled.
* @return Entitlement
*/
//
- // NOTE: after calling this method both entitlement pool and consumer parameters
- // will most certainly be stale. beware!
+ // NOTE: after calling this method both entitlement pool and consumer
+ // parameters
+ // will most certainly be stale. beware!
//
@Transactional
public Entitlement entitle(Consumer consumer, Product product) {
Owner owner = consumer.getOwner();
-
- // TODO: Don't assume we use the first pool here, once rules have support for
- // specifying the pool to use.
- Pool pool = epCurator.listByOwnerAndProduct(owner, product).get(0);
+ // TODO: Don't assume we use the first pool here, once rules have
+ // support for
+ // specifying the pool to use.
+
+ Pool pool = enforcer.selectBestPool(consumer, product.getId(),
+ epCurator.listByOwnerAndProduct(owner, product));
if (pool == null) {
- throw new RuntimeException("No entitlements for product: " + product.getName());
+ throw new RuntimeException("No entitlements for product: " +
+ product.getName());
}
-
+
return addEntitlement(consumer, pool);
}
/**
* Request an entitlement by pool..
- *
+ *
* If the entitlement cannot be granted, null will be returned.
- *
+ *
* TODO: Throw exception if entitlement not granted. Report why.
- *
- * @param consumer consumer requesting to be entitled
- * @param pool entitlement pool to consume from
+ *
+ * @param consumer
+ * consumer requesting to be entitled
+ * @param pool
+ * entitlement pool to consume from
* @return Entitlement
*/
@Transactional
@@ -100,13 +108,13 @@ public class Entitler {
return addEntitlement(consumer, pool);
}
-
private Entitlement addEntitlement(Consumer consumer, Pool pool) {
PreEntHelper preHelper = enforcer.pre(consumer, pool);
ValidationResult result = preHelper.getResult();
-
+
if (!result.isSuccessful()) {
- log.warn("Entitlement not granted: " + result.getErrors().toString());
+ log.warn("Entitlement not granted: " +
+ result.getErrors().toString());
return null;
}
@@ -122,7 +130,7 @@ public class Entitler {
}
enforcer.post(e);
-
+
entitlementCurator.create(e);
consumerCurator.update(consumer);
epCurator.merge(pool);
@@ -130,7 +138,7 @@ public class Entitler {
return e;
}
- // TODO: Does the enforcer have any rules around removing entitlements?
+ // TODO: Does the enforcer have any rules around removing entitlements?
@Transactional
public void revokeEntitlement(Entitlement entitlement) {
if (!entitlement.isFree()) {
diff --git a/proxy/src/main/java/org/fedoraproject/candlepin/policy/js/JavascriptEnforcer.java b/proxy/src/main/java/org/fedoraproject/candlepin/policy/js/JavascriptEnforcer.java
index a00e0a3..123ee74 100644
--- a/proxy/src/main/java/org/fedoraproject/candlepin/policy/js/JavascriptEnforcer.java
+++ b/proxy/src/main/java/org/fedoraproject/candlepin/policy/js/JavascriptEnforcer.java
@@ -14,7 +14,6 @@
*/
package org.fedoraproject.candlepin.policy.js;
-
import org.fedoraproject.candlepin.model.Consumer;
import org.fedoraproject.candlepin.model.Entitlement;
import org.fedoraproject.candlepin.model.Pool;
@@ -45,7 +44,7 @@ public class JavascriptEnforcer implements Enforcer {
private static Logger log = Logger.getLogger(JavascriptEnforcer.class);
private DateSource dateSource;
- private RulesCurator rulesCurator;
+
private ProductServiceAdapter prodAdapter;
private PreEntHelper preHelper;
private PostEntHelper postHelper;
@@ -55,29 +54,36 @@ public class JavascriptEnforcer implements Enforcer {
private static final String PRE_PREFIX = "pre_";
private static final String POST_PREFIX = "post_";
private static final String SELECT_POOL_PREFIX = "select_pool_";
- private static final String GLOBAL_SELECT_POOL_FUNCTION = SELECT_POOL_PREFIX + "global";
+ private static final String GLOBAL_SELECT_POOL_FUNCTION = SELECT_POOL_PREFIX +
+ "global";
private static final String GLOBAL_PRE_FUNCTION = PRE_PREFIX + "global";
private static final String GLOBAL_POST_FUNCTION = POST_PREFIX + "global";
@Inject
- public JavascriptEnforcer(DateSource dateSource,
- RulesCurator rulesCurator, PreEntHelper preHelper,
- PostEntHelper postHelper, ProductServiceAdapter prodAdapter) {
+ public JavascriptEnforcer(DateSource dateSource, RulesCurator rulesCurator,
+ PreEntHelper preHelper, PostEntHelper postHelper,
+ ProductServiceAdapter prodAdapter) {
+ this(dateSource, new StringReader(rulesCurator.getRules().getRules()),
+ preHelper, postHelper, prodAdapter, new ScriptEngineManager()
+ .getEngineByName("JavaScript"));
+ }
+
+ @Inject
+ public JavascriptEnforcer(DateSource dateSource, Reader rulesReader,
+ PreEntHelper preHelper, PostEntHelper postHelper,
+ ProductServiceAdapter prodAdapter, ScriptEngine jsEngine) {
this.dateSource = dateSource;
- this.rulesCurator = rulesCurator;
this.preHelper = preHelper;
this.postHelper = postHelper;
this.prodAdapter = prodAdapter;
-
- ScriptEngineManager mgr = new ScriptEngineManager();
- jsEngine = mgr.getEngineByName("JavaScript");
+ this.jsEngine = jsEngine;
+
if (jsEngine == null) {
- throw new RuntimeException("No Javascript engine found");
+ throw new RuntimeException("No Javascript engine");
}
try {
- Reader reader = new StringReader(this.rulesCurator.getRules().getRules());
- jsEngine.eval(reader);
+ this.jsEngine.eval(rulesReader);
}
catch (ScriptException ex) {
throw new RuleParseException(ex);
@@ -90,23 +96,24 @@ public class JavascriptEnforcer implements Enforcer {
runPre(preHelper, consumer, entitlementPool);
if (entitlementPool.isExpired(dateSource)) {
- preHelper.getResult().addError(new ValidationError("Entitlements for " +
- entitlementPool.getProductId() +
- " expired on: " + entitlementPool.getEndDate()));
+ preHelper.getResult().addError(
+ new ValidationError("Entitlements for " +
+ entitlementPool.getProductId() + " expired on: " +
+ entitlementPool.getEndDate()));
return preHelper;
}
return preHelper;
}
- private void runPre(PreEntHelper preHelper, Consumer consumer,
- Pool pool) {
+ private void runPre(PreEntHelper preHelper, Consumer consumer, Pool pool) {
Invocable inv = (Invocable) jsEngine;
String productId = pool.getProductId();
// Provide objects for the script:
jsEngine.put("consumer", new ReadOnlyConsumer(consumer));
- jsEngine.put("product", new ReadOnlyProduct(prodAdapter.getProductById(productId)));
+ jsEngine.put("product", new ReadOnlyProduct(prodAdapter
+ .getProductById(productId)));
jsEngine.put("pool", new ReadOnlyEntitlementPool(pool));
jsEngine.put("pre", preHelper);
@@ -151,12 +158,13 @@ public class JavascriptEnforcer implements Enforcer {
// Provide objects for the script:
jsEngine.put("consumer", new ReadOnlyConsumer(c));
- jsEngine.put("product", new ReadOnlyProduct(prodAdapter.getProductById(productId)));
+ jsEngine.put("product", new ReadOnlyProduct(prodAdapter
+ .getProductById(productId)));
jsEngine.put("post", postHelper);
jsEngine.put("entitlement", new ReadOnlyEntitlement(ent));
- log.debug("Running post-entitlement rules for: " + c.getUuid() + " product: " +
- pool.getProductId());
+ log.debug("Running post-entitlement rules for: " + c.getUuid() +
+ " product: " + pool.getProductId());
try {
inv.invokeFunction(POST_PREFIX + productId);
@@ -182,13 +190,13 @@ public class JavascriptEnforcer implements Enforcer {
}
}
- public Pool selectBestPool(Consumer consumer, String productId, List<Pool> pools) {
+ public Pool selectBestPool(Consumer consumer, String productId,
+ List<Pool> pools) {
Invocable inv = (Invocable) jsEngine;
log.info("Selecting best entitlement pool for product: " + productId);
- List<ReadOnlyEntitlementPool> readOnlyPools =
- new LinkedList<ReadOnlyEntitlementPool>();
+ List<ReadOnlyEntitlementPool> readOnlyPools = new LinkedList<ReadOnlyEntitlementPool>();
for (Pool p : pools) {
log.info(" " + p);
readOnlyPools.add(new ReadOnlyEntitlementPool(p));
@@ -199,20 +207,23 @@ public class JavascriptEnforcer implements Enforcer {
ReadOnlyEntitlementPool result = null;
try {
- result = (ReadOnlyEntitlementPool) inv.invokeFunction(
- SELECT_POOL_PREFIX + productId);
- log.info("Excuted javascript rule: " + SELECT_POOL_PREFIX + productId);
+ result = (ReadOnlyEntitlementPool) inv
+ .invokeFunction(SELECT_POOL_PREFIX + productId);
+ log.info("Excuted javascript rule: " + SELECT_POOL_PREFIX +
+ productId);
}
catch (NoSuchMethodException e) {
// No method for this product, try to find a global function, if
// neither exists this is ok and we'll just carry on.
try {
- result = (ReadOnlyEntitlementPool) inv.invokeFunction(
+ result = (ReadOnlyEntitlementPool) inv
+ .invokeFunction(GLOBAL_SELECT_POOL_FUNCTION);
+ log.info("Excuted javascript rule: " +
GLOBAL_SELECT_POOL_FUNCTION);
- log.info("Excuted javascript rule: " + GLOBAL_SELECT_POOL_FUNCTION);
}
catch (NoSuchMethodException ex) {
- log.warn("No default rule found: " + GLOBAL_SELECT_POOL_FUNCTION);
+ log.warn("No default rule found: " +
+ GLOBAL_SELECT_POOL_FUNCTION);
log.warn("Resorting to default pool selection behavior.");
return selectBestPoolDefault(pools);
}
@@ -225,8 +236,8 @@ public class JavascriptEnforcer implements Enforcer {
}
if (pools.size() > 0 && result == null) {
- throw new RuleExecutionException("Rule did not select a pool for product: " +
- productId);
+ throw new RuleExecutionException(
+ "Rule did not select a pool for product: " + productId);
}
for (Pool p : pools) {
@@ -240,8 +251,11 @@ public class JavascriptEnforcer implements Enforcer {
}
/**
- * Default behavior if no product specific and no global pool select rules exist.
- * @param pools Pools to choose from.
+ * Default behavior if no product specific and no global pool select rules
+ * exist.
+ *
+ * @param pools
+ * Pools to choose from.
* @return First pool in the list. (default behavior)
*/
private Pool selectBestPoolDefault(List<Pool> pools) {
diff --git a/proxy/src/main/resources/rules/default-rules.js b/proxy/src/main/resources/rules/default-rules.js
index 71de8f2..7caf73b 100644
--- a/proxy/src/main/resources/rules/default-rules.js
+++ b/proxy/src/main/resources/rules/default-rules.js
@@ -12,7 +12,8 @@ function virtualization_common() {
return;
}
- // Host must not have any guests currently (could be changed but for simplicities sake):
+ // Host must not have any guests currently (could be changed but for
+ // simplicities sake):
if (parseInt(consumer.getFact("total_guests")) > 0) {
pre.addError("rulefailed.host.already.has.guests");
}
@@ -36,16 +37,16 @@ function post_virtualization_host_platform() {
function pre_global() {
- // Support free entitlements for guests, if their parent has virt host or platform,
+ // Support free entitlements for guests, if their parent has virt host or
+ // platform,
// and is entitled to the product the guest is requesting:
if (consumer.getType() == "virt_system" && consumer.getParent() != null) {
- if ((consumer.getParent().hasEntitlement("virtualization_host") ||
- consumer.getParent().hasEntitlement("virtualization_host_platform")) &&
- consumer.getParent().hasEntitlement(product.getLabel())) {
+ if ((consumer.getParent().hasEntitlement("virtualization_host") || consumer
+ .getParent().hasEntitlement("virtualization_host_platform"))
+ && consumer.getParent().hasEntitlement(product.getLabel())) {
pre.grantFreeEntitlement();
}
- }
- else {
+ } else {
pre.checkQuantity(pool);
}
}
@@ -53,3 +54,22 @@ function pre_global() {
function post_global() {
}
+
+function select_pool_global() {
+ return pools.getFirst();
+}
+
+function select_pool_monitoring() {
+ var pool;
+ var poolItr;
+
+ for (poolItr = pools.iterator(); poolItr.hasNext();) {
+ pool = poolItr.next();
+ if (pool.productId == "monitoring") {
+ return pool;
+ }
+ }
+
+ return pools.getFirst();
+
+}
diff --git a/proxy/src/test/java/org/fedoraproject/candlepin/policy/test/DefaultRulesTest.java b/proxy/src/test/java/org/fedoraproject/candlepin/policy/test/DefaultRulesTest.java
new file mode 100644
index 0000000..1af7eb8
--- /dev/null
+++ b/proxy/src/test/java/org/fedoraproject/candlepin/policy/test/DefaultRulesTest.java
@@ -0,0 +1,83 @@
+/**
+ * Copyright (c) 2009 Red Hat, Inc.
+ *
+ * This software is licensed to you under the GNU General Public License,
+ * version 2 (GPLv2). There is NO WARRANTY for this software, express or
+ * implied, including the implied warranties of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
+ * along with this software; if not, see
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * Red Hat trademarks are not licensed under GPLv2. No permission is
+ * granted to use or replicate Red Hat trademarks that are incorporated
+ * in this software or its documentation.
+ */
+package org.fedoraproject.candlepin.policy.test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.script.ScriptEngineManager;
+
+import junit.framework.Assert;
+
+import org.fedoraproject.candlepin.model.Consumer;
+import org.fedoraproject.candlepin.model.Pool;
+import org.fedoraproject.candlepin.model.RulesCurator;
+import org.fedoraproject.candlepin.policy.Enforcer;
+import org.fedoraproject.candlepin.policy.js.JavascriptEnforcer;
+import org.fedoraproject.candlepin.policy.js.PostEntHelper;
+import org.fedoraproject.candlepin.policy.js.PreEntHelper;
+import org.fedoraproject.candlepin.service.ProductServiceAdapter;
+import org.fedoraproject.candlepin.util.DateSource;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.sun.jersey.spi.StringReader;
+
+/**
+ * DefaultRulesTest
+ */
+public class DefaultRulesTest {
+ private Enforcer enforcer;
+ private DateSource dateSource;
+ private PreEntHelper preHelper;
+ private PostEntHelper postHelper;
+ private ProductServiceAdapter prodAdapter;
+
+ @Before
+ public void createEnforcer() throws IOException {
+ // InputStream inStream = this
+ URL url = this.getClass().getClassLoader().getResource("rules/default-rules.js");
+
+ InputStreamReader inputStreamReader = new InputStreamReader(url
+ .openStream());
+
+ enforcer = new JavascriptEnforcer(dateSource, inputStreamReader,
+ preHelper, postHelper, prodAdapter, new ScriptEngineManager()
+ .getEngineByName("JavaScript"));
+ }
+
+ @Test
+ public void runDefaultRuels() {
+ Consumer consumer = new Consumer();
+ String productId = "Shampoo";
+ Pool pool = new Pool();
+ pool.setId(new Long(0));
+ pool.setProductId("default");
+ List<Pool> pools = new ArrayList<Pool>();
+ pools.add(pool);
+ Pool selected = enforcer.selectBestPool(consumer, productId, pools);
+ Assert.assertNotNull(selected);
+ }
+
+}
--
1.6.6.1