Major changes in data structures. Reimplementation & beautification.

This commit is contained in:
Dmitri Boulytchev
2010-12-11 05:26:06 +03:00
parent 8e7180e6f8
commit 05ef7eb774
11 changed files with 883 additions and 453 deletions
+1 -1
View File
@@ -5,7 +5,7 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="jdk" jdkName="IDEA jdk" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Ant" level="project" />
</component>
+3 -10
View File
@@ -7,22 +7,15 @@
<sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="jdk" jdkName="IDEA jdk" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Groovy" level="project" />
<orderEntry type="library" name="Ant" level="project" />
<orderEntry type="library" name="Javac2" level="project" />
<orderEntry type="module" module-name="antlayout" />
<orderEntry type="library" scope="TEST" name="JUnit" level="project" />
<orderEntry type="module-library">
<library name="Gant">
<CLASSES>
<root url="jar:///usr/share/groovy/lib/gant-1.8.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="library" exported="" name="Gant" level="application" />
<orderEntry type="library" name="Gant" level="application" />
</component>
</module>
+1 -1
View File
@@ -5,7 +5,7 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="jdk" jdkName="IDEA jdk" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="jps" />
<orderEntry type="library" name="Groovy" level="project" />
+1 -1
View File
@@ -5,7 +5,7 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="jdk" jdkName="IDEA jdk" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Groovy" level="project" />
<orderEntry type="module" module-name="jps" />
+1 -1
View File
@@ -5,7 +5,7 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="jdk" jdkName="IDEA jdk" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Groovy" level="project" />
<orderEntry type="module" module-name="jps" />
@@ -3,8 +3,7 @@ package org.jetbrains.ether;
import javax.xml.transform.Result;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -15,43 +14,92 @@ import java.util.regex.Pattern;
* Time: 2:01
* To change this template use File | Settings | File Templates.
*/
public class DirectoryScanner {
public static class Result {
final Set<ProjectWrapper.FileWrapper> myFiles;
long myLatest;
long myEarliest;
public Result () {
myFiles = new HashSet<ProjectWrapper.FileWrapper> ();
myLatest = 0;
myEarliest = Long.MAX_VALUE;
}
public void update (final ProjectWrapper.FileWrapper w) {
final long t = w.getStamp ();
if (t > myLatest)
myLatest = t;
if (t< myEarliest)
myEarliest = t;
myFiles.add(w);
}
public long getEarliest () {
return myEarliest;
}
public long getLatest () {
return myLatest;
}
public Set<ProjectWrapper.FileWrapper> getFiles () {
return myFiles;
}
}
private static class Crawler {
final Result myResult;
final FileFilter myFilter;
final ProjectWrapper myProjectWrapper;
public Crawler (final FileFilter ff, final ProjectWrapper pw) {
myResult = new Result();
myFilter = ff;
myProjectWrapper = pw;
}
public Result getResult () {
return myResult;
}
public void run(File root) {
if (root.exists()) {
final File[] files = root.listFiles(myFilter);
for (int i = 0; i < files.length; i++) {
myResult.update (myProjectWrapper.new FileWrapper(files[i]));
}
final File[] subdirs = root.listFiles(myDirectoryFilter);
for (int i = 0; i < subdirs.length; i++) {
run(subdirs[i]);
}
}
}
}
private static FileFilter myDirectoryFilter = new FileFilter() {
public boolean accept (File f) {
public boolean accept(File f) {
final String name = f.getName();
return f.isDirectory() && !name.equals(".") && !name.equals("..") ;
return f.isDirectory() && !name.equals(".") && !name.equals("..");
}
};
private static FileFilter filterByExtensions (final String[] exts) {
return new FileFilter (){
public boolean accept (File path) {
final String filename = path.getName();
for (int i = 0; i<exts.length; i++) {
if (filename.endsWith(exts[i]))
return true;
}
return false;
}
};
}
public static class Result {
public List<String> myFiles = new ArrayList<String> ();
public long myEarliest = Long.MAX_VALUE;
public long myLatest = 0;
}
private static FileFilter myTrueFilter = new FileFilter() {
public boolean accept (File s) {
return true;
}
};
public boolean accept(File s) {
return s.isFile();
}
};
private static FileFilter createFilter (final List<String> excludes) {
private static FileFilter createFilter(final Collection<String> excludes) {
if (excludes == null) {
return myTrueFilter;
}
@@ -62,7 +110,7 @@ public class DirectoryScanner {
StringBuffer alternative = new StringBuffer();
if (exclude != null) {
for (int i = 0; i<exclude.length(); i++) {
for (int i = 0; i < exclude.length(); i++) {
final char c = exclude.charAt(i);
switch (c) {
@@ -104,11 +152,11 @@ public class DirectoryScanner {
final Pattern patt = Pattern.compile(buf.toString());
return new FileFilter() {
public boolean accept (File f) {
public boolean accept(File f) {
final Matcher m = patt.matcher(f.getAbsolutePath());
final boolean ok = !m.matches();
return ok;
return ok && f.isFile();
}
};
}
@@ -116,36 +164,21 @@ public class DirectoryScanner {
return myTrueFilter;
}
public static Result getFiles (final String root, final List<String> excludes) {
final Result result = new Result ();
final FileFilter ff = createFilter(excludes);
public static Result getFiles(final String root, final Set<String> excludes, final ProjectWrapper pw) {
final Crawler cw = new Crawler(createFilter(excludes), pw);
new Object(){
public void run (File root) {
if (root.exists()) {
final File[] files = root.listFiles(ff);
if (root != null)
cw.run(new File(pw.getAbsolutePath(root)));
for (int i = 0; i<files.length; i++) {
long t = files[i].lastModified();
return cw.getResult();
}
if (t > result.myLatest)
result.myLatest = t;
public static Result getFiles(final Set<String> roots, final Set<String> excludes, final ProjectWrapper pw) {
final Crawler cw = new Crawler(createFilter(excludes), pw);
if (t < result.myEarliest)
result.myEarliest = t;
for (String root : roots)
cw.run(new File(pw.getAbsolutePath(root)));
result.myFiles.add(files[i].getAbsolutePath());
}
final File[] subdirs = root.listFiles(myDirectoryFilter);
for (int i=0; i<subdirs.length; i++) {
run (subdirs [i]);
}
}
}
}.run(new File (root));
return result;
return cw.getResult();
}
}
+9 -9
View File
@@ -134,14 +134,14 @@ public class Main {
}
for (String prj : projects) {
final ProjectWrapper project = new ProjectWrapper(prj);
boolean saved = false;
ProjectWrapper project = null;
switch (getAction()) {
case CLEAN:
System.out.println("Cleaning project \"" + prj + "\"");
project.load();
project = ProjectWrapper.load(prj);
project.clean();
project.save();
saved = true;
@@ -149,7 +149,7 @@ public class Main {
case REBUILD:
System.out.println("Rebuilding project \"" + prj + "\"");
project.load();
project = ProjectWrapper.load(prj);
project.rebuild();
project.save();
saved = true;
@@ -162,13 +162,13 @@ public class Main {
final String module = ((Options.Value) make).get();
System.out.println("Making module \"" + module + "\" in project \"" + prj + "\"");
project.load();
project = ProjectWrapper.load(prj);
project.makeModule(module, doForce(), doTests());
project.save();
saved = true;
} else if (make instanceof Options.Switch) {
System.out.println("Making project \"" + prj + "\"");
project.load();
project = ProjectWrapper.load(prj);
project.make(doForce(), doTests());
project.save();
saved = true;
@@ -179,14 +179,14 @@ public class Main {
final Options.Argument inspect = doInspect();
if (inspect instanceof Options.Switch) {
project.load();
project = ProjectWrapper.load(prj);
project.report();
if (doSave()) {
project.save();
saved = true;
}
} else if (inspect instanceof Options.Value) {
project.load();
project = ProjectWrapper.load(prj);
project.report(((Options.Value) inspect).get());
if (doSave()) {
project.save();
@@ -195,7 +195,7 @@ public class Main {
}
if (doSave() && !saved) {
project.load();
project = ProjectWrapper.load(prj);
project.save();
}
}
@@ -1,62 +0,0 @@
package org.jetbrains.ether;
import java.io.Serializable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by IntelliJ IDEA.
* User: db
* Date: 19.11.10
* Time: 3:40
* To change this template use File | Settings | File Templates.
*/
public class ModuleStatus {
private static Pattern myPattern = Pattern.compile("([^ ]+) ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)");
String myName;
long mySourceStamp;
long myOutputStamp;
long myTestSourceStamp;
long myTestOutputStamp;
public ModuleStatus(String name, long ss, long os, long tss, long tos) {
myName = name;
mySourceStamp = ss;
myOutputStamp = os;
myTestSourceStamp = tss;
myTestOutputStamp = tos;
}
public String getName () {
return myName;
}
public String toString () {
return myName + " " + mySourceStamp + " " + myOutputStamp + " " + myTestSourceStamp + " " + myTestOutputStamp;
}
public ModuleStatus(final String s) {
final Matcher m = myPattern.matcher(s);
if (m.matches()) {
myName = m.group(1);
mySourceStamp = Long.parseLong(m.group(2));
myOutputStamp = Long.parseLong(m.group(3));
myTestSourceStamp = Long.parseLong(m.group(4));
myTestOutputStamp = Long.parseLong(m.group(5));
}
else
System.err.println("Error converting string \"" + s + "\" to ModuleStatus");
}
private static boolean wiseCompare (long input, long output) {
final boolean result = (input > 0 && output == Long.MAX_VALUE) || (output <= input);
return result;
}
public boolean isOutdated(boolean tests) {
final boolean result = wiseCompare(mySourceStamp, myOutputStamp) || (tests && wiseCompare(myTestSourceStamp, myTestOutputStamp));
return result;
}
}
@@ -1,73 +0,0 @@
package org.jetbrains.ether;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
/**
* Created by IntelliJ IDEA.
* User: db
* Date: 19.11.10
* Time: 3:05
* To change this template use File | Settings | File Templates.
*/
public class ProjectSnapshot {
String myProjectStructure;
Map<String, ModuleStatus> myModuleHistories;
public ProjectSnapshot(final String prjStruct, final Map<String, ModuleStatus> moduleHistories) {
myProjectStructure = prjStruct;
myModuleHistories = moduleHistories;
}
public String toString () {
StringBuffer buf = new StringBuffer();
buf.append(myModuleHistories.size() + "\n");
for (ModuleStatus h : myModuleHistories.values()) {
buf.append(h.toString() + "\n");
}
buf.append(myProjectStructure);
return buf.toString();
}
public ProjectSnapshot(final String s) {
BufferedReader rd = new BufferedReader(new StringReader(s));
try {
final int n = Integer.parseInt(rd.readLine());
myModuleHistories = new HashMap<String, ModuleStatus>();
for (int i = 0; i<n; i++) {
ModuleStatus h = new ModuleStatus(rd.readLine());
myModuleHistories.put(h.getName(), h);
}
StringBuffer buf = new StringBuffer();
while (true) {
final String str = rd.readLine();
if (str == null)
break;
buf.append(str);
buf.append("\n");
}
myProjectStructure = buf.toString();
}
catch (IOException e) {
e.printStackTrace();
}
}
public boolean structureChanged (final ProjectSnapshot p) {
return ! p.myProjectStructure.equals(myProjectStructure);
}
}
+775 -50
View File
@@ -1,11 +1,9 @@
package org.jetbrains.ether;
import com.sun.org.apache.xpath.internal.operations.Mod;
import org.codehaus.gant.GantBinding;
import org.jetbrains.jps.ClasspathItem;
import org.jetbrains.jps.Module;
import org.jetbrains.jps.Project;
import org.jetbrains.jps.*;
import org.jetbrains.jps.idea.IdeaProjectLoader;
import org.jetbrains.jps.resolvers.PathEntry;
import java.io.*;
import java.util.*;
@@ -17,6 +15,7 @@ import java.util.*;
* Time: 2:58
* To change this template use File | Settings | File Templates.
*/
public class ProjectWrapper {
// Home directory
private static final String myHomeDir = System.getProperty("user.home");
@@ -24,16 +23,182 @@ public class ProjectWrapper {
// JPS directory
private static final String myJPSDir = ".jps";
// IDEA project structure directory name
private static final String myIDEADir = ".idea";
// JPS directory initialization
private static void initJPSDirectory () {
private static void initJPSDirectory() {
final File f = new File(myHomeDir + File.separator + myJPSDir);
if (! f.exists())
if (!f.exists())
f.mkdir();
}
private static <T> List<T> sort(final Collection<T> coll, final Comparator<? super T> comp) {
List<T> list = new ArrayList<T>();
for (T elem : coll) {
if (elem != null) {
list.add(elem);
}
}
Collections.sort(list, comp);
return list;
}
private static <T extends Comparable<? super T>> List<T> sort(final Collection<T> coll) {
return sort(coll, new Comparator<T>() {
public int compare(T a, T b) {
return a.compareTo(b);
}
});
}
private interface Writable extends Comparable {
public void write(BufferedWriter w);
}
private static void writeln(final BufferedWriter w, final Collection<String> c, final String desc) {
writeln(w, Integer.toString(c.size()));
if (c instanceof List) {
for (String e : c) {
writeln(w, e);
}
} else {
final List<String> sorted = sort(c);
for (String e : sorted) {
writeln(w, e);
}
}
}
private static void writeln(final BufferedWriter w, final Collection<? extends Writable> c) {
writeln(w, Integer.toString(c.size()));
if (c instanceof List) {
for (Writable e : c) {
e.write(w);
}
} else {
final List<? extends Writable> sorted = sort(c);
for (Writable e : sorted) {
e.write(w);
}
}
}
private static void writeln(final BufferedWriter w, final String s) {
try {
w.write(s);
w.newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
private interface Constructor<T> {
public T read(BufferedReader r);
}
private static Constructor<String> myStringConstructor = new Constructor<String>() {
public String read(final BufferedReader r) {
try {
return r.readLine();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
};
private static <T> Collection<T> readMany(final BufferedReader r, final Constructor<T> c, final Collection<T> acc) {
final int size = readInt(r);
for (int i = 0; i < size; i++) {
acc.add(c.read(r));
}
return acc;
}
private static String lookString(final BufferedReader r) {
try {
r.mark(256);
final String s = r.readLine();
r.reset();
return s;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private static void readTag(final BufferedReader r, final String tag) {
try {
final String s = r.readLine();
if (!s.equals(tag))
System.err.println("Parsing error: expected \"" + tag + "\", but found \"" + s + "\"");
} catch (IOException e) {
e.printStackTrace();
}
}
private static String readString(final BufferedReader r) {
try {
return r.readLine();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private static long readLong(final BufferedReader r) {
final String s = readString(r);
try {
return Long.parseLong(s);
} catch (Exception n) {
System.err.println("Parsing error: expected long, but found \"" + s + "\"");
return 0;
}
}
private static int readInt(final BufferedReader r) {
final String s = readString(r);
try {
return Integer.parseInt(s);
} catch (Exception n) {
System.err.println("Parsing error: expected integer, but found \"" + s + "\"");
return 0;
}
}
private static String readStringAttribute(final BufferedReader r, final String tag) {
try {
final String s = r.readLine();
if (s.startsWith(tag))
return s.substring(tag.length());
System.err.println("Parsing error: expected \"" + tag + "\", but found \"" + s + "\"");
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
// File separator replacement
private static final char myFileSeparatorReplacement = '-';
private static final char myFileSeparatorReplacement = '.';
// Original JPS Project
private final Project myProject;
@@ -41,60 +206,596 @@ public class ProjectWrapper {
// Project directory
private final String myRoot;
// Project snapshot file
// Project snapshot file name
private final String myProjectSnapshot;
// Project history
private ProjectSnapshot mySnapshot;
private ProjectSnapshot myPresent;
public interface ClasspathItemWrapper extends Writable {
public List<String> getClassPath(ClasspathKind kind);
}
public ProjectWrapper(final String prjDir) {
public final Constructor<LibraryWrapper> myLibraryWrapperConstructor =
new Constructor<LibraryWrapper>() {
public LibraryWrapper read(final BufferedReader r) {
return new LibraryWrapper(r);
}
};
public class LibraryWrapper implements ClasspathItemWrapper {
final String myName;
final List<String> myClassPath;
public void write(final BufferedWriter w) {
writeln(w, "Library:" + myName);
writeln(w, "Classpath:");
writeln(w, myClassPath, null);
}
public LibraryWrapper(final BufferedReader r) {
myName = readStringAttribute(r, "Library:");
readTag(r, "Classpath:");
myClassPath = (List<String>) readMany(r, myStringConstructor, new ArrayList<String>());
}
public LibraryWrapper(final Library lib) {
lib.forceInit();
myName = lib.getName();
myClassPath = (List<String>) getRelativePaths(lib.getClasspath(), new ArrayList<String>());
}
public String getName() {
return myName;
}
public List<String> getClassPath(final ClasspathKind kind) {
return myClassPath;
}
public int compareTo(Object o) {
return getName().compareTo(((LibraryWrapper) o).getName());
}
}
public final Constructor<ClasspathItemWrapper> myClasspathItemWrapperConstructor =
new Constructor<ClasspathItemWrapper>() {
public ClasspathItemWrapper read(final BufferedReader r) {
final String s = lookString(r);
if (s.startsWith("Library:")) {
return new LibraryWrapper(r);
}
if (s.startsWith("Module:")) {
return new ModuleWrapper(r);
} else {
return new GenericClasspathItemWrapper(r);
}
}
};
public class GenericClasspathItemWrapper implements ClasspathItemWrapper {
final List<String> myClassPath;
final String myType;
public GenericClasspathItemWrapper(final ClasspathItem item) {
if (item instanceof PathEntry)
myType = "PathEntry";
else if (item instanceof JavaSdk)
myType = "JavaSdk";
else if (item instanceof Sdk)
myType = "Sdk";
else
myType = null;
myClassPath = (List<String>) getRelativePaths(item.getClasspathRoots(null), new ArrayList<String>());
}
public GenericClasspathItemWrapper(final BufferedReader r) {
myType = readString(r);
readTag(r, "Classpath:");
myClassPath = (List<String>) readMany(r, myStringConstructor, new ArrayList<String>());
}
public String getType() {
return myType;
}
public List<String> getClassPath(final ClasspathKind kind) {
return myClassPath;
}
public void write(final BufferedWriter w) {
writeln(w, myType);
writeln(w, "Classpath:");
writeln(w, myClassPath, "");
}
public int compareTo(Object o) {
final GenericClasspathItemWrapper w = (GenericClasspathItemWrapper) o;
final int c = getType().compareTo(w.getType());
return
c == 0 ?
(new Object() {
public int compare(Iterator<String> x, Iterator<String> y) {
if (x.hasNext()) {
if (y.hasNext()) {
final int c = x.next().compareTo(y.next());
return c == 0 ? compare(x, y) : c;
}
return 1;
} else if (y.hasNext()) {
return -1;
}
return 0;
}
}
).compare(getClassPath(null).iterator(), w.getClassPath(null).iterator())
: c;
}
}
public final Constructor<FileWrapper> myFileWrapperConstructor =
new Constructor<FileWrapper>() {
public FileWrapper read(final BufferedReader r) {
return new FileWrapper(r);
}
};
public class FileWrapper implements Writable {
final String myName;
final long myModificationTime;
FileWrapper(final File f) {
myName = getRelativePath(f.getAbsolutePath());
myModificationTime = f.lastModified();
}
FileWrapper(final BufferedReader r) {
myName = readString(r);
myModificationTime = 0; // readLong(r);
}
public String getName() {
return myName;
}
public long getStamp() {
return myModificationTime;
}
public void write(final BufferedWriter w) {
writeln(w, getName());
// writeln(w, Long.toString(getStamp()));
}
public int compareTo(Object o) {
return getName().compareTo(((FileWrapper) o).getName());
}
}
public final Constructor<ModuleWrapper> myModuleWrapperConstructor =
new Constructor<ModuleWrapper>() {
public ModuleWrapper read(final BufferedReader r) {
return new ModuleWrapper(r);
}
};
public class ModuleWrapper implements ClasspathItemWrapper {
private class Properties implements Writable {
final Set<String> myRoots;
final Set<FileWrapper> mySources;
final String myOutput;
final Set<FileWrapper> myOutputs;
final long myLatestSource;
final long myEarliestSource;
final long myLatestOutput;
final long myEarliestOutput;
public void write(final BufferedWriter w) {
writeln(w, "Roots:");
writeln(w, myRoots, null);
writeln(w, "Sources:");
writeln(w, mySources);
writeln(w, "Output:");
writeln(w, myOutput == null ? "" : myOutput);
writeln(w, "Outputs:");
writeln(w, myOutputs);
//writeln(w, "EarliestSource:");
//writeln(w, Long.toString(myEarliestSource));
//writeln(w, "LatestSource:");
//writeln(w, Long.toString(myLatestSource));
//writeln(w, "EarliestOutput:");
//writeln(w, Long.toString(myEarliestOutput));
//writeln(w, "LatestOutput:");
//writeln(w, Long.toString(myLatestOutput));
}
public Properties(final BufferedReader r) {
readTag(r, "Roots:");
myRoots = (Set<String>) readMany(r, myStringConstructor, new HashSet<String>());
readTag(r, "Sources:");
mySources = (Set<FileWrapper>) readMany(r, myFileWrapperConstructor, new HashSet<FileWrapper>());
readTag(r, "Output:");
final String s = readString(r);
myOutput = s.equals("") ? null : s;
readTag(r, "Outputs:");
myOutputs = (Set<FileWrapper>) readMany(r, myFileWrapperConstructor, new HashSet<FileWrapper>());
//readTag(r, "EarliestSource:");
myEarliestSource = 0;//readLong(r);
//readTag(r, "LatestSource:");
myLatestSource = 0;//readLong(r);
//readTag(r, "EarliestOutput:");
myEarliestOutput = 0;//readLong(r);
//readTag(r, "LatestOutput:");
myLatestOutput = 0;//readLong(r);
}
public Properties(final List<String> sources, final String output, final Set<String> excludes) {
myRoots = (Set<String>) getRelativePaths(sources, new HashSet<String>());
{
final DirectoryScanner.Result result = DirectoryScanner.getFiles(myRoots, excludes, ProjectWrapper.this);
mySources = result.getFiles();
myEarliestSource = result.getEarliest();
myLatestSource = result.getLatest();
}
{
myOutput = getRelativePath(output);
final DirectoryScanner.Result result = DirectoryScanner.getFiles(myOutput, excludes, ProjectWrapper.this);
myOutputs = result.getFiles();
myEarliestOutput = result.getEarliest();
myLatestOutput = result.getLatest();
}
}
public Set<String> getRoots() {
return myRoots;
}
public Set<FileWrapper> getSources() {
return mySources;
}
public String getOutputPath() {
return myOutput;
}
public Set<FileWrapper> getOutputs() {
return myOutputs;
}
public long getEarliestOutput() {
return myEarliestOutput;
}
public long getLatestOutput() {
return myLatestOutput;
}
public long getEarliestSource() {
return myEarliestSource;
}
public long getLatestSource() {
return myLatestSource;
}
public boolean emptySource() {
return mySources.isEmpty();
}
public boolean emptyOutput() {
return myOutputs.isEmpty();
}
public boolean isOutdated() {
return (!emptySource() && emptyOutput()) || (getLatestSource() > getEarliestOutput());
}
public int compareTo(Object o) {
return 0;
}
}
final String myName;
final Properties mySource;
final Properties myTest;
final Set<String> myExcludes;
final Module myModule;
List<ClasspathItemWrapper> myDependsOn;
final Set<LibraryWrapper> myLibraries;
public void write(final BufferedWriter w) {
writeln(w, "Module:" + myName);
writeln(w, "SourceProperties:");
mySource.write(w);
writeln(w, "TestProperties:");
myTest.write(w);
writeln(w, "Excludes:");
writeln(w, myExcludes, null);
writeln(w, "Libraries:");
writeln(w, myLibraries);
writeln(w, "Dependencies:");
writeln(w, dependsOn());
}
public ModuleWrapper(final BufferedReader r) {
myModule = null;
myName = readStringAttribute(r, "Module:");
readTag(r, "SourceProperties:");
mySource = new Properties(r);
readTag(r, "TestProperties:");
myTest = new Properties(r);
readTag(r, "Excludes:");
myExcludes = (Set<String>) readMany(r, myStringConstructor, new HashSet<String>());
readTag(r, "Libraries:");
myLibraries = (Set<LibraryWrapper>) readMany(r, myLibraryWrapperConstructor, new HashSet<LibraryWrapper>());
readTag(r, "Dependencies:");
myDependsOn = (List<ClasspathItemWrapper>) readMany(r, myClasspathItemWrapperConstructor, new ArrayList<ClasspathItemWrapper>());
}
public ModuleWrapper(final Module m) {
m.forceInit();
myModule = m;
myDependsOn = null;
myName = m.getName();
myExcludes = (Set<String>) getRelativePaths(m.getExcludes(), new HashSet<String>());
mySource = new Properties(m.getSourceRoots(), m.getOutputPath(), myExcludes);
myTest = new Properties(m.getTestRoots(), m.getTestOutputPath(), myExcludes);
myLibraries = new HashSet<LibraryWrapper>();
for (Library lib : m.getLibraries().values()) {
myLibraries.add(new LibraryWrapper(lib));
}
}
public String getName() {
return myName;
}
public Set<String> getSourceRoots() {
return mySource.getRoots();
}
public Set<FileWrapper> getSourceFiles() {
return mySource.getSources();
}
public String getOutputPath() {
return mySource.getOutputPath();
}
public Set<String> getTestSourceRoots() {
return myTest.getRoots();
}
public Set<FileWrapper> getTestSourceFiles() {
return myTest.getSources();
}
public String getTestOutputPath() {
return myTest.getOutputPath();
}
public List<ClasspathItemWrapper> dependsOn() {
if (myDependsOn != null)
return myDependsOn;
myDependsOn = new ArrayList<ClasspathItemWrapper>();
for (Module.ModuleDependency dep : myModule.getDependencies()) {
final ClasspathItem cpi = dep.getItem();
if (cpi instanceof Module) {
myDependsOn.add(getModule(((Module) cpi).getName()));
} else if (cpi instanceof Library) {
myDependsOn.add(new LibraryWrapper((Library) cpi));
} else {
myDependsOn.add(new GenericClasspathItemWrapper(cpi));
}
}
return myDependsOn;
}
public List<String> getClassPath(final ClasspathKind kind) {
final List<String> result = new ArrayList<String>();
result.add(getOutputPath());
if (kind.isTestsIncluded()) {
result.add(getTestOutputPath());
}
return result;
}
public boolean isOutdated(final boolean tests) {
return mySource.isOutdated() || (tests && myTest.isOutdated());
}
public int compareTo(Object o) {
return getName().compareTo(((ModuleWrapper) o).getName());
}
}
final Map<String, ModuleWrapper> myModules = new HashMap<String, ModuleWrapper>();
final Map<String, LibraryWrapper> myLibraries = new HashMap<String, LibraryWrapper>();
final ProjectWrapper myHistory;
public ModuleWrapper getModule(final String name) {
return myModules.get(name);
}
public LibraryWrapper getLibrary(final String name) {
return myLibraries.get(name);
}
public Collection<LibraryWrapper> getLibraries() {
return myLibraries.values();
}
public Collection<ModuleWrapper> getModules() {
return myModules.values();
}
private ProjectWrapper(final String prjDir) {
myProject = new Project(new GantBinding());
myRoot = new File (prjDir).getAbsolutePath();
myRoot = new File(prjDir).getAbsolutePath();
myProjectSnapshot = myHomeDir + File.separator + myJPSDir + File.separator + myRoot.replace(File.separatorChar, myFileSeparatorReplacement);
IdeaProjectLoader.loadFromPath(myProject, getAbsolutePath(myIDEADir));
for (Module m : myProject.getModules().values()) {
myModules.put(m.getName(), new ModuleWrapper(m));
}
for (Library l : myProject.getLibraries().values()) {
myLibraries.put(l.getName(), new LibraryWrapper(l));
}
myHistory = loadSnapshot();
}
public String getAbsolutePath(final String relative) {
if (relative == null)
return relative;
if (new File(relative).isAbsolute())
return relative;
return myRoot + File.separator + relative;
}
public String getRelativePath(final String absolute) {
if (absolute == null)
return absolute;
if (absolute.startsWith(myRoot)) {
return absolute.substring(myRoot.length() + 1);
}
return absolute;
}
public Collection<String> getAbsolutePaths(final Collection<String> paths, final Collection<String> result) {
for (String path : paths) {
if (path != null)
result.add(getAbsolutePath(path));
}
return result;
}
public Collection<String> getRelativePaths(final Collection<String> paths, final Collection<String> result) {
for (String path : paths) {
if (path != null)
result.add(getRelativePath(path));
}
return result;
}
private boolean isHistory() {
return myProject == null;
}
private ProjectWrapper(final BufferedReader r) {
myProject = null;
myHistory = null;
myRoot = readStringAttribute(r, "Root:");
myProjectSnapshot = myHomeDir + File.separator + myJPSDir + File.separator + myRoot.replace(File.separatorChar, myFileSeparatorReplacement);
readTag(r, "Libraries:");
final Set<LibraryWrapper> libs = (Set<LibraryWrapper>) readMany(r, myLibraryWrapperConstructor, new HashSet<LibraryWrapper>());
for (LibraryWrapper l : libs) {
myLibraries.put(l.getName(), l);
}
readTag(r, "Modules:");
final Set<ModuleWrapper> mods = (Set<ModuleWrapper>) readMany(r, myModuleWrapperConstructor, new HashSet<ModuleWrapper>());
for (ModuleWrapper m : mods) {
myModules.put(m.getName(), m);
}
}
public void write(final BufferedWriter w) {
writeln(w, "Root:" + myRoot);
writeln(w, "Libraries:");
writeln(w, getLibraries());
writeln(w, "Modules:");
writeln(w, getModules());
}
private String getProjectSnapshotFileName() {
return myProjectSnapshot;
}
private ProjectSnapshot loadSnapshot() {
private ProjectWrapper loadSnapshot() {
initJPSDirectory();
ProjectSnapshot result = null;
try {
final String path = getProjectSnapshotFileName();
final BufferedReader r = new BufferedReader(new FileReader(getProjectSnapshotFileName()));
final ProjectWrapper w = new ProjectWrapper(r);
r.close();
byte[] buffer = new byte[(int) new File(path).length()];
BufferedInputStream f = new BufferedInputStream(new FileInputStream(path));
f.read(buffer);
f.close();
result = new ProjectSnapshot(new String(buffer));
}
catch (FileNotFoundException e) {
}
catch (IOException e) {
return w;
} catch (FileNotFoundException e) {
} catch (IOException e) {
e.printStackTrace();
}
return result;
return null;
}
private void saveSnapshot() {
initJPSDirectory();
final ProjectSnapshot snapshot = StatusCollector.collectHistory(myProject);
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(getProjectSnapshotFileName()));
bw.write(snapshot.toString());
write(bw);
bw.close();
} catch (IOException e) {
@@ -102,14 +803,12 @@ public class ProjectWrapper {
}
}
public void load() {
IdeaProjectLoader.loadFromPath(myProject, myRoot);
mySnapshot = loadSnapshot();
myPresent = StatusCollector.collectHistory(myProject);
public static ProjectWrapper load(final String path) {
return new ProjectWrapper(path);
}
public void report(final String module) {
final ModuleStatus m = myPresent.myModuleHistories.get(module);
final ModuleWrapper m = getModule(module);
if (m == null) {
System.out.println("No module \"" + module + "\" found in project \"");
@@ -120,10 +819,36 @@ public class ProjectWrapper {
}
private boolean structureChanged() {
if (mySnapshot == null)
if (myHistory == null)
return true;
return myPresent.structureChanged(mySnapshot);
try {
final StringWriter my = new StringWriter();
final StringWriter history = new StringWriter();
myHistory.write(new BufferedWriter(my));
write(new BufferedWriter(history));
my.close();
history.close();
final String myString = my.getBuffer().toString();
final String hisString = history.getBuffer().toString();
FileWriter f1 = new FileWriter("/home/db/tmp/1.jps");
FileWriter f2 = new FileWriter("/home/db/tmp/2.jps");
f1.write(myString);
f2.write(hisString);
f1.close();
f2.close();
return !myString.equals(hisString);
} catch (IOException e) {
e.printStackTrace();
return true;
}
}
public void report() {
@@ -131,7 +856,7 @@ public class ProjectWrapper {
System.out.println("Project \"" + myRoot + "\" report:");
if (mySnapshot == null) {
if (myHistory == null) {
System.out.println(" no project history found");
} else {
if (structureChanged()) {
@@ -141,9 +866,9 @@ public class ProjectWrapper {
}
if (moduleReport) {
for (ModuleStatus mh : myPresent.myModuleHistories.values()) {
System.out.println(" module " + mh.myName + " " + (mh.isOutdated(false) ? "is outdated" : "is up-to-date"));
System.out.println(" module " + mh.myName + " tests " + (mh.isOutdated(true) ? "are outdated" : "are up-to-date"));
for (ModuleWrapper m : myModules.values()) {
System.out.println(" module " + m.getName() + " " + (m.isOutdated(false) ? "is outdated" : "is up-to-date"));
System.out.println(" module " + m.getName() + " tests " + (m.isOutdated(true) ? "are outdated" : "are up-to-date"));
}
}
}
@@ -169,7 +894,7 @@ public class ProjectWrapper {
final List<Module> modules = new ArrayList<Module>();
for (Map.Entry<String, ModuleStatus> entry : myPresent.myModuleHistories.entrySet()) {
for (Map.Entry<String, ModuleWrapper> entry : myModules.entrySet()) {
if (entry.getValue().isOutdated(tests))
modules.add(myProject.getModules().get(entry.getKey()));
}
@@ -189,7 +914,7 @@ public class ProjectWrapper {
private void makeModules(final List<Module> initial, final boolean tests) {
final Set<Module> modules = new HashSet<Module>();
final Map<Module, Set<Module>> reversedDependencies = new HashMap<Module, Set<Module>> ();
final Map<Module, Set<Module>> reversedDependencies = new HashMap<Module, Set<Module>>();
for (Module m : myProject.getModules().values()) {
for (Module.ModuleDependency mdep : m.getDependencies()) {
@@ -199,7 +924,7 @@ public class ProjectWrapper {
Set<Module> sm = reversedDependencies.get(cpi);
if (sm == null) {
sm = new HashSet<Module> ();
sm = new HashSet<Module>();
reversedDependencies.put((Module) cpi, sm);
}
@@ -244,7 +969,7 @@ public class ProjectWrapper {
return;
}
final ModuleStatus h = myPresent.myModuleHistories.get(modName);
final ModuleWrapper h = getModule(modName);
if (h != null && !h.isOutdated(tests) && !force) {
System.out.println("Module \"" + modName + "\" in project \"" + myRoot + "\" is up-to-date.");
return;
@@ -1,186 +0,0 @@
package org.jetbrains.ether;
import com.sun.tools.javac.util.Pair;
import org.jetbrains.jps.*;
import org.jetbrains.jps.resolvers.PathEntry;
import java.util.*;
/**
* Created by IntelliJ IDEA.
* User: db
* Date: 18.11.10
* Time: 19:57
* To change this template use File | Settings | File Templates.
*/
public class StatusCollector {
private static Pair<Long, Long> myDefaultPair = new Pair<Long, Long> (Long.MAX_VALUE, 0l);
private static Pair<Long, Long> join (final Pair<Long, Long> a, final Pair<Long, Long> b) {
if (a == null)
return b;
if (b == null)
return a;
return new Pair<Long, Long> (Math.min(a.fst, b.fst), Math.max(a.snd, b.snd));
}
private static Comparator<Library> myLibraryComparator = new Comparator<Library>() {
public int compare (Library a, Library b) {
return a.getName().compareTo(b.getName());
}
};
private static Comparator<Module> myModuleComparator = new Comparator<Module>() {
public int compare (Module a, Module b) {
return a.getName().compareTo(b.getName());
}
};
private static <T> List<T> prepare (final Collection<T> coll, final Comparator<T> comp) {
List<T> list = new ArrayList<T> ();
for (T elem : coll) {
if (elem != null) {
list.add(elem);
}
}
Collections.sort(list, comp);
return list;
}
private static <T extends Comparable<? super T>> List<T> prepare (final Collection<T> coll) {
return prepare(coll, new Comparator<T> () {
public int compare (T a, T b) {
return a.compareTo(b);
}
});
}
private static void listToBuffer (StringBuffer buf, final List list) {
for (Object o : prepare (list)) {
if (o instanceof String) {
buf.append(o + "\n");
}
else {
buf.append("*** <" + o.getClass().getName() + "> is not String ***\n");
}
}
}
private static void namedListToBuffer (StringBuffer buf, final String name, final List list) {
buf.append(name + ":\n");
listToBuffer(buf, list);
}
private static Pair<Long, Long> directoryToBuffer (StringBuffer buf, final String dir, final List<String> excludes) {
if (dir != null) {
final DirectoryScanner.Result result = DirectoryScanner.getFiles(dir, excludes);
for (String name : prepare (result.myFiles)) {
buf.append(name + "\n");
}
return new Pair<Long, Long> (result.myEarliest, result.myLatest);
}
return myDefaultPair;
}
private static Pair<Long, Long> sourceRootToBuffer (StringBuffer buf, final String name, final List<String> dir, final List<String> excludes) {
Pair<Long, Long> result = myDefaultPair;
buf.append(name + ":\n");
for (String d : prepare (dir)) {
if (dir != null) {
buf.append(d + ":\n");
result = join (result, directoryToBuffer(buf, d, excludes));
}
}
return result;
}
private static void classPathItemToBuffer (StringBuffer buf, final ClasspathItem cpi, boolean all) {
final ClasspathKind[] allKinds = {ClasspathKind.PRODUCTION_COMPILE, ClasspathKind.PRODUCTION_RUNTIME, ClasspathKind.TEST_COMPILE, ClasspathKind.TEST_RUNTIME};
final ClasspathKind[] oneKind = {ClasspathKind.PRODUCTION_COMPILE};
final ClasspathKind[] kinds = all ? allKinds : oneKind;
for (int i=0; i<kinds.length; i++) {
final ClasspathKind kind = kinds[i];
final String name = kind.name();
namedListToBuffer(buf, "classpath" + (all ? " (" + name + ")" : ""), cpi.getClasspathRoots(kind));
}
}
public static void libraryToBuffer (StringBuffer buf, final Library library) {
library.forceInit();
buf.append ("Library: " + library.getName() + "\n");
classPathItemToBuffer(buf, library, false);
}
public static ModuleStatus moduleToBuffer (StringBuffer buf, final Module module) {
buf.append("Module: " + module.getName() + "\n");
classPathItemToBuffer(buf, module, true);
namedListToBuffer(buf, "Excludes", module.getExcludes());
buf.append("Libraries:\n");
for (Library lib : prepare (module.getLibraries().values(), myLibraryComparator)) {
libraryToBuffer(buf, lib);
}
long ss = sourceRootToBuffer(buf, "SourceRoots", module.getSourceRoots(), module.getExcludes()).snd;
buf.append("OutputPath: " + module.getOutputPath() + "\n");
long os = directoryToBuffer(buf, module.getOutputPath(), null).fst;
long tss = sourceRootToBuffer(buf, "TestRoots", module.getTestRoots(), module.getExcludes()).snd;
buf.append("TestOutputPath: " + module.getTestOutputPath() + "\n");
long tos = directoryToBuffer(buf, module.getTestOutputPath(), null).fst;
buf.append("Dependencies:\n");
for (Module.ModuleDependency dep : module.getDependencies()){
final ClasspathItem item = dep.getItem();
if (item instanceof Module) {
buf.append("module " + ((Module) item).getName() + "\n");
}
else if (item instanceof Library) {
buf.append("library " + ((Library) item).getName() + "\n");
}
else if (item instanceof JavaSdk) {
buf.append("javaSdk " + ((JavaSdk) item).getName() + "\n");
}
else if (item instanceof Sdk) {
buf.append("Sdk " + ((Sdk) item).getName() + "\n");
}
else if (item instanceof PathEntry) {
buf.append("pathEntry " + ((PathEntry) item).getPath() + "\n");
}
else {
buf.append("unknown ClasspathItem implementation in dependencies: <" + item.getClass().getName() + ">\n");
}
}
return new ModuleStatus(module.getName(), ss, os, tss, tos);
}
public static ProjectSnapshot collectHistory (final Project prj) {
StringBuffer buf = new StringBuffer();
Map<String, ModuleStatus> moduleHistories = new HashMap<String, ModuleStatus> ();
for (Library lib : prepare (prj.getLibraries().values(), myLibraryComparator)) {
libraryToBuffer(buf, lib);
}
for (Module mod : prepare (prj.getModules().values(), myModuleComparator)) {
moduleHistories.put(mod.getName(), moduleToBuffer(buf, mod));
}
return new ProjectSnapshot(buf.toString(), moduleHistories);
}
}