AbstractTask.java

  1. /**
  2.  * Copyright (c) 2013-2017 Polago AB
  3.  * All rights reserved.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining
  6.  * a copy of this software and associated documentation files (the
  7.  * "Software"), to deal in the Software without restriction, including
  8.  * without limitation the rights to use, copy, modify, merge, publish,
  9.  * distribute, sublicense, and/or sell copies of the Software, and to
  10.  * permit persons to whom the Software is furnished to do so, subject to
  11.  * the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be
  14.  * included in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19.  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  20.  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  21.  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  22.  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  */

  24. package org.polago.deployconf.task;

  25. import java.io.IOException;
  26. import java.util.regex.Matcher;
  27. import java.util.regex.Pattern;

  28. import javax.script.ScriptEngine;
  29. import javax.script.ScriptEngineManager;
  30. import javax.script.ScriptException;

  31. import org.jdom2.CDATA;
  32. import org.jdom2.Element;
  33. import org.jdom2.Text;
  34. import org.polago.deployconf.group.ConfigGroup;
  35. import org.polago.deployconf.group.ConfigGroupManager;
  36. import org.slf4j.Logger;
  37. import org.slf4j.LoggerFactory;

  38. /**
  39.  * Common implementation of a deployment Task.
  40.  */
  41. public abstract class AbstractTask implements Task {

  42.     private static Logger logger = LoggerFactory.getLogger(AbstractTask.class);

  43.     // Matches a property expression like ${propertyName}
  44.     private static final Pattern EXPANSION_PATTERN = Pattern.compile("(\\$\\{([^}]+?)\\})");

  45.     protected static final String DOM_ATTRIBUTE_PATH = "path";

  46.     protected static final String DOM_ATTRIBUTE_GROUP = "group";

  47.     protected static final String DOM_ATTRIBUTE_IF = "if";

  48.     protected static final String DOM_ELEMENT_DESCRIPTION = "description";

  49.     protected static final String DOM_ELEMENT_DEFAULT = "default";

  50.     protected static final String DOM_ELEMENT_VALUE = "value";

  51.     protected static final String DOM_ELEMENT_CONDITION = "condition";

  52.     private String path;

  53.     private final ScriptEngine scriptEngine;

  54.     private final ConfigGroupManager groupManager;

  55.     /**
  56.      * Public Constructor.
  57.      *
  58.      * @param groupManager the groupManager to use
  59.      */
  60.     public AbstractTask(ConfigGroupManager groupManager) {
  61.         super();

  62.         this.groupManager = groupManager;

  63.         ScriptEngineManager factory = new ScriptEngineManager();
  64.         scriptEngine = factory.getEngineByName("JavaScript");
  65.     }

  66.     /**
  67.      * Gets the groupManager property value.
  68.      *
  69.      * @return the current value of the groupManager property
  70.      */
  71.     public ConfigGroupManager getGroupManager() {
  72.         return groupManager;
  73.     }

  74.     /**
  75.      * Gets the path property value.
  76.      *
  77.      * @return the current value of the path property
  78.      */
  79.     @Override
  80.     public String getPath() {
  81.         return path;
  82.     }

  83.     /**
  84.      * Sets the path property.
  85.      *
  86.      * @param path the new property value
  87.      */
  88.     public void setPath(String path) {
  89.         this.path = path;
  90.     }

  91.     /**
  92.      * {@inheritDoc}
  93.      */
  94.     @Override
  95.     public void deserialize(Element root) throws IOException {
  96.         String attribute = root.getAttributeValue(DOM_ATTRIBUTE_PATH);
  97.         if (attribute == null) {
  98.             throw new IllegalStateException("path attribute is required");
  99.         }
  100.         setPath(attribute);
  101.     }

  102.     /**
  103.      * {@inheritDoc}
  104.      */
  105.     @Override
  106.     public void serialize(Element node) throws IOException {
  107.         node.setAttribute(DOM_ATTRIBUTE_PATH, getPath());
  108.     }

  109.     /**
  110.      * Replace matching properties from the given groupManager in the given text.
  111.      *
  112.      * @param text the text to expand
  113.      * @param group the ConfigGroup to use as source for expanding property expressions
  114.      * @return the expanded value, if possible
  115.      */
  116.     protected String expandPropertyExpression(String text, ConfigGroup group) {
  117.         String result = text;

  118.         if (text != null) {
  119.             Matcher matcher = EXPANSION_PATTERN.matcher(text);
  120.             StringBuffer expanded = new StringBuffer(text.length());
  121.             while (matcher.find()) {
  122.                 String name = matcher.group(2);
  123.                 String value = group.getProperty(name);
  124.                 if (value == null) {
  125.                     value = matcher.group(0);
  126.                 }
  127.                 matcher.appendReplacement(expanded, Matcher.quoteReplacement(value));
  128.             }
  129.             matcher.appendTail(expanded);
  130.             result = expanded.toString();
  131.         }

  132.         return result;
  133.     }

  134.     /**
  135.      * Evaluate the task condition.
  136.      *
  137.      * @param text the condition to evaluate
  138.      * @param group the ConfigGroup to use as source for expanding property expressions before evaluation
  139.      * @return the evaluation result
  140.      */
  141.     public boolean evaluateCondition(String text, ConfigGroup group) {
  142.         boolean result = true;
  143.         try {
  144.             if (text != null) {
  145.                 Object resultObject = scriptEngine.eval(expandPropertyExpression(text, group));
  146.                 if (resultObject instanceof Boolean) {
  147.                     Boolean boolResult = (Boolean) resultObject;
  148.                     return boolResult.booleanValue();
  149.                 }
  150.             }
  151.         } catch (ScriptException e) {
  152.             logger.info("Unable to evaluate condition: " + text, e);
  153.         }

  154.         return result;
  155.     }

  156.     /**
  157.      * Create a JDOM Element with the given name.
  158.      *
  159.      * @param name the element name
  160.      * @return a JDOM Element instance
  161.      */
  162.     protected Element createJDOMElement(String name) {
  163.         Element result = new Element(name);

  164.         return result;
  165.     }

  166.     /**
  167.      * Create a JDOM Text Element with the given name and possibly text.
  168.      *
  169.      * @param name the element name
  170.      * @param text the element text or null
  171.      * @return a JDOM Element instance
  172.      */
  173.     protected Element createJDOMTextElement(String name, String text) {
  174.         Element result = new Element(name);
  175.         if (text != null) {
  176.             result.setContent(new Text(text));
  177.         }

  178.         return result;
  179.     }

  180.     /**
  181.      * Create a JDOM CDATA Element with the given name and possibly text.
  182.      *
  183.      * @param name the element name
  184.      * @param text the element text or null
  185.      * @return a JDOM Element instance
  186.      */
  187.     protected Element createJDOMCDATAElement(String name, String text) {
  188.         Element result = new Element(name);
  189.         if (text != null) {
  190.             result.addContent(new CDATA(text));
  191.         }

  192.         return result;
  193.     }

  194.     /**
  195.      * {@inheritDoc}
  196.      */
  197.     @Override
  198.     public int hashCode() {
  199.         return getPath().hashCode();
  200.     }

  201.     /**
  202.      * {@inheritDoc}
  203.      */
  204.     @Override
  205.     public boolean equals(Object other) {
  206.         boolean result = false;
  207.         if (other instanceof AbstractTask) {
  208.             AbstractTask otherTask = (AbstractTask) other;
  209.             result = getPath().equals(otherTask.getPath());
  210.         }

  211.         return result;
  212.     }
  213. }