|
- /*
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 1999 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", "Tomcat", 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.beans.*;
- import java.io.File;
- import java.io.IOException;
- import java.lang.reflect.*;
- import java.util.*;
- import org.xml.sax.SAXException;
- import org.w3c.dom.*;
- import org.apache.tools.ant.taskdefs.*;
-
- /**
- * Configures a Project (complete with Targets and Tasks) based on
- * a XML build file.
- *
- * @author duncan@x180.com
- */
-
- public class ProjectHelper {
-
- public static void configureProject(Project project, File buildFile)
- throws BuildException
- {
-
- // XXX
- // need to get rid of the DOM layer and use SAX
-
- Document doc;
-
- try {
- doc=Parser.getParser(project).parse(buildFile);
- } catch (IOException ioe) {
- String msg = "Can't open config file: " + buildFile +
- " due to: " + ioe;
- throw new BuildException(msg);
- } catch (SAXException se) {
- String msg = "Can't open config file: " + buildFile +
- " due to: " + se;
- throw new BuildException(msg);
- }
-
- Element root = doc.getDocumentElement();
-
- // sanity check, make sure that we have the right element
- // as we aren't validating the input
-
- if (!root.getTagName().equals("project")) {
- String msg = "Config file is not of expected XML type";
- throw new BuildException(msg);
- }
-
- project.setDefaultTarget(root.getAttribute("default"));
-
- String name = root.getAttribute("name");
- project.setName(name);
- if (name != null) project.addReference(name, project);
-
- String id = root.getAttribute("id");
- if (id != null) project.addReference(id, project);
-
- String baseDir = project.getProperty("basedir");
- if (baseDir == null) {
- baseDir = root.getAttribute("basedir");
- if (baseDir.equals("")) {
- // Using clunky JDK1.1 methods here
- baseDir = new File(buildFile.getAbsolutePath()).getParent();
- }
- }
- project.setBasedir(baseDir);
-
- // set up any properties that may be in the config file
-
- // configureProperties(project, root);
-
- // set up any task defs that may be in the config file
-
- // configureTaskDefs(project, root);
-
- // set up the taskdefs, properties, and targets into the project
- configureProject(project, root);
- }
-
- private static void configureProject(Project project, Element root)
- throws BuildException
- {
- // configure taskdefs
- NodeList list = root.getElementsByTagName("taskdef");
- for (int i = 0; i < list.getLength(); i++) {
- Task taskdef = new Taskdef();
- configure(project, taskdef, (Element)list.item(i));
- taskdef.setProject(project);
- taskdef.init();
- }
-
- // configure properties
- list = root.getElementsByTagName("property");
- for (int i = 0; i < list.getLength(); i++) {
- Task property = new Property();
- configure(project, property, (Element)list.item(i));
- property.setProject(project);
- property.init();
- }
-
- // configure targets
- list = root.getElementsByTagName("target");
- for (int i = 0; i < list.getLength(); i++) {
- Element element = (Element)list.item(i);
- String targetName = element.getAttribute("name");
- String targetDep = element.getAttribute("depends");
- String targetCond = element.getAttribute("if");
- String targetId = element.getAttribute("id");
-
- // all targets must have a name
- if (targetName.equals("")) {
- String msg = "target element appears without a name attribute";
- throw new BuildException(msg);
- }
-
- Target target = new Target();
- target.setName(targetName);
- target.setCondition(targetCond);
- project.addTarget(targetName, target);
-
- if (targetId != null && !targetId.equals(""))
- project.addReference(targetId,target);
-
- // take care of dependencies
-
- if (targetDep.length() > 0) {
- StringTokenizer tok =
- new StringTokenizer(targetDep, ",", false);
- while (tok.hasMoreTokens()) {
- target.addDependency(tok.nextToken().trim());
- }
- }
-
- // populate target with tasks
-
- configureTasks(project, target, element);
- }
- }
-
- private static void configureTasks(Project project,
- Target target,
- Element targetElement)
- throws BuildException
- {
- NodeList list = targetElement.getChildNodes();
- for (int i = 0; i < list.getLength(); i++) {
- Node node = list.item(i);
-
- // right now, all we are interested in is element nodes
- // not quite sure what to do with others except drop 'em
-
- if (node.getNodeType() == Node.ELEMENT_NODE) {
- Element element = (Element)node;
- String taskType = element.getTagName();
-
- // XXX
- // put in some sanity checking
-
- Task task = project.createTask(taskType);
-
- // get the attributes of this element and reflect them
- // into the task
-
- configure(project, task, element);
- task.init();
- task.setTarget(target);
- target.addTask(task);
-
- processNestedProperties(project, task, element);
- }
- }
- }
-
- private static void processNestedProperties(Project project,
- Object target,
- Element targetElement)
- throws BuildException
- {
- Class targetClass = target.getClass();
- NodeList list = targetElement.getChildNodes();
-
- for (int i = 0; i < list.getLength(); i++) {
- Node node = list.item(i);
-
- // right now, all we are interested in is element nodes
- // not quite sure what to do with others except drop 'em
-
- if (node.getNodeType() == Node.TEXT_NODE) {
- String text = ((Text)node).getData();
- try {
- Method addProp = targetClass.getMethod(
- "addText", new Class[]{"".getClass()});
- Object child = addProp.invoke(target, new Object[] {text});
- } catch (NoSuchMethodException nsme) {
- if (text.trim().length() > 0)
- throw new BuildException(targetClass +
- " does not support nested text elements");
- } catch (InvocationTargetException ite) {
- throw new BuildException(ite.getMessage());
- } catch (IllegalAccessException iae) {
- throw new BuildException(iae.getMessage());
- }
- }
-
- if (node.getNodeType() == Node.ELEMENT_NODE) {
- Element element = (Element)node;
- String propType = element.getTagName();
- String methodName = "create" +
- Character.toUpperCase(propType.charAt(0)) +
- propType.substring(1);
-
- try {
- Method addProp =
- targetClass.getMethod(methodName, new Class[]{});
- Object child = addProp.invoke(target, new Object[] {});
-
- configure(project, child, element);
-
- processNestedProperties(project, child, element);
- } catch (NoSuchMethodException nsme) {
- throw new BuildException(targetClass +
- " does not support nested " + propType + " properties");
- } catch (InvocationTargetException ite) {
- throw new BuildException(ite.getMessage());
- } catch (IllegalAccessException iae) {
- throw new BuildException(iae.getMessage());
- }
-
- }
- }
- }
-
- private static void configure(Project project,
- Object target,
- Element element)
- throws BuildException
- {
- NamedNodeMap nodeMap = element.getAttributes();
-
- if( target instanceof TaskAdapter )
- target=((TaskAdapter)target).getProxy();
-
- // XXX
- // instead of doing this introspection each time around, I
- // should have a helper class to keep this info around for
- // each kind of class
-
- Hashtable propertySetters = new Hashtable();
- BeanInfo beanInfo;
- try {
- beanInfo = Introspector.getBeanInfo(target.getClass());
- } catch (IntrospectionException ie) {
- String msg = "Can't introspect class: " + target.getClass();
- throw new BuildException(msg);
- }
-
- PropertyDescriptor[] pda = beanInfo.getPropertyDescriptors();
- for (int i = 0; i < pda.length; i++) {
- PropertyDescriptor pd = pda[i];
- String property = pd.getName();
- Method setMethod = pd.getWriteMethod();
- if (setMethod != null) {
-
- // make sure that there's only 1 param and that it
- // takes a String object, all other setMethods need
- // to get screened out
-
- Class[] ma =setMethod.getParameterTypes();
- if (ma.length == 1) {
- Class c = ma[0];
- if (c.getName().equals("java.lang.String")) {
- propertySetters.put(property, setMethod);
- }
- }
- }
- }
-
- for (int i = 0; i < nodeMap.getLength(); i++) {
- Node node = nodeMap.item(i);
-
- // these should only be attribs, we won't see anything
- // else here.
-
- if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
- Attr attr = (Attr)node;
-
- // reflect these into the target
-
- Method setMethod = (Method)propertySetters.get(attr.getName());
- if (setMethod == null) {
- if (attr.getName().equals("id")) {
- project.addReference(attr.getValue(), target);
- continue;
- }
-
- String msg = "Configuration property \"" + attr.getName() +
- "\" does not have a setMethod in " + target.getClass();
- throw new BuildException(msg);
- }
-
- String value=replaceProperties( attr.getValue(), project.getProperties() );
- try {
- setMethod.invoke(target, new String[] {value});
- } catch (IllegalAccessException iae) {
- String msg = "Error setting value for attrib: " +
- attr.getName();
- iae.printStackTrace();
- throw new BuildException(msg);
- } catch (InvocationTargetException ie) {
- String msg = "Error setting value for attrib: " +
- attr.getName() + " in " + target.getClass().getName();
- ie.printStackTrace();
- ie.getTargetException().printStackTrace();
- throw new BuildException(msg);
- }
- }
- }
- }
-
- /** Replace ${NAME} with the property value
- */
- public static String replaceProperties( String value, Hashtable keys )
- throws BuildException
- {
- // XXX use Map instead of proj, it's too heavy
-
- // XXX need to replace this code with something better.
- StringBuffer sb=new StringBuffer();
- int i=0;
- int prev=0;
- // assert value!=nil
- int pos;
- while( (pos=value.indexOf( "$", prev )) >= 0 ) {
- if(pos>0)
- sb.append( value.substring( prev, pos ) );
- if( value.charAt( pos + 1 ) != '{' ) {
- sb.append( value.charAt( pos + 1 ) );
- prev=pos+2; // XXX
- } else {
- int endName=value.indexOf( '}', pos );
- if( endName < 0 ) {
- throw new BuildException("Syntax error in prop: " +
- value );
- }
- String n=value.substring( pos+2, endName );
- String v=(String) keys.get( n );
- //System.out.println("N: " + n + " " + " V:" + v);
- sb.append( v );
- prev=endName+1;
- }
- }
- if( prev < value.length() ) sb.append( value.substring( prev ) );
- // System.out.println("After replace: " + sb.toString());
- // System.out.println("Before replace: " + value);
- return sb.toString();
- }
- }
-
-
-
-
-
-
-
-
|