Browse Source

add local properties; bugzilla 23942

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@676095 13f79535-47bb-0310-9956-ffa450edef68
master
Matthew Jason Benson 17 years ago
parent
commit
93af3c50df
13 changed files with 535 additions and 10 deletions
  1. +2
    -0
      WHATSNEW
  2. +53
    -0
      docs/manual/CoreTasks/local.html
  3. +1
    -0
      docs/manual/coretasklist.html
  4. +6
    -0
      src/main/org/apache/tools/ant/MagicNames.java
  5. +17
    -7
      src/main/org/apache/tools/ant/Target.java
  6. +152
    -0
      src/main/org/apache/tools/ant/property/LocalProperties.java
  7. +151
    -0
      src/main/org/apache/tools/ant/property/LocalPropertyStack.java
  8. +47
    -0
      src/main/org/apache/tools/ant/taskdefs/Local.java
  9. +5
    -0
      src/main/org/apache/tools/ant/taskdefs/MacroInstance.java
  10. +2
    -0
      src/main/org/apache/tools/ant/taskdefs/Parallel.java
  11. +12
    -3
      src/main/org/apache/tools/ant/taskdefs/Sequential.java
  12. +1
    -0
      src/main/org/apache/tools/ant/taskdefs/defaults.properties
  13. +86
    -0
      src/tests/antunit/taskdefs/local-test.xml

+ 2
- 0
WHATSNEW View File

@@ -153,6 +153,8 @@ Other changes:
a build if a warning occurs.
Bugzilla Report 41836.

* Ant now supports local properties. Bugzilla report 23942.

Changes from Ant 1.7.0 TO Ant 1.7.1
=============================================



+ 53
- 0
docs/manual/CoreTasks/local.html View File

@@ -0,0 +1,53 @@
<!--
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.
-->
<html>

<head>
<meta http-equiv="Content-Language" content="en-us">
<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
<title>Local Task</title>
</head>

<body>

<h2>Local</h2>
<h3>Description</h3>
<p>Adds a local property to the current scope. Property scopes exist at Ant's
various "block" levels. These include targets as well as the
<a href="parallel.html">Parallel</a> and <a href="sequential.html">Sequential</a>
task containers (including <a href="macrodef.html">Macrodef</a> bodies). A local
property at a given scope "shadows" properties of the same name at higher scopes,
including the global scope (declaring a local property at the global level, i.e.
outside of any scope block, has no effect). <b>Since Ant 1.8</b></p>

<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">name</td>
<td valign="top">The property to declare in the current scope</td>
<td valign="top" align="center">Yes</td>
</tr>
</table>

</body>
</html>


+ 1
- 0
docs/manual/coretasklist.html View File

@@ -86,6 +86,7 @@
<a href="CoreTasks/loadfile.html">LoadFile</a><br/>
<a href="CoreTasks/loadproperties.html">LoadProperties</a><br/>
<a href="CoreTasks/loadresource.html">LoadResource</a><br/>
<a href="CoreTasks/local.html">Local</a><br/>
<a href="CoreTasks/makeurl.html">MakeURL</a><br/>
<a href="CoreTasks/mail.html">Mail</a><br/>
<a href="CoreTasks/macrodef.html">MacroDef</a><br/>


+ 6
- 0
src/main/org/apache/tools/ant/MagicNames.java View File

