diff --git a/proposal/sandbox/embed/ProjectHelperImpl2.java b/proposal/sandbox/embed/ProjectHelperImpl2.java index b72fe3f92..8f86e0d54 100644 --- a/proposal/sandbox/embed/ProjectHelperImpl2.java +++ b/proposal/sandbox/embed/ProjectHelperImpl2.java @@ -129,7 +129,7 @@ public class ProjectHelperImpl2 extends ProjectHelper { ex.printStackTrace(); } } - + /** * Parses the project file, configuring the project as it goes. * @@ -835,7 +835,7 @@ public class ProjectHelperImpl2 extends ProjectHelper { } } else { task.init(); - RuntimeConfigurable2.configure(task, attrs, context.project); + PropertyHelper.getPropertyHelper(context.project).configure(task, attrs, context.project); } } @@ -999,7 +999,7 @@ public class ProjectHelperImpl2 extends ProjectHelper { childWrapper.setAttributes2(attrs); parentWrapper.addChild(childWrapper); } else { - RuntimeConfigurable2.configure(child, attrs, context.project); + PropertyHelper.getPropertyHelper(context.project).configure(child, attrs, context.project); ih.storeElement(context.project, parent, child, elementName); } } catch (BuildException exc) { @@ -1117,7 +1117,7 @@ public class ProjectHelperImpl2 extends ProjectHelper { wrapper.setAttributes2(attrs); target.addDataType(wrapper); } else { - RuntimeConfigurable2.configure(element, attrs, context.project); + PropertyHelper.getPropertyHelper(context.project).configure(element, attrs, context.project); context.configureId(element, attrs); } } catch (BuildException exc) { diff --git a/proposal/sandbox/embed/PropertyHelper.java b/proposal/sandbox/embed/PropertyHelper.java new file mode 100644 index 000000000..47d0e7f46 --- /dev/null +++ b/proposal/sandbox/embed/PropertyHelper.java @@ -0,0 +1,219 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000-2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant; + +import org.apache.tools.ant.helper.*; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; +import java.util.Hashtable; +import org.xml.sax.AttributeList; +import org.xml.sax.Attributes; +import org.xml.sax.helpers.AttributeListImpl; +import org.xml.sax.helpers.AttributesImpl; + +/** + * Deals with properties - substitution, dynamic properties, etc. + * + * Eventually the static methods from ProjectHelper should be + * moved here ( with a wrapper for backward compat ). + * + * Also the property store ( Hashtable ) and all property manipulation + * logic could be moved here. + * + * @author Stefan Bodewig + * @author Costin Manolache + */ +public class PropertyHelper { + Project project; + Vector propertyInterceptors=new Vector(); + + protected PropertyHelper() { + } + + public void setProject(Project p ) { + this.project=p; + } + + /** Factory method to create a property processor. + * Right now returns the singleton instance of PropertyHelper, + * in future it may use discovery of config to return a + * customized version, for integration in other apps. + */ + public static PropertyHelper getPropertyHelper(Project project) { + PropertyHelper ph=(PropertyHelper)project.getReference( "ant.PropertyHelper" ); + if( ph!=null ) return ph; + ph=new PropertyHelper(); + ph.setProject( project ); + + project.addReference( "ant.PropertyHelper",ph ); + return ph; + } + + public void addPropertyInterceptor( PropertyInterceptor pi ) { + propertyInterceptors.addElement( pi ); + } + +// public Vector getPropertyInterceptors() { +// return propertyInterceptors; +// } + + /** Process an value, doing the replacements. + */ + public String replaceProperties( String value ) { + if (value == null) { + return null; + } + + Vector fragments = new Vector(); + Vector propertyRefs = new Vector(); + + // XXX Move the static method here - if this is accepted in the main + // branch. + ProjectHelper.parsePropertyString(value, fragments, propertyRefs); + + StringBuffer sb = new StringBuffer(); + Enumeration i = fragments.elements(); + Enumeration j = propertyRefs.elements(); + while (i.hasMoreElements()) { + + String fragment = (String) i.nextElement(); + if (fragment == null) { + String propertyName = (String) j.nextElement(); + + Object repl=processDynamic( project, propertyName); + + if( repl==null) { + // default to the static property. + repl=project.getProperty( propertyName ); + } + + if (repl==null ) { + project.log("Property ${" + propertyName + + "} has not been set", Project.MSG_VERBOSE); + fragment="${" + propertyName + "}"; + } else { + fragment = (String) repl; + } + } + sb.append(fragment); + } + + return sb.toString(); + } + + /** Use the reference table to generate values for ${} substitution. + * To preserve backward compat ( as much as possible ) we'll only process + * ids with a 'namespace-like' syntax. + * + * Currently we support: + * dom:idName:/xpath/like/syntax - the referenced node must be a DOM, we'll use + * XPath to extract a node. ( a simplified syntax is handled + * directly, XXX used for 'real' xpaths ). + * toString:idName - we use toString on the referenced object + * bean:idName.propertyName - we get the idName and call the getter for the property. + */ + Object processDynamic( Project project, String name ) { + for(int i=0; i. + */ + +package org.apache.tools.ant; + +import org.apache.tools.ant.helper.*; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; +import java.util.Hashtable; +import org.xml.sax.AttributeList; +import org.xml.sax.Attributes; +import org.xml.sax.helpers.AttributeListImpl; +import org.xml.sax.helpers.AttributesImpl; + +/** + * The new XML processor will use this interface to support + * dynamic properties. + * + * Any task/type that implements this interface will be registered + * and will receive notification of each property get operations + * executed by the processor. + * + * XXX In ant1.6+, tasks implementing the interface will also + * receive notification when a property is set. + * + * @author Costin Manolache + */ +public interface PropertyInterceptor { + + /** + * Called for each ${} property. If the result is null the + * next PropertyInterceptor will be called. If all interceptors + * return null, the properties stored in Project are used. + */ + public Object getProperty( Project p, String ns, String name ); + + /** + * Called when a property/reference is recorded. + * XXX Not implemented yet. + */ + // public boolean setProperty( String ns, String name, Object value ); + +} diff --git a/proposal/sandbox/embed/RuntimeConfigurable2.java b/proposal/sandbox/embed/RuntimeConfigurable2.java index 1e594d1cc..89540823e 100644 --- a/proposal/sandbox/embed/RuntimeConfigurable2.java +++ b/proposal/sandbox/embed/RuntimeConfigurable2.java @@ -176,7 +176,7 @@ public class RuntimeConfigurable2 extends RuntimeConfigurable { * @return The child wrapper at position index within the * list. */ - RuntimeConfigurable getChild(int index) { + public RuntimeConfigurable getChild(int index) { return (RuntimeConfigurable) children.elementAt(index); } @@ -234,7 +234,8 @@ public class RuntimeConfigurable2 extends RuntimeConfigurable { String id = null; if (attributes != null) { - configure(wrappedObject, attributes, p); + PropertyHelper ph=PropertyHelper.getPropertyHelper(p); + ph.configure(wrappedObject, attributes, p); id = attributes.getValue("id"); attributes = null; } @@ -255,125 +256,11 @@ public class RuntimeConfigurable2 extends RuntimeConfigurable { child.maybeConfigure(p); } ProjectHelper.storeChild(p, wrappedObject, child.wrappedObject, - child.getElementTag().toLowerCase(Locale.US)); + child.getElementTag().toLowerCase(Locale.US)); } if (id != null) { p.addReference(id, wrappedObject); } } - - - public static void configure( Object target, Attributes attrs, Project project ) - throws BuildException - { - if (target instanceof TaskAdapter) { - target = ((TaskAdapter) target).getProxy(); - } - - IntrospectionHelper ih = - IntrospectionHelper.getHelper(target.getClass()); - - project.addBuildListener(ih); - - for (int i = 0; i < attrs.getLength(); i++) { - // reflect these into the target - String value = RuntimeConfigurable2.replaceProperties(project, attrs.getValue(i)); - - try { - ih.setAttribute(project, target, - attrs.getQName(i).toLowerCase(Locale.US), value); - } catch (BuildException be) { - // id attribute must be set externally - if (!attrs.getQName(i).equals("id")) { - throw be; - } - } - } - } - - public static String replaceProperties( Project project ,String value ) { - if (value == null) { - return null; - } - - Vector fragments = new Vector(); - Vector propertyRefs = new Vector(); - - ProjectHelper.parsePropertyString(value, fragments, propertyRefs); - - StringBuffer sb = new StringBuffer(); - Enumeration i = fragments.elements(); - Enumeration j = propertyRefs.elements(); - while (i.hasMoreElements()) { - - String fragment = (String) i.nextElement(); - if (fragment == null) { - String propertyName = (String) j.nextElement(); - Object repl=project.getProperty( propertyName ); - - if( repl==null) { - // Try a dynamic substitiution using ref - repl=processReference( project, propertyName ); - } - - if (repl==null ) { - project.log("Property ${" + propertyName - + "} has not been set", Project.MSG_VERBOSE); - fragment="${" + propertyName + "}"; - } else { - fragment = (String) repl; - } - } - sb.append(fragment); - } - - return sb.toString(); - - } - - static Hashtable propertySources=new Hashtable(); - - public static interface ProjectPropertySource { - - public String getProperty( Project project, String key ); - - } - - public static void addPropertySource( String ns, ProjectPropertySource src ) { - propertySources.put( ns, src ); - } - - - /** Use the reference table to generate values for ${} substitution. - * To preserve backward compat ( as much as possible ) we'll only process - * ids with a 'namespace-like' syntax. - * - * Currently we support: - * dom:idName:/xpath/like/syntax - the referenced node must be a DOM, we'll use - * XPath to extract a node. ( a simplified syntax is handled - * directly, XXX used for 'real' xpaths ). - * toString:idName - we use toString on the referenced object - * bean:idName.propertyName - we get the idName and call the getter for the property. - */ - static String processReference( Project project, String name ) { - if( name.startsWith( "toString:" )) { - name=name.substring( "toString:".length()); - Object v=project.getReference( name ); - if( v==null ) return null; - return v.toString(); - } - - int idx=name.indexOf(":"); - if( idx<0 ) return null; - - String ns=name.substring( 0, idx ); - String path=name.substring( idx ); - - ProjectPropertySource ps=(ProjectPropertySource)propertySources.get( ns ); - if( ps == null ) - return null; - - return ps.getProperty( project, path ); - } } diff --git a/proposal/sandbox/embed/ant-sax2.jar b/proposal/sandbox/embed/ant-sax2.jar index 780565122..e8ca89583 100644 Binary files a/proposal/sandbox/embed/ant-sax2.jar and b/proposal/sandbox/embed/ant-sax2.jar differ diff --git a/proposal/sandbox/embed/build.xml b/proposal/sandbox/embed/build.xml index 3fcebe6a8..7c391694a 100644 --- a/proposal/sandbox/embed/build.xml +++ b/proposal/sandbox/embed/build.xml @@ -8,6 +8,10 @@ todir="${ant.src}/src/main/org/apache/tools/ant/helper" /> + + @@ -16,6 +20,8 @@ destdir="${ant.build}/classes" > + + @@ -28,6 +34,8 @@ + +