/**********************************************************************
* Copyright (c) 2005-2009 ant4eclipse project team.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nils Hartmann, Daniel Kasmeroglu, Gerd Wuetherich
**********************************************************************/
package org.ant4eclipse.ant.pde;
import org.ant4eclipse.ant.core.AbstractAnt4EclipseTask;
import org.ant4eclipse.ant.platform.core.delegate.WorkspaceDelegate;
import org.ant4eclipse.lib.core.exception.Ant4EclipseException;
import org.ant4eclipse.lib.core.util.Utilities;
import org.ant4eclipse.lib.pde.PdeExceptionCode;
import org.ant4eclipse.lib.pde.model.product.ProductDefinition;
import org.ant4eclipse.lib.pde.model.product.ProductDefinitionParser;
import org.ant4eclipse.lib.pde.model.product.ProductOs;
import org.ant4eclipse.lib.platform.model.resource.EclipseProject;
import org.ant4eclipse.lib.platform.model.resource.EclipseProject.PathStyle;
import org.apache.tools.ant.BuildException;
import org.osgi.framework.Version;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* This task allows to request several information from an eclipse product configuration.
* </p>
*
* @author Daniel Kasmeroglu (Daniel.Kasmeroglu@Kasisoft.net)
*/
public class QueryProductTask extends AbstractAnt4EclipseTask {
/**
* The query type is used to select the kind of data that is being requested.
*/
public static enum QueryType {
/** - */
id,
/** - */
name,
/** - */
basedonfeatures,
/** - */
configini,
/** - */
programargs,
/** - */
vmargs,
/** - */
application,
/** - */
version,
/** - */
launchername,
/** - */
wsplugins,
/** - */
wsfragments,
/** - */
wsfeatures,
/** - */
plugins,
/** - */
fragments,
/** - */
features;
}
/** - */
private File _product;
/** - */
private String _delimiter;
/** - */
private WorkspaceDelegate _workspacedelegate;
/** - */
private boolean _defaultisempty;
/** - */
private List<Query> _queries;
/**
* Initialises this task with default values.
*/
public QueryProductTask() {
super();
this._workspacedelegate = new WorkspaceDelegate(this);
this._queries = new ArrayList<Query>();
this._delimiter = ",";
this._product = null;
this._defaultisempty = true;
}
/**
* Enables/disables the property setting for the case no value is available.
*
* @param newdefaultisempty
* <code>true</code> <=> Enables the property setting (empty value).
*/
public void setDefaultIsEmpty(boolean newdefaultisempty) {
this._defaultisempty = newdefaultisempty;
}
/**
* Sets the workspace directory. Only necessary for queries trying to access filesystem information.
*
* @param workspace
* The workspace directory. Not <code>null</code>.
*/
public void setWorkspaceDirectory(String workspace) {
this._workspacedelegate.setWorkspaceDirectory(workspace);
}
/**
* Changes the location of the product configuration file.
*
* @param newproduct
* The new location of the product file. Not <code>null</code>.
*/
public void setProduct(File newproduct) {
this._product = newproduct;
}
/**
* Changes the delimiter which is used for list values.
*
* @param newdelimiter
* The delimiter to be used for list values.
*/
public void setDelimiter(String newdelimiter) {
this._delimiter = Utilities.cleanup(newdelimiter);
}
/**
* Adds the supplied query to this task.
*
* @param newquery
* The new query which has to be added.
*/
public void addConfiguredQuery(Query newquery) {
this._queries.add(newquery);
}
/**
* {@inheritDoc}
*/
@Override
protected void preconditions() throws BuildException {
super.preconditions();
if (this._product == null) {
throw new BuildException("The attribute 'product' has to be set.");
}
if (!this._product.isFile()) {
throw new BuildException(String.format("The product configuration '%s' is not a regular file.", this._product));
}
if (this._queries.isEmpty()) {
throw new BuildException("There must be at least one <query> element.");
}
for (Query query : this._queries) {
if (query._property == null) {
throw new BuildException("The attribute 'property' has to be set on a query.");
}
if (query._type == null) {
throw new BuildException(String.format(
"The attribute 'query' has to be set to one of the following values: %s", Utilities.listToString(QueryType
.values(), null)));
}
if ((query._type == QueryType.configini) || (query._type == QueryType.wsplugins)
|| (query._type == QueryType.wsfragments) || (query._type == QueryType.wsfeatures)) {
this._workspacedelegate.requireWorkspaceDirectoryOrWorkspaceIdSet();
}
}
}
/**
* Loads the product definition.
*
* @return The loaded product definition. Not <code>null</code>.
*/
private ProductDefinition loadProductDefinition() {
InputStream instream = null;
try {
instream = new FileInputStream(this._product);
return ProductDefinitionParser.parseProductDefinition(instream);
} catch (Ant4EclipseException ex) {
if (ex.getExceptionCode() == PdeExceptionCode.INVALID_CONFIGURATION_VALUE) {
throw new Ant4EclipseException(PdeExceptionCode.INVALID_PRODUCT_DEFINITION, this._product, ex.getMessage());
} else {
throw ex;
}
} catch (IOException ex) {
throw new BuildException(ex);
} finally {
Utilities.close(instream);
}
}
/**
* {@inheritDoc}
*/
@Override
protected void doExecute() {
ProductDefinition productdef = loadProductDefinition();
for (Query query : this._queries) {
String value = runQuery(query, productdef);
if (value != null) {
getProject().setProperty(query._property, value);
} else {
if (this._defaultisempty) {
getProject().setProperty(query._property, "");
}
}
}
}
/**
* Evaluates a single query.
*
* @param query
* The query that has to be evaluated. Not <code>null</code>.
* @param productdef
* The product definition providing the necessary information. Not <code>null</code>.
*
* @return The value of this query. Maybe <code>null</code>.
*/
private String runQuery(Query query, ProductDefinition productdef) {
switch (query._type) {
case plugins:
return Utilities.listToString(productdef.getPluginIds(), this._delimiter);
case fragments:
return Utilities.listToString(productdef.getFragmentIds(), this._delimiter);
case features:
return Utilities.listToString(productdef.getFeatureIds(), this._delimiter);
case wsplugins:
return getWorkspaceContained(productdef.getPluginIds());
case wsfragments:
return getWorkspaceContained(productdef.getFragmentIds());
case wsfeatures:
return getWorkspaceContained(productdef.getFeatureIds());
case launchername:
return productdef.getLaunchername();
case application:
return productdef.getApplication();
case programargs:
return getArgs(productdef.getProgramArgs(query._os));
case vmargs:
return getArgs(productdef.getVmArgs(query._os));
case basedonfeatures:
return String.valueOf(productdef.isBasedOnFeatures());
case id:
return productdef.getId();
case name:
return productdef.getName();
case version:
Version version = productdef.getVersion();
if (version != null) {
return version.toString();
} else {
return null;
}
case configini:
String configini = productdef.getConfigIni(query._os);
if (configini != null) {
int idx = configini.indexOf('/', 1);
String projectname = configini.substring(1, idx);
String path = configini.substring(idx + 1);
EclipseProject project = this._workspacedelegate.getWorkspace().getProject(projectname);
return project.getChild(path, PathStyle.ABSOLUTE).getAbsolutePath();
} else {
return null;
}
default:
throw new BuildException(String.format("The query type '%s' is currently not implemented.", query._type));
}
}
/**
* Filters the supplied list of ids by those that are located within the workspace.
*
* @param ids
* The ids which have to be filtered. Not <code>null</code>.
*
* @return The value providing the list of ids available within the workspace. Not <code>null</code>.
*/
private String getWorkspaceContained(String[] ids) {
List<String> list = new ArrayList<String>();
for (String id : ids) {
if (this._workspacedelegate.getWorkspace().getProject(id) != null) {
list.add(id);
}
}
if (list.isEmpty()) {
return null;
}
return Utilities.listToString(list.toArray(), this._delimiter);
}
/**
* Concatenates the supplied arguments/argumentlists.
*
* @param args
* The arguments/argumentlists that have to be concatenated.
*
* @return The resulting argumentlist. Maybe <code>null</code>.
*/
private String getArgs(String... args) {
if (args == null) {
return null;
}
StringBuffer buffer = new StringBuffer();
for (String arg : args) {
if (arg != null) {
if (buffer.length() > 0) {
buffer.append(' ');
}
buffer.append(arg);
}
}
return Utilities.cleanup(buffer.toString());
}
/**
* Representation of a single query element for this task.
*/
public static class Query {
/** - */
private String _property;
/** - */
private QueryType _type;
/** - */
private ProductOs _os;
/**
* Initialises this query instance with default values.
*/
public Query() {
this._os = ProductOs.win32;
this._type = null;
this._property = null;
}
/**
* Changes the current os used for the querying of the product configuration.
*
* @param newos
* The new os used for the querying of the product configuration. Not <code>null</code>.
*/
public void setOs(ProductOs newos) {
this._os = newos;
}
/**
* Changes the query used to access the product information.
*
* @param newquery
* The new query used to access product information. Not <code>null</code>.
*/
public void setType(QueryType newquery) {
this._type = newquery;
}
/**
* Changes the name of the property which will be set to access the value.
*
* @param newproperty
* The new property name. Neither <code>null</code> nor empty.
*/
public void setProperty(String newproperty) {
this._property = Utilities.cleanup(newproperty);
}
} /* ENDCLASS */
} /* ENDCLASS */