/// <summary> /// Asserts that the specified file is a jar file with a manifest containing a /// non-empty classpath attribute. /// </summary> /// <param name="file">File to check</param> /// <exception cref="System.IO.IOException">if there is an I/O error</exception> private static void AssertJar(FilePath file) { JarFile jarFile = null; try { jarFile = new JarFile(file); Manifest manifest = jarFile.GetManifest(); NUnit.Framework.Assert.IsNotNull(manifest); Attributes mainAttributes = manifest.GetMainAttributes(); NUnit.Framework.Assert.IsNotNull(mainAttributes); Assert.True(mainAttributes.Contains(Attributes.Name.ClassPath)); string classPathAttr = mainAttributes.GetValue(Attributes.Name.ClassPath); NUnit.Framework.Assert.IsNotNull(classPathAttr); NUnit.Framework.Assert.IsFalse(classPathAttr.IsEmpty()); } finally { // It's too bad JarFile doesn't implement Closeable. if (jarFile != null) { try { jarFile.Close(); } catch (IOException e) { Log.Warn("exception closing jarFile: " + jarFile, e); } } } }
/// <summary>Unpack matching files from a jar.</summary> /// <remarks> /// Unpack matching files from a jar. Entries inside the jar that do /// not match the given pattern will be skipped. /// </remarks> /// <param name="jarFile">the .jar file to unpack</param> /// <param name="toDir">the destination directory into which to unpack the jar</param> /// <param name="unpackRegex">the pattern to match jar entries against</param> /// <exception cref="System.IO.IOException"/> public static void UnJar(FilePath jarFile, FilePath toDir, Pattern unpackRegex ) { JarFile jar = new JarFile(jarFile); try { Enumeration <JarEntry> entries = ((Enumeration <JarEntry>)jar.Entries()); while (entries.MoveNext()) { JarEntry entry = entries.Current; if (!entry.IsDirectory() && unpackRegex.Matcher(entry.GetName()).Matches()) { InputStream @in = jar.GetInputStream(entry); try { FilePath file = new FilePath(toDir, entry.GetName()); EnsureDirectory(file.GetParentFile()); OutputStream @out = new FileOutputStream(file); try { IOUtils.CopyBytes(@in, @out, 8192); } finally { @out.Close(); } } finally { @in.Close(); } } } } finally { jar.Close(); } }
/// <exception cref="System.Exception"/> public virtual void Run(string[] args) { string usage = "RunJar jarFile [mainClass] args..."; if (args.Length < 1) { System.Console.Error.WriteLine(usage); System.Environment.Exit(-1); } int firstArg = 0; string fileName = args[firstArg++]; FilePath file = new FilePath(fileName); if (!file.Exists() || !file.IsFile()) { System.Console.Error.WriteLine("Not a valid JAR: " + file.GetCanonicalPath()); System.Environment.Exit(-1); } string mainClassName = null; JarFile jarFile; try { jarFile = new JarFile(fileName); } catch (IOException io) { throw Extensions.InitCause(new IOException("Error opening job jar: " + fileName ), io); } Manifest manifest = jarFile.GetManifest(); if (manifest != null) { mainClassName = manifest.GetMainAttributes().GetValue("Main-Class"); } jarFile.Close(); if (mainClassName == null) { if (args.Length < 2) { System.Console.Error.WriteLine(usage); System.Environment.Exit(-1); } mainClassName = args[firstArg++]; } mainClassName = mainClassName.ReplaceAll("/", "."); FilePath tmpDir = new FilePath(Runtime.GetProperty("java.io.tmpdir")); EnsureDirectory(tmpDir); FilePath workDir; try { workDir = FilePath.CreateTempFile("hadoop-unjar", string.Empty, tmpDir); } catch (IOException ioe) { // If user has insufficient perms to write to tmpDir, default // "Permission denied" message doesn't specify a filename. System.Console.Error.WriteLine("Error creating temp dir in java.io.tmpdir " + tmpDir + " due to " + ioe.Message); System.Environment.Exit(-1); return; } if (!workDir.Delete()) { System.Console.Error.WriteLine("Delete failed for " + workDir); System.Environment.Exit(-1); } EnsureDirectory(workDir); ShutdownHookManager.Get().AddShutdownHook(new _Runnable_201(workDir), ShutdownHookPriority ); UnJar(file, workDir); ClassLoader loader = CreateClassLoader(file, workDir); Thread.CurrentThread().SetContextClassLoader(loader); Type mainClass = Runtime.GetType(mainClassName, true, loader); MethodInfo main = mainClass.GetMethod("main", new Type[] { System.Array.CreateInstance (typeof(string), 0).GetType() }); string[] newArgs = Collections.ToArray(Arrays.AsList(args).SubList(firstArg , args.Length), new string[0]); try { main.Invoke(null, new object[] { newArgs }); } catch (TargetInvocationException e) { throw e.InnerException; } }
/// <exception cref="System.Exception"/> public virtual void TestCreateJarWithClassPath() { // setup test directory for files NUnit.Framework.Assert.IsFalse(tmp.Exists()); Assert.True(tmp.Mkdirs()); // create files expected to match a wildcard IList <FilePath> wildcardMatches = Arrays.AsList(new FilePath(tmp, "wildcard1.jar" ), new FilePath(tmp, "wildcard2.jar"), new FilePath(tmp, "wildcard3.JAR"), new FilePath (tmp, "wildcard4.JAR")); foreach (FilePath wildcardMatch in wildcardMatches) { Assert.True("failure creating file: " + wildcardMatch, wildcardMatch .CreateNewFile()); } // create non-jar files, which we expect to not be included in the classpath Assert.True(new FilePath(tmp, "text.txt").CreateNewFile()); Assert.True(new FilePath(tmp, "executable.exe").CreateNewFile() ); Assert.True(new FilePath(tmp, "README").CreateNewFile()); // create classpath jar string wildcardPath = tmp.GetCanonicalPath() + FilePath.separator + "*"; string nonExistentSubdir = tmp.GetCanonicalPath() + Path.Separator + "subdir" + Path .Separator; IList <string> classPaths = Arrays.AsList(string.Empty, "cp1.jar", "cp2.jar", wildcardPath , "cp3.jar", nonExistentSubdir); string inputClassPath = StringUtils.Join(FilePath.pathSeparator, classPaths); string[] jarCp = FileUtil.CreateJarWithClassPath(inputClassPath + FilePath.pathSeparator + "unexpandedwildcard/*", new Path(tmp.GetCanonicalPath()), Runtime.GetEnv ()); string classPathJar = jarCp[0]; Assert.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(); NUnit.Framework.Assert.IsNotNull(jarManifest); Attributes mainAttributes = jarManifest.GetMainAttributes(); NUnit.Framework.Assert.IsNotNull(mainAttributes); Assert.True(mainAttributes.Contains(Attributes.Name.ClassPath)); string classPathAttr = mainAttributes.GetValue(Attributes.Name.ClassPath); NUnit.Framework.Assert.IsNotNull(classPathAttr); IList <string> expectedClassPaths = new AList <string>(); foreach (string classPath in classPaths) { if (classPath.Length == 0) { continue; } if (wildcardPath.Equals(classPath)) { // add wildcard matches foreach (FilePath wildcardMatch_1 in wildcardMatches) { expectedClassPaths.AddItem(wildcardMatch_1.ToURI().ToURL().ToExternalForm()); } } else { FilePath fileCp = null; if (!new Path(classPath).IsAbsolute()) { fileCp = new FilePath(tmp, classPath); } else { fileCp = new FilePath(classPath); } if (nonExistentSubdir.Equals(classPath)) { // expect to maintain trailing path separator if present in input, even // if directory doesn't exist yet expectedClassPaths.AddItem(fileCp.ToURI().ToURL().ToExternalForm() + Path.Separator ); } else { expectedClassPaths.AddItem(fileCp.ToURI().ToURL().ToExternalForm()); } } } IList <string> actualClassPaths = Arrays.AsList(classPathAttr.Split(" ")); expectedClassPaths.Sort(); actualClassPaths.Sort(); Assert.Equal(expectedClassPaths, actualClassPaths); } finally { if (jarFile != null) { try { jarFile.Close(); } catch (IOException e) { Log.Warn("exception closing jarFile: " + classPathJar, e); } } } }