PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/hadoop-tools/hadoop-streaming/src/main/java/org/apache/hadoop/streaming/JarBuilder.java

http://github.com/apache/hadoop-common
Java | 208 lines | 162 code | 15 blank | 31 comment | 39 complexity | e29ef96d04b20d7ab6caf356fb39004e MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause
  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. package org.apache.hadoop.streaming;
  19. import java.io.*;
  20. import java.util.*;
  21. import java.util.jar.*;
  22. import java.util.zip.ZipException;
  23. /**
  24. * This class is the main class for generating job.jar
  25. * for Hadoop Streaming jobs. It includes the files specified
  26. * with the -file option and includes them in the jar. Also,
  27. * hadoop-streaming is a user level appplication, so all the classes
  28. * with hadoop-streaming that are needed in the job are also included
  29. * in the job.jar.
  30. */
  31. public class JarBuilder {
  32. public JarBuilder() {
  33. }
  34. public void setVerbose(boolean v) {
  35. this.verbose = v;
  36. }
  37. public void merge(List srcNames, List srcUnjar, String dstJar) throws IOException {
  38. String source = null;
  39. JarOutputStream jarOut = null;
  40. JarFile jarSource = null;
  41. jarOut = new JarOutputStream(new FileOutputStream(dstJar));
  42. boolean throwing = false;
  43. try {
  44. if (srcNames != null) {
  45. Iterator iter = srcNames.iterator();
  46. while (iter.hasNext()) {
  47. source = (String) iter.next();
  48. File fsource = new File(source);
  49. String base = getBasePathInJarOut(source);
  50. if (!fsource.exists()) {
  51. throwing = true;
  52. throw new FileNotFoundException(fsource.getAbsolutePath());
  53. }
  54. if (fsource.isDirectory()) {
  55. addDirectory(jarOut, base, fsource, 0);
  56. } else {
  57. addFileStream(jarOut, base, fsource);
  58. }
  59. }
  60. }
  61. if (srcUnjar != null) {
  62. Iterator iter = srcUnjar.iterator();
  63. while (iter.hasNext()) {
  64. source = (String) iter.next();
  65. jarSource = new JarFile(source);
  66. addJarEntries(jarOut, jarSource);
  67. jarSource.close();
  68. }
  69. }
  70. } finally {
  71. try {
  72. jarOut.close();
  73. } catch (ZipException z) {
  74. if (!throwing) {
  75. throw new IOException(z.toString());
  76. }
  77. }
  78. }
  79. }
  80. protected String fileExtension(String file) {
  81. int leafPos = file.lastIndexOf('/');
  82. if (leafPos == file.length() - 1) return "";
  83. String leafName = file.substring(leafPos + 1);
  84. int dotPos = leafName.lastIndexOf('.');
  85. if (dotPos == -1) return "";
  86. String ext = leafName.substring(dotPos + 1);
  87. return ext;
  88. }
  89. /** @return empty or a jar base path. Must not start with '/' */
  90. protected String getBasePathInJarOut(String sourceFile) {
  91. // TaskRunner will unjar and append to classpath: .:classes/:lib/*
  92. String ext = fileExtension(sourceFile);
  93. if (ext.equals("class")) {
  94. return "classes/"; // or ""
  95. } else if (ext.equals("jar") || ext.equals("zip")) {
  96. return "lib/";
  97. } else {
  98. return "";
  99. }
  100. }
  101. private void addJarEntries(JarOutputStream dst, JarFile src) throws IOException {
  102. Enumeration entries = src.entries();
  103. JarEntry entry = null;
  104. while (entries.hasMoreElements()) {
  105. entry = (JarEntry) entries.nextElement();
  106. //if (entry.getName().startsWith("META-INF/")) continue;
  107. InputStream in = src.getInputStream(entry);
  108. addNamedStream(dst, entry.getName(), in);
  109. }
  110. }
  111. /** @param name path in jar for this jar element. Must not start with '/' */
  112. void addNamedStream(JarOutputStream dst, String name, InputStream in) throws IOException {
  113. if (verbose) {
  114. System.err.println("JarBuilder.addNamedStream " + name);
  115. }
  116. try {
  117. dst.putNextEntry(new JarEntry(name));
  118. int bytesRead = 0;
  119. while ((bytesRead = in.read(buffer, 0, BUFF_SIZE)) != -1) {
  120. dst.write(buffer, 0, bytesRead);
  121. }
  122. } catch (ZipException ze) {
  123. if (ze.getMessage().indexOf("duplicate entry") >= 0) {
  124. if (verbose) {
  125. System.err.println(ze + " Skip duplicate entry " + name);
  126. }
  127. } else {
  128. throw ze;
  129. }
  130. } finally {
  131. in.close();
  132. dst.flush();
  133. dst.closeEntry();
  134. }
  135. }
  136. void addFileStream(JarOutputStream dst, String jarBaseName, File file) throws IOException {
  137. FileInputStream in = new FileInputStream(file);
  138. try {
  139. String name = jarBaseName + file.getName();
  140. addNamedStream(dst, name, in);
  141. } finally {
  142. in.close();
  143. }
  144. }
  145. void addDirectory(JarOutputStream dst, String jarBaseName, File dir, int depth) throws IOException {
  146. File[] contents = dir.listFiles();
  147. if (contents != null) {
  148. for (int i = 0; i < contents.length; i++) {
  149. File f = contents[i];
  150. String fBaseName = (depth == 0) ? "" : dir.getName();
  151. if (jarBaseName.length() > 0) {
  152. fBaseName = jarBaseName + "/" + fBaseName;
  153. }
  154. if (f.isDirectory()) {
  155. addDirectory(dst, fBaseName, f, depth + 1);
  156. } else {
  157. addFileStream(dst, fBaseName + "/", f);
  158. }
  159. }
  160. }
  161. }
  162. /** Test program */
  163. public static void main(String args[]) {
  164. // args = new String[] { "C:/Temp/merged.jar", "C:/jdk1.5.0/jre/lib/ext/dnsns.jar", "/Temp/addtojar2.log", "C:/jdk1.5.0/jre/lib/ext/mtest.jar", "C:/Temp/base"};
  165. if (args.length < 2) {
  166. System.err.println("Usage: JarFiles merged.jar [src.jar | dir | file ]+");
  167. } else {
  168. JarBuilder jarFiles = new JarBuilder();
  169. List names = new ArrayList();
  170. List unjar = new ArrayList();
  171. for (int i = 1; i < args.length; i++) {
  172. String f = args[i];
  173. String ext = jarFiles.fileExtension(f);
  174. boolean expandAsJar = ext.equals("jar") || ext.equals("zip");
  175. if (expandAsJar) {
  176. unjar.add(f);
  177. } else {
  178. names.add(f);
  179. }
  180. }
  181. try {
  182. jarFiles.merge(names, unjar, args[0]);
  183. Date lastMod = new Date(new File(args[0]).lastModified());
  184. System.out.println("Merge done to " + args[0] + " " + lastMod);
  185. } catch (Exception ge) {
  186. ge.printStackTrace(System.err);
  187. }
  188. }
  189. }
  190. private static final int BUFF_SIZE = 32 * 1024;
  191. private byte buffer[] = new byte[BUFF_SIZE];
  192. protected boolean verbose = false;
  193. }