View | Details | Raw Unified | Return to bug 53723
Collapse All | Expand All

(-)src/main/org/apache/tools/ant/taskdefs/Local.java (-17 / +55 lines)
Lines 17-22 Link Here
17
 */
17
 */
18
package org.apache.tools.ant.taskdefs;
18
package org.apache.tools.ant.taskdefs;
19
19
20
import org.apache.maven.artifact.resolver.WarningResolutionListener;
20
import org.apache.tools.ant.BuildException;
21
import org.apache.tools.ant.BuildException;
21
import org.apache.tools.ant.Task;
22
import org.apache.tools.ant.Task;
22
import org.apache.tools.ant.property.LocalProperties;
23
import org.apache.tools.ant.property.LocalProperties;
Lines 25-47 Link Here
25
 * Task to create a local property in the current scope.
26
 * Task to create a local property in the current scope.
26
 */
27
 */
27
public class Local extends Task {
28
public class Local extends Task {
28
    private String name;
29
	private String name;
30
	private String prefix;
31
32
	/**
33
	 * Set the name attribute.
34
	 * 
35
	 * @param name
36
	 *            the name of the local property.
37
	 */
38
	public void setName(String name) {
39
		checkAlreadyConfigured();
40
		this.name = name;
41
	}
29
42
30
    /**
43
	/**
31
     * Set the name attribute.
44
	 * Set the prefix attribute.
32
     * @param name the name of the local property.
45
	 * 
33
     */
46
	 * @param name
34
    public void setName(String name) {
47
	 *            the prefix to detect a local property. Must not be an empty
35
        this.name = name;
48
	 *            string
36
    }
49
	 */
50
	public void setPrefix(String prefix) {
51
		checkAlreadyConfigured();
52
		if (prefix != null) {
53
			if (prefix.length() == 0) {
54
				throw new BuildException("Empty prefix not supported");
55
			} else if (!prefix.endsWith(".")) {
56
				prefix = prefix + ".";
57
			}
58
		}
59
		this.prefix = prefix;
60
	}
37
61
38
    /**
62
	/**
39
     * Run the task.
63
	 * Throw a BuildException if already one attribute was set.
40
     */
64
	 */
41
    public void execute() {
65
	private void checkAlreadyConfigured() {
42
        if (name == null) {
66
		if (name != null || prefix != null) {
43
            throw new BuildException("Missing attribute name");
67
			throw new BuildException(
44
        }
68
					"Only one of the attributes name or prefix is allowed");
45
        LocalProperties.get(getProject()).addLocal(name);
69
		}
46
    }
70
71
	}
72
73
	/**
74
	 * Run the task.
75
	 */
76
	public void execute() {
77
		if (name != null) {
78
			LocalProperties.get(getProject()).addLocal(name);
79
		} else if (prefix != null) {
80
			LocalProperties.get(getProject()).addLocalPrefix(prefix);
81
		} else {
82
			LocalProperties.get(getProject()).setAllLocal();
83
		} 
84
	}
47
}
85
}
(-)src/main/org/apache/tools/ant/taskdefs/Global.java (+87 lines)
Line 0 Link Here
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;
19
20
import org.apache.tools.ant.BuildException;
21
import org.apache.tools.ant.Task;
22
import org.apache.tools.ant.property.LocalProperties;
23
24
/**
25
 * Task to create a global property in the current scope. 
26
 * 
27
 * Only useful after visibility was restricted with the local task with the 
28
 * attributes prefix or all.
29
 */
