001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.test.server.appserver.deployment;
006:
007: import org.apache.commons.io.IOUtils;
008: import org.apache.tools.ant.taskdefs.War;
009: import org.apache.tools.ant.taskdefs.Zip.Duplicate;
010: import org.apache.tools.ant.types.ZipFileSet;
011: import org.codehaus.cargo.util.AntUtils;
012: import org.springframework.remoting.rmi.RmiRegistryFactoryBean;
013: import org.springframework.web.context.ContextLoader;
014: import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
015:
016: import com.tc.logging.TCLogger;
017: import com.tc.logging.TCLogging;
018: import com.tc.test.TestConfigObject;
019:
020: import java.io.File;
021: import java.io.FileOutputStream;
022: import java.io.IOException;
023: import java.io.InputStream;
024: import java.io.PrintWriter;
025: import java.io.StringWriter;
026: import java.net.URL;
027: import java.net.URLClassLoader;
028: import java.util.ArrayList;
029: import java.util.HashMap;
030: import java.util.HashSet;
031: import java.util.Iterator;
032: import java.util.List;
033: import java.util.Map;
034: import java.util.Set;
035: import java.util.StringTokenizer;
036:
037: import junit.framework.Assert;
038:
039: /*
040: <!ELEMENT web-app (icon?, display-name?, description?, distributable?,
041: context-param*, filter*, filter-mapping*, listener*, servlet*,
042: servlet-mapping*, session-config?, mime-mapping*, welcome-file-list?,
043: error-page*, taglib*, resource-env-ref*, resource-ref*,
044: security-constraint*, login-config?, security-role*, env-entry*,
045: ejb-ref*, ejb-local-ref*)>
046: */
047:
048: public class WARBuilder implements DeploymentBuilder {
049:
050: private static final TCLogger logger = TCLogging
051: .getLogger(WARBuilder.class);
052:
053: private FileSystemPath warDirectoryPath;
054:
055: private String warFileName;
056:
057: private Set classDirectories = new HashSet(); /* <FileSystemPath> */
058:
059: private Set libs = new HashSet();
060:
061: private List resources = new ArrayList();
062:
063: private List remoteServices = new ArrayList();
064:
065: private Set beanDefinitionFiles = new HashSet();
066:
067: private Map contextParams = new HashMap();
068:
069: private Map sessionConfig = new HashMap();
070:
071: private List listeners = new ArrayList();
072:
073: private List servlets = new ArrayList();
074:
075: private List filters = new ArrayList();
076:
077: private Map taglibs = new HashMap();
078:
079: private StringBuffer remoteSvcDefBlock = new StringBuffer();
080:
081: private final FileSystemPath tempDirPath;
082:
083: private String dispatcherServletName = null;
084:
085: private final TestConfigObject testConfig;
086:
087: public WARBuilder(File tempDir, TestConfigObject config)
088: throws IOException {
089: this (File.createTempFile("test", ".war", tempDir)
090: .getAbsolutePath(), tempDir, config);
091: }
092:
093: public WARBuilder(String warFileName, File tempDir,
094: TestConfigObject config) {
095: this .warFileName = warFileName;
096: this .tempDirPath = new FileSystemPath(tempDir);
097: this .testConfig = config;
098:
099: // this is needed for spring tests
100: addDirectoryOrJARContainingClass(WARBuilder.class); // test framework
101: }
102:
103: public DeploymentBuilder addClassesDirectory(FileSystemPath path) {
104: classDirectories.add(path);
105: return this ;
106: }
107:
108: public Deployment makeDeployment() throws Exception {
109: createWARDirectory();
110:
111: FileSystemPath warFile = makeWARFileName();
112: logger.debug("Creating war file: " + warFile);
113: warFile.delete();
114:
115: War warTask = makeWarTask();
116: warTask.setUpdate(false);
117: // XXX: build-data.txt exists in all of classes folders
118: // therefore there will be duplicates. Websphere doesn't like that
119: // This option should be removed when we solve that problem
120: Duplicate df = new Duplicate();
121: df.setValue("preserve");
122: warTask.setDuplicate(df);
123: warTask.setDestFile(warFile.getFile());
124: // end XXX
125: warTask.setWebxml(warDirectoryPath.existingFile(
126: "WEB-INF/web.xml").getFile());
127: addWEBINFDirectory(warTask);
128: addClassesDirectories(warTask);
129: addLibs(warTask);
130: addResources(warTask);
131: warTask.execute();
132:
133: return new WARDeployment(warFile);
134: }
135:
136: private FileSystemPath makeWARFileName() {
137: File f = new File(warFileName);
138: if (f.isAbsolute()) {
139: return FileSystemPath.makeNewFile(warFileName);
140: } else {
141: return tempDirPath.file(warFileName);
142: }
143: }
144:
145: private void addLibs(War warTask) {
146: for (Iterator it = libs.iterator(); it.hasNext();) {
147: FileSystemPath lib = (FileSystemPath) it.next();
148: ZipFileSet zipFileSet = new ZipFileSet();
149: zipFileSet.setFile(lib.getFile());
150: warTask.addLib(zipFileSet);
151: }
152: }
153:
154: private War makeWarTask() {
155: return (War) new AntUtils().createAntTask("war");
156: }
157:
158: private void addClassesDirectories(War warTask) {
159: for (Iterator it = classDirectories.iterator(); it.hasNext();) {
160: FileSystemPath path = (FileSystemPath) it.next();
161: ZipFileSet zipFileSet = new ZipFileSet();
162: zipFileSet.setDir(path.getFile());
163: warTask.addClasses(zipFileSet);
164: }
165: }
166:
167: private void addResources(War warTask) {
168: for (Iterator it = resources.iterator(); it.hasNext();) {
169: ResourceDefinition definition = (ResourceDefinition) it
170: .next();
171: ZipFileSet zipfileset = new ZipFileSet();
172: zipfileset.setDir(definition.location);
173: zipfileset.setIncludes(definition.includes);
174: if (definition.prefix != null)
175: zipfileset.setPrefix(definition.prefix);
176: if (definition.fullpath != null)
177: zipfileset.setFullpath(definition.fullpath);
178: warTask.addZipfileset(zipfileset);
179: }
180: }
181:
182: private void addWEBINFDirectory(War warTask) {
183: ZipFileSet zipFileSet = new ZipFileSet();
184: zipFileSet.setDir(warDirectoryPath.getFile());
185: warTask.addFileset(zipFileSet);
186: }
187:
188: public DeploymentBuilder addClassesDirectory(String directory) {
189: return addClassesDirectory(FileSystemPath
190: .existingDir(directory));
191: }
192:
193: void createWARDirectory() throws IOException {
194: this .warDirectoryPath = tempDirPath.mkdir("tempwar");
195: FileSystemPath webInfDir = warDirectoryPath.mkdir("WEB-INF");
196: createWebXML(webInfDir);
197: if (this .dispatcherServletName == null) {
198: createRemotingContext(webInfDir);
199: } else {
200: createDispatcherServletContext(webInfDir);
201: }
202: }
203:
204: private void createDispatcherServletContext(FileSystemPath webInfDir)
205: throws IOException {
206: FileSystemPath springRemotingAppCtx = webInfDir
207: .file(this .dispatcherServletName + "-servlet.xml");
208: FileOutputStream fos = new FileOutputStream(
209: springRemotingAppCtx.getFile());
210:
211: try {
212: appendFile(fos, "/dispatcherServletContextHeader.txt");
213: PrintWriter pw = new PrintWriter(fos);
214: pw.println(remoteSvcDefBlock.toString());
215:
216: writeHandlerMappingBean(pw);
217:
218: for (Iterator it = remoteServices.iterator(); it.hasNext();) {
219: RemoteService remoteService = (RemoteService) it.next();
220: writeRemoteService(pw, remoteService);
221: }
222: pw.flush();
223: writeFooter(fos);
224: } finally {
225: fos.close();
226: }
227: }
228:
229: private void createRemotingContext(FileSystemPath webInfDir)
230: throws IOException {
231: FileSystemPath springRemotingAppCtx = webInfDir.mkdir(
232: "classes/com/tctest/spring")
233: .file("spring-remoting.xml");
234: FileOutputStream fos = new FileOutputStream(
235: springRemotingAppCtx.getFile());
236:
237: try {
238: appendFile(fos, "/remoteContextHeader.txt");
239: PrintWriter pw = new PrintWriter(fos);
240: pw.println(remoteSvcDefBlock.toString());
241:
242: writeRegistryFactoryBean(pw);
243:
244: for (Iterator it = remoteServices.iterator(); it.hasNext();) {
245: RemoteService remoteService = (RemoteService) it.next();
246: writeRemoteService(pw, remoteService);
247: }
248: pw.flush();
249: writeFooter(fos);
250: } finally {
251: fos.close();
252: }
253: }
254:
255: private void writeHandlerMappingBean(PrintWriter pw) {
256: pw.println("<bean id=\"defaultHandlerMapping\" class=\""
257: + BeanNameUrlHandlerMapping.class.getName() + "\"/>");
258: }
259:
260: private void writeRegistryFactoryBean(PrintWriter pw) {
261: pw.println("<bean class=\""
262: + RmiRegistryFactoryBean.class.getName()
263: + "\" name=\"registry\" >");
264: pw
265: .println("<property name=\"port\" value=\"${rmi.registry.port}\" />");
266: pw.println("</bean>");
267: }
268:
269: private void writeRemoteService(PrintWriter pw,
270: RemoteService remoteService) {
271: if (this .dispatcherServletName == null) {
272: pw
273: .println("<bean class=\""
274: + remoteService.getExporterType().getName()
275: + "\">");
276: printProperty(pw, "serviceName", remoteService
277: .getRemoteName());
278: printPropertyRef(pw, "service", remoteService.getBeanName());
279: printProperty(pw, "serviceInterface", remoteService
280: .getInterfaceType().getName());
281: printPropertyRef(pw, "registry", "registry");
282: pw.println("</bean>");
283: } else {
284: pw
285: .println("<bean name=\"/"
286: + remoteService.getRemoteName()
287: + "\" class=\""
288: + remoteService.getExporterType().getName()
289: + "\">");
290: printPropertyRef(pw, "service", remoteService.getBeanName());
291: printProperty(pw, "serviceInterface", remoteService
292: .getInterfaceType().getName());
293: pw.println("</bean>");
294: }
295: }
296:
297: private void printProperty(PrintWriter pw, String propertyName,
298: String propertyValue) {
299: pw.println("<property name=\"" + propertyName + "\" value=\""
300: + propertyValue + "\" />");
301: }
302:
303: private void printPropertyRef(PrintWriter pw, String propertyName,
304: String propertyValue) {
305: pw.println("<property name=\"" + propertyName + "\" ref=\""
306: + propertyValue + "\" />");
307: }
308:
309: private void writeFooter(FileOutputStream fos) throws IOException {
310: appendFile(fos, "/remoteContextFooter.txt");
311: }
312:
313: private void appendFile(FileOutputStream fos, String fragmentName)
314: throws IOException {
315: InputStream is = getClass().getResourceAsStream(fragmentName);
316: IOUtils.copy(is, fos);
317: IOUtils.closeQuietly(is);
318: }
319:
320: private void createWebXML(FileSystemPath webInfDir)
321: throws IOException {
322: FileSystemPath webXML = webInfDir.file("web.xml");
323: FileOutputStream fos = new FileOutputStream(webXML.getFile());
324: try {
325: logger.debug("Creating "
326: + webXML.getFile().getAbsolutePath());
327: PrintWriter pw = new PrintWriter(fos);
328:
329: pw
330: .println("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
331:
332: pw
333: .println("<!DOCTYPE web-app PUBLIC \"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN\" \"http://java.sun.com/dtd/web-app_2_3.dtd\">");
334: pw.println("<web-app>\n");
335:
336: if (!beanDefinitionFiles.isEmpty()) {
337: writeContextParam(pw,
338: ContextLoader.CONFIG_LOCATION_PARAM,
339: generateContextConfigLocationValue());
340: }
341:
342: for (Iterator it = contextParams.entrySet().iterator(); it
343: .hasNext();) {
344: Map.Entry param = (Map.Entry) it.next();
345: writeContextParam(pw, (String) param.getKey(),
346: (String) param.getValue());
347: }
348:
349: for (Iterator it = filters.iterator(); it.hasNext();) {
350: FilterDefinition definition = (FilterDefinition) it
351: .next();
352: writeFilter(pw, definition);
353: }
354:
355: for (Iterator it = filters.iterator(); it.hasNext();) {
356: FilterDefinition definition = (FilterDefinition) it
357: .next();
358: logger.debug("Writing filter mapping["
359: + definition.name + " -> " + definition.mapping
360: + "]");
361: pw.println(" <filter-mapping>");
362: pw.println(" <filter-name>" + definition.name
363: + "</filter-name>");
364: pw.println(" <url-pattern>" + definition.mapping
365: + "</url-pattern>");
366: pw.println(" </filter-mapping>");
367: }
368:
369: if (!beanDefinitionFiles.isEmpty()) {
370: writeListener(
371: pw,
372: org.springframework.web.context.ContextLoaderListener.class
373: .getName());
374: if (this .dispatcherServletName == null) {
375: writeListener(
376: pw,
377: com.tc.test.server.appserver.deployment.RemoteContextListener.class
378: .getName());
379: }
380: }
381: for (Iterator it = listeners.iterator(); it.hasNext();) {
382: writeListener(pw, ((Class) it.next()).getName());
383: }
384:
385: for (Iterator it = servlets.iterator(); it.hasNext();) {
386: ServletDefinition definition = (ServletDefinition) it
387: .next();
388: writeServlet(pw, definition);
389: }
390:
391: for (Iterator it = servlets.iterator(); it.hasNext();) {
392: ServletDefinition definition = (ServletDefinition) it
393: .next();
394: logger.debug("Writing servlet mapping["
395: + definition.name + " -> " + definition.mapping
396: + "]");
397: pw.println(" <servlet-mapping>");
398: pw.println(" <servlet-name>" + definition.name
399: + "</servlet-name>");
400: pw.println(" <url-pattern>" + definition.mapping
401: + "</url-pattern>");
402: pw.println(" </servlet-mapping>");
403: }
404:
405: for (Iterator it = sessionConfig.entrySet().iterator(); it
406: .hasNext();) {
407: Map.Entry entry = (Map.Entry) it.next();
408: writeSessionConfig(pw, (String) entry.getKey(),
409: (String) entry.getValue());
410: }
411:
412: if (!taglibs.isEmpty()) {
413: pw.println(" <jsp-config>");
414: for (Iterator it = taglibs.entrySet().iterator(); it
415: .hasNext();) {
416: Map.Entry taglib = (Map.Entry) it.next();
417: logger.debug("Writing taglib[" + taglib.getKey()
418: + "/" + taglib.getValue() + "]");
419: pw.println(" <taglib-uri>" + taglib.getKey()
420: + "</taglib-uri>");
421: pw.println(" <taglib-location>"
422: + taglib.getValue() + "</taglib-location>");
423: }
424: pw.println(" </jsp-config>");
425: }
426:
427: pw.println("</web-app>");
428: pw.flush();
429: logger.debug("Finished creating "
430: + webXML.getFile().getAbsolutePath());
431: } finally {
432: fos.close();
433: }
434: }
435:
436: private void writeContextParam(PrintWriter pw, String name,
437: String value) {
438: logger.debug("Writing context param[" + name + "/" + value
439: + "]");
440: pw.println(" <context-param>");
441: pw.println(" <param-name>" + name + "</param-name>");
442: pw.println(" <param-value>" + value + "</param-value>");
443: pw.println(" </context-param>");
444: }
445:
446: private void writeSessionConfig(PrintWriter pw, String name,
447: String value) {
448: logger.debug("Writing session config[" + name + "/" + value
449: + "]");
450: pw.println(" <session-config>");
451: pw.println(" <" + name + ">" + value + "</" + name + ">");
452: pw.println(" </session-config>");
453: }
454:
455: private void writeListener(PrintWriter pw, String className) {
456: logger.debug("Writing listener[" + className + "]");
457: pw.println(" <listener>");
458: pw.println(" <listener-class>" + className
459: + "</listener-class>");
460: pw.println(" </listener>");
461: }
462:
463: private void writeServlet(PrintWriter pw,
464: ServletDefinition definition) {
465: logger.debug("Writing servlet[" + definition.name + " of type "
466: + definition.servletClass.getName() + "]");
467: pw.println(" <servlet>");
468: pw.println(" <servlet-name>" + definition.name
469: + "</servlet-name>");
470: pw.println(" <servlet-class>"
471: + definition.servletClass.getName()
472: + "</servlet-class>");
473:
474: if (definition.initParameters != null) {
475: for (Iterator it = definition.initParameters.entrySet()
476: .iterator(); it.hasNext();) {
477: Map.Entry param = (Map.Entry) it.next();
478: logger
479: .debug("Writing servlet init parameter["
480: + param.getKey() + "/"
481: + param.getValue() + "]");
482: pw.println(" <init-param>");
483: pw.println(" <param-name>" + param.getKey()
484: + "</param-name>");
485: pw.println(" <param-value>" + param.getValue()
486: + "</param-value>");
487: pw.println(" </init-param>");
488: }
489: }
490:
491: if (definition.loadOnStartup) {
492: pw.println(" <load-on-startup>1</load-on-startup>");
493: }
494:
495: pw.println(" </servlet>");
496: }
497:
498: private void writeFilter(PrintWriter pw, FilterDefinition definition) {
499: logger.debug("Writing filter[" + definition.name + " of type "
500: + definition.filterClass.getName() + "]");
501: pw.println(" <filter>");
502: pw.println(" <filter-name>" + definition.name
503: + "</filter-name>");
504: pw.println(" <filter-class>"
505: + definition.filterClass.getName() + "</filter-class>");
506:
507: if (definition.initParameters != null) {
508: for (Iterator it = definition.initParameters.entrySet()
509: .iterator(); it.hasNext();) {
510: Map.Entry param = (Map.Entry) it.next();
511: logger
512: .debug("Writing filter init param["
513: + param.getKey() + "/"
514: + param.getValue() + "]");
515: pw.println(" <init-param>");
516: pw.println(" <param-name>" + param.getKey()
517: + "</param-name>");
518: pw.println(" <param-value>" + param.getValue()
519: + "</param-value>");
520: pw.println(" </init-param>");
521: }
522: }
523:
524: pw.println(" </filter>");
525: }
526:
527: private String generateContextConfigLocationValue() {
528: StringWriter sw = new StringWriter();
529: PrintWriter pw = new PrintWriter(sw);
530: for (Iterator it = beanDefinitionFiles.iterator(); it.hasNext();) {
531: String beanDefinitionFile = (String) it.next();
532: pw.println(beanDefinitionFile);
533: }
534: pw.flush();
535: return sw.toString();
536: }
537:
538: public DeploymentBuilder addBeanDefinitionFile(String beanDefinition) {
539: beanDefinitionFiles.add(beanDefinition);
540: return this ;
541: }
542:
543: public DeploymentBuilder addRemoteService(String remoteName,
544: String beanName, Class interfaceType) {
545: remoteServices.add(new RemoteService(remoteName, beanName,
546: interfaceType));
547: return this ;
548: }
549:
550: public DeploymentBuilder addRemoteService(Class exporterType,
551: String remoteName, String beanName, Class interfaceType) {
552: remoteServices.add(new RemoteService(exporterType, remoteName,
553: beanName, interfaceType));
554: return this ;
555: }
556:
557: public DeploymentBuilder addRemoteService(String beanName,
558: Class interfaceType) {
559: addRemoteService(capitalise(beanName), beanName, interfaceType);
560: return this ;
561: }
562:
563: private static String capitalise(String s) {
564: if (s == null) {
565: return null;
566: }
567: int size = s.length();
568: StringBuffer buffer = new StringBuffer(size);
569: boolean space = true;
570: for (int i = 0; i < size; i++) {
571: char c = s.charAt(i);
572: if (Character.isWhitespace(c)) {
573: buffer.append(c);
574: space = true;
575: } else if (space) {
576: buffer.append(Character.toTitleCase(c));
577: space = false;
578: } else {
579: buffer.append(c);
580: }
581: }
582: return buffer.toString();
583: }
584:
585: public DeploymentBuilder addRemoteServiceBlock(String block) {
586: remoteSvcDefBlock.append(block + "\n");
587: return this ;
588: }
589:
590: public void setParentApplicationContextRef(
591: String locatorFactorySelector, String parentContextKey) {
592: this .contextParams.put(
593: ContextLoader.LOCATOR_FACTORY_SELECTOR_PARAM,
594: locatorFactorySelector);
595: this .contextParams.put(ContextLoader.LOCATOR_FACTORY_KEY_PARAM,
596: parentContextKey);
597: }
598:
599: public DeploymentBuilder addDirectoryOrJARContainingClass(Class type) {
600: return addDirectoryOrJar(calculatePathToClass(type));
601: }
602:
603: public DeploymentBuilder addDirectoryOrJARContainingClassOfSelectedVersion(
604: Class type, String[] variantNames) {
605: String pathSeparator = System.getProperty("path.separator");
606:
607: for (int i = 0; i < variantNames.length; i++) {
608: String selectedVariant = testConfig
609: .selectedVariantFor(variantNames[i]);
610: String path = testConfig.variantLibraryClasspathFor(
611: variantNames[i], selectedVariant);
612: String[] paths = path.split(pathSeparator);
613: for (int j = 0; j < paths.length; j++) {
614: addDirectoryOrJar(new FileSystemPath(new File(paths[j])));
615: }
616: }
617:
618: return this ;
619: }
620:
621: public DeploymentBuilder addDirectoryContainingResource(
622: String resource) {
623: return addDirectoryOrJar(calculatePathToResource(resource));
624: }
625:
626: public DeploymentBuilder addResource(String location,
627: String includes, String prefix) {
628: FileSystemPath path = getResourceDirPath(location, includes);
629: resources.add(new ResourceDefinition(path.getFile(), includes,
630: prefix, null));
631: return this ;
632: }
633:
634: public DeploymentBuilder addResourceFullpath(String location,
635: String includes, String fullpath) {
636: FileSystemPath path = getResourceDirPath(location, includes);
637: resources.add(new ResourceDefinition(path.getFile(), includes,
638: null, fullpath));
639: return this ;
640: }
641:
642: private FileSystemPath getResourceDirPath(String location,
643: String includes) {
644: String resource = location + "/" + includes;
645: URL url = getClass().getResource(resource);
646: Assert.assertNotNull("Not found: " + resource, url);
647: FileSystemPath path = calculateDirectory(url, includes);
648: return path;
649: }
650:
651: public DeploymentBuilder addContextParameter(String name,
652: String value) {
653: contextParams.put(name, value);
654: return this ;
655: }
656:
657: public DeploymentBuilder addSessionConfig(String name, String value) {
658: sessionConfig.put(name, value);
659: return this ;
660: }
661:
662: public DeploymentBuilder addListener(Class listenerClass) {
663: listeners.add(listenerClass);
664: return this ;
665: }
666:
667: public DeploymentBuilder setDispatcherServlet(String name,
668: String mapping, Class servletClass, Map params,
669: boolean loadOnStartup) {
670: Assert.assertNull(this .dispatcherServletName);
671: this .dispatcherServletName = name;
672: addServlet(name, mapping, servletClass, params, loadOnStartup);
673: return this ;
674: }
675:
676: public DeploymentBuilder addServlet(String name, String mapping,
677: Class servletClass, Map params, boolean loadOnStartup) {
678: servlets.add(new ServletDefinition(name, mapping, servletClass,
679: params, loadOnStartup));
680: addDirectoryOrJARContainingClass(servletClass);
681: return this ;
682: }
683:
684: public DeploymentBuilder addFilter(String name, String mapping,
685: Class filterClass, Map params) {
686: filters.add(new FilterDefinition(name, mapping, filterClass,
687: params));
688: return this ;
689: }
690:
691: public DeploymentBuilder addTaglib(String uri, String location) {
692: taglibs.put(uri, location);
693: return this ;
694: }
695:
696: private DeploymentBuilder addDirectoryOrJar(FileSystemPath path) {
697: if (path.isDirectory()) {
698: classDirectories.add(path);
699: } else {
700: libs.add(path);
701: }
702: return this ;
703: }
704:
705: public static FileSystemPath calculatePathToClass(Class type) {
706: URL url = type.getResource("/" + classToPath(type));
707: Assert.assertNotNull("Not found: " + type, url);
708: FileSystemPath filepath = calculateDirectory(url, "/"
709: + classToPath(type));
710: return filepath;
711: }
712:
713: static public FileSystemPath calculatePathToClass(Class type,
714: String pathString) {
715: String pathSeparator = System.getProperty("path.separator");
716: StringTokenizer st = new StringTokenizer(pathString,
717: pathSeparator);
718: URL[] urls = new URL[st.countTokens()];
719: for (int i = 0; st.hasMoreTokens(); i++) {
720: String token = st.nextToken();
721: if (token.startsWith("/")) {
722: token = "/" + token;
723: }
724: URL u = null;
725: try {
726: if (token.endsWith(".jar")) {
727: u = new URL("jar", "", "file:/" + token + "!/");
728: } else {
729: u = new URL("file", "", token + "/");
730: }
731: urls[i] = u;
732: } catch (Exception ex) {
733: throw new RuntimeException(ex);
734: }
735: }
736: URL url = new URLClassLoader(urls, null)
737: .getResource(classToPath(type));
738: Assert.assertNotNull("Not found: " + type, url);
739: FileSystemPath filepath = calculateDirectory(url, "/"
740: + classToPath(type));
741: return filepath;
742: }
743:
744: public static FileSystemPath calculateDirectory(URL url,
745: String classNameAsPath) {
746:
747: String urlAsString = null;
748: try {
749: urlAsString = java.net.URLDecoder.decode(url.toString(),
750: "UTF-8");
751: } catch (Exception ex) {
752: throw new RuntimeException(ex);
753: }
754: Assert.assertTrue("URL should end with: " + classNameAsPath,
755: urlAsString.endsWith(classNameAsPath));
756: if (urlAsString.startsWith("file:")) {
757: return FileSystemPath.existingDir(urlAsString.substring(
758: "file:".length(), urlAsString.length()
759: - classNameAsPath.length()));
760: } else if (urlAsString.startsWith("jar:file:")) {
761: int n = urlAsString.indexOf('!');
762: return FileSystemPath.makeExistingFile(urlAsString
763: .substring("jar:file:".length(), n));
764: } else
765: throw new RuntimeException("unsupported protocol: " + url);
766: }
767:
768: private static String classToPath(Class type) {
769: return type.getName().replace('.', '/') + ".class";
770: }
771:
772: private FileSystemPath calculatePathToResource(String resource) {
773: URL url = getClass().getResource(resource);
774: Assert.assertNotNull("Not found: " + resource, url);
775: return calculateDirectory(url, resource);
776: }
777:
778: private static class ResourceDefinition {
779: public final File location;
780: public final String prefix;
781: public final String includes;
782: public final String fullpath;
783:
784: public ResourceDefinition(File location, String includes,
785: String prefix, String fullpath) {
786: this .location = location;
787: this .includes = includes;
788: this .prefix = prefix;
789: this .fullpath = fullpath;
790: }
791: }
792:
793: private static class ServletDefinition {
794: public final String name;
795: public final String mapping;
796: public final Class servletClass;
797: public final Map initParameters;
798: public final boolean loadOnStartup;
799:
800: public ServletDefinition(String name, String mapping,
801: Class servletClass, Map initParameters,
802: boolean loadOnStartup) {
803: this .name = name;
804: this .mapping = mapping;
805: this .servletClass = servletClass;
806: this .initParameters = initParameters;
807: this .loadOnStartup = loadOnStartup;
808: }
809: }
810:
811: private static class FilterDefinition {
812: public final String name;
813: public final String mapping;
814: public final Class filterClass;
815: public final Map initParameters;
816:
817: public FilterDefinition(String name, String mapping,
818: Class filterClass, Map initParameters) {
819: this.name = name;
820: this.mapping = mapping;
821: this.filterClass = filterClass;
822: this.initParameters = initParameters;
823: }
824: }
825:
826: }
|