Browse Source

Remove the ProjectHelper proposal.

The SAX2 helper remains here - I want to do few more improvement and to
keep it in sync with my next proposal ( for TaskFactory )

I'll make a separate proposal for the SAX2 ProjectHelper when it's ready -
it doesn't have to be part of the official ant1.5 ( since we'll need
more discussion/experiments to decide what's the best use of the namespaces )


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271782 13f79535-47bb-0310-9956-ffa450edef68
master
Costin Manolache 23 years ago
parent
commit
51ac64b16c
2 changed files with 0 additions and 1654 deletions
  1. +0
    -485
      proposal/sandbox/embed/ProjectHelper.java
  2. +0
    -1169
      proposal/sandbox/embed/ProjectHelperImpl.java

+ 0
- 485
proposal/sandbox/embed/ProjectHelper.java View File

@@ -1,485 +0,0 @@
/*
* 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
* <http://www.apache.org/>.
*/

package org.apache.tools.ant;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
import java.util.Locale;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.xml.sax.AttributeList;
import org.apache.tools.ant.helper.ProjectHelperImpl;

/**
* Configures a Project (complete with Targets and Tasks) based on
* a XML build file. It'll rely on a plugin to do the actual processing
* of the xml file.
*
* This class also provide static wrappers for common introspection.
*
* All helper plugins must provide backward compatiblity with the
* original ant patterns, unless a different behavior is explicitely
* specified. For example, if namespace is used on the <project> tag
* the helper can expect the entire build file to be namespace-enabled.
* Namespaces or helper-specific tags can provide meta-information to
* the helper, allowing it to use new ( or different policies ).
*
* However, if no namespace is used the behavior should be exactly
* identical with the default helper.
*
* @author duncan@x180.com
*/
public class ProjectHelper {

/**
* Configures the project with the contents of the specified XML file.
*
* @param project The project to configure. Must not be <code>null</code>.
* @param buildFile An XML file giving the project's configuration.
* Must not be <code>null</code>.
*
* @exception BuildException if the configuration is invalid or cannot
* be read
*/
public static void configureProject(Project project, File buildFile) throws BuildException {
ProjectHelper helper=ProjectHelper.getProjectHelper();
helper.parse(project, buildFile);
}

public ProjectHelper() {
}

/**
* Parses the project file, configuring the project as it goes.
*
* @param project The project for the resulting ProjectHelper to configure.
* Must not be <code>null</code>.
* @param source The source for XML configuration. A helper must support
* at least File, for backward compatibility. Helpers may
* support URL, InputStream, etc or specialized types.
*
* @since Ant1.5
* @exception BuildException if the configuration is invalid or cannot
* be read
*/
public void parse(Project project, Object source) throws BuildException {
throw new BuildException("ProjectHelper.parse() must be implemented in a helper plugin "
+ this.getClass().getName());
}

/* -------------------- Helper discovery -------------------- */
public static final String HELPER_PROPERTY =
"org.apache.tools.ant.ProjectHelper";
public static final String SERVICE_ID =
"/META-INF/services/org.apache.tools.ant.ProjectHelper";

/** Discover a project helper instance. Uses the same patterns
* as JAXP, commons-logging, etc: a system property, a JDK1.3
* service discovery, default.
*/
public static ProjectHelper getProjectHelper()
throws BuildException
{
// Identify the class loader we will be using. Ant may be
// in a webapp or embeded in a different app
ProjectHelper helper=null;
// First, try the system property
try {
String helperClass = System.getProperty(HELPER_PROPERTY);
if (helperClass != null) {
helper = newHelper(helperClass);
}
} catch (SecurityException e) {
// It's ok, we'll try next option
;
}

// A JDK1.3 'service' ( like in JAXP ). That will plug a helper
// automatically if in CLASSPATH, with the right META-INF/services.
if( helper==null ) {
try {
ClassLoader classLoader=getContextClassLoader();
InputStream is=null;
if (classLoader != null) {
is=classLoader.getResourceAsStream( SERVICE_ID );
}
if( is==null ) {
is=ClassLoader.getSystemResourceAsStream( SERVICE_ID );
}
if( is != null ) {
// This code is needed by EBCDIC and other strange systems.
// It's a fix for bugs reported in xerces
BufferedReader rd;
try {
rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
} catch (java.io.UnsupportedEncodingException e) {
rd = new BufferedReader(new InputStreamReader(is));
}
String helperClassName = rd.readLine();
rd.close();
if (helperClassName != null &&
! "".equals(helperClassName)) {
helper= newHelper( helperClassName );
}
}
} catch( Exception ex ) {
;
}
}

// Default
return new ProjectHelperImpl();
}

/** Create a new helper. It'll first try the thread class loader,
* then Class.forName() will load from the same loader that
* loaded this class.
*/
private static ProjectHelper newHelper(String helperClass)
throws BuildException
{
ClassLoader classLoader = getContextClassLoader();
try {
Class clazz = null;
if (classLoader != null) {
try {
clazz = classLoader.loadClass(helperClass);
} catch( ClassNotFoundException ex ) {
// try next method
}
}
if( clazz==null ) {
clazz = Class.forName(helperClass);
}
return ((ProjectHelper) clazz.newInstance());
} catch (Exception e) {
throw new BuildException(e);
}
}

/**
* JDK1.1 compatible access to the context class loader.
* Cut&paste from Jaxp.
*/
public static ClassLoader getContextClassLoader()
throws BuildException
{
// Are we running on a JDK 1.2 or later system?
Method method = null;
try {
method = Thread.class.getMethod("getContextClassLoader", null);
} catch (NoSuchMethodException e) {
// we are running on JDK 1.1
return null;
}

// Get the thread context class loader (if there is one)
ClassLoader classLoader = null;
try {
classLoader = (ClassLoader)
method.invoke(Thread.currentThread(), null);
} catch (IllegalAccessException e) {
throw new BuildException
("Unexpected IllegalAccessException", e);
} catch (InvocationTargetException e) {
throw new BuildException
("Unexpected InvocationTargetException", e);
}

// Return the selected class loader
return (classLoader);
}

// -------------------- Static utils, used by most helpers --------------------

/**
* Configures an object using an introspection handler.
*
* @param target The target object to be configured.
* Must not be <code>null</code>.
* @param attrs A list of attributes to configure within the target.
* Must not be <code>null</code>.
* @param project The project containing the target.
* Must not be <code>null</code>.
*
* @exception BuildException if any of the attributes can't be handled by
* the target
*/
public static void configure(Object target, AttributeList 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=replaceProperties(project, attrs.getValue(i),
project.getProperties() );
try {
ih.setAttribute(project, target,
attrs.getName(i).toLowerCase(Locale.US), value);

} catch (BuildException be) {
// id attribute must be set externally
if (!attrs.getName(i).equals("id")) {
throw be;
}
}
}
}

