diff --git a/jps/.idea/modules.xml b/jps/.idea/modules.xml
index d8e1dbbd8f97..ae879f386b29 100644
--- a/jps/.idea/modules.xml
+++ b/jps/.idea/modules.xml
@@ -4,6 +4,7 @@
+
diff --git a/jps/antLayout/antlayout.iml b/jps/antLayout/antlayout.iml
new file mode 100644
index 000000000000..c053808175a3
--- /dev/null
+++ b/jps/antLayout/antlayout.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jps/antLayout/src/jetbrains/antlayout/antlib.xml b/jps/antLayout/src/jetbrains/antlayout/antlib.xml
new file mode 100755
index 000000000000..e1100dea26af
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/antlib.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/Container.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/Container.java
new file mode 100755
index 000000000000..e87c1c8e0e43
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/Container.java
@@ -0,0 +1,118 @@
+package jetbrains.antlayout.datatypes;
+
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.ZipFileSet;
+import org.apache.tools.ant.BuildException;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.HashSet;
+
+import jetbrains.antlayout.util.TempFileFactory;
+import jetbrains.antlayout.util.LayoutFileSet;
+
+/**
+ * @author max
+ */
+public abstract class Container extends Content {
+ private List filesets = new ArrayList();
+ private List children = new ArrayList();
+
+ private String excludes = null;
+ private String includes = null;
+
+ public void addFileset(FileSet set) {
+ filesets.add(set);
+ }
+
+ public void addZipfileset(ZipFileSet set) {
+ filesets.add(set);
+ }
+
+ public void addDir(DirContainer container) {
+ children.add(container);
+ }
+
+ public void addJar(JarContainer container) {
+ children.add(container);
+ }
+
+ public void addZip(ZipContainer container) {
+ children.add(container);
+ }
+
+ public void addContainer(Container container) {
+ children.add(container);
+ }
+
+ public void addModule(IdeaModule module) {
+ filesets.add(module);
+ }
+
+ public List getFilesets() {
+ return filesets;
+ }
+
+ public List getChildren() {
+ return children;
+ }
+
+
+ public void setExcludes(String excludes) {
+ this.excludes = excludes;
+ }
+
+ public void setIncludes(String includes) {
+ this.includes = includes;
+ }
+
+ public List build(TempFileFactory temp) {
+ Set result = new HashSet();
+ for (FileSet set : filesets) {
+ result.add(createCopy(set));
+ }
+
+ for (Container child : children) {
+ for (LayoutFileSet set : child.build(temp)) {
+ result.add(createCopy(set));
+ }
+ }
+
+ ArrayList list = new ArrayList(result);
+ for (LayoutFileSet set : list) {
+ if (includes != null) {
+ set.setIncludes(includes);
+ }
+
+ if (excludes != null) {
+ set.setExcludes(excludes);
+ }
+ }
+
+ return list;
+ }
+
+ protected LayoutFileSet createCopy(FileSet set) {
+ if (set instanceof IdeaModule) {
+ return new IdeaModule((IdeaModule) set);
+ }
+ if (set instanceof ZipFileSet) {
+ return new LayoutFileSet((ZipFileSet) set.clone());
+ } else {
+ return new LayoutFileSet((FileSet) set.clone());
+ }
+ }
+
+ public void validateArguments() throws BuildException {
+ for (Container child : children) {
+ child.validateArguments();
+ }
+
+ for (FileSet set : filesets) {
+ if (set instanceof IdeaModule) {
+ ((IdeaModule) set).validateArguments();
+ }
+ }
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/Content.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/Content.java
new file mode 100755
index 000000000000..f306200d25a0
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/Content.java
@@ -0,0 +1,18 @@
+package jetbrains.antlayout.datatypes;
+
+import org.apache.tools.ant.types.DataType;
+import org.apache.tools.ant.BuildException;
+
+import java.util.List;
+
+import jetbrains.antlayout.util.TempFileFactory;
+import jetbrains.antlayout.util.LayoutFileSet;
+
+/**
+ * @author max
+ */
+public abstract class Content extends DataType {
+ public abstract List build(TempFileFactory temp);
+
+ public abstract void validateArguments() throws BuildException;
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/DirContainer.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/DirContainer.java
new file mode 100755
index 000000000000..c5f334543e4c
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/DirContainer.java
@@ -0,0 +1,41 @@
+package jetbrains.antlayout.datatypes;
+
+import jetbrains.antlayout.util.TempFileFactory;
+import jetbrains.antlayout.util.LayoutFileSet;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tools.ant.BuildException;
+
+/**
+ * @author max
+ */
+public class DirContainer extends Container {
+ private String dirName;
+
+ public void setName(String name) {
+ dirName = name;
+ }
+
+ public List build(TempFileFactory temp) {
+ List unprefixed = super.build(temp);
+ List prefixed = new ArrayList();
+
+ for (LayoutFileSet set : unprefixed) {
+ LayoutFileSet copy = createCopy(set);
+ copy.setPrefix(dirName + "/" + set.getPrefix(getProject()));
+ prefixed.add(copy);
+ }
+
+ return prefixed;
+ }
+
+
+ public void validateArguments() throws BuildException {
+ super.validateArguments();
+ if (dirName == null) {
+ throw new BuildException("dirname attribute must be specified for direntry");
+ }
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/IdeaModule.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/IdeaModule.java
new file mode 100755
index 000000000000..7435db1053d7
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/IdeaModule.java
@@ -0,0 +1,65 @@
+package jetbrains.antlayout.datatypes;
+
+import jetbrains.antlayout.util.LayoutFileSet;
+import org.apache.tools.ant.BuildException;
+
+import java.io.File;
+
+/**
+ * @author max
+ */
+public class IdeaModule extends LayoutFileSet {
+ private String name;
+
+ public IdeaModule() {
+ }
+
+ public IdeaModule(IdeaModule fileset) {
+ super(fileset);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ setDir(getMainOutput());
+ }
+
+ private File getMainOutput() {
+ String common = getProject().getProperty("modules.output");
+ if (common != null) {
+ return new File(new File(common), "production/" + name);
+ }
+
+ String adhoc = getProject().getProperty("module." + name +".output.main");
+ return adhoc != null ? new File(adhoc) : null;
+ }
+
+ public void validateArguments() throws BuildException {
+ if (name == null) {
+ throw new BuildException("name attribute must be specified for moduleentry");
+ }
+
+ File main = getMainOutput();
+
+ if (main == null || !main.exists()) {
+ throw new BuildException("No production output found for module " + name +
+ ". Either modules.output property references project output that doesn't contain this module or " +
+ "module." + name +".output.main is not defined or references non-existing directory.");
+ }
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ IdeaModule that = (IdeaModule) o;
+ return getDir(getProject()).equals(that.getDir(getProject()));
+ }
+
+ public int hashCode() {
+ return getDir(getProject()).hashCode();
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/JarContainer.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/JarContainer.java
new file mode 100755
index 000000000000..d27918cd69d6
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/JarContainer.java
@@ -0,0 +1,45 @@
+package jetbrains.antlayout.datatypes;
+
+import org.apache.tools.ant.taskdefs.Zip;
+import org.apache.tools.ant.taskdefs.Jar;
+import org.apache.tools.ant.taskdefs.Manifest;
+import org.apache.tools.ant.taskdefs.ManifestException;
+import org.apache.tools.ant.types.ZipFileSet;
+import org.apache.tools.ant.types.Path;
+
+import java.io.File;
+
+/**
+ * @author max
+ */
+public class JarContainer extends ZipContainer {
+ protected Zip createTask() {
+ Jar task = new Jar();
+ task.setTaskName("jar");
+ return task;
+ }
+
+ public void setIndex(boolean flag) {
+ ((Jar) task).setIndex(flag);
+ }
+
+ public void setManifestEncoding(String manifestEncoding) {
+ ((Jar) task).setManifestEncoding(manifestEncoding);
+ }
+
+ public void setManifest(File manifestFile) {
+ ((Jar) task).setManifest(manifestFile);
+ }
+
+ public void setFilesetmanifest(Jar.FilesetManifestConfig config) {
+ ((Jar) task).setFilesetmanifest(config);
+ }
+
+ public void addConfiguredManifest(Manifest newManifest) throws ManifestException {
+ ((Jar) task).addConfiguredManifest(newManifest);
+ }
+
+ public void addMetainf(ZipFileSet fs) {
+ ((Jar) task).addMetainf(fs);
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/RootContainer.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/RootContainer.java
new file mode 100755
index 000000000000..e619e48b233b
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/RootContainer.java
@@ -0,0 +1,53 @@
+package jetbrains.antlayout.datatypes;
+
+import jetbrains.antlayout.util.TempFileFactory;
+import jetbrains.antlayout.util.LayoutFileSet;
+
+import java.io.File;
+import java.util.List;
+import java.util.Collections;
+
+import org.apache.tools.ant.taskdefs.Copy;
+import org.apache.tools.ant.BuildException;
+
+/**
+ * @author max
+ */
+public class RootContainer extends Container {
+ private File destDirectory;
+
+ public RootContainer(File destDirectory) {
+ this.destDirectory = destDirectory;
+ }
+
+
+ public List build(TempFileFactory temp) {
+ List built = super.build(temp);
+ for (LayoutFileSet set : built) {
+ copySet(set);
+ }
+
+ return Collections.emptyList();
+ }
+
+ private void copySet(LayoutFileSet set) {
+ Copy task = new Copy();
+ task.setTaskName("copy");
+ task.setProject(getProject());
+ String prefix = set.getPrefix(getProject());
+ File target = prefix.length() > 0 ? new File(destDirectory, prefix + "/") : destDirectory;
+
+ target.mkdirs();
+
+ task.setTodir(target);
+ LayoutFileSet unprefixed = (LayoutFileSet) set.clone();
+ unprefixed.setPrefix("");
+
+ task.addFileset(unprefixed);
+ task.perform();
+ }
+
+ public void validateArguments() throws BuildException {
+ super.validateArguments();
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/datatypes/ZipContainer.java b/jps/antLayout/src/jetbrains/antlayout/datatypes/ZipContainer.java
new file mode 100755
index 000000000000..f00fd01fad32
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/datatypes/ZipContainer.java
@@ -0,0 +1,84 @@
+package jetbrains.antlayout.datatypes;
+
+import jetbrains.antlayout.util.TempFileFactory;
+import jetbrains.antlayout.util.LayoutFileSet;
+import org.apache.tools.ant.taskdefs.Zip;
+import org.apache.tools.ant.BuildException;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author max
+ */
+public class ZipContainer extends Container {
+ private String name;
+ protected Zip task;
+
+ public ZipContainer() {
+ task = createTask();
+ task.setCompress(true); // Default compress is false
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List build(TempFileFactory temp) {
+ List built = super.build(temp);
+ File dest = temp.allocateTempFile(name);
+
+ task.setProject(getProject());
+ task.setDestFile(dest);
+
+ for (LayoutFileSet set : built) {
+ task.addZipfileset(set);
+ }
+
+ LayoutFileSet result = new LayoutFileSet();
+ result.setFile(dest);
+
+ task.perform();
+
+ return Arrays.asList(result);
+ }
+
+ protected Zip createTask() {
+ Zip task = new Zip();
+ task.setTaskName("zip");
+ return task;
+ }
+
+ public void setCompress(boolean compress) {
+ task.setCompress(compress);
+ }
+
+ public void setFilesonly(boolean f) {
+ task.setFilesonly(f);
+ }
+
+ public void setDuplicate(Zip.Duplicate df) {
+ task.setDuplicate(df);
+ }
+
+ public void setEncoding(String encoding) {
+ task.setEncoding(encoding);
+ }
+
+ public void setBasedir(File baseDir) {
+ task.setBasedir(baseDir);
+ }
+
+ public void validateArguments() throws BuildException {
+ super.validateArguments();
+
+ if (name == null) {
+ throw new BuildException("name attribute must be specified for zipentry or jarentry");
+ }
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/tasks/LayoutTask.java b/jps/antLayout/src/jetbrains/antlayout/tasks/LayoutTask.java
new file mode 100755
index 000000000000..09ac536fee64
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/tasks/LayoutTask.java
@@ -0,0 +1,85 @@
+package jetbrains.antlayout.tasks;
+
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.BuildException;
+import jetbrains.antlayout.datatypes.*;
+import jetbrains.antlayout.util.TempFileFactory;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.io.File;
+
+/**
+ * @author max
+ */
+public class LayoutTask extends Task {
+ private List containers = new ArrayList();
+ private File destDir;
+
+ public void addDir(DirContainer container) {
+ containers.add(container);
+ }
+
+ public void addJar(JarContainer container) {
+ containers.add(container);
+ }
+
+ public void addZip(ZipContainer container) {
+ containers.add(container);
+ }
+
+ public void setTodir(File dir) {
+ destDir = dir;
+ }
+
+ public File getDestDir() {
+ return destDir;
+ }
+
+ public void execute() throws BuildException {
+ validateArguments();
+
+ RootContainer root = new RootContainer(destDir);
+ root.setProject(getProject());
+ for (Container container : containers) {
+ root.addContainer(container);
+ }
+
+ final File tempDir = new File(destDir, "___tmp___");
+ tempDir.mkdirs();
+
+ root.build(new TempFileFactory() {
+ int counter = 0;
+ public File allocateTempFile(String name) {
+ File localTmp = new File(tempDir, "_" + counter + "/");
+ counter++;
+ localTmp.mkdirs();
+ return new File(localTmp, name);
+ }
+ });
+
+ deleteRecursively(tempDir);
+ }
+
+ protected void deleteRecursively(File d) {
+ if (d.isDirectory()) {
+ for (File file : d.listFiles()) {
+ deleteRecursively(file);
+ }
+ }
+
+ if (!d.delete()) {
+ throw new BuildException("Unable to delete file " + d.getAbsolutePath());
+ }
+ }
+
+ private void validateArguments() throws BuildException {
+ if (destDir == null) {
+ throw new BuildException("todir attribute must be specified");
+ }
+
+ for (Container container : containers) {
+ container.validateArguments();
+ }
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/util/LayoutFileSet.java b/jps/antLayout/src/jetbrains/antlayout/util/LayoutFileSet.java
new file mode 100755
index 000000000000..178d08bfa5d0
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/util/LayoutFileSet.java
@@ -0,0 +1,20 @@
+package jetbrains.antlayout.util;
+
+import org.apache.tools.ant.types.ZipFileSet;
+import org.apache.tools.ant.types.FileSet;
+
+/**
+ * @author max
+ */
+public class LayoutFileSet extends ZipFileSet {
+ public LayoutFileSet() {
+ }
+
+ public LayoutFileSet(FileSet fileset) {
+ super(fileset);
+ }
+
+ public LayoutFileSet(ZipFileSet fileset) {
+ super(fileset);
+ }
+}
diff --git a/jps/antLayout/src/jetbrains/antlayout/util/TempFileFactory.java b/jps/antLayout/src/jetbrains/antlayout/util/TempFileFactory.java
new file mode 100755
index 000000000000..26b22013b619
--- /dev/null
+++ b/jps/antLayout/src/jetbrains/antlayout/util/TempFileFactory.java
@@ -0,0 +1,10 @@
+package jetbrains.antlayout.util;
+
+import java.io.File;
+
+/**
+ * @author max
+ */
+public interface TempFileFactory {
+ File allocateTempFile(String name);
+}
diff --git a/jps/build.gant b/jps/build.gant
index 641d30b11a2b..8f7505938be4 100644
--- a/jps/build.gant
+++ b/jps/build.gant
@@ -3,13 +3,30 @@ import org.jetbrains.jps.*
includeTool << Jps
def projectHome = "."
+def libs = "$projectHome/lib/"
project.targetFolder = "${projectHome}/build"
-module("jps") {
+
+library("ANT") {
+ new File(libs).eachFile{ jar ->
+ def path = jar.absolutePath
+ def name = jar.name
+ if (name.startsWith("ant")) {
+ classpath path
+ }
+ }
+}
+
+module("JPS") {
src "${projectHome}/src"
}
+module("antlayout") {
+ classpath ANT
+ src "${projectHome}/antLayout/src"
+}
+
target('default' : 'Default target') {
project.clean()
long start = System.currentTimeMillis()
@@ -17,9 +34,11 @@ target('default' : 'Default target') {
layout("${project.targetFolder}/deploy") {
jar("jps.jar") {
- module("jps")
- zipfileset(src: "${projectHome}/lib/javac2.jar")
- zipfileset(src: "${projectHome}/lib/antlayout.jar")
+ module("JPS")
+ module("antlayout")
+ zipfileset(src: "${projectHome}/lib/javac2.jar") {
+ exclude (name: "JDOM*.class")
+ }
}
}
diff --git a/jps/lib/ant-1.7.1.jar b/jps/lib/ant-1.7.1.jar
new file mode 100644
index 000000000000..704717779f6d
Binary files /dev/null and b/jps/lib/ant-1.7.1.jar differ