/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.optional.script;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.apache.tools.ant.AntTypeDefinition;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.ComponentHelper;
import org.apache.tools.ant.MagicNames;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper;
import org.apache.tools.ant.taskdefs.DefBase;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.util.ClasspathUtils;
import org.apache.tools.ant.util.ScriptRunnerBase;
import org.apache.tools.ant.util.ScriptRunnerHelper;
Defines a task using a script.
Since: Ant 1.6
/**
* Defines a task using a script.
*
* @since Ant 1.6
*/
public class ScriptDef extends DefBase {
script runner helper
/**
* script runner helper
*/
private ScriptRunnerHelper helper = new ScriptRunnerHelper();
the name by which this script will be activated /** the name by which this script will be activated */
private String name;
Attributes definitions of this script /** Attributes definitions of this script */
private List<Attribute> attributes = new ArrayList<>();
Nested Element definitions of this script /** Nested Element definitions of this script */
private List<NestedElement> nestedElements = new ArrayList<>();
The attribute names as a set /** The attribute names as a set */
private Set<String> attributeSet;
The nested element definitions indexed by their names /** The nested element definitions indexed by their names */
private Map<String, NestedElement> nestedElementMap;
Set the project.
Params: - project – the project that this definition belongs to.
/**
* Set the project.
* @param project the project that this definition belongs to.
*/
@Override
public void setProject(Project project) {
super.setProject(project);
helper.setProjectComponent(this);
helper.setSetBeans(false);
}
Sets the name under which this script will be activated in a build
file
Params: - name – the name of the script
/**
* Sets the name under which this script will be activated in a build
* file
*
* @param name the name of the script
*/
public void setName(String name) {
this.name = name;
}
Indicates whether the task supports a given attribute name
Params: - attributeName – the name of the attribute.
Returns: true if the attribute is supported by the script.
/**
* Indicates whether the task supports a given attribute name
*
* @param attributeName the name of the attribute.
*
* @return true if the attribute is supported by the script.
*/
public boolean isAttributeSupported(String attributeName) {
return attributeSet.contains(attributeName);
}
Class representing an attribute definition
/**
* Class representing an attribute definition
*/
public static class Attribute {
The attribute name /** The attribute name */
private String name;
Sets the attribute name
Params: - name – the attribute name
/**
* Sets the attribute name
*
* @param name the attribute name
*/
public void setName(String name) {
this.name = name.toLowerCase(Locale.ENGLISH);
}
}
Adds an attribute definition to this script.
Params: - attribute – the attribute definition.
/**
* Adds an attribute definition to this script.
*
* @param attribute the attribute definition.
*/
public void addAttribute(Attribute attribute) {
attributes.add(attribute);
}
Class to represent a nested element definition
/**
* Class to represent a nested element definition
*/
public static class NestedElement {
The name of the nested element /** The name of the nested element */
private String name;
The Ant type to which this nested element corresponds. /** The Ant type to which this nested element corresponds. */
private String type;
The class to be created for this nested element /** The class to be created for this nested element */
private String className;
Sets the tag name for this nested element
Params: - name – the name of this nested element
/**
* Sets the tag name for this nested element
*
* @param name the name of this nested element
*/
public void setName(String name) {
this.name = name.toLowerCase(Locale.ENGLISH);
}
Sets the type of this element. This is the name of an
Ant task or type which is to be used when this element is to be
created. This is an alternative to specifying the class name directly
Params: - type – the name of an Ant type, or task, to use for this nested
element.
/**
* Sets the type of this element. This is the name of an
* Ant task or type which is to be used when this element is to be
* created. This is an alternative to specifying the class name directly
*
* @param type the name of an Ant type, or task, to use for this nested
* element.
*/
public void setType(String type) {
this.type = type;
}
Sets the classname of the class to be used for the nested element.
This specifies the class directly and is an alternative to specifying
the Ant type name.
Params: - className – the name of the class to use for this nested
element.
/**
* Sets the classname of the class to be used for the nested element.
* This specifies the class directly and is an alternative to specifying
* the Ant type name.
*
* @param className the name of the class to use for this nested
* element.
*/
public void setClassName(String className) {
this.className = className;
}
}
Adds a nested element definition.
Params: - nestedElement – the nested element definition.
/**
* Adds a nested element definition.
*
* @param nestedElement the nested element definition.
*/
public void addElement(NestedElement nestedElement) {
nestedElements.add(nestedElement);
}
Defines the script.
/**
* Defines the script.
*/
@Override
public void execute() {
if (name == null) {
throw new BuildException(
"scriptdef requires a name attribute to name the script");
}
if (helper.getLanguage() == null) {
throw new BuildException(
"scriptdef requires a language attribute to specify the script language");
}
if (helper.getSrc() == null && helper.getEncoding() != null) {
throw new BuildException(
"scriptdef requires a src attribute if the encoding is set");
}
// Check if need to set the loader
if (getAntlibClassLoader() != null || hasCpDelegate()) {
helper.setClassLoader(createLoader());
}
attributeSet = new HashSet<>();
for (Attribute attribute : attributes) {
if (attribute.name == null) {
throw new BuildException(
"scriptdef <attribute> elements must specify an attribute name");
}
if (attributeSet.contains(attribute.name)) {
throw new BuildException(
"scriptdef <%s> declares the %s attribute more than once",
name, attribute.name);
}
attributeSet.add(attribute.name);
}
nestedElementMap = new HashMap<>();
for (NestedElement nestedElement : nestedElements) {
if (nestedElement.name == null) {
throw new BuildException(
"scriptdef <element> elements must specify an element name");
}
if (nestedElementMap.containsKey(nestedElement.name)) {
throw new BuildException(
"scriptdef <%s> declares the %s nested element more than once",
name, nestedElement.name);
}
if (nestedElement.className == null
&& nestedElement.type == null) {
throw new BuildException(
"scriptdef <element> elements must specify either a classname or type attribute");
}
if (nestedElement.className != null
&& nestedElement.type != null) {
throw new BuildException(
"scriptdef <element> elements must specify only one of the classname and type attributes");
}
nestedElementMap.put(nestedElement.name, nestedElement);
}
// find the script repository - it is stored in the project
Map<String, ScriptDef> scriptRepository = lookupScriptRepository();
name = ProjectHelper.genComponentName(getURI(), name);
scriptRepository.put(name, this);
AntTypeDefinition def = new AntTypeDefinition();
def.setName(name);
def.setClass(ScriptDefBase.class);
ComponentHelper.getComponentHelper(
getProject()).addDataTypeDefinition(def);
}
Finds or creates the script repository - it is stored in the project. This method is synchronized on the project under MagicNames.SCRIPT_REPOSITORY
Returns: the current script repository registered as a reference.
/**
* Finds or creates the script repository - it is stored in the project.
* This method is synchronized on the project under {@link MagicNames#SCRIPT_REPOSITORY}
* @return the current script repository registered as a reference.
*/
private Map<String, ScriptDef> lookupScriptRepository() {
Map<String, ScriptDef> scriptRepository;
Project p = getProject();
synchronized (p) {
scriptRepository =
p.getReference(MagicNames.SCRIPT_REPOSITORY);
if (scriptRepository == null) {
scriptRepository = new HashMap<>();
p.addReference(MagicNames.SCRIPT_REPOSITORY,
scriptRepository);
}
}
return scriptRepository;
}
Creates a nested element to be configured.
Params: - elementName – the name of the nested element.
Returns: object representing the element name.
/**
* Creates a nested element to be configured.
*
* @param elementName the name of the nested element.
* @return object representing the element name.
*/
public Object createNestedElement(String elementName) {
NestedElement definition = nestedElementMap.get(elementName);
if (definition == null) {
throw new BuildException(
"<%s> does not support the <%s> nested element", name,
elementName);
}
Object instance;
String classname = definition.className;
if (classname == null) {
instance = getProject().createTask(definition.type);
if (instance == null) {
instance = getProject().createDataType(definition.type);
}
} else {
ClassLoader loader = createLoader();
try {
instance = ClasspathUtils.newInstance(classname, loader);
} catch (BuildException e) {
instance = ClasspathUtils.newInstance(classname, ScriptDef.class.getClassLoader());
}
getProject().setProjectReference(instance);
}
if (instance == null) {
throw new BuildException(
"<%s> is unable to create the <%s> nested element", name,
elementName);
}
return instance;
}
Executes the script.
Params: - attributes – collection of attributes
- elements – a list of nested element values.
Deprecated: since 1.7.
Use executeScript(attribute, elements, instance) instead.
/**
* Executes the script.
*
* @param attributes collection of attributes
* @param elements a list of nested element values.
* @deprecated since 1.7.
* Use executeScript(attribute, elements, instance) instead.
*/
@Deprecated
public void executeScript(Map<String, String> attributes,
Map<String, List<Object>> elements) {
executeScript(attributes, elements, null);
}
Executes the script.
This is called by the script instance to execute the script for this
definition.
Params: - attributes – collection of attributes
- elements – a list of nested element values.
- instance – the script instance; can be null
/**
* Executes the script.
* This is called by the script instance to execute the script for this
* definition.
*
* @param attributes collection of attributes
* @param elements a list of nested element values.
* @param instance the script instance; can be null
*/
public void executeScript(Map<String, String> attributes,
Map<String, List<Object>> elements, ScriptDefBase instance) {
ScriptRunnerBase runner = helper.getScriptRunner();
runner.addBean("attributes", attributes);
runner.addBean("elements", elements);
runner.addBean("project", getProject());
if (instance != null) {
runner.addBean("self", instance);
}
runner.executeScript("scriptdef_" + name);
}
Defines the manager.
Params: - manager – the scripting manager.
/**
* Defines the manager.
*
* @param manager the scripting manager.
*/
public void setManager(String manager) {
helper.setManager(manager);
}
Defines the language (required).
Params: - language – the scripting language name for the script.
/**
* Defines the language (required).
*
* @param language the scripting language name for the script.
*/
public void setLanguage(String language) {
helper.setLanguage(language);
}
Defines the compilation feature; optional.
Params: - compiled – enables the script compilation if available.
Since: Ant 1.10.2
/**
* Defines the compilation feature; optional.
*
* @param compiled enables the script compilation if available.
* @since Ant 1.10.2
*/
public void setCompiled(boolean compiled) {
helper.setCompiled(compiled);
}
Loads the script from an external file; optional.
Params: - file – the file containing the script source.
/**
* Loads the script from an external file; optional.
*
* @param file the file containing the script source.
*/
public void setSrc(File file) {
helper.setSrc(file);
}
Sets the encoding of the script from an external file; optional.
Params: - encoding – the encoding of the file containing the script source.
Since: Ant 1.10.2
/**
* Sets the encoding of the script from an external file; optional.
*
* @param encoding the encoding of the file containing the script source.
* @since Ant 1.10.2
*/
public void setEncoding(String encoding) {
helper.setEncoding(encoding);
}
Sets the script text.
Params: - text – a component of the script text to be added.
/**
* Sets the script text.
*
* @param text a component of the script text to be added.
*/
public void addText(String text) {
helper.addText(text);
}
Adds any source resource.
Params: - resource – source of script
Since: Ant 1.7.1
/**
* Adds any source resource.
* @since Ant 1.7.1
* @param resource source of script
*/
public void add(ResourceCollection resource) {
helper.add(resource);
}
}