/**
* Adds the content of #PCDATA sections to an element.
*
* @param project The project containing the target.
* Must not be <code>null</code>.
* @param target The target object to be configured.
* Must not be <code>null</code>.
* @param buf A character array of the text within the element.
* Will not be <code>null</code>.
* @param start The start element in the array.
* @param count The number of characters to read from the array.
*
* @exception BuildException if the target object doesn't accept text
*/
public static void addText(Project project, Object target, char[] buf, int start, int count)
throws BuildException {
addText(project, target, new String(buf, start, count));
}

/**
* Adds the content of #PCDATA sections to an element.
*
* @param project The project containing the target.
* Must not be <code>null</code>.
* @param target The target object to be configured.
* Must not be <code>null</code>.
* @param text Text to add to the target.
* May be <code>null</code>, in which case this
* method call is a no-op.
*
* @exception BuildException if the target object doesn't accept text
*/
public static void addText(Project project, Object target, String text)
throws BuildException {

if (text == null ) {
return;
}

if(target instanceof TaskAdapter) {
target = ((TaskAdapter) target).getProxy();
}

IntrospectionHelper.getHelper(target.getClass()).addText(project, target, text);
}

/**
* Stores a configured child element within its parent object.
*
* @param project Project containing the objects.
* May be <code>null</code>.
* @param parent Parent object to add child to.
* Must not be <code>null</code>.
* @param child Child object to store in parent.
* Should not be <code>null</code>.
* @param tag Name of element which generated the child.
* May be <code>null</code>, in which case
* the child is not stored.
*/
public static void storeChild(Project project, Object parent, Object child, String tag) {
IntrospectionHelper ih = IntrospectionHelper.getHelper(parent.getClass());
ih.storeElement(project, parent, child, tag);
}

