diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Property.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Property.java | 726 |
1 files changed, 726 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Property.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Property.java new file mode 100644 index 00000000..4aee3d0f --- /dev/null +++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Property.java @@ -0,0 +1,726 @@ +/* + * 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 + * + * http://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; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; + +import org.apache.tools.ant.AntClassLoader; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.PropertyHelper; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.property.ResolvePropertyMap; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.types.Reference; +import org.apache.tools.ant.util.FileUtils; + +/** + * <p>Sets a property by name, or set of properties (from file or + * resource) in the project. </p> + * <p>Properties are immutable: whoever sets a property first freezes it for the + * rest of the build; they are most definitely not variable. + * <p>There are seven ways to set properties:</p> + * <ul> + * <li>By supplying both the <i>name</i> and <i>value</i> attribute.</li> + * <li>By supplying the <i>name</i> and nested text.</li> + * <li>By supplying both the <i>name</i> and <i>refid</i> attribute.</li> + * <li>By setting the <i>file</i> attribute with the filename of the property + * file to load. This property file has the format as defined by the file used + * in the class java.util.Properties.</li> + * <li>By setting the <i>url</i> attribute with the url from which to load the + * properties. This url must be directed to a file that has the format as defined + * by the file used in the class java.util.Properties.</li> + * <li>By setting the <i>resource</i> attribute with the resource name of the + * property file to load. This property file has the format as defined by the + * file used in the class java.util.Properties.</li> + * <li>By setting the <i>environment</i> attribute with a prefix to use. + * Properties will be defined for every environment variable by + * prefixing the supplied name and a period to the name of the variable.</li> + * </ul> + * <p>Although combinations of these ways are possible, only one should be used + * at a time. Problems might occur with the order in which properties are set, for + * instance.</p> + * <p>The value part of the properties being set, might contain references to other + * properties. These references are resolved at the time these properties are set. + * This also holds for properties loaded from a property file.</p> + * Properties are case sensitive. + * + * @since Ant 1.1 + * + * @ant.attribute.group name="name" description="One of these, when using the name attribute" + * @ant.attribute.group name="noname" description="One of these, when not using the name attribute" + * @ant.task category="property" + */ +public class Property extends Task { + + // CheckStyle:VisibilityModifier OFF - bc + protected String name; + protected String value; + protected File file; + protected URL url; + protected String resource; + protected Path classpath; + protected String env; + protected Reference ref; + protected String prefix; + private Project fallback; + private Object untypedValue; + private boolean valueAttributeUsed = false; + private boolean relative = false; + private File basedir; + private boolean prefixValues = false; + + protected boolean userProperty; // set read-only properties + // CheckStyle:VisibilityModifier ON + + /** + * Constructor for Property. + */ + public Property() { + this(false); + } + + /** + * Constructor for Property. + * @param userProperty if true this is a user property + * @since Ant 1.5 + */ + protected Property(boolean userProperty) { + this(userProperty, null); + } + + /** + * Constructor for Property. + * @param userProperty if true this is a user property + * @param fallback a project to use to look for references if the reference is + * not in the current project + * @since Ant 1.5 + */ + protected Property(boolean userProperty, Project fallback) { + this.userProperty = userProperty; + this.fallback = fallback; + } + + /** + * Sets 'relative' attribute. + * @param relative new value + * @since Ant 1.8.0 + */ + public void setRelative(boolean relative) { + this.relative = relative; + } + + /** + * Sets 'basedir' attribute. + * @param basedir new value + * @since Ant 1.8.0 + */ + public void setBasedir(File basedir) { + this.basedir = basedir; + } + + /** + * The name of the property to set. + * @param name property name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Get the property name. + * @return the property name + */ + public String getName() { + return name; + } + + /** + * Sets the property to the absolute filename of the + * given file. If the value of this attribute is an absolute path, it + * is left unchanged (with / and \ characters converted to the + * current platforms conventions). Otherwise it is taken as a path + * relative to the project's basedir and expanded. + * @param location path to set + * + * @ant.attribute group="name" + */ + public void setLocation(File location) { + if (relative) { + internalSetValue(location); + } else { + setValue(location.getAbsolutePath()); + } + } + + /* the following method is first in source so IH will pick it up first: + * Hopefully we'll never get any classes compiled by wise-guy compilers that behave otherwise... + */ + + /** + * Set the value of the property. + * @param value the value to use. + */ + public void setValue(Object value) { + valueAttributeUsed = true; + internalSetValue(value); + } + + private void internalSetValue(Object value) { + this.untypedValue = value; + //preserve protected string value for subclasses :( + this.value = value == null ? null : value.toString(); + } + + /** + * Set the value of the property as a String. + * @param value value to assign + * + * @ant.attribute group="name" + */ + public void setValue(String value) { + setValue((Object) value); + } + + /** + * Set a (multiline) property as nested text. + * @param msg the text to append to the output text + * @since Ant 1.8.0 + */ + public void addText(String msg) { + if (!valueAttributeUsed) { + msg = getProject().replaceProperties(msg); + String currentValue = getValue(); + if (currentValue != null) { + msg = currentValue + msg; + } + internalSetValue(msg); + } else if (msg.trim().length() > 0) { + throw new BuildException("can't combine nested text with value" + + " attribute"); + } + } + + /** + * Get the property value. + * @return the property value + */ + public String getValue() { + return value; + } + + /** + * Filename of a property file to load. + * @param file filename + * + * @ant.attribute group="noname" + */ + public void setFile(File file) { + this.file = file; + } + + /** + * Get the file attribute. + * @return the file attribute + */ + public File getFile() { + return file; + } + + /** + * The url from which to load properties. + * @param url url string + * + * @ant.attribute group="noname" + */ + public void setUrl(URL url) { + this.url = url; + } + + /** + * Get the url attribute. + * @return the url attribute + */ + public URL getUrl() { + return url; + } + + /** + * Prefix to apply to properties loaded using <code>file</code> + * or <code>resource</code>. + * A "." is appended to the prefix if not specified. + * @param prefix prefix string + * @since Ant 1.5 + */ + public void setPrefix(String prefix) { + this.prefix = prefix; + if (prefix != null && !prefix.endsWith(".")) { + this.prefix += "."; + } + } + + /** + * Get the prefix attribute. + * @return the prefix attribute + * @since Ant 1.5 + */ + public String getPrefix() { + return prefix; + } + + /** + * Whether to apply the prefix when expanding properties on the + * right hand side of a properties file as well. + * + * @since Ant 1.8.2 + */ + public void setPrefixValues(boolean b) { + prefixValues = b; + } + + /** + * Whether to apply the prefix when expanding properties on the + * right hand side of a properties file as well. + * + * @since Ant 1.8.2 + */ + public boolean getPrefixValues() { + return prefixValues; + } + + /** + * Sets a reference to an Ant datatype + * declared elsewhere. + * Only yields reasonable results for references + * PATH like structures or properties. + * @param ref reference + * + * @ant.attribute group="name" + */ + public void setRefid(Reference ref) { + this.ref = ref; + } + + /** + * Get the refid attribute. + * @return the refid attribute + */ + public Reference getRefid() { + return ref; + } + + /** + * The resource name of a property file to load + * @param resource resource on classpath + * + * @ant.attribute group="noname" + */ + public void setResource(String resource) { + this.resource = resource; + } + + /** + * Get the resource attribute. + * @return the resource attribute + */ + public String getResource() { + return resource; + } + + /** + * Prefix to use when retrieving environment variables. + * Thus if you specify environment="myenv" + * you will be able to access OS-specific + * environment variables via property names "myenv.PATH" or + * "myenv.TERM". + * <p> + * Note that if you supply a property name with a final + * "." it will not be doubled. ie environment="myenv." will still + * allow access of environment variables through "myenv.PATH" and + * "myenv.TERM". This functionality is currently only implemented + * on select platforms. Feel free to send patches to increase the number of platforms + * this functionality is supported on ;).<br> + * Note also that properties are case sensitive, even if the + * environment variables on your operating system are not, e.g. it + * will be ${env.Path} not ${env.PATH} on Windows 2000. + * @param env prefix + * + * @ant.attribute group="noname" + */ + public void setEnvironment(String env) { + this.env = env; + } + + /** + * Get the environment attribute. + * @return the environment attribute + * @since Ant 1.5 + */ + public String getEnvironment() { + return env; + } + + /** + * The classpath to use when looking up a resource. + * @param classpath to add to any existing classpath + */ + public void setClasspath(Path classpath) { + if (this.classpath == null) { + this.classpath = classpath; + } else { + this.classpath.append(classpath); + } + } + + /** + * The classpath to use when looking up a resource. + * @return a path to be configured + */ + public Path createClasspath() { + if (this.classpath == null) { + this.classpath = new Path(getProject()); + } + return this.classpath.createPath(); + } + + /** + * the classpath to use when looking up a resource, + * given as reference to a <path> defined elsewhere + * @param r a reference to a classpath + */ + public void setClasspathRef(Reference r) { + createClasspath().setRefid(r); + } + + /** + * Get the classpath used when looking up a resource. + * @return the classpath + * @since Ant 1.5 + */ + public Path getClasspath() { + return classpath; + } + + /** + * @param userProperty ignored + * @deprecated since 1.5.x. + * This was never a supported feature and has been + * deprecated without replacement. + * @ant.attribute ignore="true" + */ + @Deprecated + public void setUserProperty(boolean userProperty) { + log("DEPRECATED: Ignoring request to set user property in Property" + + " task.", Project.MSG_WARN); + } + + /** + * get the value of this property + * @return the current value or the empty string + */ + @Override + public String toString() { + return value == null ? "" : value; + } + + /** + * set the property in the project to the value. + * if the task was give a file, resource or env attribute + * here is where it is loaded + * @throws BuildException on error + */ + @Override + public void execute() throws BuildException { + if (getProject() == null) { + throw new IllegalStateException("project has not been set"); + } + + if (name != null) { + if (untypedValue == null && ref == null) { + throw new BuildException("You must specify value, location or " + + "refid with the name attribute", + getLocation()); + } + } else { + if (url == null && file == null && resource == null && env == null) { + throw new BuildException("You must specify url, file, resource or " + + "environment when not using the " + + "name attribute", getLocation()); + } + } + + if (url == null && file == null && resource == null && prefix != null) { + throw new BuildException("Prefix is only valid when loading from " + + "a url, file or resource", getLocation()); + } + + if (name != null && untypedValue != null) { + if (relative) { + try { + File from = untypedValue instanceof File ? (File)untypedValue : new File(untypedValue.toString()); + File to = basedir != null ? basedir : getProject().getBaseDir(); + String relPath = FileUtils.getRelativePath(to, from); + relPath = relPath.replace('/', File.separatorChar); + addProperty(name, relPath); + } catch (Exception e) { + throw new BuildException(e, getLocation()); + } + } else { + addProperty(name, untypedValue); + } + } + + if (file != null) { + loadFile(file); + } + + if (url != null) { + loadUrl(url); + } + + if (resource != null) { + loadResource(resource); + } + + if (env != null) { + loadEnvironment(env); + } + + if ((name != null) && (ref != null)) { + try { + addProperty(name, + ref.getReferencedObject(getProject()).toString()); + } catch (BuildException be) { + if (fallback != null) { + addProperty(name, + ref.getReferencedObject(fallback).toString()); + } else { + throw be; + } + } + } + } + + /** + * load properties from a url + * @param url url to load from + * @throws BuildException on error + */ + protected void loadUrl(URL url) throws BuildException { + Properties props = new Properties(); + log("Loading " + url, Project.MSG_VERBOSE); + try { + InputStream is = url.openStream(); + try { + loadProperties(props, is, url.getFile().endsWith(".xml")); + } finally { + if (is != null) { + is.close(); + } + } + addProperties(props); + } catch (IOException ex) { + throw new BuildException(ex, getLocation()); + } + } + + /** + * Loads the properties defined in the InputStream into the given + * property. On Java5+ it supports reading from XML based property + * definition. + * @param props The property object to load into + * @param is The input stream from where to load + * @param isXml <tt>true</tt> if we should try to load from xml + * @throws IOException if something goes wrong + * @since 1.8.0 + * @see "http://java.sun.com/dtd/properties.dtd" + * @see java.util.Properties#loadFromXML(InputStream) + */ + private void loadProperties( + Properties props, InputStream is, boolean isXml) throws IOException { + if (isXml) { + // load the xml based property definition + props.loadFromXML(is); + } else { + // load ".properties" format + props.load(is); + } + } + + /** + * load properties from a file + * @param file file to load + * @throws BuildException on error + */ + protected void loadFile(File file) throws BuildException { + Properties props = new Properties(); + log("Loading " + file.getAbsolutePath(), Project.MSG_VERBOSE); + try { + if (file.exists()) { + FileInputStream fis = null; + try { + fis = new FileInputStream(file); + loadProperties(props, fis, file.getName().endsWith(".xml")); + } finally { + FileUtils.close(fis); + } + addProperties(props); + } else { + log("Unable to find property file: " + file.getAbsolutePath(), + Project.MSG_VERBOSE); + } + } catch (IOException ex) { + throw new BuildException(ex, getLocation()); + } + } + + /** + * load properties from a resource in the current classpath + * @param name name of resource to load + */ + protected void loadResource(String name) { + Properties props = new Properties(); + log("Resource Loading " + name, Project.MSG_VERBOSE); + InputStream is = null; + ClassLoader cL = null; + boolean cleanup = false; + try { + if (classpath != null) { + cleanup = true; + cL = getProject().createClassLoader(classpath); + } else { + cL = this.getClass().getClassLoader(); + } + + if (cL == null) { + is = ClassLoader.getSystemResourceAsStream(name); + } else { + is = cL.getResourceAsStream(name); + } + + if (is != null) { + loadProperties(props, is, name.endsWith(".xml")); + addProperties(props); + } else { + log("Unable to find resource " + name, Project.MSG_WARN); + } + } catch (IOException ex) { + throw new BuildException(ex, getLocation()); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + // ignore + } + } + if (cleanup && cL != null) { + ((AntClassLoader) cL).cleanup(); + } + } + } + + /** + * load the environment values + * @param prefix prefix to place before them + */ + protected void loadEnvironment(String prefix) { + Properties props = new Properties(); + if (!prefix.endsWith(".")) { + prefix += "."; + } + log("Loading Environment " + prefix, Project.MSG_VERBOSE); + Map osEnv = Execute.getEnvironmentVariables(); + for (Iterator e = osEnv.entrySet().iterator(); e.hasNext();) { + Map.Entry entry = (Map.Entry) e.next(); + props.put(prefix + entry.getKey(), entry.getValue()); + } + addProperties(props); + } + + /** + * iterate through a set of properties, + * resolve them then assign them + * @param props the properties to iterate over + */ + protected void addProperties(Properties props) { + HashMap m = new HashMap(props); + resolveAllProperties(m); + for (Iterator it = m.keySet().iterator(); it.hasNext();) { + Object k = it.next(); + if (k instanceof String) { + String propertyName = (String) k; + if (prefix != null) { + propertyName = prefix + propertyName; + } + addProperty(propertyName, m.get(k)); + } + } + } + + /** + * add a name value pair to the project property set + * @param n name of property + * @param v value to set + */ + protected void addProperty(String n, String v) { + addProperty(n, (Object) v); + } + + /** + * add a name value pair to the project property set + * @param n name of property + * @param v value to set + * @since Ant 1.8 + */ + protected void addProperty(String n, Object v) { + PropertyHelper ph = PropertyHelper.getPropertyHelper(getProject()); + if (userProperty) { + if (ph.getUserProperty(n) == null) { + ph.setInheritedProperty(n, v); + } else { + log("Override ignored for " + n, Project.MSG_VERBOSE); + } + } else { + ph.setNewProperty(n, v); + } + } + + /** + * resolve properties inside a properties hashtable + * @param props properties object to resolve + */ + private void resolveAllProperties(Map props) throws BuildException { + PropertyHelper propertyHelper + = PropertyHelper.getPropertyHelper(getProject()); + new ResolvePropertyMap( + getProject(), + propertyHelper, + propertyHelper.getExpanders()) + .resolveAllProperties(props, getPrefix(), getPrefixValues()); + } + +} |