读书人

tomcat解压war包的1点例外

发布时间: 2013-10-30 12:56:22 作者: rapoo

tomcat解压war包的一点例外
我在项目的开发过程中,发现Tomcat解压war 的一点例外。

现象如下:

使用ANT工具把web应用程序打包为war文件。然后把war文件放到tomcat的webapps,让tomcat自己解压。结果出现解压的web应用程序文件丢失。使用rar工具打开war文件。文件都齐全。怎么有这种现象呢??查看tomcat的log文档。发现在解压war文档NullpointException.我升级tomcat到5.0还是出现这种现象。

jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/startup/HostConfig.java

解决方法:

我从tomcat网站下载了catalina 的原代码,进行分析。发现是在解压war文件出现input为null,而 input= jar.getInputStream(entry);然后提高tomcat的debug级别。可以在tomcat的log文档看到tomcat解压war文档的过程。发现如果某些文件名为???.txt,经检查发现原来这个文件的文件名为汉字。
噢!才发现war文件在解压的过程中无法处理汉字的文件名。(因为找不到文件名为???.txt的文件而导致null例外。原来这个文件是个注释文档),所以在使用ant把web应用程序打包为war文件,一定要把文件名为汉字的文件去掉。使用Forte for java的IDE工具把web应用程序打包为war文件会不包含这些文件名为汉字的文件


下面是部分war文档解压的部分代码

代码采自jakarta.org



类HostConfig.java

jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/startup/HostConfig.java



解决方法:

我从tomcat网站下载了catalina 的原代码,进行分析。发现是在解压war文件出现input为null,而 input= jar.getInputStream(entry);然后提高tomcat的debug级别。可以在tomcat的log文档看到tomcat解压war文档的过程。发现如果某些文件名为???.txt,经检查发现原来这个文件的文件名为汉字。
噢!才发现war文件在解压的过程中无法处理汉字的文件名。(因为找不到文件名为???.txt的文件而导致null例外。原来这个文件是个注释文档),所以在使用ant把web应用程序打包为war文件,一定要把文件名为汉字的文件去掉。使用Forte for java的IDE工具把web应用程序打包为war文件会不包含这些文件名为汉字的文件


下面是部分war文档解压的部分代码

代码采自jakarta.org



类HostConfig.java

jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/startup/HostConfig.java


  1. protected void deployWARs(File appBase, String[] files) {
  2. for (int i = 0; i < files.length; i++) {
  3. if (files[i].equalsIgnoreCase("META-INF"))
  4. continue;
  5. if (files[i].equalsIgnoreCase("WEB-INF"))
  6. continue;
  7. if (deployed.contains(files[i]))
  8. continue;
  9. File dir = new File(appBase, files[i]);
  10. if (files[i].toLowerCase().endsWith(".war")) {
  11. deployed.add(files[i]);
  12. // Calculate the context path and make sure it is unique
  13. String contextPath = "/" + files[i];
  14. int period = contextPath.lastIndexOf(".");
  15. if (period >= 0)
  16. contextPath = contextPath.substring(0, period);
  17. if (contextPath.equals("/ROOT"))
  18. contextPath = "";
  19. if (host.findChild(contextPath) != null)
  20. continue;
  21. // Checking for a nested /META-INF/context.xml
  22. JarFile jar = null;
  23. JarEntry entry = null;
  24. InputStream istream = null;
  25. BufferedOutputStream ostream = null;
  26. File xml = new File
  27. (configBase, files[i].substring
  28. (0, files[i].lastIndexOf(".")) + ".xml");
  29. if (!xml.exists()) {
  30. try {
  31. jar = new JarFile(dir);
  32. entry = jar.getJarEntry("META-INF/context.xml");
  33. if (entry != null) {
  34. istream = jar.getInputStream(entry);
  35. ostream =
  36. new BufferedOutputStream
  37. (new FileOutputStream(xml), 1024);
  38. byte buffer[] = new byte[1024];
  39. while (true) {
  40. int n = istream.read(buffer);
  41. if (n < 0) {
  42. break;
  43. }
  44. ostream.write(buffer, 0, n);
  45. }
  46. ostream.flush();
  47. ostream.close();
  48. ostream = null;
  49. istream.close();
  50. istream = null;
  51. entry = null;
  52. jar.close();
  53. jar = null;
  54. deployDescriptors(configBase(), configBase.list());
  55. return;
  56. }
  57. } catch (Exception e) {
  58. // Ignore and continue
  59. if (ostream != null) {
  60. try {
  61. ostream.close();
  62. } catch (Throwable t) {
  63. ;
  64. }
  65. ostream = null;
  66. }
  67. if (istream != null) {
  68. try {
  69. istream.close();
  70. } catch (Throwable t) {
  71. ;
  72. }
  73. istream = null;
  74. }
  75. entry = null;
  76. if (jar != null) {
  77. try {
  78. jar.close();
  79. } catch (Throwable t) {
  80. ;
  81. }
  82. jar = null;
  83. }
  84. }
  85. }
  86. if (isUnpackWARs()) {
  87. // Expand and deploy this application as a directory
  88. log.debug(sm.getString("hostConfig.expand", files[i]));
  89. URL url = null;
  90. String path = null;
  91. try {
  92. url = new URL("jar:file:" +
  93. dir.getCanonicalPath() + "!/");
  94. path = ExpandWar.expand(host, url);
  95. } catch (IOException e) {
  96. // JAR decompression failure
  97. log.warn(sm.getString
  98. ("hostConfig.expand.error", files[i]));
  99. continue;
  100. } catch (Throwable t) {
  101. log.error(sm.getString
  102. ("hostConfig.expand.error", files[i]), t);
  103. continue;
  104. }
  105. try {
  106. if (path != null) {
  107. url = new URL("file:" + path);
  108. ((Deployer) host).install(contextPath, url);
  109. }
  110. } catch (Throwable t) {
  111. log.error(sm.getString
  112. ("hostConfig.expand.error", files[i]), t);
  113. }
  114. } else {
  115. // Deploy the application in this WAR file
  116. log.info(sm.getString("hostConfig.deployJar", files[i]));
  117. try {
  118. URL url = new URL("file", null,
  119. dir.getCanonicalPath());
  120. url = new URL("jar:" + url.toString() + "!/");
  121. ((Deployer) host).install(contextPath, url);
  122. } catch (Throwable t) {
  123. log.error(sm.getString("hostConfig.deployJar.error",
  124. files[i]), t);
  125. }
  126. }
  127. }
  128. }
  129. }

