SyncEclipse.java
001 /*
002  * Copyright (c) 1995-2012, The University of Sheffield. See the file
003  * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
004  
005  * This file is part of GATE (see http://gate.ac.uk/), and is free software,
006  * licenced under the GNU Library General Public License, Version 2, June 1991
007  * (in the distribution as file licence.html, and also available at
008  * http://gate.ac.uk/gate/licence.html).
009  
010  * Mark A. Greenwood, 21/01/2012
011  
012  * $Id: SyncEclipse.java 15185 2012-01-22 16:10:41Z markagreenwood $
013  */
014 
015 package gate.util.ant;
016 
017 import gate.util.ExtensionFileFilter;
018 import gate.util.Files;
019 import gate.util.persistence.PersistenceManager;
020 
021 import java.io.File;
022 import java.io.FileFilter;
023 import java.io.FileWriter;
024 import java.util.Arrays;
025 import java.util.HashSet;
026 import java.util.List;
027 import java.util.Set;
028 
029 import org.apache.tools.ant.BuildException;
030 import org.apache.tools.ant.Task;
031 import org.jdom.Document;
032 import org.jdom.Element;
033 import org.jdom.input.SAXBuilder;
034 import org.jdom.output.Format;
035 import org.jdom.output.XMLOutputter;
036 import org.jdom.xpath.XPath;
037 
038 /**
039  * An ANT task that syncs an Eclipse classpath file against a folder of jar
040  * files. Once the task has completed all jar files in the specified folder will
041  * be mentioned within the Eclipse classpath file and any jars that were
042  * mentioned in the classpath file as being with the specified folder and which
043  * no longer exist will have been removed.
044  */
045 public class SyncEclipse extends Task {
046 
047   private XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat()
048       .setIndent("\t"));
049 
050   private File dir, classpath;
051 
052   private boolean recursive = true;
053   
054   private boolean verbose = false;
055 
056   public boolean isRecursive() {
057     return recursive;
058   }
059 
060   public void setRecursive(boolean recursive) {
061     this.recursive = recursive;
062   }
063   
064   public boolean isVerbose() {
065     return verbose;
066   }
067 
068   public void setVerbose(boolean verbose) {
069     this.verbose = verbose;
070   }
071 
072   public File getDir() {
073     return dir;
074   }
075 
076   public void setDir(File dir) {
077     this.dir = dir;
078   }
079 
080   public File getClasspathFile() {
081     return classpath;
082   }
083 
084   public void setClasspathFile(File classpath) {
085     this.classpath = classpath;
086   }
087 
088   @Override
089   public void execute() throws BuildException {
090     if(dir == null)
091       throw new BuildException("Please specify a directory", getLocation());
092 
093     if(!dir.exists() || !dir.isDirectory())
094       throw new BuildException("Specified directory doesn't exist",
095           getLocation());
096 
097     FileFilter ff = new ExtensionFileFilter("JAR Files""jar");
098 
099     if(classpath == null)
100       classpath = new File(getProject().getBaseDir()".classpath");
101 
102     if(!classpath.exists() || !classpath.isFile())
103       throw new BuildException("Eclipse classpath file can't be located",
104           getLocation());
105 
106     Set<File> jars = new HashSet<File>();
107     for(File f : Arrays.asList(recursive
108         ? Files.listFilesRecursively(dir, ff)
109         : dir.listFiles(ff))) {
110       if(!f.isDirectory()) jars.add(f);
111     }
112 
113     boolean dirty = false;
114 
115     try {
116       SAXBuilder builder = new SAXBuilder();
117       Document classpathDoc = builder.build(classpath);
118 
119       @SuppressWarnings("unchecked")
120       List<Element> libEntries =
121           XPath.newInstance("/classpath/classpathentry[@kind='lib']")
122               .selectNodes(classpathDoc);
123 
124       String relative = PersistenceManager.getRelativePath(classpath.toURI().toURL(), dir.toURI().toURL());
125             
126       for(Element e : libEntries) {
127         String path = e.getAttributeValue("path");
128         if(path.startsWith(relative)) {
129           File f = new File(classpath.getParentFile(), path);
130           if(jars.contains(f)) {
131             if (verboseSystem.out.println("KEEPING: " + path);
132             jars.remove(f);
133           else {
134             dirty = true;
135             if (verboseSystem.out.println("REMOVED: " + path);
136             Element parent = e.getParentElement();
137             parent.removeContent(e);
138           }
139         }
140       }
141 
142       if(!jars.isEmpty()) {
143         dirty = true;
144         for(File f : jars) {
145           String path =
146               PersistenceManager.getRelativePath(classpath.toURI().toURL(), f
147                   .toURI().toURL());
148           if (verboseSystem.out.println("ADDED: " + path);
149           Element libElement =
150               new Element("classpathentry").setAttribute("kind""lib")
151                   .setAttribute("exported""true").setAttribute("path", path);
152           classpathDoc.getRootElement().addContent(libElement);
153         }
154       }
155 
156       if(dirty) {
157         outputter.output(classpathDoc, new FileWriter(classpath));
158       }
159 
160     catch(Exception e) {
161       throw new BuildException(e, getLocation());
162     }
163   }
164 }