blob: 514334567544d0a6781d3f37496f56954c133210 [file] [log] [blame]
package org.eclipse.ant.core;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
/*
* 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", "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/>.
*/
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.apache.tools.ant.*;
import java.io.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* An Ant project adapted to running inside the Eclipse Platform. Because of the class
* loading structure of the Eclipse platform, the standard techniques for creating instances
* of tasks and datatypes needs to be adapted.
* <p>
* <b>Note:</b> This class/interface is part of an interim API that is still under
* development and expected to change significantly before reaching stability.
* It is being made available at this early stage to solicit feedback from pioneering
* adopters on the understanding that any code that uses this API will almost
* certainly be broken (repeatedly) as the API evolves.
* </p>
*/
public class EclipseProject extends Project {
/**
* Creates a new project for use in running Ant inside the Eclipse Platform.
*/
public EclipseProject() {
super();
}
/**
* Creates and returns a new instance of the identified data type.
*
* @return the new data type instance
* @param typeName the name of the type to create
* @exception BuildException thrown if a problem occurs during data type creation
*/
public Object createDataType(String typeName) throws BuildException {
// First look in the types defined in the plugin extension points. If not
// found, do the super behaviour.
// check to see if the ant plugin is available. If we are running from
// the command line (i.e., no platform) it will not be.
if (AntPlugin.getPlugin() == null)
return internalCreateDataType(typeName);
Map types = AntPlugin.getPlugin().getTypeExtensions();
if (types == null)
return internalCreateDataType(typeName);
IConfigurationElement declaration = (IConfigurationElement) types.get(typeName);
if (declaration == null)
return internalCreateDataType(typeName);
String className = declaration.getAttribute(AntPlugin.CLASS);
try {
Class typeClass = declaration.getDeclaringExtension().getDeclaringPluginDescriptor().getPluginClassLoader().loadClass(className);
addDataTypeDefinition(typeName, typeClass);
} catch (ClassNotFoundException e) {
return internalCreateDataType(typeName);
}
return internalCreateDataType(typeName);
}
/**
* Creates and returns a new instance of the identified task.
*
* @return the new task
* @param taskName the name of the task to create
* @exception BuildException thrown if a problem occurs during task creation
*/
public Task createTask(String taskName) throws BuildException {
// First try to find if the task is defined in a plug-in. If not, call
// the super method.
// check to see if the ant plugin is available. If we are running from
// the command line (i.e., no platform) it will not be.
if (AntPlugin.getPlugin() == null)
return super.createTask(taskName);
Map tasks = AntPlugin.getPlugin().getTaskExtensions();
if (tasks == null)
return super.createTask(taskName);
IConfigurationElement declaration = (IConfigurationElement) tasks.get(taskName);
if (declaration == null)
return super.createTask(taskName);
String className = declaration.getAttribute(AntPlugin.CLASS);
try {
Class taskClass = declaration.getDeclaringExtension().getDeclaringPluginDescriptor().getPluginClassLoader().loadClass(className);
addTaskDefinition(taskName, taskClass);
} catch (ClassNotFoundException e) {
return super.createTask(taskName);
}
return super.createTask(taskName);
}
/**
* Sends a build finished notification to all registered listeners along with
* the exception that caused the termination.
*
* @param exception the exception to include with the notification
*/
protected void fireBuildFinished(Throwable exception) {
super.fireBuildFinished(exception);
}
/**
* Sends a build started notification to all registered listeners.
*/
protected void fireBuildStarted() {
super.fireBuildStarted();
}
/**
* Sends a target started notification to all the listeners when an execute target
* has just been started.
*/
protected void fireExecuteTargetStarted(Target target) {
BuildEvent event = new BuildEvent(target);
Vector buildListeners = getBuildListeners();
for (int i = 0; i < buildListeners.size(); i++) {
if (buildListeners.elementAt(i) instanceof IAntRunnerListener) {
IAntRunnerListener listener = (IAntRunnerListener) buildListeners.elementAt(i);
listener.executeTargetStarted(event);
}
}
}
/**
* Sends a target finished notification to all the listeners when an execute target
* has just been finished.
*/
protected void fireExecuteTargetFinished(Target target, Throwable exception) {
BuildEvent event = new BuildEvent(target);
event.setException(exception);
Vector buildListeners = getBuildListeners();
for (int i = 0; i < buildListeners.size(); i++) {
if (buildListeners.elementAt(i) instanceof IAntRunnerListener) {
IAntRunnerListener listener = (IAntRunnerListener) buildListeners.elementAt(i);
listener.executeTargetFinished(event);
}
}
}
/**
* Initializes the receiver.
*
* @exception BuildException thrown if a problem occurs during initialization.
*/
public void init() throws BuildException {
super.init();
// add some additional tasks and datatypes. Normally they would be found
// in the plugin.xml markup for the Ant Support plugin but if we are not running
// the platform we need to add them here.
addTaskDefinition("ant", EclipseAnt.class);
addTaskDefinition("javac", EclipseJavac.class);
addDataTypeDefinition("commapatternset", CommaPatternSet.class);
addDataTypeDefinition("command", CommandDataType.class);
System.setProperty("ant.regexp.matcherimpl", "org.eclipse.ant.core.XercesRegexpMatcher");
// initialize the datatype table with marker values so that the table contains
// the keys (needed while parsing) but don't load the classes to prevent plugin activation.
if (AntPlugin.getPlugin() == null)
return;
Map types = AntPlugin.getPlugin().getTypeExtensions();
if (types == null)
return;
for (Iterator i = types.keySet().iterator(); i.hasNext();) {
String typeName = (String)i.next();
if (getDataTypeDefinitions().get(typeName) == null)
addDataTypeDefinition(typeName, EclipseProject.class);
}
}
protected Object internalCreateDataType(String typeName) throws BuildException {
Class c = (Class) getDataTypeDefinitions().get(typeName);
if (c == null)
return null;
try {
java.lang.reflect.Constructor ctor = null;
boolean noArg = false;
// DataType can have a "no arg" constructor or take a single
// Project argument.
try {
ctor = c.getConstructor(new Class[0]);
noArg = true;
} catch (NoSuchMethodException nse) {
ctor = c.getConstructor(new Class[] {Project.class});
noArg = false;
}
Object o = null;
if (noArg) {
o = ctor.newInstance(new Object[0]);
} else {
o = ctor.newInstance(new Object[] {this});
}
if (o instanceof ProjectComponent) {
((ProjectComponent)o).setProject(this);
}
String msg = " +DataType: " + typeName;
log (msg, MSG_DEBUG);
return o;
} catch (java.lang.reflect.InvocationTargetException ite) {
Throwable t = ite.getTargetException();
String msg = "Could not create datatype of type: "
+ typeName + " due to " + t;
throw new BuildException(msg, t);
} catch (Throwable t) {
String msg = "Could not create datatype of type: "
+ typeName + " due to " + t;
throw new BuildException(msg, t);
}
}
/**
* Executes a target. Notification has been added: the build listener knows that a top level
* target is being executed and when it is finished.
*
* @see Project#executeTarget(String targetName)
*/
public void executeTarget(String targetName) throws BuildException {
Target targetToExecute = (Target) getTargets().get(targetName);
if (targetToExecute == null)
// can happen if the user has specified a target name that is not valid
throw new BuildException(Policy.bind("exception.targetDoesNotExist", targetName));
try {
fireExecuteTargetStarted(targetToExecute);
super.executeTarget(targetName);
fireExecuteTargetFinished(targetToExecute, null);
} catch(RuntimeException exc) {
fireExecuteTargetFinished(targetToExecute, exc);
throw exc;
}
}
}