use of java.util.jar.Manifest in project buck by facebook.
the class Main method makeManifest.
/**
* Creates and returns the manifest to use for the output. This may
* modify {@link #outputResources} (removing the pre-existing manifest).
*
* @return {@code non-null;} the manifest
*/
private Manifest makeManifest() throws IOException {
byte[] manifestBytes = outputResources.get(MANIFEST_NAME);
Manifest manifest;
Attributes attribs;
if (manifestBytes == null) {
// We need to construct an entirely new manifest.
manifest = new Manifest();
attribs = manifest.getMainAttributes();
attribs.put(Attributes.Name.MANIFEST_VERSION, "1.0");
} else {
manifest = new Manifest(new ByteArrayInputStream(manifestBytes));
attribs = manifest.getMainAttributes();
outputResources.remove(MANIFEST_NAME);
}
String createdBy = attribs.getValue(CREATED_BY);
if (createdBy == null) {
createdBy = "";
} else {
createdBy += " + ";
}
createdBy += "dx " + Version.VERSION;
attribs.put(CREATED_BY, createdBy);
attribs.putValue("Dex-Location", DexFormat.DEX_IN_JAR_NAME);
return manifest;
}
use of java.util.jar.Manifest in project hadoop by apache.
the class RunJar method run.
public void run(String[] args) throws Throwable {
String usage = "RunJar jarFile [mainClass] args...";
if (args.length < 1) {
System.err.println(usage);
System.exit(-1);
}
int firstArg = 0;
String fileName = args[firstArg++];
File file = new File(fileName);
if (!file.exists() || !file.isFile()) {
System.err.println("JAR does not exist or is not a normal file: " + file.getCanonicalPath());
System.exit(-1);
}
String mainClassName = null;
JarFile jarFile;
try {
jarFile = new JarFile(fileName);
} catch (IOException io) {
throw new IOException("Error opening job jar: " + fileName).initCause(io);
}
Manifest manifest = jarFile.getManifest();
if (manifest != null) {
mainClassName = manifest.getMainAttributes().getValue("Main-Class");
}
jarFile.close();
if (mainClassName == null) {
if (args.length < 2) {
System.err.println(usage);
System.exit(-1);
}
mainClassName = args[firstArg++];
}
mainClassName = mainClassName.replaceAll("/", ".");
File tmpDir = new File(System.getProperty("java.io.tmpdir"));
ensureDirectory(tmpDir);
final File workDir;
try {
workDir = File.createTempFile("hadoop-unjar", "", tmpDir);
} catch (IOException ioe) {
// If user has insufficient perms to write to tmpDir, default
// "Permission denied" message doesn't specify a filename.
System.err.println("Error creating temp dir in java.io.tmpdir " + tmpDir + " due to " + ioe.getMessage());
System.exit(-1);
return;
}
if (!workDir.delete()) {
System.err.println("Delete failed for " + workDir);
System.exit(-1);
}
ensureDirectory(workDir);
ShutdownHookManager.get().addShutdownHook(new Runnable() {
@Override
public void run() {
FileUtil.fullyDelete(workDir);
}
}, SHUTDOWN_HOOK_PRIORITY);
unJar(file, workDir);
ClassLoader loader = createClassLoader(file, workDir);
Thread.currentThread().setContextClassLoader(loader);
Class<?> mainClass = Class.forName(mainClassName, true, loader);
Method main = mainClass.getMethod("main", String[].class);
List<String> newArgsSubList = Arrays.asList(args).subList(firstArg, args.length);
String[] newArgs = newArgsSubList.toArray(new String[newArgsSubList.size()]);
try {
main.invoke(null, new Object[] { newArgs });
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
use of java.util.jar.Manifest in project flink by apache.
the class JarFileCreator method createJarFile.
/**
* Creates a jar file which contains the previously added class. The content of the jar file is written to
* <code>outputFile</code> which has been provided to the constructor. If <code>outputFile</code> already exists, it
* is overwritten by this operation.
*
* @throws IOException
* thrown if an error occurs while writing to the output file
*/
public synchronized void createJarFile() throws IOException {
//Retrieve dependencies automatically
addDependencies();
// Temporary buffer for the stream copy
final byte[] buf = new byte[128];
// Check if output file is valid
if (this.outputFile == null) {
throw new IOException("Output file is null");
}
// If output file already exists, delete it
if (this.outputFile.exists()) {
this.outputFile.delete();
}
try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(this.outputFile), new Manifest())) {
final Iterator<Class<?>> it = this.classSet.iterator();
while (it.hasNext()) {
final Class<?> clazz = it.next();
final String entry = clazz.getName().replace('.', '/') + CLASS_EXTENSION;
jos.putNextEntry(new JarEntry(entry));
String name = clazz.getName();
int n = name.lastIndexOf('.');
String className = null;
if (n > -1) {
className = name.substring(n + 1, name.length());
}
//Using the part after last dot instead of class.getSimpleName() could resolve the problem of inner class.
final InputStream classInputStream = clazz.getResourceAsStream(className + CLASS_EXTENSION);
int num = classInputStream.read(buf);
while (num != -1) {
jos.write(buf, 0, num);
num = classInputStream.read(buf);
}
classInputStream.close();
jos.closeEntry();
}
}
}
use of java.util.jar.Manifest in project hadoop by apache.
the class FileUtil method createJarWithClassPath.
/**
* Create a jar file at the given path, containing a manifest with a classpath
* that references all specified entries.
*
* Some platforms may have an upper limit on command line length. For example,
* the maximum command line length on Windows is 8191 characters, but the
* length of the classpath may exceed this. To work around this limitation,
* use this method to create a small intermediate jar with a manifest that
* contains the full classpath. It returns the absolute path to the new jar,
* which the caller may set as the classpath for a new process.
*
* Environment variable evaluation is not supported within a jar manifest, so
* this method expands environment variables before inserting classpath entries
* to the manifest. The method parses environment variables according to
* platform-specific syntax (%VAR% on Windows, or $VAR otherwise). On Windows,
* environment variables are case-insensitive. For example, %VAR% and %var%
* evaluate to the same value.
*
* Specifying the classpath in a jar manifest does not support wildcards, so
* this method expands wildcards internally. Any classpath entry that ends
* with * is translated to all files at that path with extension .jar or .JAR.
*
* @param inputClassPath String input classpath to bundle into the jar manifest
* @param pwd Path to working directory to save jar
* @param targetDir path to where the jar execution will have its working dir
* @param callerEnv Map<String, String> caller's environment variables to use
* for expansion
* @return String[] with absolute path to new jar in position 0 and
* unexpanded wild card entry path in position 1
* @throws IOException if there is an I/O error while writing the jar file
*/
public static String[] createJarWithClassPath(String inputClassPath, Path pwd, Path targetDir, Map<String, String> callerEnv) throws IOException {
// Replace environment variables, case-insensitive on Windows
@SuppressWarnings("unchecked") Map<String, String> env = Shell.WINDOWS ? new CaseInsensitiveMap(callerEnv) : callerEnv;
String[] classPathEntries = inputClassPath.split(File.pathSeparator);
for (int i = 0; i < classPathEntries.length; ++i) {
classPathEntries[i] = StringUtils.replaceTokens(classPathEntries[i], StringUtils.ENV_VAR_PATTERN, env);
}
File workingDir = new File(pwd.toString());
if (!workingDir.mkdirs()) {
// If mkdirs returns false because the working directory already exists,
// then this is acceptable. If it returns false due to some other I/O
// error, then this method will fail later with an IOException while saving
// the jar.
LOG.debug("mkdirs false for " + workingDir + ", execution will continue");
}
StringBuilder unexpandedWildcardClasspath = new StringBuilder();
// Append all entries
List<String> classPathEntryList = new ArrayList<String>(classPathEntries.length);
for (String classPathEntry : classPathEntries) {
if (classPathEntry.length() == 0) {
continue;
}
if (classPathEntry.endsWith("*")) {
// Append all jars that match the wildcard
List<Path> jars = getJarsInDirectory(classPathEntry);
if (!jars.isEmpty()) {
for (Path jar : jars) {
classPathEntryList.add(jar.toUri().toURL().toExternalForm());
}
} else {
unexpandedWildcardClasspath.append(File.pathSeparator);
unexpandedWildcardClasspath.append(classPathEntry);
}
} else {
// Append just this entry
File fileCpEntry = null;
if (!new Path(classPathEntry).isAbsolute()) {
fileCpEntry = new File(targetDir.toString(), classPathEntry);
} else {
fileCpEntry = new File(classPathEntry);
}
String classPathEntryUrl = fileCpEntry.toURI().toURL().toExternalForm();
// created yet, but will definitely be created before running.
if (classPathEntry.endsWith(Path.SEPARATOR) && !classPathEntryUrl.endsWith(Path.SEPARATOR)) {
classPathEntryUrl = classPathEntryUrl + Path.SEPARATOR;
}
classPathEntryList.add(classPathEntryUrl);
}
}
String jarClassPath = StringUtils.join(" ", classPathEntryList);
// Create the manifest
Manifest jarManifest = new Manifest();
jarManifest.getMainAttributes().putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
jarManifest.getMainAttributes().putValue(Attributes.Name.CLASS_PATH.toString(), jarClassPath);
// Write the manifest to output JAR file
File classPathJar = File.createTempFile("classpath-", ".jar", workingDir);
FileOutputStream fos = null;
BufferedOutputStream bos = null;
JarOutputStream jos = null;
try {
fos = new FileOutputStream(classPathJar);
bos = new BufferedOutputStream(fos);
jos = new JarOutputStream(bos, jarManifest);
} finally {
IOUtils.cleanup(LOG, jos, bos, fos);
}
String[] jarCp = { classPathJar.getCanonicalPath(), unexpandedWildcardClasspath.toString() };
return jarCp;
}
use of java.util.jar.Manifest in project hadoop by apache.
the class TestFileUtil method testCreateJarWithClassPath.
@Test(timeout = 30000)
public void testCreateJarWithClassPath() throws Exception {
// setup test directory for files
Assert.assertFalse(tmp.exists());
Assert.assertTrue(tmp.mkdirs());
// create files expected to match a wildcard
List<File> wildcardMatches = Arrays.asList(new File(tmp, "wildcard1.jar"), new File(tmp, "wildcard2.jar"), new File(tmp, "wildcard3.JAR"), new File(tmp, "wildcard4.JAR"));
for (File wildcardMatch : wildcardMatches) {
Assert.assertTrue("failure creating file: " + wildcardMatch, wildcardMatch.createNewFile());
}
// create non-jar files, which we expect to not be included in the classpath
Assert.assertTrue(new File(tmp, "text.txt").createNewFile());
Assert.assertTrue(new File(tmp, "executable.exe").createNewFile());
Assert.assertTrue(new File(tmp, "README").createNewFile());
// create classpath jar
String wildcardPath = tmp.getCanonicalPath() + File.separator + "*";
String nonExistentSubdir = tmp.getCanonicalPath() + Path.SEPARATOR + "subdir" + Path.SEPARATOR;
List<String> classPaths = Arrays.asList("", "cp1.jar", "cp2.jar", wildcardPath, "cp3.jar", nonExistentSubdir);
String inputClassPath = StringUtils.join(File.pathSeparator, classPaths);
String[] jarCp = FileUtil.createJarWithClassPath(inputClassPath + File.pathSeparator + "unexpandedwildcard/*", new Path(tmp.getCanonicalPath()), System.getenv());
String classPathJar = jarCp[0];
assertNotEquals("Unexpanded wildcard was not placed in extra classpath", jarCp[1].indexOf("unexpanded"), -1);
// verify classpath by reading manifest from jar file
JarFile jarFile = null;
try {
jarFile = new JarFile(classPathJar);
Manifest jarManifest = jarFile.getManifest();
Assert.assertNotNull(jarManifest);
Attributes mainAttributes = jarManifest.getMainAttributes();
Assert.assertNotNull(mainAttributes);
Assert.assertTrue(mainAttributes.containsKey(Attributes.Name.CLASS_PATH));
String classPathAttr = mainAttributes.getValue(Attributes.Name.CLASS_PATH);
Assert.assertNotNull(classPathAttr);
List<String> expectedClassPaths = new ArrayList<String>();
for (String classPath : classPaths) {
if (classPath.length() == 0) {
continue;
}
if (wildcardPath.equals(classPath)) {
// add wildcard matches
for (File wildcardMatch : wildcardMatches) {
expectedClassPaths.add(wildcardMatch.toURI().toURL().toExternalForm());
}
} else {
File fileCp = null;
if (!new Path(classPath).isAbsolute()) {
fileCp = new File(tmp, classPath);
} else {
fileCp = new File(classPath);
}
if (nonExistentSubdir.equals(classPath)) {
// expect to maintain trailing path separator if present in input, even
// if directory doesn't exist yet
expectedClassPaths.add(fileCp.toURI().toURL().toExternalForm() + Path.SEPARATOR);
} else {
expectedClassPaths.add(fileCp.toURI().toURL().toExternalForm());
}
}
}
List<String> actualClassPaths = Arrays.asList(classPathAttr.split(" "));
Collections.sort(expectedClassPaths);
Collections.sort(actualClassPaths);
Assert.assertEquals(expectedClassPaths, actualClassPaths);
} finally {
if (jarFile != null) {
try {
jarFile.close();
} catch (IOException e) {
LOG.warn("exception closing jarFile: " + classPathJar, e);
}
}
}
}
Aggregations