30
public class Global extends Task {
31
	private String name;
32
	private String prefix;
33
34
	/**
35
	 * Set the name attribute.
36
	 * 
37
	 * @param name
38
	 *            the name of the global property.
39
	 */
40
	public void setName(String name) {
41
    	checkAlreadyConfigured();
42
        this.name = name;
43
    }
44
45
	/**
46
	 * Set the prefix attribute.
47
	 * 
48
	 * @param name
49
	 *            the prefix to detect a global property.
50
	 */
51
	public void setPrefix(String prefix) {
52
    	checkAlreadyConfigured();
53
		if (prefix != null) {
54
			if (prefix.length() == 0) {
55
				throw new BuildException("Empty prefix not supported");
56
			} else if (!prefix.endsWith(".")) {
57
				prefix = prefix + ".";
58
			}
59
		}
60
		this.prefix = prefix;
61
	}
62
63
	/**
64
	 * Throw a BuildException if already one attribute was set.
65
	 */
66
	private void checkAlreadyConfigured() {
67
		if (name != null || prefix != null) {
68
			throw new BuildException(
69
					"Only one of the attributes name or prefix is allowed");
70
		}
71
72
	}
73
74
	/**
75
	 * Run the task.
76
	 */
77
	public void execute() {
78
		if (name != null) {
79
			LocalProperties.get(getProject()).addGlobal(name);
80
		} else if (prefix != null) {
81
			LocalProperties.get(getProject()).addGlobalPrefix(prefix);
82
		}
83
		else {
84
			throw new BuildException("Missing attribute. Either attribute name or prefix must be set");
85
		}
86
	}
87
}
(-)src/main/org/apache/tools/ant/taskdefs/defaults.properties (+1 lines)
Lines 56-61 Link Here
56
#funtest=org.apache.tools.ant.taskdefs.optional.testing.Funtest
56
#funtest=org.apache.tools.ant.taskdefs.optional.testing.Funtest
57
genkey=org.apache.tools.ant.taskdefs.GenerateKey
57
genkey=org.apache.tools.ant.taskdefs.GenerateKey
58
get=org.apache.tools.ant.taskdefs.Get
58
get=org.apache.tools.ant.taskdefs.Get
59
global=org.apache.tools.ant.taskdefs.Global
59
gunzip=org.apache.tools.ant.taskdefs.GUnzip
60
gunzip=org.apache.tools.ant.taskdefs.GUnzip
60
gzip=org.apache.tools.ant.taskdefs.GZip
61
gzip=org.apache.tools.ant.taskdefs.GZip
61
hostinfo=org.apache.tools.ant.taskdefs.HostInfo
62
hostinfo=org.apache.tools.ant.taskdefs.HostInfo
(-)src/main/org/apache/tools/ant/property/LocalPropertyStack.java (-38 / +190 lines)
Lines 17-51 Link Here
17
 */
17
 */
18
package org.apache.tools.ant.property;
18
package org.apache.tools.ant.property;
19
19
20
21
import java.util.LinkedList;
22
import java.util.HashMap;
20
import java.util.HashMap;
21
import java.util.HashSet;
23
import java.util.Iterator;
22
import java.util.Iterator;
23
import java.util.LinkedList;
24
import java.util.Map;
24
import java.util.Map;
25
import java.util.Set;
25
26
26
import org.apache.tools.ant.PropertyHelper;
27
import org.apache.tools.ant.PropertyHelper;
27
28
28
/**
29
/**
29
 * A stack of local property maps.
30
 * A stack of local property maps. There is a map for each scope (target,
30
 * There is a map for each scope (target, sequential, macro).
31
 * sequential, macro).
32
 * 
31
 * @since Ant 1.8.0
33
 * @since Ant 1.8.0
32
 */
34
 */