@@ -174,6 +174,12 @@ public final class MagicNames {
*/
public static final String REFID_PROPERTY_HELPER = "ant.PropertyHelper";

/**
* Reference used to store the local properties.
* Value: {@value}
*/
public static final String REFID_LOCAL_PROPERTIES = "ant.LocalProperties";

/**
* Name of JVM system property which provides the name of the ProjectHelper class to use.
* Value: {@value}


+ 17
- 7
src/main/org/apache/tools/ant/Target.java View File

@@ -25,6 +25,8 @@ import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.tools.ant.property.LocalProperties;

/**
* Class to implement a target object with required parameters.
*
@@ -347,14 +349,22 @@ public class Target implements TaskContainer {
*/
public void execute() throws BuildException {
if (testIfCondition() && testUnlessCondition()) {
for (int taskPosition = 0; taskPosition < children.size(); ++taskPosition) {
Object o = children.get(taskPosition);
if (o instanceof Task) {
Task task = (Task) o;
task.perform();
} else {
((RuntimeConfigurable) o).maybeConfigure(project);
LocalProperties localProperties
= LocalProperties.get(getProject());
localProperties.enterScope();
try {
for (int taskPosition = 0; taskPosition < children.size();
++taskPosition) {
Object o = children.get(taskPosition);
if (o instanceof Task) {
Task task = (Task) o;
task.perform();
} else {
((RuntimeConfigurable) o).maybeConfigure(project);
}
}
} finally {
localProperties.exitScope();
}
} else if (!testIfCondition()) {
project.log(this, "Skipped because property '" + project.replaceProperties(ifCondition)


+ 152
- 0
src/main/org/apache/tools/ant/property/LocalProperties.java View File

@@ -0,0 +1,152 @@
/*
* 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.property;

import org.apache.tools.ant.PropertyHelper;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.MagicNames;

/**
* Thread local class containing local properties.
* @since Ant 1.8.0
*/
public class LocalProperties
extends InheritableThreadLocal
implements PropertyHelper.PropertyEvaluator,
PropertyHelper.PropertySetter {

/**
* Get a localproperties for the given project.
* @param project the project to retieve the localproperties for.
* @return the localproperties.
*/
public static synchronized LocalProperties get(Project project) {
LocalProperties l = (LocalProperties) project.getReference(
MagicNames.REFID_LOCAL_PROPERTIES);
if (l == null) {
l = new LocalProperties();
project.addReference(MagicNames.REFID_LOCAL_PROPERTIES, l);
PropertyHelper.getPropertyHelper(project).add(l);
}
return l;
}

// --------------------------------------------------
//
// Thread stuff
//
// --------------------------------------------------

/**
* Construct a new LocalProperties object.
*/
private LocalProperties() {
}

/**
* Get the initial value.
* @return a new localproperties stack.
*/
protected synchronized Object initialValue() {
return new LocalPropertyStack();
}

private LocalPropertyStack current() {
return (LocalPropertyStack) get();
}

// --------------------------------------------------
//
// Local property adding and scoping
//
// --------------------------------------------------

/**
* Add a local property to the current scope.
* @param property the property name to add.
*/
public void addLocal(String property) {
current().addLocal(property);
}

/** enter the scope */
public void enterScope() {
current().enterScope();
}

/** exit the scope */
public void exitScope() {
current().exitScope();
}

// --------------------------------------------------
//
// Copy - used in parallel to make a new stack
//
// --------------------------------------------------

/**
* Copy the stack for a parallel thread.
* To be called from the parallel thread itself.
*/
public void copy() {
set(current().copy());
}

// --------------------------------------------------
//
// PropertyHelper delegate methods
//
// --------------------------------------------------

/**
* Evaluate a property.
* @param property the property's String "identifier".
* @param helper the invoking PropertyHelper.
* @return Object value.
*/
public Object evaluate(String property, PropertyHelper helper) {
return current().evaluate(property, helper);
}

/**
* Set a *new" property.
* @param property the property's String "identifier".
* @param value the value to set.
* @param propertyHelper the invoking PropertyHelper.
* @return true if this entity 'owns' the property.
*/
public boolean setNew(
String property, Object value, PropertyHelper propertyHelper) {
return current().setNew(property, value, propertyHelper);
}

/**
* Set a property.
* @param property the property's String "identifier".
* @param value the value to set.
* @param propertyHelper the invoking PropertyHelper.
* @return true if this entity 'owns' the property.
*/
public boolean set(
String property, Object value, PropertyHelper propertyHelper) {
return current().set(property, value, propertyHelper);
}
}



+ 151
- 0
src/main/org/apache/tools/ant/property/LocalPropertyStack.java View File

@@ -0,0 +1,151 @@
/*
* 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.property;


import java.util.LinkedList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.tools.ant.PropertyHelper;

/**
* A stack of local property maps.
* There is a map for each scope (target, sequential, macro).
* @since Ant 1.8.0
*/
public class LocalPropertyStack {
private LinkedList stack = new LinkedList();

// --------------------------------------------------
//
// Local property adding and scoping
//
// --------------------------------------------------

/**
* Add a local property.
* @param property the name of the local proeprty.
*/
public void addLocal(String property) {
if (!stack.isEmpty()) {
((Map) stack.getFirst()).put(property, NullReturn.NULL);
}
}

/**
* Enter the local scope.
*/
public void enterScope() {
stack.addFirst(new HashMap());
}

/**
* Exit the local scope.
*/
public void exitScope() {
((HashMap) stack.removeFirst()).clear();
}

// --------------------------------------------------
//
// Copy - used in parallel to make a new stack
//
// --------------------------------------------------

/**
* Copy the stack for a parallel thread.
* @return a copy.
*/
public LocalPropertyStack copy() {
LocalPropertyStack ret = new LocalPropertyStack();
ret.stack.addAll(stack);
return ret;
}

// --------------------------------------------------
//
// PropertyHelper delegate methods
//
// --------------------------------------------------

/**
* Evaluate a property.
* @param property the property's String "identifier".
* @param helper the invoking PropertyHelper.
* @return Object value.
*/
public Object evaluate(String property, PropertyHelper helper) {
for (Iterator i = stack.iterator(); i.hasNext();) {
Map map = (Map) i.next();
Object ret = map.get(property);
if (ret != null) {
return ret;
}
}
return null;
}

/**
* Set a *new" property.
* @param property the property's String "identifier".
* @param value the value to set.
* @param propertyHelper the invoking PropertyHelper.
* @return true if this entity 'owns' the property.
*/
public boolean setNew(
String property, Object value, PropertyHelper propertyHelper) {
Map map = getMapForProperty(property);
if (map == null) {
return false;
}
Object currValue = map.get(property);
if (currValue == NullReturn.NULL) {
map.put(property, value);
}
return true;
}

/**
* Set a property.
* @param property the property's String "identifier".
* @param value the value to set.
* @param propertyHelper the invoking PropertyHelper.
* @return true if this entity 'owns' the property.
*/
public boolean set(String property, Object value, PropertyHelper propertyHelper) {
Map map = getMapForProperty(property);
if (map == null) {
return false;
}
map.put(property, value);
return true;
}

private Map getMapForProperty(String property) {
for (Iterator i = stack.iterator(); i.hasNext();) {
Map map = (Map) i.next();
if (map.get(property) != null) {
return map;
}
}
return null;
}
}


+ 47
- 0
src/main/org/apache/tools/ant/taskdefs/Local.java View File

@@ -0,0 +1,47 @@
/*
* 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 org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.property.LocalProperties;

/**
* Task to create a local property in the current scope.
*/
public class Local extends Task {
private String name;

/**
* Set the name attribute.
* @param name the name of the local property.
*/
public void setName(String name) {
this.name = name;
}

/**
* Run the task.
*/
public void execute() {
if (name == null) {
throw new BuildException("Missing attribute name");
}
LocalProperties.get(getProject()).addLocal(name);
}
}

+ 5
- 0
src/main/org/apache/tools/ant/taskdefs/MacroInstance.java View File

@@ -37,6 +37,7 @@ import org.apache.tools.ant.Target;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.TaskContainer;
import org.apache.tools.ant.UnknownElement;
import org.apache.tools.ant.property.LocalProperties;

/**
* The class to be placed in the ant type definition.
@@ -390,6 +391,9 @@ public class MacroInstance extends Task implements DynamicAttribute, TaskContain
// need to set the project on unknown element
UnknownElement c = copy(macroDef.getNestedTask(), false);
c.init();
LocalProperties localProperties
= LocalProperties.get(getProject());
localProperties.enterScope();
try {
c.perform();
} catch (BuildException ex) {
@@ -403,6 +407,7 @@ public class MacroInstance extends Task implements DynamicAttribute, TaskContain
} finally {
presentElements = null;
localAttributes = null;
localProperties.exitScope();
}
}
}

+ 2
- 0
src/main/org/apache/tools/ant/taskdefs/Parallel.java View File

@@ -26,6 +26,7 @@ import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Location;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.TaskContainer;
import org.apache.tools.ant.property.LocalProperties;
import org.apache.tools.ant.util.StringUtils;

/**
@@ -451,6 +452,7 @@ public class Parallel extends Task
*/
public void run() {
try {
LocalProperties.get(getProject()).copy();
thread = Thread.currentThread();
task.perform();
} catch (Throwable t) {


+ 12
- 3
src/main/org/apache/tools/ant/taskdefs/Sequential.java View File

@@ -23,6 +23,8 @@ import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.TaskContainer;

import org.apache.tools.ant.property.LocalProperties;

/**
* Sequential is a container task - it can contain other Ant tasks. The nested
* tasks are simply executed in sequence. Sequential's primary use is to support
@@ -57,9 +59,16 @@ public class Sequential extends Task implements TaskContainer {
* @throws BuildException if one of the nested tasks fails.
*/
public void execute() throws BuildException {
for (Iterator i = nestedTasks.iterator(); i.hasNext();) {
Task nestedTask = (Task) i.next();
nestedTask.perform();
LocalProperties localProperties
= LocalProperties.get(getProject());
localProperties.enterScope();
try {
for (Iterator i = nestedTasks.iterator(); i.hasNext();) {
Task nestedTask = (Task) i.next();
nestedTask.perform();
}
} finally {
localProperties.exitScope();
}
}
}

+ 1
- 0
src/main/org/apache/tools/ant/taskdefs/defaults.properties View File

@@ -61,6 +61,7 @@ length=org.apache.tools.ant.taskdefs.Length
loadfile=org.apache.tools.ant.taskdefs.LoadFile
loadproperties=org.apache.tools.ant.taskdefs.LoadProperties
loadresource=org.apache.tools.ant.taskdefs.LoadResource
local=org.apache.tools.ant.taskdefs.Local
macrodef=org.apache.tools.ant.taskdefs.MacroDef
mail=org.apache.tools.ant.taskdefs.email.EmailTask
manifest=org.apache.tools.ant.taskdefs.ManifestTask


+ 86
- 0
src/tests/antunit/taskdefs/local-test.xml View File

@@ -0,0 +1,86 @@
<?xml version="1.0"?>
<!--
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.
-->
<project default="antunit" xmlns:au="antlib:org.apache.ant.antunit">
<import file="../antunit-base.xml" />

<property name="foo" value="foo" />

<target name="testBaseline">
<au:assertPropertyEquals name="foo" value="foo" />
</target>

<target name="testTarget">
<au:assertPropertyEquals name="foo" value="foo" />
<local name="foo" />
<property name="foo" value="foo.target" />
<au:assertPropertyEquals name="foo" value="foo.target" />
</target>

<target name="testSequential">
<sequential>
<local name="foo" />
<property name="foo" value="foo.1" />
<sequential>
<local name="foo" />
<property name="foo" value="foo.2" />
<au:assertPropertyEquals name="foo" value="foo.2" />
</sequential>
<au:assertPropertyEquals name="foo" value="foo.1" />
</sequential>
<au:assertPropertyEquals name="foo" value="foo" />
</target>

<target name="testParallel">
<macrodef name="p">
<attribute name="value" />
<attribute name="sleep" default="0" />
<sequential>
<local name="foo" />
<sleep seconds="@{sleep}" />
<property name="foo" value="@{value}" />
<au:assertPropertyEquals name="foo" value="@{value}" />
</sequential>
</macrodef>
<parallel>
<p sleep="2" value="foo.a" />
<au:assertPropertyEquals name="foo" value="foo" />
<p sleep="1" value="foo.b" />
<au:assertPropertyEquals name="foo" value="foo" />
<p sleep="0" value="foo.c" />
<au:assertPropertyEquals name="foo" value="foo" />
</parallel>
<au:assertPropertyEquals name="foo" value="foo" />
</target>

<target name="testMacrodef">
<macrodef name="m">
<sequential>
<local name="foo" />
<property name="foo" value="foo.x" />
<au:assertPropertyEquals name="foo" value="foo.x" />
</sequential>
</macrodef>
<m />
<au:assertPropertyEquals name="foo" value="foo" />
<m />
<au:assertPropertyEquals name="foo" value="foo" />
<m />
<au:assertPropertyEquals name="foo" value="foo" />
</target>

</project>

Loading…
Cancel
Save