blob: 3cd8662afb567de0d5575ec41627817b2bbcb750 [file] [log] [blame]
package org.eclipse.dash.common.releng;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.FileSet;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* @author Eike Stepper
*/
public class FeatureFileSet extends FileSet
{
private String featureID;
private transient boolean isPopulated;
public FeatureFileSet()
{
}
protected FeatureFileSet(FeatureFileSet s)
{
super(s);
featureID = s.featureID;
}
public String getFeatureID()
{
return getFeatureID(getProject());
}
public synchronized String getFeatureID(Project p)
{
return isReference() ? ((FeatureFileSet)getRef(p)).getFeatureID(p) : featureID;
}
public synchronized void setFeatureID(String featureID) throws BuildException
{
if (isReference())
{
throw tooManyAttributes();
}
this.featureID = featureID;
}
public Object clone()
{
return new FeatureFileSet(isReference() ? (FeatureFileSet)getRef(getProject()) : this);
}
public DirectoryScanner getDirectoryScanner(Project p)
{
synchronized (this)
{
if (!isPopulated)
{
populate(p);
isPopulated = true;
}
}
return super.getDirectoryScanner(p);
}
private void populate(Project p)
{
String featureID = getFeatureID(p);
File dir = getDir(p);
p.log(" ");
p.log("Populating " + featureID);
p.log("From " + dir);
p.log(" ");
File[] features = getComponents(dir, "features");
File[] plugins = getComponents(dir, "plugins");
File rootFeature = getComponent(features, featureID, null);
Set includes = new HashSet();
calculateIncludes(p, features, plugins, rootFeature, includes);
p.log(" ");
log(p, "Includes ", includes);
p.log(" ");
appendExcludes(p, features, includes);
appendExcludes(p, plugins, includes);
}
private File[] getComponents(File dir, String path)
{
return new File(dir, path).listFiles();
}
private File getComponent(File[] components, String id, String version)
{
File result = null;
String prefix = id + "_";
if (version != null)
{
prefix += version;
}
for (int i = 0; i < components.length; i++)
{
File component = components[i];
if (component.getName().startsWith(prefix))
{
if (result != null)
{
throw new BuildException("Duplicate component: " + id);
}
result = component;
}
}
if (result == null)
{
throw new BuildException("Component not found: " + id);
}
return result;
}
private void calculateIncludes(Project p, File[] features, File[] plugins, File feature, Set includes)
{
if (includes.contains(feature))
{
return;
}
p.log("Scanning " + feature);
includes.add(feature);
InputStream stream = null;
try
{
stream = getFeatureStream(feature);
Element topElement = loadXmlElement(stream);
includes.addAll(caluculateIncludes(plugins, topElement.getElementsByTagName("plugin")));
List featureIncludes = caluculateIncludes(features, topElement.getElementsByTagName("includes"));
for (Iterator it = featureIncludes.iterator(); it.hasNext();)
{
File featureToInclude = (File)it.next();
calculateIncludes(p, features, plugins, featureToInclude, includes);
}
}
catch (Exception ex)
{
throw new BuildException(ex);
}
finally
{
if (stream != null)
{
try
{
stream.close();
}
catch (IOException ex)
{
p.log("", ex, Project.MSG_DEBUG);
}
}
}
}
private List caluculateIncludes(File[] components, NodeList componentNodes)
{
List result = new ArrayList();
for (int i = 0; i < componentNodes.getLength(); i++)
{
Node node = componentNodes.item(i);
NamedNodeMap attributes = node.getAttributes();
String id = attributes.getNamedItem("id").getNodeValue();
String version = attributes.getNamedItem("version").getNodeValue();
File component = getComponent(components, id, version);
result.add(component);
}
return result;
}
private InputStream getFeatureStream(File feature) throws IOException
{
if (feature.isDirectory())
{
return new FileInputStream(new File(feature, "feature.xml"));
}
return new URL("jar:file://" + feature + "!/feature.xml").openStream();
}
private Element loadXmlElement(InputStream stream) throws ParserConfigurationException, SAXException, IOException
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setNamespaceAware(false);
Document document = factory.newDocumentBuilder().parse(stream);
return document.getDocumentElement();
}
private void appendExcludes(Project p, File[] components, Set includes)
{
for (int i = 0; i < components.length; i++)
{
File component = components[i];
if (!includes.contains(component))
{
String exclude = component.getParentFile().getName() + "/" + component.getName();
if (component.isDirectory())
{
exclude += "/**";
}
// p.log("Excludes " + exclude);
appendExcludes(new String[] { exclude });
}
}
}
private void log(Project p, String prefix, Collection collection)
{
List sorted = collection instanceof List ? (List)collection : new ArrayList(collection);
Collections.sort(sorted);
for (Iterator it = sorted.iterator(); it.hasNext();)
{
Object object = it.next();
p.log(prefix + object);
}
}
}