/**
* Replaces <code>${xxx}</code> style constructions in the given value with
* the string value of the corresponding properties.
*
* @param value The string to be scanned for property references.
* May be <code>null</code>.
*
* @exception BuildException if the string contains an opening
* <code>${</code> without a closing
* <code>}</code>
* @return the original string with the properties replaced, or
* <code>null</code> if the original string is <code>null</code>.
*
* @since 1.5
*/
public static String replaceProperties(Project project, String value)
throws BuildException {
return project.replaceProperties(value);
}

/**
* Replaces <code>${xxx}</code> style constructions in the given value
* with the string value of the corresponding data types.
*
* @param project The container project. This is used solely for
* logging purposes. Must not be <code>null</code>.
* @param value The string to be scanned for property references.
* May be <code>null</code>, in which case this
* method returns immediately with no effect.
* @param keys Mapping (String to String) of property names to their
* values. Must not be <code>null</code>.
*
* @exception BuildException if the string contains an opening
* <code>${</code> without a closing
* <code>}</code>
* @return the original string with the properties replaced, or
* <code>null</code> if the original string is <code>null</code>.
*/
public static String replaceProperties(Project project, String value, Hashtable keys)
throws BuildException {
if (value == null) {
return null;
}

Vector fragments = new Vector();
Vector propertyRefs = new Vector();
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();
if (!keys.containsKey(propertyName)) {
project.log("Property ${" + propertyName + "} has not been set", Project.MSG_VERBOSE);
}
fragment = (keys.containsKey(propertyName)) ? (String) keys.get(propertyName)
: "${" + propertyName + "}";
}
sb.append(fragment);
}
return sb.toString();
}

/**
* Parses a string containing <code>${xxx}</code> style property
* references into two lists. The first list is a collection
* of text fragments, while the other is a set of string property names.
* <code>null</code> entries in the first list indicate a property
* reference from the second list.
*
* @param value Text to parse. Must not be <code>null</code>.
* @param fragments List to add text fragments to.
* Must not be <code>null</code>.
* @param propertyRefs List to add property names to.
* Must not be <code>null</code>.
*
* @exception BuildException if the string contains an opening
* <code>${</code> without a closing
* <code>}</code>
*/
public static void parsePropertyString(String value, Vector fragments, Vector propertyRefs)
throws BuildException {
int prev = 0;
int pos;
while ((pos = value.indexOf("$", prev)) >= 0) {
if (pos > 0) {
fragments.addElement(value.substring(prev, pos));
}

if( pos == (value.length() - 1)) {
fragments.addElement("$");
prev = pos + 1;
}
else if (value.charAt(pos + 1) != '{' ) {
fragments.addElement(value.substring(pos + 1, pos + 2));
prev = pos + 2;
} else {
int endName = value.indexOf('}', pos);
if (endName < 0) {
throw new BuildException("Syntax error in property: "
+ value );
}
String propertyName = value.substring(pos + 2, endName);
fragments.addElement(null);
propertyRefs.addElement(propertyName);
prev = endName + 1;
}
}

if (prev < value.length()) {
fragments.addElement(value.substring(prev));
}
}
}

+ 0
- 1169
proposal/sandbox/embed/ProjectHelperImpl.java
File diff suppressed because it is too large
View File


Loading…
Cancel
Save