1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 package org.apache.hadoop.util;
20
21 import java.util.jar;
22 import java.lang.reflect;
23 import java.net.URL;
24 import java.net.URLClassLoader;
25 import java.io;
26 import java.util;
27
28 import org.apache.hadoop.conf.Configuration;
29 import org.apache.hadoop.fs.FileUtil;
30
31 /** Run a Hadoop job jar. */
32 public class RunJar {
33
34 /** Unpack a jar file into a directory. */
35 public static void unJar(File jarFile, File toDir) throws IOException {
36 JarFile jar = new JarFile(jarFile);
37 try {
38 Enumeration entries = jar.entries();
39 while (entries.hasMoreElements()) {
40 JarEntry entry = (JarEntry)entries.nextElement();
41 if (!entry.isDirectory()) {
42 InputStream in = jar.getInputStream(entry);
43 try {
44 File file = new File(toDir, entry.getName());
45 if (!file.getParentFile().mkdirs()) {
46 if (!file.getParentFile().isDirectory()) {
47 throw new IOException("Mkdirs failed to create " +
48 file.getParentFile().toString());
49 }
50 }
51 OutputStream out = new FileOutputStream(file);
52 try {
53 byte[] buffer = new byte[8192];
54 int i;
55 while ((i = in.read(buffer)) != -1) {
56 out.write(buffer, 0, i);
57 }
58 } finally {
59 out.close();
60 }
61 } finally {
62 in.close();
63 }
64 }
65 }
66 } finally {
67 jar.close();
68 }
69 }
70
71 /** Run a Hadoop job jar. If the main class is not in the jar's manifest,
72 * then it must be provided on the command line. */
73 public static void main(String[] args) throws Throwable {
74 String usage = "RunJar jarFile [mainClass] args...";
75
76 if (args.length < 1) {
77 System.err.println(usage);
78 System.exit(-1);
79 }
80
81 int firstArg = 0;
82 String fileName = args[firstArg++];
83 File file = new File(fileName);
84 String mainClassName = null;
85
86 JarFile jarFile;
87 try {
88 jarFile = new JarFile(fileName);
89 } catch(IOException io) {
90 throw new IOException("Error opening job jar: " + fileName)
91 .initCause(io);
92 }
93
94 Manifest manifest = jarFile.getManifest();
95 if (manifest != null) {
96 mainClassName = manifest.getMainAttributes().getValue("Main-Class");
97 }
98 jarFile.close();
99
100 if (mainClassName == null) {
101 if (args.length < 2) {
102 System.err.println(usage);
103 System.exit(-1);
104 }
105 mainClassName = args[firstArg++];
106 }
107 mainClassName = mainClassName.replaceAll("/", ".");
108
109 File tmpDir = new File(new Configuration().get("hadoop.tmp.dir"));
110 tmpDir.mkdirs();
111 if (!tmpDir.isDirectory()) {
112 System.err.println("Mkdirs failed to create " + tmpDir);
113 System.exit(-1);
114 }
115 final File workDir = File.createTempFile("hadoop-unjar", "", tmpDir);
116 workDir.delete();
117 workDir.mkdirs();
118 if (!workDir.isDirectory()) {
119 System.err.println("Mkdirs failed to create " + workDir);
120 System.exit(-1);
121 }
122
123 Runtime.getRuntime().addShutdownHook(new Thread() {
124 public void run() {
125 try {
126 FileUtil.fullyDelete(workDir);
127 } catch (IOException e) {
128 }
129 }
130 });
131
132 unJar(file, workDir);
133
134 ArrayList<URL> classPath = new ArrayList<URL>();
135 classPath.add(new File(workDir+"/").toURL());
136 classPath.add(file.toURL());
137 classPath.add(new File(workDir, "classes/").toURL());
138 File[] libs = new File(workDir, "lib").listFiles();
139 if (libs != null) {
140 for (int i = 0; i < libs.length; i++) {
141 classPath.add(libs[i].toURL());
142 }
143 }
144 ClassLoader loader =
145 new URLClassLoader(classPath.toArray(new URL[0]));
146
147 Thread.currentThread().setContextClassLoader(loader);
148 Class<?> mainClass = Class.forName(mainClassName, true, loader);
149 Method main = mainClass.getMethod("main", new Class[] {
150 Array.newInstance(String.class, 0).getClass()
151 });
152 String[] newArgs = (String[])Arrays.asList(args)
153 .subList(firstArg, args.length).toArray(new String[0]);
154 try {
155 main.invoke(null, new Object[] { newArgs });
156 } catch (InvocationTargetException e) {
157 throw e.getTargetException();
158 }
159 }
160
161 }