类 ExpandWar.java
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/startup/ExpandWar.java

  1. package org.apache.catalina.startup;
  2. import java.io.BufferedOutputStream;
  3. import java.io.File;
  4. import java.io.FileOutputStream;
  5. import java.io.InputStream;
  6. import java.io.IOException;
  7. import java.net.JarURLConnection;
  8. import java.net.URL;
  9. import java.util.Enumeration;
  10. import java.util.jar.JarEntry;
  11. import java.util.jar.JarFile;
  12. import org.apache.catalina.Host;
  13. import org.apache.catalina.Logger;
  14. import org.apache.catalina.core.StandardHost;
  15. import org.apache.catalina.util.StringManager;
  16. /**
  17. * Expand out a WAR in a Host‘s appBase.
  18. *
  19. * @author Craig R. McClanahan
  20. * @author Remy Maucherat
  21. * @author Glenn L. Nielsen
  22. * @version $Revision: 1.4 $
  23. */
  24. public class ExpandWar {
  25. /**
  26. * The string resources for this package.
  27. */
  28. protected static final StringManager sm =
  29. StringManager.getManager(Constants.Package);
  30. /**
  31. * Expand the WAR file found at the specified URL into an unpacked
  32. * directory structure, and return the absolute pathname to the expanded
  33. * directory.
  34. *
  35. * @param host Host war is being installed for
  36. * @param war URL of the web application archive to be expanded
  37. * (must start with "jar:")
  38. *
  39. * @exception IllegalArgumentException if this is not a "jar:" URL
  40. * @exception IOException if an input/output error was encountered
  41. * during expansion
  42. */
  43. public static String expand(Host host, URL war)
  44. throws IOException {
  45. int debug = 0;
  46. Logger logger = host.getLogger();
  47. if (host instanceof StandardHost) {
  48. debug = ((StandardHost) host).getDebug();
  49. }
  50. // Calculate the directory name of the expanded directory
  51. if (debug >= 1) {
  52. logger.log("expand(" + war.toString() + ")");
  53. }
  54. String pathname = war.toString().replace(‘\\‘, ‘/‘);
  55. if (pathname.endsWith("!/")) {
  56. pathname = pathname.substring(0, pathname.length() - 2);
  57. }
  58. int period = pathname.lastIndexOf(‘.‘);
  59. if (period >= pathname.length() - 4)
  60. pathname = pathname.substring(0, period);
  61. int slash = pathname.lastIndexOf(‘/‘);
  62. if (slash >= 0) {
  63. pathname = pathname.substring(slash + 1);
  64. }
  65. if (debug >= 1) {
  66. logger.log(" Proposed directory name: " + pathname);
  67. }
  68. return expand(host, war, pathname);
  69. }
  70. /**
  71. * Expand the WAR file found at the specified URL into an unpacked
  72. * directory structure, and return the absolute pathname to the expanded
  73. * directory.
  74. *
  75. * @param host Host war is being installed for
  76. * @param war URL of the web application archive to be expanded
  77. * (must start with "jar:")
  78. * @param pathname Context path name for web application
  79. *
  80. * @exception IllegalArgumentException if this is not a "jar:" URL
  81. * @exception IOException if an input/output error was encountered
  82. * during expansion
  83. */
  84. public static String expand(Host host, URL war, String pathname)
  85. throws IOException {
  86. int debug = 0;
  87. Logger logger = host.getLogger();
  88. if (host instanceof StandardHost) {
  89. debug = ((StandardHost) host).getDebug();
  90. }
  91. // Make sure that there is no such directory already existing
  92. File appBase = new File(host.getAppBase());
  93. if (!appBase.isAbsolute()) {
  94. appBase = new File(System.getProperty("catalina.base"),
  95. host.getAppBase());
  96. }
  97. if (!appBase.exists() || !appBase.isDirectory()) {
  98. throw new IOException
  99. (sm.getString("hostConfig.appBase",
  100. appBase.getAbsolutePath()));
  101. }
  102. File docBase = new File(appBase, pathname);
  103. if (docBase.exists()) {
  104. // War file is already installed
  105. return (docBase.getAbsolutePath());
  106. }
  107. // Create the new document base directory
  108. docBase.mkdir();
  109. if (debug >= 2) {
  110. logger.log(" Have created expansion directory " +
  111. docBase.getAbsolutePath());
  112. }
  113. // Expand the WAR into the new document base directory
  114. JarURLConnection juc = (JarURLConnection) war.openConnection();
  115. juc.setUseCaches(false);
  116. JarFile jarFile = null;
  117. InputStream input = null;
  118. try {
  119. jarFile = juc.getJarFile();
  120. if (debug >= 2) {
  121. logger.log(" Have opened JAR file successfully");
  122. }
  123. Enumeration jarEntries = jarFile.entries();
  124. if (debug >= 2) {
  125. logger.log(" Have retrieved entries enumeration");
  126. }
  127. while (jarEntries.hasMoreElements()) {
  128. JarEntry jarEntry = (JarEntry) jarEntries.nextElement();
  129. String name = jarEntry.getName();
  130. if (debug >= 2) {
  131. logger.log(" Am processing entry " + name);
  132. }
  133. int last = name.lastIndexOf(‘/‘);
  134. if (last >= 0) {
  135. File parent = new File(docBase,
  136. name.substring(0, last));
  137. if (debug >= 2) {
  138. logger.log(" Creating parent directory " + parent);
  139. }
  140. parent.mkdirs();
  141. }
  142. if (name.endsWith("/")) {
  143. continue;
  144. }
  145. if (debug >= 2) {
  146. logger.log(" Creating expanded file " + name);
  147. }
  148. input = jarFile.getInputStream(jarEntry);
  149. expand(input, docBase, name);
  150. input.close();
  151. input = null;
  152. }
  153. } catch (IOException e) {
  154. // If something went wrong, delete expanded dir to keep things
  155. // clean
  156. deleteDir(docBase);
  157. throw e;
  158. } finally {
  159. if (input != null) {
  160. try {
  161. input.close();
  162. } catch (Throwable t) {
  163. ;
  164. }
  165. input = null;
  166. }
  167. if (jarFile != null) {
  168. try {
  169. jarFile.close();
  170. } catch (Throwable t) {
  171. ;
  172. }
  173. jarFile = null;
  174. }
  175. }
  176. // Return the absolute path to our new document base directory
  177. return (docBase.getAbsolutePath());
  178. }
  179. /**
  180. * Delete the specified directory, including all of its contents and
  181. * subdirectories recursively.
  182. *
  183. * @param dir File object representing the directory to be deleted
  184. */
  185. public static void deleteDir(File dir) {
  186. String files[] = dir.list();
  187. if (files == null) {
  188. files = new String[0];
  189. }
  190. for (int i = 0; i < files.length; i++) {
  191. File file = new File(dir, files[i]);
  192. if (file.isDirectory()) {
  193. deleteDir(file);
  194. } else {
  195. file.delete();
  196. }
  197. }
  198. dir.delete();
  199. }
  200. /**
  201. * Expand the specified input stream into the specified directory, creating
  202. * a file named from the specified relative path.
  203. *
  204. * @param input InputStream to be copied
  205. * @param docBase Document base directory into which we are expanding
  206. * @param name Relative pathname of the file to be created
  207. *
  208. * @exception IOException if an input/output error occurs
  209. */
  210. protected static void expand(InputStream input, File docBase, String name)
  211. throws IOException {
  212. File file = new File(docBase, name);
  213. BufferedOutputStream output = null;
  214. try {
  215. output =
  216. new BufferedOutputStream(new FileOutputStream(file));
  217. byte buffer[] = new byte[2048];
  218. while (true) {
  219. [b]int n = input.read(buffer);[/b]
  220. if (n <= 0)
  221. break;
  222. output.write(buffer, 0, n);
  223. }
  224. } finally {
  225. if (output != null) {
  226. try {
  227. output.close();
  228. } catch (IOException e) {
  229. // Ignore
  230. }
  231. }
  232. }
  233. }
  234. }

读书人网 >系统运维

热点推荐