33
public class LocalPropertyStack {
35
public class LocalPropertyStack {
34
    private LinkedList stack = new LinkedList();
36
37
    /**
38
     * An entry in the property stack.
39
     */
40
    private static class StackEntry {
41
        /** Map of local properties. */
42
        private Map<String, Object> propertyMap;
43
        /**
44
         * Set of local prefixes. All variables with such a prefix are local.
45
         */
46
        private Set<String> localPrefixSet;
47
        /** If true, all properties in the current scope are local. */
48
        private boolean allLocal;
49
        /**
50
         * Properties named in this set are not local to this scope, even if
51
         * they are named in propertyMap or have a prefix contained in
52
         * localPrefixSet or allLocal is set.
53
         */
54
        private Set<String> globalProperties;
55
        /**
56
         * Properties with a prefix contained in this set are not local to this
57
         * scope, even if they are named in propertyMap or have a prefix
58
         * contained in localPrefixSet or allLocal is set.
59
         */
60
        private Set<String> globalPrefixSet;
61
62
        private StackEntry() {
63
            propertyMap = new HashMap<String, Object>();
64
            localPrefixSet = new HashSet<String>();
65
            globalProperties = new HashSet<String>();
66
            globalPrefixSet = new HashSet<String>();
67
        }
68
69
        private void clear() {
70
            propertyMap.clear();
71
            localPrefixSet.clear();
72
            globalPrefixSet.clear();
73
            globalProperties.clear();
74
            propertyMap = null;
75
            localPrefixSet = null;
76
            globalPrefixSet = null;
77
            globalProperties = null;
78
        }
79
80
        /**
81
         * Determine if the given property is local to this scope.
82
         * 
83
         * @param property
84
         *            property name to check
85
         * @return true if it is local, else false
86
         */
87
        private boolean isLocalProperty(String property) {
88
            if (globalProperties.contains(property)) {
89
                return false;
90
            }
91
            for (Iterator<String> prefixIter = globalPrefixSet.iterator(); prefixIter
92
                    .hasNext();) {
93
                if (property.startsWith(prefixIter.next())) {
94
                    return false;
95
                }
96
            }
97
98
            if (allLocal) {
99
                return true;
100
            }
101
            if (propertyMap.get(property) != null) {
102
                return true;
103
            }
104
            for (Iterator<String> prefixIter = localPrefixSet.iterator(); prefixIter
105
                    .hasNext();) {
106
                if (property.startsWith(prefixIter.next())) {
107
                    return true;
108
                }
109
            }
110
111
            return false;
112
        }
113
114
    }
115
116
    private LinkedList<StackEntry> stack = new LinkedList<StackEntry>();
35
117
36
    // --------------------------------------------------
118
    // --------------------------------------------------
37
    //
119
    //
38
    //  Local property adding and scoping
120
    // Local property adding and scoping
39
    //
121
    //
40
    // --------------------------------------------------
122
    // --------------------------------------------------
41
123
42
    /**
124
    /**
43
     * Add a local property.
125
     * Add a local property.
44
     * @param property the name of the local property.
126
     * 
127
     * @param property
128
     *            the name of the local property.
45
     */
129
     */
46
    public void addLocal(String property) {
130
    public void addLocal(String property) {
47
        if (!stack.isEmpty()) {
131
        if (!stack.isEmpty()) {
48
            ((Map) stack.getFirst()).put(property, NullReturn.NULL);
132
            stack.getFirst().propertyMap.put(property, NullReturn.NULL);
133
        }
134
    }
135
136
    /**
137
     * Add a local prefix. All properties with this prefix are handled as local
138
     * property.
139
     * 
140
     * @param prefix
141
     *            the prefix to detect a local property.
142
     */
143
    public void addLocalPrefix(String prefix) {
144
        if (!stack.isEmpty()) {
145
            stack.getFirst().localPrefixSet.add(prefix);
146
        }
147
    }
148
149
    /**
150
     * Set all properties in the current scope as local.
151
     */
152
    public void setAllLocal() {
153
        if (!stack.isEmpty()) {
154
            stack.getFirst().allLocal = true;
155
        }
156
    }
157
158
    /**
159
     * Add a global property.
160
     * 
161
     * This is useful if the visibility of properties were restricted with
162
     * {@link #addLocalPrefix(String)} or {@link #setAllLocal()} but a certain
163
     * property should be global.
164
     * 
165
     * @param property
166
     *            the name of the global property.
167
     */
168
    public void addGlobal(String property) {
169
        if (!stack.isEmpty()) {
170
            stack.getFirst().globalProperties.add(property);
171
        }
172
    }
173
174
    /**
175
     * Add a global prefix.
176
     * 
177
     * This is useful if the visibility of properties were restricted with
178
     * {@link #setAllLocal()} but properties with the given prefix should be
179
     * global.
180
     * 
181
     * @param prefix
182
     *            the prefix to detect a global property.
183
     */
184
    public void addGlobalPrefix(String prefix) {
185
        if (!stack.isEmpty()) {
186
            stack.getFirst().globalPrefixSet.add(prefix);
49
        }
187
        }
50
    }
188
    }
51
189
Lines 53-76 Link Here
53
     * Enter the local scope.
191
     * Enter the local scope.
54
     */
192
     */
55
    public void enterScope() {
193
    public void enterScope() {
56
        stack.addFirst(new HashMap());
194
        stack.addFirst(new StackEntry());
57
    }
195
    }
58
196
59
    /**
197
    /**
60
     * Exit the local scope.
198
     * Exit the local scope.
61
     */
199
     */
62
    public void exitScope() {
200
    public void exitScope() {
63
        ((HashMap) stack.removeFirst()).clear();
201
        ((StackEntry) stack.removeFirst()).clear();
64
    }
202
    }
65
203
66
    // --------------------------------------------------
204
    // --------------------------------------------------
67
    //
205
    //
68
    //  Copy - used in parallel to make a new stack
206
    // Copy - used in parallel to make a new stack
69
    //
207
    //
70
    // --------------------------------------------------
208
    // --------------------------------------------------
71
209
72
    /**
210
    /**
73
     * Copy the stack for a parallel thread.
211
     * Copy the stack for a parallel thread.
212
     * 
74
     * @return a copy.
213
     * @return a copy.
75
     */
214
     */
76
    public LocalPropertyStack copy() {
215
    public LocalPropertyStack copy() {
Lines 81-122 Link Here
81
220
82
    // --------------------------------------------------
221
    // --------------------------------------------------
83
    //
222
    //
84
    //  PropertyHelper delegate methods
223
    // PropertyHelper delegate methods
85
    //
224
    //
86
    // --------------------------------------------------
225
    // --------------------------------------------------
87
226
88
    /**
227
    /**
89
     * Evaluate a property.
228
     * Evaluate a property.
90
     * @param property the property's String "identifier".
229
     * 
91
     * @param helper the invoking PropertyHelper.
230
     * @param property
231
     *            the property's String "identifier".
232
     * @param helper
233
     *            the invoking PropertyHelper.
92
     * @return Object value.
234
     * @return Object value.
93
     */
235
     */
94
    public Object evaluate(String property, PropertyHelper helper) {
236
    public Object evaluate(String property, PropertyHelper helper) {
95
        for (Iterator i = stack.iterator(); i.hasNext();) {
237
        Map<String, Object> map = getMapForProperty(property);
96
            Map map = (Map) i.next();
238
        if (map == null) {
97
            Object ret = map.get(property);
239
            return null;
98
            if (ret != null) {
240
        }
99
                return ret;
241
        Object ret = map.get(property);
100
            }
242
        if (ret != null) {
243
            // Note: NullReturn.NULL is handled on upper level.
244
            return ret;
101
        }
245
        }
102
        return null;
246
        return null;
103
    }
247
    }
104
248
105
    /**
249
    /**
106
     * Set a *new" property.
250
     * Set a *new" property.
107
     * @param property the property's String "identifier".
251
     * 
108
     * @param value    the value to set.
252
     * @param property
109
     * @param propertyHelper the invoking PropertyHelper.
253
     *            the property's String "identifier".
254
     * @param value
255
     *            the value to set.
256
     * @param propertyHelper
257
     *            the invoking PropertyHelper.
110
     * @return true if this entity 'owns' the property.
258
     * @return true if this entity 'owns' the property.
111
     */
259
     */
112
    public boolean setNew(
260
    public boolean setNew(String property, Object value,
113
        String property, Object value, PropertyHelper propertyHelper) {
261
            PropertyHelper propertyHelper) {
114
        Map map = getMapForProperty(property);
262
        Map<String, Object> map = getMapForProperty(property);
115
        if (map == null) {
263
        if (map == null) {
116
            return false;
264
            return false;
117
        }
265
        }
118
        Object currValue = map.get(property);
266
        Object currValue = map.get(property);
119
        if (currValue == NullReturn.NULL) {
267
        if (currValue == NullReturn.NULL || !map.containsKey(property)) {
120
            map.put(property, value);
268
            map.put(property, value);
121
        }
269
        }
122
        return true;
270
        return true;
Lines 124-136 Link Here
124
272
125
    /**
273
    /**
126
     * Set a property.
274
     * Set a property.
127
     * @param property the property's String "identifier".
275
     * 
128
     * @param value    the value to set.
276
     * @param property
129
     * @param propertyHelper the invoking PropertyHelper.
277
     *            the property's String "identifier".
278
     * @param value
279
     *            the value to set.
280
     * @param propertyHelper
281
     *            the invoking PropertyHelper.
130
     * @return true if this entity 'owns' the property.
282
     * @return true if this entity 'owns' the property.
131
     */
283
     */
132
    public boolean set(String property, Object value, PropertyHelper propertyHelper) {
284
    public boolean set(String property, Object value,
133
        Map map = getMapForProperty(property);
285
            PropertyHelper propertyHelper) {
286
        Map<String, Object> map = getMapForProperty(property);
134
        if (map == null) {
287
        if (map == null) {
135
            return false;
288
            return false;
136
        }
289
        }
Lines 138-151 Link Here
138
        return true;
291
        return true;
139
    }
292
    }
140
293
141
    private Map getMapForProperty(String property) {
294
    private Map<String, Object> getMapForProperty(String property) {
142
        for (Iterator i = stack.iterator(); i.hasNext();) {
295
        for (Iterator<StackEntry> i = stack.iterator(); i.hasNext();) {
143
            Map map = (Map) i.next();
296
            StackEntry se = i.next();
144
            if (map.get(property) != null) {
297
            if (se.isLocalProperty(property)) {
145
                return map;
298
                return se.propertyMap;
146
            }
299
            }
147
        }
300
        }
148
        return null;
301
        return null;
149
    }
302
    }
150
}
303
}
151
(-)src/main/org/apache/tools/ant/property/LocalProperties.java (-2 / +34 lines)
Lines 26-32 Link Here
26
 * @since Ant 1.8.0
26
 * @since Ant 1.8.0
27
 */
27
 */
28
public class LocalProperties
28
public class LocalProperties
29
    extends InheritableThreadLocal
29
    extends InheritableThreadLocal<LocalPropertyStack>
30
    implements PropertyHelper.PropertyEvaluator,
30
    implements PropertyHelper.PropertyEvaluator,
31
    PropertyHelper.PropertySetter {
31
    PropertyHelper.PropertySetter {
32
32
Lines 62-68 Link Here
62
     * Get the initial value.
62
     * Get the initial value.
63
     * @return a new localproperties stack.
63
     * @return a new localproperties stack.
64
     */
64
     */
65
    protected synchronized Object initialValue() {
65
    protected synchronized LocalPropertyStack initialValue() {
66
        return new LocalPropertyStack();
66
        return new LocalPropertyStack();
67
    }
67
    }
68
68
Lines 84-89 Link Here
84
        current().addLocal(property);
84
        current().addLocal(property);
85
    }
85
    }
86
86
87
    /**
88
     * Add a local prefix to the current scope.
89
     * @param prefix the prefix to add.
90
     */
91
    public void addLocalPrefix(String prefix) {
92
        current().addLocalPrefix(prefix);
93
    }
94
95
    /**
96
     * Add a local prefix to the current scope.
97
     * @param property the prefix to add.
98
     */
99
    public void setAllLocal() {
100
        current().setAllLocal();
101
    }
102
103
    /**
104
     * Add a global property to the current scope.
105
     * @param property the property name to add.
106
     */
107
    public void addGlobal(String property) {
108
        current().addGlobal(property);
109
    }
110
111
    /**
112
     * Add a global prefix to the current scope.
113
     * @param property the prefix to add.
114
     */
115
    public void addGlobalPrefix(String prefix) {
116
        current().addGlobalPrefix(prefix);
117
    }
118
87
    /** enter the scope */
119
    /** enter the scope */
88
    public void enterScope() {
120
    public void enterScope() {
89
        current().enterScope();
121
        current().enterScope();
(-)src/tests/antunit/taskdefs/local-test.xml (+105 lines)
Lines 19-24 Link Here
19
  <import file="../antunit-base.xml" />
19
  <import file="../antunit-base.xml" />
20
20
21
  <property name="foo" value="foo" />
21
  <property name="foo" value="foo" />
22
  <property name="prefix.foo" value="prefix.foo" />
22
23
23
  <local name="bar" />
24
  <local name="bar" />
24
  <property name="bar" value="bar" />
25
  <property name="bar" value="bar" />
Lines 93-96 Link Here
93
    <au:assertPropertyEquals name="foo" value="foo" />
94
    <au:assertPropertyEquals name="foo" value="foo" />
94
  </target>
95
  </target>
95
96
97
  <target name="testLocalPrefix">
98
    <sequential>
99
      <local prefix="prefix" />
100
      <property name="prefix.foo" value="foo.1" />
101
      <sequential>
102
        <local prefix="prefix" />
103
        <property name="prefix.foo" value="foo.2" />
104
        <au:assertPropertyEquals name="prefix.foo" value="foo.2" />
105
      </sequential>
106
      <au:assertPropertyEquals name="prefix.foo" value="foo.1" />
107
    </sequential>
108
    <au:assertPropertyEquals name="prefix.foo" value="prefix.foo" />
109
  </target>
110
111
  <target name="testAllLocal">
112
    <sequential>
113
      <local name="foo" />
114
      <property name="foo" value="foo.1" />
115
      <sequential>
116
        <local />
117
        <property name="foo" value="foo.2" />
118
        <au:assertPropertyEquals name="foo" value="foo.2" />
119
      </sequential>
120
      <au:assertPropertyEquals name="foo" value="foo.1" />
121
    </sequential>
122
    <au:assertPropertyEquals name="foo" value="foo" />
123
  </target>
124
125
  <target name="testGlobal">
126
    <sequential>
127
      <local name="foo" />
128
      <property name="foo" value="foo.1" />
129
      <sequential>
130
        <local />
131
        <global name="gFoo" />
132
        <property name="foo" value="foo.2" />
133
        <property name="gFoo" value="global" />
134
        <au:assertPropertyEquals name="foo" value="foo.2" />
135
      </sequential>
136
      <au:assertPropertyEquals name="foo" value="foo.1" />
137
    </sequential>
138
    <au:assertPropertyEquals name="foo" value="foo" />
139
    <au:assertPropertyEquals name="gFoo" value="global" />
140
  </target>
141
142
  <target name="testGlobalPrefix">
143
    <sequential>
144
      <local name="foo" />
145
      <property name="foo" value="foo.1" />
146
      <sequential>
147
        <local />
148
        <global prefix="global" />
149
        <property name="foo" value="foo.2" />
150
        <property name="global.foo" value="global" />
151
        <au:assertPropertyEquals name="foo" value="foo.2" />
152
      </sequential>
153
      <au:assertPropertyEquals name="foo" value="foo.1" />
154
    </sequential>
155
    <au:assertPropertyEquals name="foo" value="foo" />
156
    <au:assertPropertyEquals name="global.foo" value="global" />
157
  </target>
158
159
  <target name="testLocalAttributes">
160
    <au:expectfailure expectedMessage="Only one of the attributes name or prefix is allowed">
161
      <local name="name" prefix="prefix" />
162
    </au:expectfailure>
163
    <au:expectfailure expectedMessage="Empty prefix not supported">
164
      <local prefix="" />
165
    </au:expectfailure>
166
  </target>
167
168
  <target name="testGlobalAttributes">
169
    <au:expectfailure expectedMessage="Only one of the attributes name or prefix is allowed">
170
      <global name="name" prefix="prefix" />
171
    </au:expectfailure>
172
    <au:expectfailure expectedMessage="Empty prefix not supported">
173
      <global prefix="" />
174
    </au:expectfailure>
175
    <au:expectfailure expectedMessage="Missing attribute. Either attribute name or prefix must be set">
176
      <global />
177
    </au:expectfailure>
178
  </target>
179
180
  <target name="testStrangeUsage">
181
    <sequential>
182
      <local name="strange" />
183
      <property name="strange" value="bar" />
184
      <au:assertPropertyEquals name="strange" value="bar" />
185
      <global name="strange" />
186
      <au:assertTrue message="Property 'strange' should not be set.">
187
        <not>
188
          <isset property="strange" />
189
        </not>
190
      </au:assertTrue>
191
      <property name="strange" value="bar2" />
192
      <au:assertPropertyEquals name="strange" value="bar2" />
193
      <local name="strange" />
194
      <au:assertPropertyEquals name="strange" value="bar2" />
195
    </sequential>
196
    <au:assertPropertyEquals name="strange" value="bar2" />
197
  </target>
198
199
200
96
</project>
201
</project>

Return to bug 53723