Home » apache-ant-1.7.1-src » org.apache.tools » ant » taskdefs » optional » script » [javadoc | source]
    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    *
   17    */
   18   package org.apache.tools.ant.taskdefs.optional.script;
   19   
   20   import org.apache.tools.ant.AntTypeDefinition;
   21   import org.apache.tools.ant.ComponentHelper;
   22   import org.apache.tools.ant.Project;
   23   import org.apache.tools.ant.MagicNames;
   24   import org.apache.tools.ant.BuildException;
   25   import org.apache.tools.ant.ProjectHelper;
   26   import org.apache.tools.ant.types.ResourceCollection;
   27   import org.apache.tools.ant.taskdefs.DefBase;
   28   
   29   import java.util.Map;
   30   import java.util.HashMap;
   31   import java.util.List;
   32   import java.util.Locale;
   33   import java.util.ArrayList;
   34   import java.util.Iterator;
   35   import java.util.Set;
   36   import java.util.HashSet;
   37   import java.io.File;
   38   
   39   import org.apache.tools.ant.util.ClasspathUtils;
   40   import org.apache.tools.ant.util.ScriptRunnerBase;
   41   import org.apache.tools.ant.util.ScriptRunnerHelper;
   42   
   43   /**
   44    * Define a task using a script
   45    *
   46    * @since Ant 1.6
   47    */
   48   public class ScriptDef extends DefBase {
   49       /**
   50        * script runner helper
   51        */
   52       private ScriptRunnerHelper helper = new ScriptRunnerHelper();
   53       /**
   54        * script runner.
   55        */
   56       /** Used to run the script */
   57       private ScriptRunnerBase   runner = null;
   58   
   59       /** the name by which this script will be activated */
   60       private String name;
   61   
   62       /** Attributes definitions of this script */
   63       private List attributes = new ArrayList();
   64   
   65       /** Nested Element definitions of this script */
   66       private List nestedElements = new ArrayList();
   67   
   68       /** The attribute names as a set */
   69       private Set attributeSet;
   70   
   71       /** The nested element definitions indexed by their names */
   72       private Map nestedElementMap;
   73   
   74       /**
   75        * Set the project.
   76        * @param project the project that this def belows to.
   77        */
   78       public void setProject(Project project) {
   79           super.setProject(project);
   80           helper.setProjectComponent(this);
   81           helper.setSetBeans(false);
   82       }
   83   
   84       /**
   85        * set the name under which this script will be activated in a build
   86        * file
   87        *
   88        * @param name the name of the script
   89        */
   90       public void setName(String name) {
   91           this.name = name;
   92       }
   93   
   94       /**
   95        * Indicates whether the task supports a given attribute name
   96        *
   97        * @param attributeName the name of the attribute.
   98        *
   99        * @return true if the attribute is supported by the script.
  100        */
  101       public boolean isAttributeSupported(String attributeName) {
  102           return attributeSet.contains(attributeName);
  103       }
  104   
  105       /**
  106        * Class representing an attribute definition
  107        */
  108       public static class Attribute {
  109           /** The attribute name */
  110           private String name;
  111   
  112           /**
  113            * Set the attribute name
  114            *
  115            * @param name the attribute name
  116            */
  117           public void setName(String name) {
  118               this.name = name.toLowerCase(Locale.US);
  119           }
  120       }
  121   
  122       /**
  123        * Add an attribute definition to this script.
  124        *
  125        * @param attribute the attribute definition.
  126        */
  127       public void addAttribute(Attribute attribute) {
  128           attributes.add(attribute);
  129       }
  130   
  131       /**
  132        * Class to represent a nested element definition
  133        */
  134       public static class NestedElement {
  135           /** The name of the neseted element */
  136           private String name;
  137   
  138           /** The Ant type to which this nested element corresponds. */
  139           private String type;
  140   
  141           /** The class to be created for this nested element */
  142           private String className;
  143   
  144           /**
  145            * set the tag name for this nested element
  146            *
  147            * @param name the name of this nested element
  148            */
  149           public void setName(String name) {
  150               this.name = name.toLowerCase(Locale.US);
  151           }
  152   
  153           /**
  154            * Set the type of this element. This is the name of an
  155            * Ant task or type which is to be used when this element is to be
  156            * created. This is an alternative to specifying the class name directly
  157            *
  158            * @param type the name of an Ant type, or task, to use for this nested
  159            * element.
  160            */
  161           public void setType(String type) {
  162               this.type = type;
  163           }
  164   
  165           /**
  166            * Set the classname of the class to be used for the nested element.
  167            * This specifies the class directly and is an alternative to specifying
  168            * the Ant type name.
  169            *
  170            * @param className the name of the class to use for this nested
  171            * element.
  172            */
  173           public void setClassName(String className) {
  174               this.className = className;
  175           }
  176       }
  177   
  178       /**
  179        * Add a nested element definition.
  180        *
  181        * @param nestedElement the nested element definition.
  182        */
  183       public void addElement(NestedElement nestedElement) {
  184           nestedElements.add(nestedElement);
  185       }
  186   
  187       /**
  188        * Define the script.
  189        */
  190       public void execute() {
  191           if (name == null) {
  192               throw new BuildException("scriptdef requires a name attribute to "
  193                   + "name the script");
  194           }
  195   
  196           if (helper.getLanguage() == null) {
  197               throw new BuildException("<scriptdef> requires a language attribute "
  198                   + "to specify the script language");
  199           }
  200   
  201           // Check if need to set the loader
  202           if (getAntlibClassLoader() != null || hasCpDelegate()) {
  203               helper.setClassLoader(createLoader());
  204           }
  205   
  206           // Now create the scriptRunner
  207           runner = helper.getScriptRunner();
  208   
  209           attributeSet = new HashSet();
  210           for (Iterator i = attributes.iterator(); i.hasNext();) {
  211               Attribute attribute = (Attribute) i.next();
  212               if (attribute.name == null) {
  213                   throw new BuildException("scriptdef <attribute> elements "
  214                       + "must specify an attribute name");
  215               }
  216   
  217               if (attributeSet.contains(attribute.name)) {
  218                   throw new BuildException("scriptdef <" + name + "> declares "
  219                       + "the " + attribute.name + " attribute more than once");
  220               }
  221               attributeSet.add(attribute.name);
  222           }
  223   
  224           nestedElementMap = new HashMap();
  225           for (Iterator i = nestedElements.iterator(); i.hasNext();) {
  226               NestedElement nestedElement = (NestedElement) i.next();
  227               if (nestedElement.name == null) {
  228                   throw new BuildException("scriptdef <element> elements "
  229                       + "must specify an element name");
  230               }
  231               if (nestedElementMap.containsKey(nestedElement.name)) {
  232                   throw new BuildException("scriptdef <" + name + "> declares "
  233                       + "the " + nestedElement.name + " nested element more "
  234                       + "than once");
  235               }
  236   
  237               if (nestedElement.className == null
  238                   && nestedElement.type == null) {
  239                   throw new BuildException("scriptdef <element> elements "
  240                       + "must specify either a classname or type attribute");
  241               }
  242               if (nestedElement.className != null
  243                   && nestedElement.type != null) {
  244                   throw new BuildException("scriptdef <element> elements "
  245                       + "must specify only one of the classname and type "
  246                       + "attributes");
  247               }
  248   
  249   
  250               nestedElementMap.put(nestedElement.name, nestedElement);
  251           }
  252   
  253           // find the script repository - it is stored in the project
  254           Map scriptRepository = lookupScriptRepository();
  255           name = ProjectHelper.genComponentName(getURI(), name);
  256           scriptRepository.put(name, this);
  257           AntTypeDefinition def = new AntTypeDefinition();
  258           def.setName(name);
  259           def.setClass(ScriptDefBase.class);
  260           ComponentHelper.getComponentHelper(
  261               getProject()).addDataTypeDefinition(def);
  262       }
  263   
  264       /**
  265        * Find or create the script repository - it is stored in the project.
  266        * This method is synchronized on the project under {@link MagicNames#SCRIPT_REPOSITORY}
  267        * @return the current script repository registered as a refrence.
  268        */
  269       private Map lookupScriptRepository() {
  270           Map scriptRepository = null;
  271           Project p = getProject();
  272           synchronized (p) {
  273               scriptRepository =
  274                       (Map) p.getReference(MagicNames.SCRIPT_REPOSITORY);
  275               if (scriptRepository == null) {
  276                   scriptRepository = new HashMap();
  277                   p.addReference(MagicNames.SCRIPT_REPOSITORY,
  278                           scriptRepository);
  279               }
  280           }
  281           return scriptRepository;
  282       }
  283   
  284       /**
  285        * Create a nested element to be configured.
  286        *
  287        * @param elementName the name of the nested element.
  288        * @return object representing the element name.
  289        */
  290       public Object createNestedElement(String elementName) {
  291           NestedElement definition
  292               = (NestedElement) nestedElementMap.get(elementName);
  293           if (definition == null) {
  294               throw new BuildException("<" + name + "> does not support "
  295                   + "the <" + elementName + "> nested element");
  296           }
  297   
  298           Object instance = null;
  299           String classname = definition.className;
  300           if (classname == null) {
  301               instance = getProject().createTask(definition.type);
  302               if (instance == null) {
  303                   instance = getProject().createDataType(definition.type);
  304               }
  305           } else {
  306               /*
  307               // try the context classloader
  308               ClassLoader loader
  309                   = Thread.currentThread().getContextClassLoader();
  310               */
  311               ClassLoader loader = createLoader();
  312   
  313               try {
  314                   instance = ClasspathUtils.newInstance(classname, loader);
  315               } catch (BuildException e) {
  316                   instance = ClasspathUtils.newInstance(classname, ScriptDef.class.getClassLoader());
  317               }
  318   
  319               getProject().setProjectReference(instance);
  320           }
  321   
  322           if (instance == null) {
  323               throw new BuildException("<" + name + "> is unable to create "
  324                   + "the <" + elementName + "> nested element");
  325           }
  326           return instance;
  327       }
  328   
  329       /**
  330        * Execute the script.
  331        *
  332        * @param attributes collection of attributes
  333        * @param elements a list of nested element values.
  334        * @deprecated since 1.7.
  335        *             Use executeScript(attribute, elements, instance) instead.
  336        */
  337       public void executeScript(Map attributes, Map elements) {
  338           executeScript(attributes, elements, null);
  339       }
  340   
  341       /**
  342        * Execute the script.
  343        * This is called by the script instance to execute the script for this
  344        * definition.
  345        *
  346        * @param attributes collection of attributes
  347        * @param elements   a list of nested element values.
  348        * @param instance   the script instance; can be null
  349        */
  350       public void executeScript(Map attributes, Map elements, ScriptDefBase instance) {
  351           runner.addBean("attributes", attributes);
  352           runner.addBean("elements", elements);
  353           runner.addBean("project", getProject());
  354           if (instance != null) {
  355               runner.addBean("self", instance);
  356           }
  357           runner.executeScript("scriptdef_" + name);
  358       }
  359   
  360       /**
  361        * Defines the manager.
  362        *
  363        * @param manager the scripting manager.
  364        */
  365       public void setManager(String manager) {
  366           helper.setManager(manager);
  367       }
  368   
  369       /**
  370        * Defines the language (required).
  371        *
  372        * @param language the scripting language name for the script.
  373        */
  374       public void setLanguage(String language) {
  375           helper.setLanguage(language);
  376       }
  377   
  378       /**
  379        * Load the script from an external file ; optional.
  380        *
  381        * @param file the file containing the script source.
  382        */
  383       public void setSrc(File file) {
  384           helper.setSrc(file);
  385       }
  386   
  387       /**
  388        * Set the script text.
  389        *
  390        * @param text a component of the script text to be added.
  391        */
  392       public void addText(String text) {
  393           helper.addText(text);
  394       }
  395   
  396       /**
  397        * Add any source resource.
  398        * @since Ant1.7.1
  399        * @param resource source of script
  400        */
  401       public void add(ResourceCollection resource) {
  402           helper.add(resource);
  403       }
  404   }
  405   

Save This Page
Home » apache-ant-1.7.1-src » org.apache.tools » ant » taskdefs » optional » script » [javadoc | source]