1 4 package com.tc.test.server.appserver.war; 5 6 import org.apache.commons.io.FileUtils; 7 8 import com.tc.test.server.appserver.unit.TCServletFilter; 9 import com.tc.util.Assert; 10 11 import java.io.ByteArrayOutputStream ; 12 import java.io.File ; 13 import java.io.FileInputStream ; 14 import java.io.FileOutputStream ; 15 import java.io.IOException ; 16 import java.io.InputStream ; 17 import java.net.URL ; 18 import java.util.ArrayList ; 19 import java.util.HashSet ; 20 import java.util.Iterator ; 21 import java.util.List ; 22 import java.util.Map ; 23 import java.util.jar.JarOutputStream ; 24 import java.util.jar.Manifest ; 25 import java.util.regex.Pattern ; 26 import java.util.zip.CRC32 ; 27 import java.util.zip.ZipEntry ; 28 29 35 public abstract class AbstractWar implements War { 36 37 protected final String appName; 38 private final WebXml webXml; 39 private final List containerXml; 40 private final List servlets; 41 private final List listeners; 42 private final List filters; 43 private final List libraries; 44 private final List classes; 45 private final CRC32 crc32; 46 private final HashSet dirSet = new HashSet (); 47 private final HashSet classSet = new HashSet (); 48 49 private static final String WEB_INF = "WEB-INF/"; 50 private static final String CLASSES = "WEB-INF/classes/"; 51 private static final String LIB = "WEB-INF/lib/"; 52 53 public AbstractWar(String appName, WebXml webXml) { 54 Assert.assertNotBlank(appName); 55 this.appName = appName; 56 this.webXml = webXml; 57 this.containerXml = new ArrayList (); 58 this.servlets = new ArrayList (); 59 this.listeners = new ArrayList (); 60 this.filters = new ArrayList (); 61 this.libraries = new ArrayList (); 62 this.classes = new ArrayList (); 63 this.crc32 = new CRC32 (); 64 } 65 66 public final String addServlet(Class servletClass) { 67 Assert.assertNotNull(servletClass); 68 servlets.add(servletClass); 69 return webXml.addServlet(servletClass); 70 } 71 72 public final void addListener(Class listenerClass) { 73 Assert.assertNotNull(listenerClass); 74 listeners.add(listenerClass); 75 webXml.addListener(listenerClass); 76 } 77 78 public final void addFilter(Class filterClass, String pattern, Map initParams) { 79 Assert.assertNotNull(filterClass); 80 if (filters.size() == 0) addClass(TCServletFilter.class); 81 filters.add(filterClass); 82 webXml.addFilter(filterClass, pattern, initParams); 83 } 84 85 public final void addClass(Class clazz) { 86 Assert.assertNotNull(clazz); 87 classes.add(clazz); 88 } 89 90 public final void addContainerSpecificXml(String fileName, byte[] containerXmlBytes) { 91 containerXml.add(new ContainerXmlValues(fileName, containerXmlBytes)); 92 } 93 94 private class ContainerXmlValues { 95 private String fileName; 96 private byte[] bytes; 97 98 private ContainerXmlValues(String fileName, byte[] bytes) { 99 this.bytes = bytes; 100 this.fileName = fileName; 101 } 102 } 103 104 public final String writeWarFileToDirectory(File directory) throws IOException { 105 Assert.assertNotNull(directory); 106 File warFile = new File (directory + File.separator + appName + ".war"); 107 JarOutputStream jout = null; 108 IOException exception = null; 109 try { 110 jout = new JarOutputStream (new FileOutputStream (warFile), new Manifest ()); 111 jout.setMethod(ZipEntry.STORED); 112 jout.setLevel(ZipEntry.STORED); 113 114 putEntry(jout, WEB_INF); 115 putEntry(jout, CLASSES); 116 putEntry(jout, LIB); 117 putEntry(jout, WEB_INF + webXml.getFileName(), webXml.getBytes()); 118 putClasses(jout, servlets); 119 putClasses(jout, listeners); 120 putClasses(jout, filters); 121 putClasses(jout, classes); 122 putLibraries(jout); 123 putContainerSpecificXmlFiles(jout); 124 125 } catch (IOException ioe) { 126 exception = ioe; 127 } finally { 128 try { 129 if (jout != null) jout.close(); 130 } catch (IOException ioe2) { 131 } 133 } 134 if (exception != null) { 135 FileUtils.cleanDirectory(directory); 136 exception.printStackTrace(); 137 throw new IOException ("Unable to create war file."); 138 } 139 140 return appName + ".war"; 141 } 142 143 public final void addLibrary(File lib) { 144 Assert.assertNotNull(lib); 145 if (!lib.isDirectory() && !lib.getName().endsWith("jar")) { throw new RuntimeException ( 146 "Library must be either a directory or a .jar file"); } 147 libraries.add(lib); 148 } 149 150 private void putClasses(JarOutputStream jout, List classList) throws IOException { 151 Class clazz; 152 String [] parts; 153 String currentPath; 154 String className; 155 156 for (Iterator iter = classList.iterator(); iter.hasNext();) { 157 clazz = (Class ) iter.next(); 158 parts = clazz.getName().split("\\."); 159 className = parts[parts.length - 1]; 160 currentPath = CLASSES; 161 162 for (int i = 0; i < (parts.length - 1); i++) { 163 currentPath += parts[i] + File.separator; 164 if (!dirSet.contains(currentPath)) { 165 putEntry(jout, currentPath); 166 dirSet.add(currentPath); 167 } 168 } 169 170 String [] outerClass = className.split("\\$"); 171 URL servletURL = clazz.getResource(className + ".class"); 172 String [] files = new File (servletURL.getPath()).getParentFile().list(); 173 for (int i = 0; i < files.length; i++) { 174 if (Pattern.matches(outerClass[0] + "(\\$.*)?\\.class", files[i])) { 175 if (!classSet.contains(files[i])) { 176 InputStream in = clazz.getResourceAsStream(files[i]); 177 byte[] servletBytes = new byte[in.available()]; 178 in.read(servletBytes); 179 putEntry(jout, currentPath + files[i], servletBytes); 180 classSet.add(files[i]); 181 } 182 } 183 } 184 } 185 } 186 187 private void putContainerSpecificXmlFiles(JarOutputStream jout) throws IOException { 188 ContainerXmlValues values; 189 for (Iterator iter = containerXml.iterator(); iter.hasNext();) { 190 values = (ContainerXmlValues) iter.next(); 191 putEntry(jout, WEB_INF + values.fileName, values.bytes); 192 } 193 } 194 195 private void putLibraries(JarOutputStream jout) throws IOException { 196 File lib; 197 for (Iterator iter = libraries.iterator(); iter.hasNext();) { 198 lib = (File ) iter.next(); 199 if (lib.getName().endsWith("jar")) { 200 InputStream in = new FileInputStream (lib); 201 byte[] bytes = new byte[in.available()]; 202 in.read(bytes); 203 putEntry(jout, LIB + lib.getName(), bytes); 204 205 } else { 206 createLibraryJar(jout, lib); 207 } 208 } 209 } 210 211 private void createLibraryJar(JarOutputStream jout, File lib) throws IOException { 212 List relativePath = new ArrayList (); 213 ByteArrayOutputStream bout = new ByteArrayOutputStream (); 214 JarOutputStream newj = new JarOutputStream (bout, new Manifest ()); 215 newj.setMethod(ZipEntry.STORED); 216 newj.setLevel(ZipEntry.STORED); 217 218 String [] contents = lib.list(); 219 File dir; 220 for (int i = 0; i < contents.length; i++) { 221 dir = new File (lib.getPath() + File.separator + contents[i]); 222 recurseLibTree(newj, dir, relativePath); 223 } 224 if (newj != null) newj.close(); 225 putEntry(jout, LIB + lib.getName() + ".jar", bout.toByteArray()); 226 } 227 228 private void recurseLibTree(JarOutputStream newj, File file, List relativePath) throws IOException { 229 if (file.isDirectory()) { 230 putEntry(newj, makePath(relativePath, file.getName()) + "/"); 231 String [] contents = file.list(); 232 if (contents.length > 0) relativePath.add(file.getName()); 233 for (int i = 0; i < contents.length; i++) { 234 recurseLibTree(newj, new File (file.getPath() + File.separator + contents[i]), relativePath); 235 } 236 relativePath.remove(relativePath.size() - 1); 237 238 } else { 239 InputStream in = new FileInputStream (file); 240 byte[] bytes = new byte[in.available()]; 241 in.read(bytes); 242 putEntry(newj, makePath(relativePath, file.getName()), bytes); 243 } 244 } 245 246 private String makePath(List path, String file) { 247 String url = ""; 248 for (Iterator iter = path.iterator(); iter.hasNext();) { 249 url += (String ) iter.next() + "/"; 250 } 251 if (url.equals("")) return file; 252 return url + file; 253 } 254 255 private void putEntry(JarOutputStream jout, String file) throws IOException { 256 ZipEntry entry = new ZipEntry (file + "/"); 257 entry.setSize(0); 258 entry.setCrc(0); 259 jout.putNextEntry(entry); 260 } 261 262 private void putEntry(JarOutputStream jout, String file, byte[] bytes) throws IOException { 263 ZipEntry entry = new ZipEntry (file); 264 entry.setSize(bytes.length); 265 entry.setCrc(getCrc32(bytes)); 266 jout.putNextEntry(entry); 267 jout.write(bytes, 0, bytes.length); 268 } 269 270 private long getCrc32(byte[] bytes) { 271 crc32.update(bytes); 272 long checksum = crc32.getValue(); 273 crc32.reset(); 274 return checksum; 275 } 276 } | Popular Tags |