blob: 58e4a9f0b57d456f5d75a7393bbdffb24bfe5828 [file] [log] [blame]
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cocoon;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DynamicConfigurator;
import org.apache.tools.ant.ExitException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.CommandlineJava;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
/**
* Ant task for running Cocoon. Allows for the embedding of Cocoon into
*
* @version $Id$
*/
public class CocoonTask extends Task implements DynamicConfigurator {
private CommandlineJava cmdl = new CommandlineJava();
private boolean failOnError = false;
private Throwable caught = null;
private String uriGroup = null;
private Document xconf;
private Element root;
private ElementWrapper _wrapper;
private static final String CLASS_DELEGATE = "org.apache.cocoon.bean.helpers.AntDelegate";
public CocoonTask() {
try {
DocumentBuilder builder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
xconf = builder.newDocument();
root = xconf.createElement("cocoon");
xconf.appendChild(root);
_wrapper = new ElementWrapper(root);
cmdl.setClassname(CLASS_DELEGATE);
}
catch (ParserConfigurationException e) {
throw new BuildException(e);
}
}
/**
* Adds a path to the classpath.
*
* @return created classpath
*/
public Path createClasspath() {
return cmdl.createClasspath(getProject()).createPath();
}
/**
* Classpath to use, by reference.
*
* @param r a reference to an existing classpath
*/
public void setClasspathRef(Reference r) {
createClasspath().setRefid(r);
}
/**
* Set the classpath to be used when running the Java class
*
* @param s an Ant Path object containing the classpath.
*/
public void setClasspath(Path s) {
createClasspath().append(s);
}
public void setUrigroup(String group) {
this.uriGroup = group;
}
/**
* A dynamic configurator for each element.
*/
private static class ElementWrapper
implements DynamicConfigurator {
private Node node;
/** Instantiate a root wrapper */
private ElementWrapper(Node node) {
this.node = node;
}
/** Instantiate a child wrapper */
private ElementWrapper(Node parent, String childName) {
Document document = parent.getOwnerDocument();
if (document == null) {
document = (Document)parent; // Node is the document!
}
node = document.createElement(childName);
parent.appendChild(node);
}
//
// interface DynamicConfigurator
public void setDynamicAttribute(String name, String value)
throws BuildException {
// Never called for anything by Element wrappers
Element element = (Element)node;
element.setAttribute(name, value);
}
public Object createDynamicElement(String name)
throws BuildException {
return new ElementWrapper(node, name);
}
}
public File getLibDir() throws BuildException {
Element root = xconf.getDocumentElement();
String contextDir = null;
if (root!=null) {
if (hasAttribute(root, "context-dir")){
contextDir = getAttributeValue(root, "context-dir");
}
}
if (contextDir != null) {
return new File(contextDir + "/WEB-INF/lib");
}
throw new BuildException("No context directory specified. Cannot find Cocoon");
}
private static String getAttributeValue(Node node, String attr) throws IllegalArgumentException {
NamedNodeMap nodes = node.getAttributes();
if (nodes != null) {
Node attribute = nodes.getNamedItem(attr);
if (attribute != null && attribute.getNodeValue() != null) {
return attribute.getNodeValue();
}
}
throw new IllegalArgumentException("Missing " + attr + " attribute on <" + node.getNodeName() + "> node");
}
private static boolean hasAttribute(Node node, String attr) {
NamedNodeMap nodes = node.getAttributes();
if (nodes != null) {
Node attribute = nodes.getNamedItem(attr);
return (attribute != null);
}
return false;
}
//
// interface DynamicConfigurator
public void setDynamicAttribute(String name, String value)
throws BuildException {
root.setAttribute(name, value);
}
public Object createDynamicElement(String name)
throws BuildException {
return _wrapper.createDynamicElement(name);
}
/**
* Do the execution .
*
* @throws BuildException if required parameters are missing
*/
public void execute() throws BuildException {
if (cmdl.getClasspath() == null) {
throw new BuildException("Could not find a classpath that points to the Cocoon classes");
}
try {
try {
execute(cmdl);
} catch (ExitException ex) {
// ignore
}
} catch (BuildException e) {
if (failOnError) {
throw e;
}
log(e.getMessage(), Project.MSG_ERR);
} catch (Throwable t) {
if (failOnError) {
throw new BuildException(t);
}
log(t.getMessage(), Project.MSG_ERR);
}
}
public void execute(CommandlineJava command) throws BuildException {
final String classname = command.getJavaCommand().getExecutable();
AntClassLoader loader = null;
try {
if (command.getSystemProperties() != null) {
command.getSystemProperties().setSystem();
}
final Class[] param = {Class.forName("org.w3c.dom.Document"), Class.forName("java.lang.String")};
Class target = null;
if (command.getClasspath() == null) {
target = Class.forName(classname);
} else {
loader = new AntClassLoader(getProject().getCoreLoader(), getProject(),
command.getClasspath(), false);
loader.setIsolated(true);
loader.setThreadContextLoader();
target = loader.forceLoadClass(classname);
Class.forName(classname, true, loader);
}
Method method = target.getMethod("process", param);
if (method == null) {
throw new BuildException("Could not find process() method in "
+ classname);
}
run(method);
if (caught != null) {
throw caught;
}
} catch (ClassNotFoundException e) {
throw new BuildException("Could not find " + classname + "."
+ " Make sure you have it in your"
+ " classpath");
} catch (SecurityException e) {
throw e;
} catch (Throwable e) {
throw new BuildException(e);
} finally {
if (loader != null) {
loader.resetThreadContextLoader();
loader.cleanup();
}
if (command.getSystemProperties() != null) {
command.getSystemProperties().restoreSystem();
}
}
}
public void run(Method method) {
final Object[] argument = {xconf, uriGroup};
try {
method.invoke(null, argument);
} catch (InvocationTargetException e) {
Throwable t = e.getTargetException();
if (!(t instanceof InterruptedException)) {
caught = t;
} /* else { swallow, probably due to timeout } */
} catch (Throwable t) {
caught = t;
} finally {
synchronized (this) {
notifyAll();
}
}
}
}