![JAR search and dependency download from the Maven repository](/logo.png)
protoj.lang.ArchiveFeature Maven / Gradle / Ivy
Show all versions of protoj-jdk6 Show documentation
/**
* Copyright 2009 Ashley Williams
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package protoj.lang;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.launch.AntMain;
import org.aspectj.lang.SoftException;
import protoj.lang.ClassesArchive.ClassesEntry;
import protoj.util.ArgRunnable;
import protoj.util.UntarTask;
/**
* Provides support for the creation of source, javadoc, classes jar files,
* project tar file and a self extracting project archive. This class is an
* aggregate of implementation objects so see the {@link SourceArchive},
* {@link JavadocArchive}, {@link ClassesArchive} and {@link ProjectArchive}
* classes for more information.
*
* @author Ashley Williams
*
*/
public final class ArchiveFeature {
/**
* The name of the tar gz file created with
* {@link #createSelfExtractingArchive(boolean, boolean, boolean)}.
*/
private static final String PROJECT_DIST_ARCHIVE = "project-dist";
/**
* See {@link #getClassesArchive()}.
*/
private ClassesArchive classesArchive;
/**
* See {@link #getSourceArchive()}.
*/
private SourceArchive sourceArchive;
/**
* See {@link #getJavadocArchive()}.
*/
private JavadocArchive javadocArchive;
/**
* See {@link #getProjectArchive()}.
*/
private ProjectArchive projectArchive;
/**
* See {@link #getProject()}.
*/
private final StandardProject project;
/**
* A cached reference to this frequently used instance.
*/
private ProjectLayout layout;
/**
* The name of the self extracting archive, see
* {@link #initSelfExtractingArchive(String, String, String, String, String)}
* .
*/
private String extractingArchiveName;
/**
* Enables creation of source, javadoc and classes jar files.
*
* @param parent
*/
public ArchiveFeature(StandardProject parent) {
this.project = parent;
this.layout = parent.getLayout();
this.classesArchive = new ClassesArchive(this);
this.sourceArchive = new SourceArchive(this);
this.javadocArchive = new JavadocArchive(this);
}
/**
* This method must be called if support for creating a compressed tar file
* of the project is required.
*
* @param name
* the name of the tar file without any extension
* @param prefix
* used as the name of the root directory when the tarfile is
* extracted
* @param userName
* the user name for the tar entry, can be null
* @param group
* the group for the tar entry, can be null
*/
public void initProjectArchive(String name, String prefix, String userName,
String group) {
this.projectArchive = new ProjectArchive(this, name, prefix, userName,
group);
}
/**
* Convenient wrapper when just the default tar is required with no
* customization and applying tar name suffixes as necessary. See
* {@link #initProjectArchive(String, String, String, String)}.
*
* @param name
* @param prefix
*/
public void initProjectArchive(String name, String prefix) {
initProjectArchive(name, prefix, null, null);
}
/**
* Enables the creation of a self extracting jar file with the name
* specified by the extractingArchiveName argument and whose contents are a
* compressed tar of the whole project. The resultant archive is executable
* and so when executed will extract the project into the same directory.
*
* This works by initializing the project archive with a call to
* {@link #initProjectArchive(String, String)} and configuring a new classes
* archive with a call to
* {@link ClassesArchive#addEntry(String, String, String, String)} and
* coordinating between the two. Therefore it is advisable not to separately
* call initProjectArchive.
*
*
* @param extractingArchiveName
* the name of the archive
* @param jarManifest
* the name of the manifest, null to accept default
* @param tarPrefix
* the name of the root directory when the tar is extracted
* @param tarUserName
* the user name for the tar entries
* @param tarGroup
* the group for the tar entries
*/
public void initSelfExtractingArchive(String extractingArchiveName,
String jarManifest, String tarPrefix, String tarUserName,
String tarGroup) {
this.extractingArchiveName = extractingArchiveName;
// enable the creation of the project tar archive
initProjectArchive(PROJECT_DIST_ARCHIVE, tarPrefix, tarUserName,
tarGroup);
// enable the executable jar that will perform the extraction
getClassesArchive().addEntry(extractingArchiveName, jarManifest, null,
"**/*");
getClassesArchive().getEntry(extractingArchiveName).initConfig(
new ArgRunnable() {
public void run(ClassesArchive archive) {
archive.initExecutableJar(ArchiveFeature.class
.getName());
}
});
getClassesArchive().initIncludeArchives(extractingArchiveName,
getPath(Task.class).getName(),
getPath(AntMain.class).getName(),
getPath(Logger.class).getName(),
getPath(IOUtils.class).getName(),
getPath(StandardProject.class).getName(),
getPath(SoftException.class).getName());
}
/**
* Gets the filename of the jar that contains the specified class name.
* Helper for
* {@link #initSelfExtractingArchive(String, String, String, String, String)}
* .
*
* @param name
* @return
*/
private File getPath(Class> name) {
File jar = new File(name.getProtectionDomain().getCodeSource()
.getLocation().toURI());
return jar;
}
/**
* Creates a self extracting archive of the project as initialized in
* {@link #initSelfExtractingArchive(String, String, String, String, String)}
* .
*
*
* - the first party jars are updated in the lib directory for those
* archives that are supposed to be on the classpath - see
* {@link ClassesArchive#initClasspathLib(String)}
* - the project tar file is created in the classes directory - see
* {@link ProjectArchive#createArchive(boolean, boolean, boolean)} for an
* explanation of the tar parameters below
* - the self extracting jar is created from the files in the classes
* directory, including importantly the project tar file just mentioned
*
*
*
*
* @param noSrc
* @param noClasses
* @param isGlobalRwx
*/
public void createSelfExtractingArchive(boolean noSrc, boolean noClasses,
boolean isGlobalRwx) {
File srcFile = getProjectArchive().getArchiveFile();
File destFile = new File(getLayout().getClassesDir(), srcFile.getName());
// delete any previous dest file so it can't be included in next tar
destFile.delete();
// ensure first party libs have been created in lib directory
classesArchive.visit(new ArgRunnable() {
public void run(ClassesEntry entry) {
if (entry.isClasspathLib()) {
String name = entry.getArchiveEntry().getName();
classesArchive.createArchive(name);
}
}
});
// create the project tar file with no source directory
getProjectArchive().createArchive(noSrc, noClasses, isGlobalRwx);
// copy the tar file to the classes directory
FileUtils.copyFile(srcFile, destFile);
// create a jar of the classes directory which includes tar
getClassesArchive().createArchive(extractingArchiveName);
}
/**
* Deletes the target/ and classes/ directories as well as any jars that
* have been copied to the lib/ directory. These are identified by finding
* those classes archive entries that were configured with a call to
* {@link ClassesArchive#initClasspathLib(String)}.
*/
public void clean() {
FileUtils.deleteDirectory(getLayout().getTargetDir());
FileUtils.deleteDirectory(getLayout().getClassesDir());
getClassesArchive().visit(new ArgRunnable() {
public void run(ClassesEntry entry) {
if (entry.isClasspathLib()) {
String name = entry.getArchiveEntry().getName();
File file = new File(getLayout().getLibDir(), name);
FileUtils.deleteDirectory(file);
}
}
});
}
/**
* Convenience method that schedules the creation of a single jar file with
* the given name. See
* {@link ClassesArchive#addEntry(String, String, String, String)} .
*
* @param name
*/
public void addClasses(String name) {
getClassesArchive().addEntry(name, null, null, null);
}
/**
* Convenience method that schedules the creation of a single javadoc
* archive file with the given name and memory. See
* {@link JavadocArchive#addEntry(String, String, String, String, String)} .
*
* @param name
*/
public void addJavadoc(String name, String memory) {
getJavadocArchive().addEntry(name, null, null, null, memory);
}
/**
* Convenience method that schedules the creation of a single sources
* archive file with the given name and memory. See
* {@link JavadocArchive#addEntry(String, String, String, String, String)} .
* .
*
* @param name
*/
public void addSources(String name) {
getSourceArchive().addEntry(name, null, null, null);
}
/**
* Returns whether or not the given jar name represents a valid classes jar
* file. This is a jar file that doesn't contain the strings
* {@link ProjectLayout#getSourcePostfix()},
* {@link ProjectLayout#getJavadocPostfix()} or
* {@link ProjectLayout#getSrcPostfix()}.
*
* @param name
* @return
*/
public boolean isClassesJar(String name) {
return name.endsWith(".jar") && !isSourcesJar(name)
&& !isJavadocJar(name);
}
/**
* Returns whether or not the given jar name represents a valid javadoc jar
* file. This is a jar file that contain the string
* {@link ProjectLayout#getJavadocPostfix()}.
*
* @param name
* @return
*/
public boolean isJavadocJar(String name) {
return name.endsWith(".jar")
&& name.contains(layout.getJavadocPostfix());
}
/**
* Returns whether or not the given jar name represents a valid sources jar
* file. This is a jar file that contains either of the strings
* {@link ProjectLayout#getSourcePostfix()} or
* {@link ProjectLayout#getSrcPostfix()}.
*
* @param name
* @return
*/
public boolean isSourcesJar(String name) {
return name.endsWith(".jar")
&& (name.contains(layout.getSourcePostfix()) || name
.contains(layout.getSrcPostfix()));
}
/**
* Use this instance to configure the creation of java archives from the
* classes directory. See {@link ClassesArchive}.
*
* @return
*/
public ClassesArchive getClassesArchive() {
return classesArchive;
}
/**
* Use this instance to configure the creation of java archives from the
* source directory. See {@link SourceArchive}.
*
* @return
*/
public SourceArchive getSourceArchive() {
return sourceArchive;
}
/**
* Use this instance to configure the creation of java archives from the
* javadoc directory. See {@link JavadocArchive}.
*
* @return
*/
public JavadocArchive getJavadocArchive() {
return javadocArchive;
}
/**
* Use this instance to configure the creation of a compressed tar file for
* the entire application. See {@link ProjectArchive}.
*
* @return
*/
public ProjectArchive getProjectArchive() {
return projectArchive;
}
/**
* The parent project for this feature.
*
* @return
*/
public StandardProject getProject() {
return project;
}
/**
* The parent layout for convenient access.
*
* @return
*/
public ProjectLayout getLayout() {
return layout;
}
/**
* Extracts the project contained in this executable jar. This use-case is
* therefore only available when called from the executable jar created in
* the first place with a call to
* {@link ArchiveFeature#createSelfExtractingArchive(boolean, boolean, boolean)}
* .
*/
public static void main(String[] args) {
File container = new File(ArchiveFeature.class.getProtectionDomain()
.getCodeSource().getLocation().toURI());
if (container == null) {
throw new RuntimeException(
"this use-case isn't being invoked from the executable jar");
}
JarFile jarFile = new JarFile(container);
String artifactName = PROJECT_DIST_ARCHIVE + ".tar.gz";
File artifactFile = new File(".", artifactName);
ZipEntry artifactEntry = jarFile.getEntry(artifactName);
InputStream source = jarFile.getInputStream(artifactEntry);
try {
FileOutputStream dest = new FileOutputStream(artifactFile);
try {
IOUtils.copy(source, dest);
} finally {
IOUtils.closeQuietly(dest);
}
} finally {
IOUtils.closeQuietly(source);
}
UntarTask untarTask = new UntarTask(artifactFile, new File("."));
untarTask.initCompression("gzip");
untarTask.execute();
}
}