pax_global_header00006660000000000000000000000064124357356640014531gustar00rootroot0000000000000052 comment=c76ef37008d1dbb074ef931ac4e5d684a01a7700 ivyplusplus-1.14/000077500000000000000000000000001243573566400140755ustar00rootroot00000000000000ivyplusplus-1.14/.gitignore000066400000000000000000000001141243573566400160610ustar00rootroot00000000000000.classpath .project .settings escudo-upload.key bin build dist lib ivyCache ivyplusplus-1.14/LICENSE000066400000000000000000000020471243573566400151050ustar00rootroot00000000000000Copyright © 2010 Reinier Zwitserloot. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ivyplusplus-1.14/README.markdown000066400000000000000000000256101243573566400166020ustar00rootroot00000000000000# com.zwitserloot.ivyplusplus `com.zwitserloot.ivyplusplus` is a jar containing [Apache Ivy](http://ant.apache.org/ivy/) as well as a few useful constructs built on top of it. Aside from ivy itself, you get a few extra tasks and a command line tool that creates a new project by filling out a skeleton build.xml and ivy configuration. ## How to use Run `java -jar ivyplusplus.jar --help` for more information on how to create a skeleton project. _Supported since ipp 1.5_ For a more thorough example, just like at the build file of this very project (com.zwitserloot.ivyplusplus eats its own dog food). ## Developing com.zwitserloot.ivyplusplus in eclipse Run `ant eclipse` first, then just load the main directory of the project as eclipse project. ## Developing com.zwitserloot.ivyplusplus in intellij Run `ant intellij` first, then just load the main directory of the project as intellij project. ## Extra Tasks ### `` - creates intellij project files from your ivy configuration. Specify your preferred target/source JVM as attribute named 'source'. Specify the target directory as attribute named 'todir' (default: project dir, which is what you should leave it at unless you know what you are doing or want to test). First specify all the configurations you need with inner `` constructs. Each such configuration will be turned into a library set. 'sources' is optional, of course. All artifacts that would be downloaded when resolving _build_ will be added to this library set, and all artifacts that would be downloaded when resolving _contrib_ are added to this library set as sources. Finally, create intellij modules with inner `` entries. These modules will be dependent on the listed library sets (which you just made using ``). The `` tag should include nested `` entries. To enable annotation processing, include `` inside your `` task. intellijgen will also generate the project settings (warnings, errors, source and target compatibility, formatters, styles, etcetera) if you want, by including the `` element. Put ant resource elements inside. To write your own file, configure a project the way you want it, then mix together all the various `` elements in the files in your `.idea` directory. `intellijgen` knows how to sort each element back into the appropriate file. Note that intellij won't itself actually download any of the files, so it would be a good idea to run `` on the needed confs first. Example: _Supported since ipp 1.4_ ### `` - creates eclipse project files from your ivy configuration. Specify your preferred target/source JVM as attribute named 'source'. Specify the target directory as attribute named 'todir' (default: project dir, which is what you should leave it at unless you know what you are doing or want to test). Then, specify each source dir with an inner `` element, with an optional attribute named `optional="true"` for optional sources. For annotation processing, `.apt_generated` is automatically added as optional source dir for you. Specify ivy configuration using inner elements like so: `` - this will add all artifacts that would be downloaded when resolving _build_ to the eclipse classpath, and if a certain dependency would also download some files for the _contrib_ configuration, attaches those as sources. You can specify multiple configurations, and if a certain artifact is in multiple configurations, only the one from the highest listed 'conf' element is used. `sources` is of course optional. If you have apt processors, specify them with ``. If you have separate jar files, you can specify these with ``. To set up the eclipse project so that sibling/child projects also under active development are registered as project dependencies instead of dependencies on the ivy artifacts, use ``; this will look for `../your.org.projname/.project` relative to the current directory, and, _only if that file exists_, it will replace any ivy dependency on the stated org/name pair (of any version!) with that project. If that file does not exist, no warning or error is generated and the normal dependency is inserted. This way, a 'fresh' clone from a source repo compiles cleanly, but you can replace any dependency with tandem development on that project by just checking it out into the same workspace and rerunning 'ant eclipse'. eclipsegen will also generate the project settings (warnings, errors, source and target compatibility, formatters, styles, etcetera) if you want, by including the `` element. Put eclipse settings properties inside as plain text, as well as ant resource elements. If any of the following keys aren't defined, they will be added based on the `source` attribute of eclipsegen: * `org.eclipse.jdt.core.compiler.processAnnotations` - disabled for 1.5, enabled for anything above that. * `org.eclipse.jdt.core.compiler.source` - set to 'source' value. * `org.eclipse.jdt.core.compiler.compliance` - set to 'source' value. * `org.eclipse.jdt.core.compiler.codegen.targetPlatform` - set to 'source' value. To write your own file, configure a project the way you want it, then mix together all the various files in the `.settings` directory. `eclipsegen` knows how to sort each key back into the appropriate file. Note that eclipsegen won't itself actually download any of the files, so it would be a good idea to run `` on the needed confs first. Example: org.eclipse.jdt.core.formatter.lineSplit=100 _Supported since ipp 1.0_ ### `` - Error out or set a property if available version of ivyplusplus is not sufficient. Ivy takes care of version control, but who will take care of Ivy's own version control? With this task you can error out (or set a property) if the cached ivyplusplus.jar is a version that's not equal to/higher than what you need. Example: `` the `property` set in the attribute will be set if the version available is equal to or higher than the version put in the mandatory `version` attribute. Alternative usage is to omit `property`. In that case, a build error will occur if `version` is higher than what's available. _Supported since ipp 1.4_ ### `` - just like ``, but this task will also copy any non-java, non-class files to the destination directory. The defaults are also different: debug = on source = 1.6 target = 1.6 encoding = UTF-8 The _destdir_ directory is also created automatically, so you don't have to `` it first. _Supported since ipp 1.0_ ### `` - similar to unjar, except will not unpack jars that don't need to be unpacked. While `cachedunjar` is similar to `unjar`, it supports only file resources, either via a `source` attribute or nested `` elements. You must specify a `dest` attribute just like with `unjar`. In addition, you must specify a file via the `marker` attribute. This file is used to track the state of the unpacked jars; a 'savefile' of sorts. Example: _Supported since ipp 1.7_ ### `` - creates a dependency report, and then opens your browser to show it. The last executed `` serves as the configuration for which a dependency report will be generated. By default `build/report` is used as target dir for both temporary files needed to create and view the report as well as the report itself. Change it with the `todir` attribute. _Supported since ipp 1.0_ ### `` - loads version info from a text file. Set the file containing the version name in the `file` attribute. The property will be read from it by stripping linebreaks and treating the rest as the version. This version will then be loaded into a property named `version`. You can change the property by setting the `property` attribute. _Supported since ipp 1.3_ ### `` - runs git. Only works if git is locally installed (for windows users, you'd have to be running ant inside cygwin/msys). Set the git command, such as _pull_ in the `command` attribute. The command will run in the project dir, unless you override this by specifying the optional `dir` attribute. You can add more arguments via a nested `args` element containing `` elements. Fails with a helpful error message if git doesn't exist. _Supported since ipp 1.0_ ### `` - runs git clone. Required attributes: `repository` listing the repository URL and `dest` listing the directory to place the git repository. _Supported since ipp 1.0_ ### `` - convenience for `` _Supported since ipp 1.0_ ### `` - creates/updates maven-compatible repositories Attributes: * `url` - list the base URL where the repository is located. Example: `http://projectlombok.org/mavenrepo` * `group` - group name. Example: `org.projectlombok` * `artifact` - artifact name. Example: `lombok` * `version` - this version. make-maven-repo won't work if this version name is already available from the repository. * `outfile` - a bzip2 tarball will be produced that must be unpacked in the existing mavenrepo to update it. This describes where to build it. * `tmpdir` (optional) - where to put the files that will end up being bzip2 tarballed. By default `build/maven`. * `artifactfile` - Location of the artifact (e.g. jar file). This will be uploaded along with the logistics to be a maven repository. * `pomfile` - Location of the pom file describing this project. `@VERSION@` will be replaced with the version. artifact and group IDs and the like must match. Inner elements: * `sources` - should contain filesets pointing at source files. Will be used to create a source artifact. _Supported since ipp 1.3_ NB: make-maven-repo is no longer under active development since sonatype changed their policy on how maven artifacts are to be added to maven central. ivyplusplus-1.14/build.xml000066400000000000000000000221201243573566400157130ustar00rootroot00000000000000 com.zwitserloot.ivyplusplus version: ${ivyplusplus.version} A new version of ivyplusplus was required and has been downloaded. Rerun the script to continue. You don't have the escudo-upload.key; you'll need it to get write access to the server. ivyplusplus-1.14/buildScripts/000077500000000000000000000000001243573566400165445ustar00rootroot00000000000000ivyplusplus-1.14/buildScripts/ivy-repo/000077500000000000000000000000001243573566400203165ustar00rootroot00000000000000ivyplusplus-1.14/buildScripts/ivy-repo/com.zwitserloot-cmdreader-1.5.xml000066400000000000000000000014611243573566400264510ustar00rootroot00000000000000 ivyplusplus-1.14/buildScripts/ivy-repo/org.projectlombok-jsch-ant-fixed-0.1.42.xml000066400000000000000000000007331243573566400300250ustar00rootroot00000000000000 ivyplusplus-1.14/buildScripts/ivy.xml000066400000000000000000000022111243573566400200710ustar00rootroot00000000000000 ivyplusplus-1.14/buildScripts/ivysettings.xml000066400000000000000000000010121243573566400216500ustar00rootroot00000000000000 ivyplusplus-1.14/buildScripts/maven-pom.xml000066400000000000000000000017161243573566400211720ustar00rootroot00000000000000 4.0.0 com.zwitserloot ivyplusplus jar @VERSION@ IvyPlusPlus http://zwitserloot.com/ivyplusplus Adds some useful features to ant based on ivy, such as building an eclipse project based on your dependencies. The MIT License http://www.opensource.org/licenses/mit-license.php repo scm:git:git://github.com/rzwitserloot/ivyplusplus.git scm:git:git://github.com/rzwitserloot/ivyplusplus.git ivyplusplus-1.14/src/000077500000000000000000000000001243573566400146645ustar00rootroot00000000000000ivyplusplus-1.14/src/com/000077500000000000000000000000001243573566400154425ustar00rootroot00000000000000ivyplusplus-1.14/src/com/zwitserloot/000077500000000000000000000000001243573566400200475ustar00rootroot00000000000000ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/000077500000000000000000000000001243573566400224665ustar00rootroot00000000000000ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/CachedUnjar.java000066400000000000000000000155011243573566400255020ustar00rootroot00000000000000/** * Copyright © 2011 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import lombok.Cleanup; import lombok.Data; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.taskdefs.Delete; import org.apache.tools.ant.taskdefs.Expand; import org.apache.tools.ant.taskdefs.MatchingTask; import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.Resource; import org.apache.tools.ant.types.resources.FileResource; public class CachedUnjar extends MatchingTask { private File dest; private File source; private File marker; private List fileSets = new ArrayList(); private List paths = new ArrayList(); public void addFileset(FileSet set) { this.fileSets.add(set); } public void addPath(Path path) { this.paths.add(path); } public void setSource(File file) { this.source = file; } public void setMarker(File file) { this.marker = file; } public void setDest(File file) { this.dest = file; } public void execute() throws BuildException { if (source == null && fileSets.isEmpty() && paths.isEmpty()) { throw new BuildException("Specify either 'source' or include a fileset or path.", getLocation()); } if (marker == null) throw new BuildException("Specify 'marker' which is a file that carries caching info.", getLocation()); if (dest == null) throw new BuildException("Specify 'dest' which is the directory the jars are unpacked to.", getLocation()); if (!dest.exists()) if (!dest.mkdirs()) throw new BuildException("'dest' does not exist and cannot be created as directory: " + dest, getLocation()); if (!dest.isDirectory()) throw new BuildException("'dest' must be a directory: " + dest, getLocation()); if (source != null && (!fileSets.isEmpty() || !paths.isEmpty())) { throw new BuildException("Specify either 'source' or include filesets/paths, not both.", getLocation()); } Set caches; try { caches = readCaches(marker); } catch (IOException e) { throw new BuildException("Can't read marker file", e, getLocation()); } Set newCache = new LinkedHashSet(); Set toUnpack = new LinkedHashSet(); List toUnpackRes = new ArrayList(); List allRes = new ArrayList(); if (source != null) { FileSet fs = new FileSet(); fs.setFile(source); fileSets.add(fs); } if (!fileSets.isEmpty()) { Path fsPath = new Path(getProject()); for (FileSet fs : fileSets) fsPath.addFileset(fs); paths.add(fsPath); } try { for (Path path : paths) { Iterator it = path.iterator(); while (it.hasNext()) { Resource res = (Resource) it.next(); if (!(res instanceof FileResource)) { throw new BuildException("Only file resources supported: " + res.getName(), getLocation()); } File jarFile = ((FileResource)res).getFile(); allRes.add(jarFile); CacheRecord cr = new CacheRecord(jarFile.getCanonicalPath(), res.getLastModified(), res.getSize()); if (caches.contains(cr)) { this.log(String.format("Skipping %s due to cache", jarFile.getCanonicalPath()), Project.MSG_VERBOSE); newCache.add(cr); } else { newCache.add(cr); toUnpack.add(cr); toUnpackRes.add(jarFile); } } } if (newCache.size() - toUnpack.size() == caches.size()) { // We just need to unpack toUnpack. unpack(toUnpackRes); } else { // At least one unpack library is no longer in the set, so we delete and unpack all. this.log(String.format("Deleting %s because previously present jar is no longer there.", dest), Project.MSG_INFO); clearDest(); unpack(allRes); } } catch (IOException e) { throw new BuildException(e, getLocation()); } try { saveCache(newCache); } catch (IOException e) { throw new BuildException("Can't write marker file", e, getLocation()); } } private void clearDest() { Delete d = new Delete(); d.setDir(dest); d.execute(); } private void unpack(Collection ress) { for (File res : ress) { Expand ex = new Expand(); ex.setDest(dest); ex.setSrc(res); ex.setTaskName("cachingunjar"); ex.setTaskType("unjar"); ex.execute(); } } private void saveCache(Collection crs) throws IOException { @Cleanup FileOutputStream fos = new FileOutputStream(marker); for (CacheRecord cr : crs) fos.write(cr.write().getBytes("UTF-8")); } private static Set readCaches(File marker) throws IOException { Set out = new LinkedHashSet(); try { @Cleanup FileInputStream fis = new FileInputStream(marker); BufferedReader br = new BufferedReader(new InputStreamReader(fis, "UTF-8")); for (String line = br.readLine(); line != null; line = br.readLine()) { line = line.trim(); if (line.startsWith("#")) continue; if (line.length() == 0) continue; out.add(CacheRecord.read(line)); } } catch (FileNotFoundException e) {} return out; } @Data private static class CacheRecord { private final String name; private final long lastMod, len; static CacheRecord read(String line) { String[] elems = line.split(" ::: ", 3); return new CacheRecord(elems[0], Long.parseLong(elems[1]), Long.parseLong(elems[2])); } String write() { return String.format("%s ::: %d ::: %d\n", name, lastMod, len); } } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/Compile.java000066400000000000000000000212501243573566400247210ustar00rootroot00000000000000/** * Copyright © 2010-2011 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus; import static java.util.Collections.unmodifiableMap; import java.io.File; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import lombok.Setter; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DynamicAttribute; import org.apache.tools.ant.RuntimeConfigurable; import org.apache.tools.ant.UnknownElement; import org.apache.tools.ant.taskdefs.Copy; import org.apache.tools.ant.taskdefs.Javac; import org.apache.tools.ant.taskdefs.MatchingTask; import org.apache.tools.ant.taskdefs.Mkdir; import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.util.facade.FacadeTaskHelper; import org.apache.tools.ant.util.facade.ImplementationSpecificArgument; public class Compile extends MatchingTask implements DynamicAttribute { private UnknownElement javac, copy, mkdir; private Path src; private boolean doCopy = true; @Setter private String copyExcludes; private boolean destdirSet; public void setCopy(boolean copy) { this.doCopy = copy; } public void init() { javac = new UnknownElement("javac"); copy = new UnknownElement("copy"); mkdir = new UnknownElement("mkdir"); javac.setTaskName("compile:javac"); copy.setTaskName("compile:copy"); mkdir.setTaskName("compile:mkdir"); new RuntimeConfigurable(javac, javac.getTaskName()); new RuntimeConfigurable(copy, copy.getTaskName()); new RuntimeConfigurable(mkdir, mkdir.getTaskName()); javac.setProject(getProject()); copy.setProject(getProject()); mkdir.setProject(getProject()); } private static final Map JAVAC_ATTR_MAP, COPY_ATTR_MAP, MKDIR_ATTR_MAP, JAVAC_DEFAULTS, COPY_DEFAULTS; static { Map m; m = new HashMap(); m.put("destdir", "dir"); MKDIR_ATTR_MAP = unmodifiableMap(m); m = new HashMap(); m.put("destdir", "destdir"); m.put("classpath", "classpath"); m.put("sourcepath", "sourcepath"); m.put("bootclasspath", "bootclasspath"); m.put("classpathref", "classpathref"); m.put("sourcepathref", "sourcepathref"); m.put("bootclasspathref", "bootclasspathref"); m.put("extdirs", "extdirs"); m.put("encoding", "encoding"); m.put("nowarn", "nowarn"); m.put("debug", "debug"); m.put("debuglevel", "debuglevel"); m.put("deprecation", "deprecation"); m.put("target", "target"); m.put("source", "source"); m.put("verbose", "verbose"); m.put("depend", "depend"); m.put("includeantruntime", "includeantruntime"); m.put("includejavaruntime", "includejavaruntime"); m.put("fork", "fork"); m.put("executable", "executable"); m.put("memoryinitialsize", "memoryinitialsize"); m.put("memorymaximumsize", "memorymaximumsize"); m.put("failonerror", "failonerror"); m.put("errorproperty", "errorproperty"); m.put("compiler", "compiler"); m.put("listfiles", "listfiles"); m.put("tempdir", "tempdir"); m.put("updatedproperty", "updatedproperty"); m.put("includedestclasses", "includedestclasses"); JAVAC_ATTR_MAP = unmodifiableMap(m); m = new HashMap(); m.put("encoding", "UTF-8"); m.put("debug", "on"); m.put("target", "1.8"); m.put("source", "1.8"); m.put("includeantruntime", "false"); JAVAC_DEFAULTS = unmodifiableMap(m); m = new HashMap(); m.put("destdir", "todir"); m.put("preservelastmodified", "preservelastmodified"); m.put("includeemptydirs", "includeemptydirs"); m.put("failonerror", "failonerror"); m.put("verbose", "verbose"); COPY_ATTR_MAP = unmodifiableMap(m); m = new HashMap(); m.put("includeemptydirs", "false"); COPY_DEFAULTS = unmodifiableMap(m); } private boolean setWithKey(UnknownElement elem, Map map, String name, String value) { String key = map.get(name); if (key == null) return false; elem.getWrapper().setAttribute(key, value); return true; } public void setDynamicAttribute(String name, String value) throws BuildException { boolean matched = false; matched |= setWithKey(mkdir, MKDIR_ATTR_MAP, name, value); matched |= setWithKey(javac, JAVAC_ATTR_MAP, name, value); matched |= setWithKey(copy, COPY_ATTR_MAP, name, value); if (!matched) throw new BuildException("Unknown property of compile task: " + name, getLocation()); if ("destdir".equals(name)) destdirSet = true; } public void setSrcdir(Path srcDir) { if (src == null) src = srcDir; else src.append(srcDir); } public Path createSrc() { if (src == null) { src = new Path(getProject()); } return src.createPath(); } private Path compileClasspath, compileSourcepath, bootclasspath, extdirs; public Path createSourcepath() { if (compileSourcepath == null) compileSourcepath = new Path(getProject()); return compileSourcepath.createPath(); } public Path createClasspath() { if (compileClasspath == null) compileClasspath = new Path(getProject()); return compileClasspath.createPath(); } public Path createBootclasspath() { if (bootclasspath == null) bootclasspath = new Path(getProject()); return bootclasspath.createPath(); } public Path createExtdirs() { if (extdirs == null) extdirs = new Path(getProject()); return extdirs.createPath(); } private List compilerArgs = new ArrayList(); public ImplementationSpecificArgument createCompilerArg() { ImplementationSpecificArgument arg = new ImplementationSpecificArgument(); compilerArgs.add(arg); return arg; } public void execute() { if (!destdirSet) throw new BuildException("mandatory property 'destdir' not set."); if (src == null) src = new Path(getProject()); Map attributeMap = javac.getWrapper().getAttributeMap(); for (Map.Entry e : JAVAC_DEFAULTS.entrySet()) { if (!attributeMap.containsKey(e.getKey())) javac.getWrapper().setAttribute(e.getKey(), e.getValue()); } attributeMap = copy.getWrapper().getAttributeMap(); for (Map.Entry e : COPY_DEFAULTS.entrySet()) { if (!attributeMap.containsKey(e.getKey())) copy.getWrapper().setAttribute(e.getKey(), e.getValue()); } mkdir.maybeConfigure(); Mkdir mkdirTask = (Mkdir) mkdir.getRealThing(); mkdirTask.execute(); javac.maybeConfigure(); Javac javacTask = (Javac) javac.getRealThing(); javacTask.setSrcdir(src); javacTask.createCompilerArg().setValue("-Xlint:unchecked"); if (bootclasspath != null) javacTask.setBootclasspath(bootclasspath); if (compileClasspath != null) javacTask.setClasspath(compileClasspath); if (compileSourcepath != null) javacTask.setSourcepath(compileSourcepath); if (extdirs != null) javacTask.setExtdirs(extdirs); try { Field f = MatchingTask.class.getDeclaredField("fileset"); f.setAccessible(true); f.set(javacTask, getImplicitFileSet().clone()); f = Javac.class.getDeclaredField("facade"); f.setAccessible(true); FacadeTaskHelper facade = (FacadeTaskHelper) f.get(javacTask); for (ImplementationSpecificArgument isa : compilerArgs) facade.addImplementationArgument(isa); } catch (Exception e) { throw new BuildException(e, getLocation()); } javacTask.execute(); if (doCopy) { copy.maybeConfigure(); Copy copyTask = (Copy) copy.getRealThing(); for (String pathElem : src.list()) { File srcPath = getProject().resolveFile(pathElem); FileSet fs = (FileSet) getImplicitFileSet().clone(); fs.setDir(srcPath); fs.createExclude().setName("**/*.java"); if (copyExcludes != null) fs.createExclude().setName(copyExcludes); copyTask.addFileset(fs); } copyTask.execute(); } } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/EnsureVersion.java000066400000000000000000000074331243573566400261470ustar00rootroot00000000000000/** * Copyright © 2010 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus; import java.util.ArrayList; import java.util.Collections; import java.util.List; import lombok.Data; import lombok.Getter; import lombok.Setter; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; public class EnsureVersion extends Task { @Getter @Setter private String version; @Getter @Setter private String property; @Override public void execute() throws BuildException { if (version == null || version.isEmpty()) throw new BuildException("Must specify mandatory attribute 'version'", getLocation()); List want = toVersion(version); List have = toVersion(Version.getVersion()); if (!isEqualOrHigher(have, want)) { if (property == null) throw new BuildException("ivyplusplus version not sufficient; delete ivyplusplus.jar and run this script again. You have: " + Version.getVersion() + " but need: " + version); } else { if (property != null) getProject().setProperty(property, "true"); } } public static List toVersion(String version) { String[] parts = version.split("[-.]"); List ret = new ArrayList(); for (String part : parts) { ret.add(VersionPart.of(part)); } return Collections.unmodifiableList(ret); } /** * Returns {@code true} if {@code have} is a version equal to or higher than {@code want}. */ public static boolean isEqualOrHigher(List have, List want) { int largest = Math.max(have.size(), want.size()); for (int i = 0; i < largest; i++) { VersionPart a = i < have.size() ? have.get(i) : VersionPart.zero(); VersionPart b = i < want.size() ? want.get(i) : VersionPart.zero(); int res = a.compareTo(b); if (res < 0) return false; if (res > 0) return true; } return true; } @Data private static class VersionPart implements Comparable { private final int number; private final String name; public int compareTo(VersionPart o) { if (o.name == null) { if (name != null) return -1; if (number < o.number) return -1; if (number > o.number) return +1; return 0; } if (name == null) return +1; return name.compareTo(o.name); } public static VersionPart zero() { return new VersionPart(0, null); } public static VersionPart of(String part) { int v = 0; String name = null; for (char c : part.toCharArray()) { if (c >= '0' && c <= '9') { v = (v * 10) + (c - '0'); } else { v = 0; name = part.trim(); break; } } if (name != null && name.isEmpty()) name = null; if (name == null) return new VersionPart(v, null); else return new VersionPart(0, name); } } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/Version.java000066400000000000000000000032151243573566400247570ustar00rootroot00000000000000/** * Copyright © 2010-2014 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus; public class Version { // ** CAREFUL ** - this class must always compile with 0 dependencies (it must not refer to any other sources or libraries). private static final String VERSION = "1.14"; private Version() { //Prevent instantiation } /** * Prints the version followed by a newline, and exits. */ public static void main(String[] args) { System.out.println(VERSION); } /** * Get the current ivyplusplus version. */ public static String getVersion() { return VERSION; } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/antlib.xml000066400000000000000000000251501243573566400244640ustar00rootroot00000000000000 public class ShowHtml { public static void main(String[] args) { try { java.awt.Desktop.getDesktop().browse(new java.io.File(args[0]).toURI()); } catch (Throwable t) { t.printStackTrace(); System.err.println("To see the file, browse to: " + new java.io.File(args[0]).toURI()); } } } public class ShowDependencyReport { public static void main(String[] args) { try { java.awt.Desktop.getDesktop().browse(new java.io.File(args[0]).toURI()); } catch (Throwable t) { t.printStackTrace(); System.err.println("To see the dependency report, browse to: " + new java.io.File(args[0]).toURI()); } } } [GIT NOT FOUND] You don't appear to have git installed. If you're on windows, try running this in your git shell. Otherwise, install git. git is a free and open source version control system. You can download it from: http://git-scm.com/ @{group} <version>@{version}</version> ${mvn.bin.md5.@{group}.@{artifact}} ${mvn.bin.sha1.@{group}.@{artifact}} ${mvn.src.md5.@{group}.@{artifact}} ${mvn.src.sha1.@{group}.@{artifact}} ${mvn.pom.md5.@{group}.@{artifact}} ${mvn.pom.sha1.@{group}.@{artifact}} <?xml version="1.0" encoding="UTF-8"?> <metadata> <groupId>@{group}</groupId> <artifactId>@{artifact}</artifactId> <version>@{version}</version> <versioning> <versions> <version>@{version}</version> ${mvn.oldversions.@{group}.@{artifact}} </versions> <lastUpdated>${now.millis.@{group}.@{artifact}}</lastUpdated> </versioning> </metadata> ${mvn.manifest.md5.@{group}.@{artifact}} ${mvn.manifest.sha1.@{group}.@{artifact}} ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/createProject/000077500000000000000000000000001243573566400252605ustar00rootroot00000000000000ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/createProject/CreateProject.java000066400000000000000000000244701243573566400306640ustar00rootroot00000000000000/** * Copyright © 2011-2014 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.createProject; import java.io.Console; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.security.Security; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.Scanner; import com.zwitserloot.cmdreader.CmdReader; import com.zwitserloot.cmdreader.Description; import com.zwitserloot.cmdreader.Excludes; import com.zwitserloot.cmdreader.FullName; import com.zwitserloot.cmdreader.InvalidCommandLineException; import com.zwitserloot.cmdreader.Mandatory; import com.zwitserloot.cmdreader.Sequential; import com.zwitserloot.cmdreader.Shorthand; import com.zwitserloot.ivyplusplus.Version; import com.zwitserloot.ivyplusplus.mavencentral.CreateSigningKey; import com.zwitserloot.ivyplusplus.mavencentral.InitializeBouncyCastle; import com.zwitserloot.ivyplusplus.mavencentral.SigningException; import com.zwitserloot.ivyplusplus.template.TemplateApplier; public class CreateProject { private static class CmdArgs { @Shorthand("h") @Description("Show this command line help") boolean help; @Sequential @Mandatory(onlyIfNot={"help", "generate-key", "version"}) @Description("The name of your project. Example: com.zwitserloot.cmdreader") String projectName; @Shorthand("j") @Description("If present, a jUnit test framework will be generated.") boolean junit; @Shorthand("d") @Description("If present, javadoc ant targets will be produced.") boolean javadoc; @FullName("sonatype-forge") @Description("Creates a 'maven-build' and 'maven-upload' task that creates (and uploads) this project to Sonatype Forge. Run --generate-key to make a signing pair first if you need one.") boolean sonatypeForge; @Shorthand("f") @Description("Overwrite files if they already exist.") boolean force; @Shorthand("l") @Description("This project is not an app - do not generate a main class and dont include Main-Class in the manifest.") boolean library; @Description("Add a simple bsd-like license to the top of generated sources, using the supplied name as copyright holder.") String freeware; @Description("Generates a key pair for signing artifacts so that i.e. Sonatype Forge, which is one way to get your libraries into maven central, accepts them.") @FullName("generate-key") @Excludes({"freeware", "library", "junit", "projectName", "sonatype-forge"}) boolean generateMavenRepoSigningKey; @Description("Shows version number and exits") boolean version; } public static void main(String[] rawArgs) throws IOException { CmdReader reader = CmdReader.of(CmdArgs.class); CmdArgs args; try { args = reader.make(rawArgs); } catch (InvalidCommandLineException e) { System.err.println(e.getMessage()); System.err.println(reader.generateCommandLineHelp("java -jar ivyplusplus.jar")); System.exit(1); return; } if (args.help) { System.out.println(reader.generateCommandLineHelp("java -jar ivyplusplus.jar")); System.exit(0); return; } if (args.version) { System.out.println("ivyplusplus v" + Version.getVersion()); System.exit(0); return; } if (args.generateMavenRepoSigningKey) { System.exit(runGenerateMavenSigningKey()); return; } TemplateApplier template = new TemplateApplier(); template.put("PROJECTNAME", args.projectName); template.put("MIN_IPP_VERSION", Version.getVersion()); if (args.javadoc) template.put("JAVADOC", "true"); if (args.sonatypeForge) { template.put("JAVADOC", "true"); template.put("MAVEN", "true"); } if (args.junit) template.put("JUNIT", "true"); if (args.freeware != null) { handleAndAddFreewareCopyright(template, args.freeware, args.force); template.put("MIT_LICENSE_SET", "true"); } else { template.put("MIT_LICENSE_UNSET", "true"); } if (!args.library) template.put("APP", "true"); String organization, simpleName; { int idx = args.projectName.lastIndexOf('.'); if (idx == -1) { organization = args.projectName; simpleName = args.projectName; } else { organization = reverseOnDots(args.projectName.substring(0, idx)); simpleName = args.projectName.substring(idx + 1); } } template.put("ORGANIZATION", organization); template.put("SIMPLENAME", simpleName); template.put("PATH_TO_VERSIONJAVA", reverseOnDots(args.projectName).replace(".", "/") + "/Version.java"); new File("buildScripts").mkdir(); new File("buildScripts/ivy-repo").mkdir(); writeFile(template.applyResource(CreateProject.class, "build.xml.template"), "build.xml", args.force); writeFile(template.applyResource(CreateProject.class, "ivy.xml.template"), "buildScripts/ivy.xml", args.force); writeFile(template.applyResource(CreateProject.class, "ivysettings.xml.template"), "buildScripts/ivysettings.xml", args.force); new File("src").mkdir(); new File("src/main").mkdir(); if (args.junit) new File("src/test").mkdir(); File srcDir = new File("src/main"); File testDir = new File("src/test"); for (String pkgElem : reverseOnDots(args.projectName).split("\\.")) { srcDir = new File(srcDir, pkgElem); srcDir.mkdir(); testDir = new File(testDir, pkgElem); if (args.junit) testDir.mkdir(); } if (!args.library) { writeFile(template.applyResource(CreateProject.class, "Main.java.template"), new File(srcDir, "Main.java").getPath(), args.force); } if (args.sonatypeForge) { File docDir = new File("doc"); docDir.mkdir(); writeFile(template.applyResource(CreateProject.class, "maven-pom.xml.template"), new File(docDir, "maven-pom.xml").getPath(), args.force); System.out.println("doc/maven-pom.xml is a pom skeleton.\nYou'll need to edit it and replace all the stuff between the exclamation marks with appropriate strings."); } writeFile(template.applyResource(CreateProject.class, "Version.java.template"), new File(srcDir, "Version.java").getPath(), args.force); } private static int runGenerateMavenSigningKey() { try { InitializeBouncyCastle.init(); } catch (SigningException e) { System.err.println(e.getMessage()); return 12; } System.out.println(java.util.Arrays.toString(Security.getProviders())); System.out.println("Generating a new key pair. The generated key pair will be used by the task."); System.out.print("What is the full name of the owner of this key: "); Scanner s = new Scanner(System.in); String fullName = s.nextLine(); System.out.print("What is the email of the owner of this key: " ); String email = s.nextLine(); String identity = fullName + " <" + email + ">"; System.out.println("Key's identity: " + identity); System.out.println(); System.out.println("Hit enter to set a blank passphrase.\n" + "This means anyone with the key ring file can sign as you,\n" + "so don't do this unless you know what you're doing!"); Console console = System.console(); String passphrase, verify; if (console == null) { System.out.print("Passphrase for this key: "); passphrase = s.nextLine(); System.out.print("Repeat passphrase: "); verify = s.nextLine(); } else { System.out.print("Passphrase for this key: "); passphrase = new String(console.readPassword()); System.out.print("Repeat passphrase: "); verify = new String(console.readPassword()); } if (!passphrase.equals(verify)) { System.err.println("Passwords do not match - key creation aborted."); return 5; } try { new CreateSigningKey().createSigningKey(identity, passphrase, System.out); } catch (IOException e) { System.err.println("Problem creating passkey files. Is the current directory writable?"); System.err.println(e); return 1; } catch (SigningException e) { System.err.println("Problem creating keys: " + e.getMessage()); return 1; } System.out.println("Key files created. You don't need mavenrepo-signing-key-public.bpr, but its there if you want others to be able to encrypt things so only you can read them."); return 0; } private static String reverseOnDots(String in) { StringBuilder sb = new StringBuilder(); for (String elem : in.split("\\.")) { if (sb.length() > 0) sb.append("."); sb.append(elem); } return sb.toString(); } private static void writeFile(String content, String fileName, boolean force) throws IOException { File f = new File(fileName); if (f.exists() && !force) { throw new IllegalStateException(String.format("File %s already exists. Delete it first if you want me to overwrite it, or use --force", f)); } FileOutputStream fos = new FileOutputStream(fileName); try { fos.write(content.getBytes("UTF-8")); } finally { fos.close(); } } private static void handleAndAddFreewareCopyright(TemplateApplier template, String holder, boolean force) throws IOException { template.put("YEAR", String.valueOf(new GregorianCalendar().get(Calendar.YEAR))); template.put("HOLDER", holder); String copyright = template.applyResource(CreateProject.class, "simpleLicense.txt.template"); template.put("COPYRIGHT", copyright); String sourceCopyright = " * " + copyright.replace("\n", "\n * "); if (sourceCopyright.endsWith(" * ")) sourceCopyright = sourceCopyright.substring(0, sourceCopyright.length() - 3) + "\n"; template.put("SOURCE_COPYRIGHT",sourceCopyright); writeFile(copyright, "LICENSE", force); } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/createProject/Main.java.template000066400000000000000000000003471243573566400306250ustar00rootroot00000000000000{{if SOURCE_COPYRIGHT}} /** {{@SOURCE_COPYRIGHT}} */ {{end SOURCE_COPYRIGHT}} package {{@PROJECTNAME}}; public class Main { public static void main(String[] args) { System.out.println("Hello, world! - {{@PROJECTNAME}}"); } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/createProject/Version.java.template000066400000000000000000000011501243573566400313570ustar00rootroot00000000000000{{if SOURCE_COPYRIGHT}} /** {{@SOURCE_COPYRIGHT}} */ {{end SOURCE_COPYRIGHT}} package {{@PROJECTNAME}}; public class Version { // ** CAREFUL ** - this class must always compile with 0 dependencies (it must not refer to any other sources or libraries). private static final String VERSION = "0.1"; private Version() { //Prevent instantiation } /** * Prints the version followed by a newline, and exits. */ public static void main(String[] args) { System.out.println(VERSION); } /** * Get the current {{@PROJECTNAME}} version. */ public static String getVersion() { return VERSION; } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/createProject/build.xml.template000066400000000000000000000216561243573566400307250ustar00rootroot00000000000000{{if COPYRIGHT}} {{end COPYRIGHT}} {{if DESCRIPTION}} {{@DESCRIPTION}} {{end DESCRIPTION}} {{if JUNIT}} {{end JUNIT}} ivyplusplus has been updated to a new version. Restart the script to continue. {{@PROJECTNAME}} version: ${app.version} {{if JUNIT}} {{end JUNIT}} {{if JAVADOC}} {{end JAVADOC}} {{if JUNIT}} {{end JUNIT}} {{if APP}} {{end APP}} {{if JAVADOC}} {{end JAVADOC}} {{if JUNIT}} All tests successful. {{end JUNIT}} {{if JAVADOC}} {{end JAVADOC}} {{if JUNIT}} {{end JUNIT}} {{if JUNIT}} {{end JUNIT}} {{if JUNIT}} {{end JUNIT}} {{if JUNIT}} {{end JUNIT}} {{if MAVEN}} {{end MAVEN}} ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/createProject/ivy.xml.template000066400000000000000000000014321243573566400304230ustar00rootroot00000000000000 {{if JUNIT}} {{end JUNIT}} {{if JUNIT}} {{end JUNIT}} ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/createProject/ivysettings.xml.template000066400000000000000000000010121243573566400321760ustar00rootroot00000000000000 ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/createProject/maven-pom.xml.template000066400000000000000000000027111243573566400315140ustar00rootroot00000000000000 4.0.0 {{@ORGANIZATION}} {{@SIMPLENAME}} jar @VERSION@ {{@PROJECTNAME}} !! FILL IN URL TO PROJECT SITE HERE !! !! FILL IN DESCRIPTION HERE !! {{if MIT_LICENSE_SET}} The MIT License !! URL TO PROJECT SITE HERE !!/LICENSE {{end MIT_LICENSE_SET}} {{if MIT_LICENSE_UNSET}} !! FILL IN LICENSE NAME HERE !! !! URL TO LICENSE HERE !! {{end MIT_LICENSE_UNSET}} repo scm:git:git://github.com/!!git username here!!/!!gitname here!!.git scm:git:git://github.com/!!git username here!!/!!gitname here!!.git Google Code http://code.google.com/p/!!projectname here!!/issues !!your name!! !!your full name!! !!your mail!! !!your site!! !!your timestamp!! ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/createProject/simpleLicense.txt.template000066400000000000000000000020441243573566400324270ustar00rootroot00000000000000Copyright © {{@YEAR}} {{@HOLDER}}. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/eclipse/000077500000000000000000000000001243573566400241125ustar00rootroot00000000000000ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/eclipse/Apt.java000066400000000000000000000023401243573566400255000ustar00rootroot00000000000000/** * Copyright © 2010 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.eclipse; import lombok.Data; @Data public class Apt { private String location; } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/eclipse/BuildEclipseProject.java000066400000000000000000000314641243573566400306600ustar00rootroot00000000000000/** * Copyright © 2010-2014 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.eclipse; import static java.util.Collections.unmodifiableMap; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Writer; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import lombok.Cleanup; import lombok.Setter; import org.apache.ivy.ant.IvyPostResolveTask; import org.apache.ivy.core.IvyPatternHelper; import org.apache.ivy.core.module.descriptor.Artifact; import org.apache.ivy.core.module.descriptor.ModuleDescriptor; import org.apache.ivy.core.module.id.ArtifactRevisionId; import org.apache.ivy.core.resolve.IvyNode; import org.apache.ivy.core.resolve.ResolveOptions; import org.apache.tools.ant.BuildException; public class BuildEclipseProject extends IvyPostResolveTask { @Setter private File todir = null; @Setter private String projectname; private List srcdirs = new ArrayList(); private List confs = new ArrayList(); private List apts = new ArrayList(); private List locals = new ArrayList(); private List exports = new ArrayList(); private List libs = new ArrayList(); @Setter private String source = "1.8"; @Setter private Settings settings; @Setter private boolean pde = false; private void generateDotProject() throws IOException { File f = new File(todir, ".project"); f.delete(); @Cleanup FileOutputStream fos = new FileOutputStream(f); @Cleanup InputStream in = BuildEclipseProject.class.getResourceAsStream(pde ? "pde_project.template" : "project.template"); byte[] b = new byte[4096]; for (int r = in.read(b); r != -1; r = in.read(b)) { for (int i = 0; i < r; i++) { if (b[i] == '%') { fos.write(b, 0, i); fos.write(projectname.getBytes("UTF-8")); if (i < r - 1) fos.write(b, i + 1, r - i - 1); break; } else if (i == r - 1) { fos.write(b, 0, r); } } } in.close(); fos.close(); } private void generateDotFactorypath() throws IOException { if (apts.isEmpty()) return; File f = new File(todir, ".factorypath"); f.delete(); @Cleanup FileOutputStream fos = new FileOutputStream(f); @Cleanup Writer out = new OutputStreamWriter(fos, "UTF-8"); out.write("\n"); for (Apt apt : apts) { String loc = apt.getLocation(); if (loc == null) throw new BuildException("'location' attribute is required on ", getLocation()); File abs = getProject().resolveFile(loc); File workspace = todir == null ? getProject().getBaseDir() : todir; URI rel = workspace.toURI().relativize(abs.toURI()); out.write("\t\n"); } out.write("\n"); out.close(); } private static String unixize(String path) { if (File.separatorChar == '/') return path; return path.replace(File.separator, "/"); } private void generateDotClasspath(String content) throws IOException { File f = new File(todir, ".classpath"); f.delete(); @Cleanup FileOutputStream fos = new FileOutputStream(f); @Cleanup Writer out = new OutputStreamWriter(fos, "UTF-8"); out.write(content); } public void addSrcdir(Srcdir srcdir) { srcdirs.add(srcdir); } public void addConf(Conf conf) { confs.add(conf); } public void addApt(Apt apt) { apts.add(apt); } public void addLocal(Local local) { locals.add(local); } public void addExport(Export export) { exports.add(export); } public void addLib(Lib lib) { libs.add(lib); } public void addSettings(Settings settings) { if (this.settings != null) throw new BuildException("Only one allowed.", getLocation()); this.settings = settings; } private static final Map SOURCE_TO_CON; static { Map map = new LinkedHashMap(); map.put("1.8", "JavaSE-1.8"); map.put("1.7", "JavaSE-1.7"); map.put("1.6", "JavaSE-1.6"); map.put("1.5", "J2SE-1.5"); map.put("1.4", "J2SE-1.4"); map.put("1.3", "J2SE-1.3"); map.put("1.2", "J2SE-1.2"); map.put("1.1", "JRE-1.1"); SOURCE_TO_CON = unmodifiableMap(map); } private List calculateConfsWithSources() { List out = new ArrayList(); for (Conf conf : confs) { String confName = conf.getName(); if (confName == null) throw new BuildException(" requires a 'name' attribute naming an ivy configuration.", getLocation()); if (!out.contains(confName)) out.add(confName); String sourcesName = conf.getSources(); if (sourcesName != null && !out.contains(sourcesName)) out.add(sourcesName); } return out; } private static String readProjName(File in) throws IOException { @Cleanup InputStream raw = new FileInputStream(in); BufferedReader br = new BufferedReader(new InputStreamReader(raw, "UTF-8")); for (String line = br.readLine(); line != null; line = br.readLine()) { line = line.trim(); if (!line.startsWith("'); if (start == -1) continue; int end = line.indexOf("", start); if (end > -1) return line.substring(start + 1, end); } throw new IOException("Can't find project name from " + in.getAbsolutePath()); } @Override public void doExecute() throws BuildException { if (todir == null) todir = getProject().getBaseDir(); for (Srcdir dir : srcdirs) { if (dir.getDir() == null) throw new BuildException(" requires a 'src' attribute with the source dir you'd like to include.", getLocation()); } Map localsToConsider = new HashMap(); List toExport = new ArrayList(); for (Local local : locals) { if (local.getName() == null) throw new BuildException(" requires a 'name' attribute with a name like an ivy dependency's 'name' attribute.", getLocation()); if (local.getOrg() == null) throw new BuildException(" requires an 'org' attribute with a name like an ivy dependency's 'org' attribute.", getLocation()); String dir = local.getDir(); if (dir == null) { dir = "../" + local.getOrg() + "." + local.getName(); } if (new File(dir, ".project").isFile()) { localsToConsider.put(local.getOrg() + "." + local.getName(), dir); } } for (Export export : exports) { if (export.getName() == null) throw new BuildException(" requires a 'name' attribute with a name like an ivy dependency's 'name' attribute.", getLocation()); if (export.getOrg() == null) throw new BuildException(" requires an 'org' attribute with a name like an ivy dependency's 'org' attribute.", getLocation()); toExport.add(export.getOrg() + "." + export.getName()); } List confsWithSources = calculateConfsWithSources(); if (!SOURCE_TO_CON.containsKey(source)) throw new BuildException("Invalid value for 'source'. Valid values: " + SOURCE_TO_CON.keySet(), getLocation()); if (projectname == null) projectname = getProject().getName(); prepareAndCheck(); if (settings != null) settings.execute(todir, getLocation(), source); StringBuilder elements = new StringBuilder(); String retrievePattern = getProject().getProperty("ivy.retrieve.pattern"); assert retrievePattern != null; retrievePattern = IvyPatternHelper.substituteVariables(retrievePattern, getIvyInstance().getSettings().getVariables()); elements.append("\n"); elements.append("\n"); for (Srcdir dir : srcdirs) { String path = getProject().getBaseDir().toURI().relativize(dir.getDir().toURI()).toString(); elements.append("\t\n\t\t\n\t\t\t\n\t\t\n\t\n"); } else { elements.append("/>\n"); } } if (pde) { elements.append("\t\n"); } elements.append("\t\n"); elements.append("\t\t\n\t\t\t\n\t\t\n"); elements.append("\t\n"); ModuleDescriptor md = null; if (getResolveId() != null) md = (ModuleDescriptor) getResolvedDescriptor(getResolveId()); else md = (ModuleDescriptor) getResolvedDescriptor(getOrganisation(), getModule(), false); IvyNode[] deps = getIvyInstance().getResolveEngine().getDependencies(md, new ResolveOptions() .setConfs(confsWithSources.toArray(new String[0])).setResolveId(getResolveId()).setValidate(doValidate(getSettings())), null); List handledArtifacts = new ArrayList(); for (IvyNode dep : deps) { if (dep.isCompletelyEvicted()) continue; boolean export = toExport.contains(dep.getId().getOrganisation() + "." + dep.getId().getName()); String exportString = export ? "exported=\"true\" " : ""; String localDir = localsToConsider.get(dep.getId().getOrganisation() + "." + dep.getId().getName()); if (localDir != null) { String projName; try { projName = readProjName(new File(localDir, ".project")); } catch (IOException e) { throw new BuildException(e.getMessage()); } elements.append("\t\n"); } else for (Conf conf : confs) { for (Artifact artifact : dep.getArtifacts(conf.getName())) { if (handledArtifacts.contains(artifact.getId())) continue; handledArtifacts.add(artifact.getId()); if (!"jar".equals(artifact.getType()) && !"bundle".equals(artifact.getType())) continue; String destFileName = IvyPatternHelper.substitute(retrievePattern, artifact.getModuleRevisionId(), artifact, conf.getName(), null); String sourceConf = conf.getSources(); String sourceAttachment = null; if (sourceConf != null) for (Artifact sourceArtifact : dep.getArtifacts(sourceConf)) { sourceAttachment = IvyPatternHelper.substitute(retrievePattern, sourceArtifact.getModuleRevisionId(), sourceArtifact, sourceConf, null); break; } elements.append("\t\n"); } } } for (Lib lib : libs) { if (lib.getLocation() == null) throw new BuildException(" requires 'src' attribute pointing to a jar file.", getLocation()); String exportString = lib.export ? "exported=\"true\" " : ""; String path = getProject().getBaseDir().toURI().relativize(lib.getLocation().toURI()).toString(); elements.append("\t\n"); } elements.append("\t\n"); elements.append("\t\n"); elements.append("\n"); try { generateDotProject(); generateDotClasspath(elements.toString()); generateDotFactorypath(); } catch (IOException e) { throw new BuildException(e, getLocation()); } } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/eclipse/Conf.java000066400000000000000000000023661243573566400256510ustar00rootroot00000000000000/** * Copyright © 2010 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.eclipse; import lombok.Data; @Data public class Conf { private String name; private String sources; } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/eclipse/Export.java000066400000000000000000000002141243573566400262330ustar00rootroot00000000000000package com.zwitserloot.ivyplusplus.eclipse; import lombok.Data; @Data public class Export { private String org; private String name; } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/eclipse/Lib.java000066400000000000000000000002351243573566400254630ustar00rootroot00000000000000package com.zwitserloot.ivyplusplus.eclipse; import java.io.File; import lombok.Data; @Data public class Lib { File location; boolean export = false; } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/eclipse/Local.java000066400000000000000000000002401243573566400260030ustar00rootroot00000000000000package com.zwitserloot.ivyplusplus.eclipse; import lombok.Data; @Data public class Local { private String org; private String name; private String dir; } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/eclipse/Settings.java000066400000000000000000000200411243573566400265520ustar00rootroot00000000000000/** * Copyright © 2010 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.eclipse; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.TreeMap; import lombok.Cleanup; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Location; import org.apache.tools.ant.types.Resource; public class Settings { private TreeMap properties = new TreeMap(String.CASE_INSENSITIVE_ORDER); private List inputs = new ArrayList(); public void addText(String text) { inputs.add(text); } private void loadProps(InputStream in, boolean overwrite) throws IOException { Properties p = new Properties(); p.load(in); for (Map.Entry e : p.entrySet()) { String key = (String) e.getKey(); String value = (String) e.getValue(); if (overwrite || !properties.containsKey(key)) properties.put(key, value); } } public void add(Resource resource) { inputs.add(resource); } private static final Map PROPERTY_NAME_MAP; static { Map map = new HashMap(); map.put("eclipse.preferences.version", null); map.put("cleanup.", "org.eclipse.jdt.ui"); map.put("cleanup_", "org.eclipse.jdt.ui"); map.put("sp_cleanup.", "org.eclipse.jdt.ui"); map.put("formatter_", "org.eclipse.jdt.ui"); map.put("editor_save_participant_org.eclipse.jdt.ui.", "org.eclipse.jdt.ui"); map.put("org.eclipse.jdt.ui.", "org.eclipse.jdt.ui"); map.put("encoding/", "org.eclipse.core.resources"); map.put("org.eclipse.jdt.core.", "org.eclipse.jdt.core"); map.put("line.separator", "org.eclipse.core.runtime"); map.put("org.eclipse.jdt.launching.", "org.eclipse.jdt.launching"); map.put("org.eclipse.jdt.apt.", "org.eclipse.jdt.apt.core"); map.put("org.eclipse.ltk.core.refactoring.", "org.eclipse.ltk.core.refactoring"); map.put("org.eclipse.jdt.apt.", "org.eclipse.jdt.apt.core"); PROPERTY_NAME_MAP = Collections.unmodifiableMap(map); } public void execute(File todir, Location location, String source) { boolean is5 = "1.5".equals(source); boolean is6 = "1.6".equals(source); boolean is7 = "1.7".equals(source); boolean is8 = "1.8".equals(source); todir = new File(todir, ".settings"); boolean normalExit = false; for (Object input : inputs) { if (input == null) continue; if (input instanceof String) { try { @Cleanup InputStream in = new ByteArrayInputStream(((String) input).getBytes("ISO-8859-1")); loadProps(in, true); } catch (IOException e) { throw new BuildException(e, location); } } else if (input instanceof Resource) { try { @Cleanup InputStream in = ((Resource) input).getInputStream(); loadProps(in, false); } catch (IOException e) { throw new BuildException(e, location); } } else { assert false: "A non-string, non-resource showed up"; } } if (!properties.containsKey("org.eclipse.jdt.core.compiler.processAnnotations")) { if (is5) properties.put("org.eclipse.jdt.core.compiler.processAnnotations", "disabled"); if (is6 || is7 || is8) properties.put("org.eclipse.jdt.core.compiler.processAnnotations", "enabled"); } if (!properties.containsKey("org.eclipse.jdt.core.compiler.source")) { if (is5 || is6 || is7 || is8) properties.put("org.eclipse.jdt.core.compiler.source", source); } if (!properties.containsKey("org.eclipse.jdt.core.compiler.compliance")) { if (is5 || is6 || is7 || is8) properties.put("org.eclipse.jdt.core.compiler.compliance", source); } if (!properties.containsKey("org.eclipse.jdt.core.compiler.codegen.targetPlatform")) { if (is5 || is6 || is7 || is8) properties.put("org.eclipse.jdt.core.compiler.codegen.targetPlatform", source); } try { for (Map.Entry e : properties.entrySet()) { String key = e.getKey(); String value = e.getValue(); boolean handled = false; for (Map.Entry f : PROPERTY_NAME_MAP.entrySet()) { if (key.startsWith(f.getKey())) { handled = true; addToFile(f.getValue(), key, value, todir, location); break; } } if (!handled) { throw new BuildException("Unknown eclipse property: " + key, location); } } normalExit = true; } catch (IOException e) { throw new BuildException(e); } finally { Throwable stored = null; for (FileOutputStream out : createdFiles.values()) { try { out.close(); } catch (Throwable t) { if (stored != null) stored = t; } } if (normalExit && stored != null) { if (stored instanceof BuildException) throw (BuildException) stored; throw new BuildException(stored, location); } } } private Map createdFiles = new HashMap(); private void addToFile(String fileName, String key, String value, File todir, Location location) throws IOException { if (!todir.exists()) { if (!todir.mkdirs()) throw new BuildException("Can't create directory: " + todir.getAbsolutePath(), location); } if (!todir.isDirectory()) throw new BuildException("Not a directory: " + todir.getAbsolutePath(), location); FileOutputStream out; if (!createdFiles.containsKey(fileName)) { File f = new File(todir, fileName + ".prefs"); if (f.exists()) f.delete(); createdFiles.put(fileName, out = new FileOutputStream(f)); writePreamble(out); } else { out = createdFiles.get(fileName); } out.write(escapeKey(key).getBytes("ISO-8859-1")); out.write('='); out.write(escapeValue(value).getBytes("ISO-8859-1")); out.write(System.getProperty("line.separator", "\n").getBytes("ISO-8859-1")); } private String escapeKey(String key) { StringBuilder sb = new StringBuilder(); for (char c : escapeValue(key).toCharArray()) { if (c == ':' || c == '=' || c == ' ') { sb.append('\\'); sb.append(c); } else sb.append(c); } return sb.toString(); } private String escapeValue(String key) { StringBuilder sb = new StringBuilder(); for (char c : key.toCharArray()) { if (c == '\n') sb.append("\\n"); else if (c == '\r') sb.append("\\r"); else if (c == '\t') sb.append("\\t"); else if (c == '\f') sb.append("\\f"); else if (c == '\\') sb.append("\\\\"); else if (c < 32 || c > 126) { sb.append('\\').append('u').append(String.format("%04X", (int)c)); } else { sb.append(c); } } return sb.toString(); } private void writePreamble(OutputStream out) throws IOException { out.write(("#" + new Date().toString()).getBytes("ISO-8859-1")); out.write(System.getProperty("line.separator", "\n").getBytes("ISO-8859-1")); out.write("eclipse.preferences.version=1".getBytes("ISO-8859-1")); out.write(System.getProperty("line.separator", "\n").getBytes("ISO-8859-1")); } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/eclipse/Srcdir.java000066400000000000000000000024641243573566400262110ustar00rootroot00000000000000/** * Copyright © 2010 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.eclipse; import java.io.File; import lombok.Data; @Data public class Srcdir { private File dir; private boolean optional = false; private boolean test = false; } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/eclipse/pde_project.template000066400000000000000000000011721243573566400301460ustar00rootroot00000000000000 % org.eclipse.jdt.core.javabuilder org.eclipse.pde.ManifestBuilder org.eclipse.pde.SchemaBuilder org.eclipse.pde.PluginNature org.eclipse.jdt.core.javanature ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/eclipse/project.template000066400000000000000000000005501243573566400273150ustar00rootroot00000000000000 % org.eclipse.jdt.core.javabuilder org.eclipse.jdt.core.javanature ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/intellij/000077500000000000000000000000001243573566400243005ustar00rootroot00000000000000ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/intellij/Apt.java000066400000000000000000000024031243573566400256660ustar00rootroot00000000000000/** * Copyright © 2010 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.intellij; import lombok.Getter; import lombok.Setter; public class Apt { @Getter @Setter private boolean enabled; } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/intellij/BuildIntellijProject.java000066400000000000000000000217231243573566400312310ustar00rootroot00000000000000/** * Copyright © 2010 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.intellij; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import lombok.Cleanup; import lombok.Setter; import org.apache.ivy.ant.IvyPostResolveTask; import org.apache.ivy.core.IvyPatternHelper; import org.apache.ivy.core.module.descriptor.Artifact; import org.apache.ivy.core.module.descriptor.ModuleDescriptor; import org.apache.ivy.core.module.id.ArtifactRevisionId; import org.apache.ivy.core.resolve.IvyNode; import org.apache.ivy.core.resolve.ResolveOptions; import org.apache.tools.ant.BuildException; public class BuildIntellijProject extends IvyPostResolveTask { @Setter private File todir = null; private List modules = new ArrayList(); private List confs = new ArrayList(); private Apt apt; @Setter private String source = "1.8"; @Setter private Settings settings; public void addConf(Conf conf) { confs.add(conf); } public void addApt(Apt apt) { if (this.apt != null) throw new BuildException("Only one allowed.", getLocation()); this.apt = apt; } public void addSettings(Settings settings) { if (this.settings != null) throw new BuildException("Only one allowed.", getLocation()); this.settings = settings; } public void addModule(Module module) { modules.add(module); } @Override public void doExecute() throws BuildException { if (todir == null) todir = getProject().getBaseDir(); for (Module m : modules) m.validate(getLocation()); try { generateAntXml(todir); generateCompilerXml(todir, apt != null && apt.isEnabled()); generateLibraryXml(todir); generateModulesXml(todir); for (Module m : modules) { generateModuleXml(todir, m); } } catch (IOException e) { throw new BuildException(e, getLocation()); } } private void generateAntXml(File toDir) throws IOException { applyTemplate("ant.xml.template", new File(toDir, ".idea/ant.xml")); } private void generateCompilerXml(File toDir, boolean isAptEnabled) throws IOException { applyTemplate("compiler.xml.template", new File(toDir, ".idea/compiler.xml"), isAptEnabled ? "true" : "false"); } private void generateModulesXml(File toDir) throws IOException { StringBuilder moduleLines = new StringBuilder(); for (Module m : modules) { moduleLines.append(" \n"); } applyTemplate("modules.xml.template", new File(toDir, ".idea/modules.xml"), moduleLines.toString()); } private List calculateConfsWithSources() { List out = new ArrayList(); for (Conf conf : confs) { String confName = conf.getName(); if (confName == null) throw new BuildException(" requires a 'name' attribute naming an ivy configuration.", getLocation()); if (!out.contains(confName)) out.add(confName); String sourcesName = conf.getSources(); if (sourcesName != null && !out.contains(sourcesName)) out.add(sourcesName); } return out; } private void generateLibraryXml(File toDir) throws IOException { ModuleDescriptor md = null; if (getResolveId() != null) md = (ModuleDescriptor) getResolvedDescriptor(getResolveId()); else md = (ModuleDescriptor) getResolvedDescriptor(getOrganisation(), getModule(), false); prepareAndCheck(); if (settings != null) settings.execute(todir, getLocation(), source); List confsWithSources = calculateConfsWithSources(); String retrievePattern = getProject().getProperty("ivy.retrieve.pattern"); assert retrievePattern != null; IvyNode[] deps = getIvyInstance().getResolveEngine().getDependencies(md, new ResolveOptions() .setConfs(confsWithSources.toArray(new String[0])).setResolveId(getResolveId()).setValidate(doValidate(getSettings())), null); List handledArtifacts = new ArrayList(); Map depLines = new HashMap(); Map sourceLines = new HashMap(); for (IvyNode dep : deps) { for (Conf conf : confs) { for (Artifact artifact : dep.getArtifacts(conf.getName())) { if (handledArtifacts.contains(artifact.getId())) continue; handledArtifacts.add(artifact.getId()); if (!"jar".equals(artifact.getType()) && !"bundle".equals(artifact.getType())) continue; String destFileName = IvyPatternHelper.substitute(retrievePattern, artifact.getModuleRevisionId(), artifact, conf.getName(), null); String sourceConf = conf.getSources(); String sourceAttachment = null; if (sourceConf != null) for (Artifact sourceArtifact : dep.getArtifacts(sourceConf)) { sourceAttachment = IvyPatternHelper.substitute(retrievePattern, sourceArtifact.getModuleRevisionId(), sourceArtifact, sourceConf, null); break; } StringBuilder sb = depLines.get(conf); if (sb == null) { sb = new StringBuilder(); depLines.put(conf, sb); } sb.append(" \n"); if (sourceAttachment != null) { sb = sourceLines.get(conf); if (sb == null) { sb = new StringBuilder(); sourceLines.put(conf, sb); } sb.append(" \n"); } } } } for (Conf conf : confs) { String depLine = depLines.get(conf) == null ? "" : depLines.get(conf).toString(); String sourceLine = sourceLines.get(conf) == null ? "" : sourceLines.get(conf).toString(); applyTemplate("librarySet.xml.template", new File(toDir, ".idea/libraries/" + conf.getName() + "_libs.xml"), conf.getName() + " libs", depLine, sourceLine); } } private void generateModuleXml(File toDir, Module m) throws IOException { // // StringBuilder sourceDirs = new StringBuilder(); StringBuilder libSets = new StringBuilder(); for (Srcdir dir : m.getSrcdirs()) { String path = getProject().getBaseDir().toURI().relativize(dir.getDir().toURI()).toString(); sourceDirs.append(" \n"); } String deps = m.getDepends(); if (deps == null) deps = ""; for (String dep : deps.split(",")) { dep = dep.trim(); libSets.append(" \n"); } applyTemplate("module.xml.template", new File(toDir, m.getName() + ".iml"), sourceDirs.toString(), source, libSets.toString()); } private static final String MARKER = "%%"; private static void applyTemplate(String resource, File out, String... replacements) throws IOException { out.delete(); out.getParentFile().mkdirs(); @Cleanup FileOutputStream fos = new FileOutputStream(out); @Cleanup InputStream in = BuildIntellijProject.class.getResourceAsStream(resource); byte[] b = new byte[4096]; int state = 0; for (int r = in.read(b); r != -1; r = in.read(b)) { int start = 0; for (int i = 0; i < r; i++) { if (b[i] == '%') { if (state == 0) { fos.write(b, start, i - start); start = i; } if (++state > MARKER.length()) { state--; start++; fos.write('%'); } } else if (state == MARKER.length() && Character.isDigit(b[i])) { start = i + 1; fos.write(replacements[b[i] - '1'].getBytes("UTF-8")); state = 0; } else if (state > 0) { state = 0; fos.write(b, start, i - start); start = i; } } if (start < r) { fos.write(b, start, r - start); } } in.close(); fos.close(); } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/intellij/Conf.java000066400000000000000000000023671243573566400260400ustar00rootroot00000000000000/** * Copyright © 2010 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.intellij; import lombok.Data; @Data public class Conf { private String name; private String sources; } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/intellij/Module.java000066400000000000000000000036711243573566400263770ustar00rootroot00000000000000/** * Copyright © 2010 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.intellij; import java.util.ArrayList; import java.util.List; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Location; public class Module { @Getter(AccessLevel.PACKAGE) private List srcdirs = new ArrayList(); @Getter @Setter private String name; @Getter @Setter private String depends; public void addSrcdir(Srcdir srcdir) { srcdirs.add(srcdir); } void validate(Location location) { for (Srcdir dir : srcdirs) { if (dir.getDir() == null) throw new BuildException(" requires a 'src' attribute with the source dir you'd like to include.", location); } if (name == null || name.isEmpty()) throw new BuildException(" requires a 'name' attribute.", location); } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/intellij/Settings.java000066400000000000000000000155431243573566400267530ustar00rootroot00000000000000/** * Copyright © 2010 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.intellij; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import lombok.Cleanup; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Location; import org.apache.tools.ant.types.Resource; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class Settings { private TreeMap components = new TreeMap(String.CASE_INSENSITIVE_ORDER); private List inputs = new ArrayList(); private DocumentBuilderFactory factory; public void addText(String text) { inputs.add(text); } public static void main(String[] args) throws Exception { new Settings().loadXML(new FileInputStream(args[0]), true); } private void loadXML(InputStream in, boolean overwrite) throws IOException { try { DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(in); List components = new ArrayList(); gatherComponents(doc.getDocumentElement(), components); for (Element component : components) { String name = component.getAttribute("name"); if (overwrite || !this.components.containsKey(name)) this.components.put(name, component); } } catch (ParserConfigurationException e) { throw new IOException(e); } catch (SAXException e) { throw new IOException(e); } } private void gatherComponents(Element element, List list) { if ("component".equals(element.getNodeName())) { list.add(element); return; } NodeList nodeList = element.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node n = nodeList.item(i); if (n instanceof Element) gatherComponents((Element) nodeList.item(i), list); } } public void add(Resource resource) { inputs.add(resource); } private static final Map COMPONENT_NAME_MAP; static { Map map = new HashMap(); map.put("CompilerConfiguration", ".idea/compiler.xml"); map.put("CodeStyleSettingsManager", ".idea/projectCodeStyle.xml"); map.put("Encoding", ".idea/encodings.xml"); map.put("Palette2", ".idea/uiDesigner.xml"); map.put("VcsDirectoryMappings", ".idea/vcs.xml"); map.put("ProjectModuleManager", ".idea/modules.xml"); map.put("", ".idea/misc.xml"); COMPONENT_NAME_MAP = Collections.unmodifiableMap(map); } public void execute(File todir, Location location, String source) { this.factory = DocumentBuilderFactory.newInstance(); for (Object input : inputs) { if (input == null) continue; if (input instanceof String) { if (!((String)input).trim().isEmpty()) { try { @Cleanup InputStream in = new ByteArrayInputStream(((String) input).getBytes("ISO-8859-1")); loadXML(in, true); } catch (IOException e) { throw new BuildException(e, location); } } } else if (input instanceof Resource) { try { @Cleanup InputStream in = ((Resource) input).getInputStream(); loadXML(in, false); } catch (IOException e) { throw new BuildException(e, location); } } else { assert false: "A non-string, non-resource showed up"; } } Map> fileToComponents = new HashMap>(); for (Map.Entry e : components.entrySet()) { String key = e.getKey(); Element value = e.getValue(); File file = null; for (Map.Entry f : COMPONENT_NAME_MAP.entrySet()) { if (key.equalsIgnoreCase(f.getKey())) { file = new File(todir, f.getValue()); break; } } if (file == null) file = new File(todir, COMPONENT_NAME_MAP.get("")); List elemList = fileToComponents.get(file); if (elemList == null) { elemList = new ArrayList(); fileToComponents.put(file, elemList); } elemList.add(value); } try { for (Map.Entry> e : fileToComponents.entrySet()) { File key = e.getKey(); List elemList = e.getValue(); createFile(key, elemList, location); } } catch (IOException e) { throw new BuildException(e, location); } } private void createFile(File file, List elemList, Location location) throws IOException { try { file.getParentFile().mkdirs(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.newDocument(); Element top = doc.createElement("project"); top.setAttribute("version", "4"); for (Element elem : elemList) { top.appendChild(doc.importNode(elem, true)); } doc.appendChild(top); DOMSource src = new DOMSource(doc); Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.transform(src, new StreamResult(file)); } catch (ParserConfigurationException e) { throw new IOException(e); } catch (TransformerConfigurationException e) { throw new IOException(e); } catch (TransformerFactoryConfigurationError e) { throw new IOException(e); } catch (TransformerException e) { throw new IOException(e); } } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/intellij/Srcdir.java000066400000000000000000000024221243573566400263710ustar00rootroot00000000000000/** * Copyright © 2010 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.intellij; import java.io.File; import lombok.Data; @Data public class Srcdir { private File dir; private boolean test = false; } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/intellij/ant.xml.template000066400000000000000000000006641243573566400274240ustar00rootroot00000000000000 ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/intellij/compiler.xml.template000066400000000000000000000017301243573566400304470ustar00rootroot00000000000000 ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/intellij/librarySet.xml.template000066400000000000000000000003071243573566400307540ustar00rootroot00000000000000 %%2 %%3 ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/intellij/module.xml.template000066400000000000000000000005731243573566400301260ustar00rootroot00000000000000 %%1 %%3 ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/intellij/modules.xml.template000066400000000000000000000002411243573566400303010ustar00rootroot00000000000000 %%1 ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/mavencentral/000077500000000000000000000000001243573566400251455ustar00rootroot00000000000000ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/mavencentral/CreateArtifactBundle.java000066400000000000000000000176471243573566400320420ustar00rootroot00000000000000/** * Copyright © 2011 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.mavencentral; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; import lombok.Cleanup; import lombok.Setter; import lombok.SneakyThrows; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; public class CreateArtifactBundle extends Task { @Setter private File src, bin, javadoc, pom, key, out; @Setter private String version, artifactId, passphrase; @Setter private boolean noSourceOrJavadocNeeded; @Override public void execute() throws BuildException { try { InitializeBouncyCastle.init(); } catch (SigningException e) { throw new BuildException(e.getMessage(), e.getCause(), getLocation()); } if (bin == null) throw new BuildException("Must specify mandatory attribute 'bin' (points at the jar with class files in it)", getLocation()); if (pom == null) throw new BuildException("Must specify mandatory attribute 'pom' (points at your maven pom file)", getLocation()); if (out == null) throw new BuildException("Must specify mandatory attribute 'out' (this is where the artifact bundle will be written to)", getLocation()); if (key == null) throw new BuildException("Must specify mandatory attribute 'key' (file containing your signing key. Created by running ivyplusplus.jar with java -jar)", getLocation()); if (version == null) throw new BuildException("Must specify mandatory attribute 'version'", getLocation()); if (artifactId == null) throw new BuildException("Must specify mandatory attribute 'artifactId'", getLocation()); if (passphrase == null) passphrase = ""; if (!noSourceOrJavadocNeeded && src == null) throw new BuildException("Must specify mandatory attribute 'src' unless 'noSourceOrJavadocNeeded' is true (points at the jar with sources in it)", getLocation()); if (!noSourceOrJavadocNeeded && javadoc == null) throw new BuildException("Must specify mandatory attribute 'javadoc' unless 'noSourceOrJavadocNeeded' is true (points at the jar with javadocs in it)", getLocation()); if (bin != null && !bin.getName().toLowerCase().endsWith(".jar")) throw new BuildException("Only jar files are supported by create-artifact-bundle; 'bin' attribute isn't one.", getLocation()); if (src != null && !src.getName().toLowerCase().endsWith(".jar")) throw new BuildException("Only jar files are supported by create-artifact-bundle; 'src' attribute isn't one.", getLocation()); if (javadoc != null && !javadoc.getName().toLowerCase().endsWith(".jar")) throw new BuildException("Only jar files are supported by create-artifact-bundle; 'javadoc' attribute isn't one.", getLocation()); byte[] pomData; try { @Cleanup InputStream pomStream = new FileInputStream(pom); pomData = readStream(pomStream); pomStream.close(); } catch (FileNotFoundException e) { throw new BuildException("Missing pom file", e, getLocation()); } catch (IOException e) { throw new BuildException("Can't read pom file", e, getLocation()); } if (version != null && !version.isEmpty()) { pomData = replaceVersion(pomData, "@VERSION@", version); } CreateDetachedSignatures signer = new CreateDetachedSignatures(); try { @Cleanup FileOutputStream outStream = new FileOutputStream(out); JarOutputStream zipOut = new JarOutputStream(outStream); zipOut.putNextEntry(new JarEntry("pom.xml")); zipOut.write(pomData); ByteArrayOutputStream signature = new ByteArrayOutputStream(); signer.signFile(new ByteArrayInputStream(pomData), signature, key, passphrase); zipOut.putNextEntry(new JarEntry("pom.xml.asc")); zipOut.write(signature.toByteArray()); writeToJar(zipOut, artifactId + "-" + version + ".jar", bin); if (src != null) writeToJar(zipOut, artifactId + "-" + version + "-sources.jar", src); if (src != null) writeToJar(zipOut, artifactId + "-" + version + "-javadoc.jar", javadoc); zipOut.closeEntry(); zipOut.close(); } catch (FileNotFoundException e) { throw new BuildException("File not found: " + e.getMessage(), e, getLocation()); } catch (IOException e) { throw new BuildException("I/O problem writing out file or reading in files", e, getLocation()); } catch (SigningException e) { throw new BuildException("Problem signing files", e, getLocation()); } } private void writeToJar(JarOutputStream zipOut, String filename, File data) throws IOException, SigningException { ByteArrayOutputStream signature = new ByteArrayOutputStream(); zipOut.putNextEntry(new JarEntry(filename)); @Cleanup FileInputStream fis = new FileInputStream(data); CreateDetachedSignatures signer = new CreateDetachedSignatures(); signer.signFile(new DuplicatingInputStream(fis, zipOut), signature, key, passphrase); zipOut.putNextEntry(new JarEntry(filename + ".asc")); zipOut.write(signature.toByteArray()); zipOut.closeEntry(); } private static class DuplicatingInputStream extends InputStream { private final InputStream wrapped; private final OutputStream pipe; DuplicatingInputStream(InputStream wrapped, OutputStream pipe) { this.wrapped = wrapped; this.pipe = pipe; } @Override public int read() throws IOException { int c = wrapped.read(); if (c != -1) pipe.write(c); return c; } @Override public int read(byte[] b) throws IOException { int r = wrapped.read(b); if (r != -1) pipe.write(b, 0, r); return r; } @Override public int read(byte[] b, int off, int len) throws IOException { int r = wrapped.read(b, off, len); if (r != -1) pipe.write(b, off, r); return r; } } private static byte[] readStream(InputStream in) throws IOException { byte[] b = new byte[4096]; ByteArrayOutputStream out = new ByteArrayOutputStream(); while (true) { int r = in.read(b); if (r == -1) return out.toByteArray(); out.write(b, 0, r); } } @SneakyThrows(IOException.class) private static byte[] replaceVersion(byte[] in, String token_, String replacement_) { int start = 0; ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] token = token_.getBytes("US-ASCII"); byte[] replacement = replacement_.getBytes("US-ASCII"); while (true) { int idx = find(in, token, start); if (idx == -1) break; out.write(in, start, idx - start); start = idx + token.length; out.write(replacement); } if (start < in.length) { out.write(in, start, in.length - start); } return out.toByteArray(); } private static int find(byte[] haystack, byte[] needle, int start) { int pos = 0; for (int i = start; i < haystack.length; i++) { if (pos == needle.length) return i; if (haystack[i] == needle[pos]) pos++; else pos = 0; } return -1; } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/mavencentral/CreateDetachedSignatures.java000066400000000000000000000016001243573566400326770ustar00rootroot00000000000000package com.zwitserloot.ivyplusplus.mavencentral; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Arrays; public class CreateDetachedSignatures { public void signFile(File file, File keyFile, String passphrase) throws IOException, SigningException { InitializeBouncyCastle.call(getClass().getName() + "_", "signFile", Arrays.>asList(File.class, File.class, String.class), Arrays.asList(file, keyFile, passphrase)); } public void signFile(InputStream dataIn, OutputStream signOut, File keyFile, String passphrase) throws SigningException, IOException { InitializeBouncyCastle.call(getClass().getName() + "_", "signFile", Arrays.>asList(InputStream.class, OutputStream.class, File.class, String.class), Arrays.asList(dataIn, signOut, keyFile, passphrase)); } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/mavencentral/CreateDetachedSignatures_.java000066400000000000000000000122461243573566400330460ustar00rootroot00000000000000/** * Copyright © 2011 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.mavencentral; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SignatureException; import java.util.Iterator; import lombok.Cleanup; import org.bouncycastle.bcpg.ArmoredOutputStream; import org.bouncycastle.bcpg.BCPGOutputStream; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPrivateKey; import org.bouncycastle.openpgp.PGPSecretKey; import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.bouncycastle.openpgp.PGPSignature; import org.bouncycastle.openpgp.PGPSignatureGenerator; import org.bouncycastle.openpgp.PGPUtil; public class CreateDetachedSignatures_ { public void signFile(File file, File keyFile, String passphrase) throws IOException, SigningException { try { PGPSecretKey key; { @Cleanup FileInputStream keyIn = new FileInputStream(keyFile); key = getSigningKey(keyIn, keyFile.getName()); } { @Cleanup OutputStream outStream = new FileOutputStream(file.getAbsolutePath() + ".asc"); @Cleanup InputStream fileIn = new FileInputStream(file); signFile(fileIn, key, passphrase, outStream); } } catch (NoSuchProviderException e) { throw new SigningException("Bouncycastle provider not loaded", e); } catch (NoSuchAlgorithmException e) { throw new SigningException("Signature key uses an algorithm that is not compatible with ivyplusplus", e); } catch (PGPException e) { throw new SigningException("Unknown signing problem: " + e.getMessage(), e); } catch (SignatureException e) { throw new SigningException("Problem with signature: " + e.getMessage(), e); } } public void signFile(InputStream dataIn, OutputStream signOut, File keyFile, String passphrase) throws IOException, SigningException { try { PGPSecretKey key; { @Cleanup FileInputStream keyIn = new FileInputStream(keyFile); key = getSigningKey(keyIn, keyFile.getName()); } { signFile(dataIn, key, passphrase, signOut); } } catch (NoSuchProviderException e) { throw new SigningException("Bouncycastle provider not loaded", e); } catch (NoSuchAlgorithmException e) { throw new SigningException("Signature key uses an algorithm that is not compatible with ivyplusplus", e); } catch (PGPException e) { throw new SigningException("Unknown signing problem: " + e.getMessage(), e); } catch (SignatureException e) { throw new SigningException("Problem with signature: " + e.getMessage(), e); } } void signFile(InputStream fileData, PGPSecretKey signingKey, String passphrase, OutputStream out) throws IOException, NoSuchProviderException, PGPException, NoSuchAlgorithmException, SignatureException { PGPPrivateKey privKey = signingKey.extractPrivateKey(passphrase.toCharArray(), "BC"); PGPSignatureGenerator sigGen = new PGPSignatureGenerator(signingKey.getPublicKey().getAlgorithm(), PGPUtil.SHA1, "BC"); sigGen.initSign(PGPSignature.BINARY_DOCUMENT, privKey); out = new ArmoredOutputStream(out); BCPGOutputStream bOut = new BCPGOutputStream(out); byte[] b = new byte[4096]; while (true) { int r = fileData.read(b); if (r == -1) break; sigGen.update(b, 0, r); } sigGen.generate().encode(bOut); bOut.close(); out.close(); } PGPSecretKey getSigningKey(InputStream keyData, String streamName) throws IOException, PGPException, SigningException { PGPSecretKeyRingCollection keyrings_ = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyData)); Iterator keyrings = keyrings_.getKeyRings(); while (keyrings.hasNext()) { PGPSecretKeyRing keys_ = (PGPSecretKeyRing) keyrings.next(); Iterator keys = keys_.getSecretKeys(); while (keys.hasNext()) { PGPSecretKey key = (PGPSecretKey) keys.next(); if (key.isSigningKey()) return key; } } throw new SigningException("No signing key found in keyring: " + streamName); } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/mavencentral/CreateSigningKey.java000066400000000000000000000007651243573566400312130ustar00rootroot00000000000000package com.zwitserloot.ivyplusplus.mavencentral; import java.io.IOException; import java.io.PrintStream; import java.util.Arrays; public class CreateSigningKey { public void createSigningKey(String identity, String passphrase, PrintStream log) throws IOException, SigningException { InitializeBouncyCastle.call(getClass().getName() + "_", "createSigningKey", Arrays.>asList(String.class, String.class, PrintStream.class), Arrays.asList(identity, passphrase, log)); } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/mavencentral/CreateSigningKey_.java000066400000000000000000000106501243573566400313440ustar00rootroot00000000000000/** * Copyright © 2011 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.mavencentral; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.math.BigInteger; import java.security.InvalidAlgorithmParameterException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; import java.util.Date; import lombok.Cleanup; import org.bouncycastle.jce.spec.ElGamalParameterSpec; import org.bouncycastle.openpgp.PGPEncryptedData; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPKeyPair; import org.bouncycastle.openpgp.PGPKeyRingGenerator; import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPSignature; public class CreateSigningKey_ { public void createSigningKey(String identity, String passphrase, PrintStream log) throws IOException, SigningException { if (passphrase == null) passphrase = ""; try { KeyPairGenerator gen = KeyPairGenerator.getInstance("DSA", "BC"); gen.initialize(1024); log.printf("Please hold on, a 1024 bit key is being generated. This takes a while and requires a lot of random data, so try moving the mouse at random.\n"); KeyPair privPair = gen.generateKeyPair(); KeyPairGenerator elgamal = KeyPairGenerator.getInstance("ELGAMAL", "BC"); BigInteger g = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16); BigInteger p = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16); elgamal.initialize(new ElGamalParameterSpec(g, p)); KeyPair signPair = elgamal.generateKeyPair(); @Cleanup OutputStream privOut = new FileOutputStream("mavenrepo-signing-key-secret.bpr"); @Cleanup OutputStream pubOut = new FileOutputStream("mavenrepo-signing-key-public.bpr"); export(privOut,pubOut, privPair, signPair, identity, passphrase); } catch (NoSuchAlgorithmException e) { throw new SigningException("Bouncycastle not configured correctly", e); } catch (InvalidAlgorithmParameterException e) { throw new SigningException("Bouncycastle not configured correctly", e); } catch (NoSuchProviderException e) { throw new SigningException("Bouncycastle provider not loaded", e); } catch (PGPException e) { e.printStackTrace(); throw new SigningException("Unknown signing problem: " + e.getMessage(), e); } } void export(OutputStream privOut, OutputStream pubOut, KeyPair privPair_, KeyPair signPair_, String identity, String passphrase) throws PGPException, NoSuchProviderException, IOException { PGPKeyPair privPair = new PGPKeyPair(PGPPublicKey.DSA, privPair_, new Date()); PGPKeyPair signPair = new PGPKeyPair(PGPPublicKey.ELGAMAL_ENCRYPT, signPair_, new Date()); PGPKeyRingGenerator ringGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, privPair, identity, PGPEncryptedData.AES_256, passphrase.toCharArray(), true, null, null, new SecureRandom(), "BC"); ringGen.addSubKey(signPair); ringGen.generateSecretKeyRing().encode(privOut); privOut.close(); ringGen.generatePublicKeyRing().encode(pubOut); pubOut.close(); } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/mavencentral/InitializeBouncyCastle.java000066400000000000000000000075471243573566400324420ustar00rootroot00000000000000/** * Copyright © 2011 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.mavencentral; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.net.URLClassLoader; import java.security.Provider; import java.security.Security; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import lombok.Cleanup; import lombok.Lombok; public class InitializeBouncyCastle { private static AtomicBoolean initialized = new AtomicBoolean(false); private static ClassLoader loader; public static void init() throws SigningException { if (initialized.getAndSet(true)) return; URL[] urls = new URL[3]; urls[0] = writeToTemp("bcprov-jdk16"); urls[1] = writeToTemp("bcpg-jdk16"); urls[2] = writeToTemp("ipp-bc-bridges"); try { loader = new URLClassLoader(urls, InitializeBouncyCastle.class.getClassLoader()); Class provider = loader.loadClass("org.bouncycastle.jce.provider.BouncyCastleProvider"); Security.addProvider((Provider) provider.newInstance()); } catch (ClassNotFoundException e) { throw new SigningException("Included bouncycastle provider jar is corrupted", e); } catch (IllegalAccessException e) { throw new SigningException("Included bouncycastle provider jar is corrupted", e); } catch (InstantiationException e) { throw new SigningException("Included bouncycastle provider jar is corrupted", e); } } private static URL writeToTemp(String resourceKey) throws SigningException { try { File file = File.createTempFile(resourceKey, "jar"); file.deleteOnExit(); @Cleanup FileOutputStream out = new FileOutputStream(file); @Cleanup InputStream in = InitializeBouncyCastle.class.getResourceAsStream("/" + resourceKey + ".jar"); byte[] b = new byte[4096]; while (true) { int r = in.read(b); if (r == -1) break; out.write(b, 0, r); } in.close(); out.close(); return file.toURI().toURL(); } catch (IOException e) { throw new SigningException("Can't unpack bouncycastle crypto provider to temp dir: " + e, e); } } public static Object call(String fqn, String methodName, List> types, List params) throws SigningException { Throwable t; try { Class c = loader.loadClass(fqn); return c.getMethod(methodName, types.toArray(new Class[0])).invoke(c.newInstance(), params.toArray(new Object[0])); } catch (ClassNotFoundException e) { t = e; } catch (IllegalAccessException e) { t = e; } catch (InstantiationException e) { t = e; } catch (InvocationTargetException e) { throw Lombok.sneakyThrow(e); } catch (NoSuchMethodException e) { t = e; } t.printStackTrace(); throw new SigningException("bouncycastle corrupted", t); } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/mavencentral/SigningException.java000066400000000000000000000025511243573566400312700ustar00rootroot00000000000000/** * Copyright © 2011 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.mavencentral; public class SigningException extends Exception { public SigningException(String message) { super(message); } public SigningException(String message, Throwable cause) { super(message, cause); } } ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/template/000077500000000000000000000000001243573566400243015ustar00rootroot00000000000000ivyplusplus-1.14/src/com/zwitserloot/ivyplusplus/template/TemplateApplier.java000066400000000000000000000146521243573566400302440ustar00rootroot00000000000000/** * Copyright © 2011 Reinier Zwitserloot. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.zwitserloot.ivyplusplus.template; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayDeque; import java.util.Deque; import java.util.HashMap; import java.util.Map; public class TemplateApplier { private static final class IfStackEntry { final String key; final boolean value; final int pos; IfStackEntry(String key, int pos, boolean value) { this.key = key; this.value = value; this.pos = pos; } } @Override public String toString() { return map.toString(); } private final Map map = new HashMap(); public String applyStream(InputStream in) throws IOException { return applyStream(in, "UTF-8"); } public String applyStream(InputStream in, String charset) throws IOException { byte[] data; try { data = read(in); } finally { in.close(); } return applyTemplate(new String(data, charset)); } public String applyFile(File in) throws IOException { return applyFile(in, "UTF-8"); } public String applyFile(File in, String charset) throws IOException { FileInputStream fis = new FileInputStream(in); byte[] data; try { data = read(fis); } finally { fis.close(); } return applyTemplate(new String(data, charset)); } public String applyResource(Class context, String resource) throws IOException { return applyResource(context, resource, "UTF-8"); } public String applyResource(Class context, String resource, String charset) throws IOException { InputStream is = context.getResourceAsStream(resource); byte[] data; try { data = read(is); } finally { is.close(); } return applyTemplate(new String(data, charset)); } public void put(String key, String value) { this.map.put(key, value); } public String applyTemplate(String template) { StringBuilder sb = new StringBuilder(); int pos = 0; Deque ifStack = new ArrayDeque(); boolean suppress = false; while (pos < template.length()) { int idx = template.indexOf("{{", pos); if (idx == -1) { if (!suppress) sb.append(template.substring(pos)); break; } if (!suppress) sb.append(template.substring(pos, idx)); int braceCount = 2; while (idx + braceCount < template.length()) { if (template.charAt(idx + braceCount) != '{') break; braceCount++; } if (braceCount > 2) { pos = idx + braceCount; while (braceCount > 1) { if (!suppress) sb.append("{"); braceCount--; } continue; } int endIdx = template.indexOf("}}", idx); if (endIdx == -1) { if (!suppress) sb.append(template.substring(idx)); break; } String command = template.substring(idx + 2, endIdx); boolean removePrefixWhitespace = false; pos = endIdx + 2; if (template.length() == endIdx + 2) { removePrefixWhitespace = true; } else if (template.length() > endIdx + 2 && template.charAt(endIdx + 2) == '\n') { removePrefixWhitespace = true; pos = endIdx + 3; } else if (template.length() > endIdx + 3 && template.charAt(endIdx + 2) == '\r' && template.charAt(endIdx + 2) == '\n') { removePrefixWhitespace = true; pos = endIdx + 4; } StringBuilder prefixWhitespace = new StringBuilder(); if (removePrefixWhitespace) while (sb.length() > 0) { char ws = sb.charAt(sb.length() - 1); if (ws != ' ' && ws != '\t') break; prefixWhitespace.insert(0, ws); sb.setLength(sb.length() - 1); } if (command.startsWith("@")) { String key = command.substring(1).trim(); if (!suppress) sb.append(map.containsKey(key) ? addWhitespacePrefix(prefixWhitespace.toString(), map.get(key)) : ""); } else if (command.startsWith("if ")) { String key = command.substring(3).trim(); boolean val = map.containsKey(key); ifStack.push(new IfStackEntry(key, idx, val)); suppress |= !val; } else if (command.startsWith("end ")) { String key = command.substring(4).trim(); if (ifStack.isEmpty()) throw new IllegalArgumentException(String.format("%s floating {{end %s}}", toLinePos(template, idx), key)); ifStack.pop(); suppress = false; for (IfStackEntry v : ifStack) suppress |= !v.value; } else { throw new IllegalArgumentException(String.format("%s Unknown command: %s", toLinePos(template, idx), command)); } } if (!ifStack.isEmpty()) throw new IllegalArgumentException(String.format("%s {{if %s}} not closed", toLinePos(template, ifStack.peek().pos), ifStack.peek().key)); return sb.toString(); } private String addWhitespacePrefix(String prefix, String text) { String t = text.replace("\n", "\n" + prefix).trim(); return prefix + t + (prefix.length() > 0 ? "\n" : ""); } private static final byte[] read(InputStream in) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] b = new byte[4096]; while (true) { int r = in.read(b); if (r == -1) break; baos.write(b, 0, r); } return baos.toByteArray(); } public static String toLinePos(String template, int idx) { int line = 0; int col = 0; for (int i = 0; i < idx; i++) { char c = template.charAt(i); col += c == '\t' ? 4 : 1; if (c == '\n') { line++; col = 0; } } return String.format("[%d, %d]", line + 1, col + 1); } }