From 13c833611e42de1bf8e25966d4c6812345866c83 Mon Sep 17 00:00:00 2001 From: Costin Manolache Date: Sun, 14 Jul 2002 01:15:59 +0000 Subject: [PATCH] A small refactoring, getting to a more 'real' interface for the dynamic properties. This is not final, of course. PropertyHelper will implement all property manipulation. Eventually in ant1.6 the static methods in various places should just wrap and call this. In 1.6 the property storage can also be migrated to this class. It should be possible by a task or embedding application to replace the whole mechanism - no need for discovery on this one, it can be done by a task. The PropertyInterceptor will be used to plug different sources for the property. I'm thinking to just have tasks/types implementing this interface automatically get registered - it's the simpler solution for tasks developers ( I think ). git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@273107 13f79535-47bb-0310-9956-ffa450edef68 --- .../sandbox/embed/ProjectHelperImpl2.java | 8 +- proposal/sandbox/embed/PropertyHelper.java | 219 ++++++++++++++++++ .../sandbox/embed/PropertyInterceptor.java | 95 ++++++++ .../sandbox/embed/RuntimeConfigurable2.java | 121 +--------- proposal/sandbox/embed/ant-sax2.jar | Bin 40847 -> 42368 bytes proposal/sandbox/embed/build.xml | 8 + 6 files changed, 330 insertions(+), 121 deletions(-) create mode 100644 proposal/sandbox/embed/PropertyHelper.java create mode 100644 proposal/sandbox/embed/PropertyInterceptor.java 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 7805651226b4291e4138be1ab55227407e7d7fc4..e8ca895837d5eec10e512cb4e48cb7147d1a589e 100644 GIT binary patch delta 10676 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 S{_% + + @@ -16,6 +20,8 @@ destdir="${ant.build}/classes" > + + @@ -28,6 +34,8 @@ + +