/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 IVY1016; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.ivy.ant.*; import org.apache.ivy.core.report.ArtifactDownloadReport; import org.apache.ivy.util.Message; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.util.DOMElementWriter; import org.apache.tools.ant.util.FileUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.Text; /** * An Ant task that updates a project's Eclipse .classpath file according to the result of * <code>ivy:resolve</code>. Supports attaching sources jars to entries if any are available. */ public class EclipseClasspath extends IvyCacheTask { private static List<String> IGNORE = Arrays.asList( "blitz-test", "blitz", "server", "common", "model-", "dsl", "romio", "rendering", "common-test", "dsl-test", "omero_client" //"postgresql", These are needed. //"ice", //"ice-db", ); private static final String ATTR_IVYGEN = "ivygen"; private static final String TAG_CLASSPATH_ENTRY = "classpathentry"; private String sourceType = "sources"; private String classpathFile = ".classpath"; private boolean filter = false; public void doExecute() throws BuildException { prepareAndCheck(); FileWriter output = null; try { Map binMap = new HashMap(); Map sourceMap = new HashMap(); OUTER: for (Iterator iter = getArtifactReports().iterator(); iter.hasNext();) { ArtifactDownloadReport a = (ArtifactDownloadReport) iter.next(); org.apache.ivy.core.module.id.ArtifactRevisionId arid = a.getArtifact().getId(); org.apache.ivy.core.module.id.ArtifactId aid = arid.getArtifactId(); org.apache.ivy.core.module.id.ModuleId mid = aid.getModuleId(); String modOrg = mid.getOrganisation(); String modName = mid.getName(); if (filter && "omero".equals(modOrg)) { for (String prefix : IGNORE) { if (modName.startsWith(prefix)) { continue OUTER; } } } String artifactName = a.getArtifact().getName(); if (a.getType().equals(sourceType)) { sourceMap.put(artifactName, a.getLocalFile()); } else { binMap.put(artifactName, a.getLocalFile()); } Message.verbose("Artifact " + artifactName + ": " + a.getLocalFile()); } File template = new File(classpathFile+"-template"); // Changed by OME if (!template.exists()) { log("No .classpath-template file found."); return; // EARLY EXIT! } DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(template); Element root = doc.getDocumentElement(); // go through the classpath entries Node node = root.getFirstChild(); while (node != null) { if (node instanceof Element && ((Element)node).getTagName().equals(TAG_CLASSPATH_ENTRY) && Boolean.parseBoolean(((Element)node).getAttribute(ATTR_IVYGEN))) { // remove an entry if it has ivygen="true" Node prev = node; node = node.getNextSibling(); root.removeChild(prev); } else if (node instanceof Text && Pattern.matches("\\s+", node.getTextContent())) { // remove the whitespaces between classpathentry elements. This helps keeping // the changes minimal when writing the dom, and makes it easier to diff and merge. Node prev = node; node = node.getNextSibling(); root.removeChild(prev); } else { node = node.getNextSibling(); } } // insert entries, marking them with ivygen="true" for (Iterator iEntry = binMap.entrySet().iterator(); iEntry.hasNext();) { Map.Entry entry = (Map.Entry)iEntry.next(); String artifactName = (String)entry.getKey(); Element newEntry = doc.createElement(TAG_CLASSPATH_ENTRY); newEntry.setAttribute(ATTR_IVYGEN, "true"); newEntry.setAttribute("kind", "lib"); newEntry.setAttribute("path", ((File)entry.getValue()).getAbsolutePath()); File sourcePath = (File)sourceMap.get(artifactName); if (sourcePath != null) { newEntry.setAttribute("sourcepath", sourcePath.getAbsolutePath()); } root.appendChild(newEntry); } // write the result DOM to a temp file. final FileUtils fileUtils = FileUtils.newFileUtils(); File newClasspath = fileUtils.createTempFile("ivygen-", ".classpath", getProject().getBaseDir()); output = new FileWriter(newClasspath); DOMElementWriter writer = new DOMElementWriter(); output.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); writer.write(root, output, 0, "\t"); // overwrite the original .classpath if all went well. fileUtils.copyFile(newClasspath, new File(classpathFile)); newClasspath.delete(); } catch (Exception ex) { throw new BuildException("Unable to generate Eclipse classpath:", ex); } finally { try { if (output != null) { output.close(); } } catch (IOException e) { } } } /** * @see org.apache.ivy.ant.IvyPostResolveTask#prepareAndCheck() */ protected void prepareAndCheck() { super.prepareAndCheck(); classpathFile = getProject().getBaseDir() + "/" + classpathFile; } /** * @return the sourceType */ public String getSourceType() { return sourceType; } /** * @param sourceType the sourceType to set */ public void setSourceType(String sourceType) { this.sourceType = sourceType; } /** * @return the classpathFile */ public String getClasspathFile() { return classpathFile; } /** * @param classpathFile the classpathFile to set */ public void setClasspathFile(String classpathFile) { this.classpathFile = classpathFile; } /** * @param whether or not to filter out OMERO items. */ public void setFilter(boolean filter) { this.filter = filter; } }