001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.geronimo.jasper.deployment;
017:
018: import java.io.File;
019: import java.io.IOException;
020: import java.net.JarURLConnection;
021: import java.net.MalformedURLException;
022: import java.net.URI;
023: import java.net.URISyntaxException;
024: import java.net.URL;
025: import java.util.ArrayList;
026: import java.util.Collection;
027: import java.util.Enumeration;
028: import java.util.HashMap;
029: import java.util.HashSet;
030: import java.util.List;
031: import java.util.Map;
032: import java.util.Set;
033: import java.util.jar.JarEntry;
034: import java.util.jar.JarFile;
035:
036: import javax.xml.namespace.QName;
037:
038: import org.apache.commons.logging.Log;
039: import org.apache.commons.logging.LogFactory;
040: import org.apache.geronimo.common.DeploymentException;
041: import org.apache.geronimo.deployment.ModuleIDBuilder;
042: import org.apache.geronimo.deployment.service.EnvironmentBuilder;
043: import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
044: import org.apache.geronimo.gbean.AbstractName;
045: import org.apache.geronimo.gbean.GBeanData;
046: import org.apache.geronimo.gbean.GBeanInfo;
047: import org.apache.geronimo.gbean.GBeanInfoBuilder;
048: import org.apache.geronimo.j2ee.annotation.Holder;
049: import org.apache.geronimo.j2ee.deployment.EARContext;
050: import org.apache.geronimo.j2ee.deployment.Module;
051: import org.apache.geronimo.j2ee.deployment.ModuleBuilderExtension;
052: import org.apache.geronimo.j2ee.deployment.NamingBuilder;
053: import org.apache.geronimo.j2ee.deployment.WebModule;
054: import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
055: import org.apache.geronimo.jasper.JasperServletContextCustomizer;
056: import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
057: import org.apache.geronimo.kernel.Naming;
058: import org.apache.geronimo.kernel.config.Configuration;
059: import org.apache.geronimo.kernel.config.ConfigurationStore;
060: import org.apache.geronimo.kernel.repository.Environment;
061: import org.apache.geronimo.schema.SchemaConversionUtils;
062: import org.apache.geronimo.xbeans.javaee.FullyQualifiedClassType;
063: import org.apache.geronimo.xbeans.javaee.JspConfigType;
064: import org.apache.geronimo.xbeans.javaee.ListenerType;
065: import org.apache.geronimo.xbeans.javaee.TagType;
066: import org.apache.geronimo.xbeans.javaee.TaglibDocument;
067: import org.apache.geronimo.xbeans.javaee.TaglibType;
068: import org.apache.geronimo.xbeans.javaee.TldTaglibType;
069: import org.apache.geronimo.xbeans.javaee.WebAppType;
070: import org.apache.xbean.finder.ClassFinder;
071: import org.apache.xmlbeans.XmlCursor;
072: import org.apache.xmlbeans.XmlException;
073: import org.apache.xmlbeans.XmlObject;
074:
075: /**
076: * This JSP module builder extension is meant to find all the TLD descriptor files associated with a
077: * deployable artifact, search those TLD files for listeners, search those listeners for
078: * annotations, and ultimately create a ClassFinder using those annoated classes (for later
079: * processing by the various naming builders)
080: *
081: * @version $Rev $Date
082: */
083: public class JspModuleBuilderExtension implements
084: ModuleBuilderExtension {
085:
086: private static final Log log = LogFactory
087: .getLog(JspModuleBuilderExtension.class);
088:
089: private final Environment defaultEnvironment;
090: private final NamingBuilder namingBuilders;
091:
092: private static final QName TLIB_VERSION = new QName(
093: SchemaConversionUtils.JAVAEE_NAMESPACE, "tlib-version");
094: private static final QName SHORT_NAME = new QName(
095: SchemaConversionUtils.JAVAEE_NAMESPACE, "short-name");
096: private static final QName TAG_CLASS = new QName(
097: SchemaConversionUtils.JAVAEE_NAMESPACE, "tag-class");
098: private static final QName TEI_CLASS = new QName(
099: SchemaConversionUtils.JAVAEE_NAMESPACE, "tei-class");
100: private static final QName BODY_CONTENT = new QName(
101: SchemaConversionUtils.JAVAEE_NAMESPACE, "body-content");
102:
103: private static final String SCHEMA_LOCATION_URL = "http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd";
104: private static final String VERSION = "2.1";
105:
106: public JspModuleBuilderExtension(Environment defaultEnvironment,
107: NamingBuilder namingBuilders) {
108: this .defaultEnvironment = defaultEnvironment;
109: this .namingBuilders = namingBuilders;
110: }
111:
112: public void createModule(Module module, Object plan,
113: JarFile moduleFile, String targetPath, URL specDDUrl,
114: Environment environment, Object moduleContextInfo,
115: AbstractName earName, Naming naming,
116: ModuleIDBuilder idBuilder) throws DeploymentException {
117: }
118:
119: public void installModule(JarFile earFile, EARContext earContext,
120: Module module, Collection configurationStores,
121: ConfigurationStore targetConfigurationStore,
122: Collection repository) throws DeploymentException {
123: }
124:
125: public void initContext(EARContext earContext, Module module,
126: ClassLoader cl) throws DeploymentException {
127: }
128:
129: public void addGBeans(EARContext earContext, Module module,
130: ClassLoader cl, Collection repository)
131: throws DeploymentException {
132: if (!(module instanceof WebModule)) {
133: //not a web module, nothing to do
134: return;
135: }
136: //TODO Only merge if we detect jsps???
137: EnvironmentBuilder.mergeEnvironments(module.getEnvironment(),
138: defaultEnvironment);
139:
140: WebModule webModule = (WebModule) module;
141: WebAppType webApp = (WebAppType) webModule.getSpecDD();
142:
143: EARContext moduleContext = module.getEarContext();
144: Map sharedContext = module.getSharedContext();
145:
146: GBeanData webAppData = (GBeanData) sharedContext
147: .get(WebModule.WEB_APP_DATA);
148:
149: AbstractName moduleName = moduleContext.getModuleName();
150: Map<NamingBuilder.Key, Object> buildingContext = new HashMap<NamingBuilder.Key, Object>();
151: buildingContext.put(NamingBuilder.GBEAN_NAME_KEY, moduleName);
152:
153: //use the same jndi context as the web app
154: Map compContext = NamingBuilder.JNDI_KEY.get(sharedContext);
155: buildingContext.put(NamingBuilder.JNDI_KEY, compContext);
156:
157: //use the same holder object as the web app.
158: Holder holder = NamingBuilder.INJECTION_KEY.get(sharedContext);
159: buildingContext.put(NamingBuilder.INJECTION_KEY, holder);
160:
161: XmlObject jettyWebApp = webModule.getVendorDD();
162:
163: Configuration earConfiguration = earContext.getConfiguration();
164:
165: Set<String> listenerNames = new HashSet<String>();
166:
167: ClassFinder classFinder = createJspClassFinder(webApp,
168: webModule, listenerNames);
169: webModule.setClassFinder(classFinder);
170:
171: namingBuilders.buildNaming(webApp, jettyWebApp, webModule,
172: buildingContext);
173:
174: //only try to install it if reference will work.
175: //Some users (tomcat?) may have back doors into jasper that make adding this gbean unnecessary.
176: GBeanInfo webAppGBeanInfo = webAppData.getGBeanInfo();
177: if (webAppGBeanInfo.getReference("ContextCustomizer") != null) {
178: AbstractName jspLifecycleName = moduleContext.getNaming()
179: .createChildName(moduleName,
180: "jspLifecycleProvider",
181: NameFactory.GERONIMO_SERVICE);
182: GBeanData gbeanData = new GBeanData(jspLifecycleName,
183: JasperServletContextCustomizer.GBEAN_INFO);
184: gbeanData.setAttribute("holder", holder);
185:
186: try {
187: moduleContext.addGBean(gbeanData);
188: } catch (GBeanAlreadyExistsException e) {
189: throw new DeploymentException(
190: "Duplicate jspLifecycleProvider", e);
191: }
192:
193: webAppData.setReferencePattern("ContextCustomizer",
194: jspLifecycleName);
195: }
196: //add listeners if possible
197: //we may need to add them in another way for tomcat
198: Object value = webAppData.getAttribute("listenerClassNames");
199: if (value instanceof Collection) {
200: ((Collection<String>) value).addAll(listenerNames);
201: }
202: }
203:
204: protected ClassFinder createJspClassFinder(WebAppType webApp,
205: WebModule webModule, Set<String> listenerNames)
206: throws DeploymentException {
207: List<URL> urls = getTldFiles(webApp, webModule);
208: List<Class> classes = getListenerClasses(webApp, webModule,
209: urls, listenerNames);
210: return new ClassFinder(classes);
211: }
212:
213: /**
214: * getTldFiles(): Find all the TLD files in the web module being deployed
215: *
216: * <p>Locations to search for these TLD file(s) (matches the precedence search order for TLD
217: * files per the JSP specs):
218: * <ol>
219: * <li>web.xml <taglib> entries
220: * <li>TLD(s) in JAR files in WEB-INF/lib
221: * <li>TLD(s) under WEB-INF
222: * <li>All TLD files in all META-INF(s)
223: * </ol>
224: *
225: * @param webApp spec DD for module
226: * @param webModule module being deployed
227: * @return list of the URL(s) for the TLD files
228: * @throws DeploymentException if there's a problem finding a tld file
229: */
230: private List<URL> getTldFiles(WebAppType webApp, WebModule webModule)
231: throws DeploymentException {
232: if (log.isDebugEnabled()) {
233: log.debug("getTldFiles( " + webApp.toString() + ","
234: + webModule.getName() + " ): Entry");
235: }
236:
237: List<URL> tldURLs = new ArrayList<URL>();
238:
239: // 1. web.xml <taglib> entries
240: JspConfigType[] jspConfigs = webApp.getJspConfigArray();
241: for (JspConfigType jspConfig : jspConfigs) {
242: TaglibType[] taglibs = jspConfig.getTaglibArray();
243: for (TaglibType taglib : taglibs) {
244: String uri = taglib.getTaglibUri().getStringValue()
245: .trim();
246: String location = taglib.getTaglibLocation()
247: .getStringValue().trim();
248: if (!location.equals("")) {
249: if (location.startsWith("/")) {
250: location = location.substring(1);
251: }
252: try {
253: File targetFile = webModule.getEarContext()
254: .getTargetFile(createURI(location));
255: if (targetFile != null) {
256: tldURLs.add(targetFile.toURL());
257: }
258: } catch (MalformedURLException mfe) {
259: throw new DeploymentException(
260: "Could not locate TLD file specified in <taglib>: URI: "
261: + uri + " Location: "
262: + location + " "
263: + mfe.getMessage(), mfe);
264: } catch (URISyntaxException use) {
265: throw new DeploymentException(
266: "Could not locate TLD file specified in <taglib>: URI: "
267: + uri + " Location: "
268: + location + " "
269: + use.getMessage(), use);
270: }
271: }
272: }
273: }
274:
275: // 2. TLD(s) in JAR files in WEB-INF/lib
276: // 3. TLD(s) under WEB-INF
277: List<URL> tempURLs = scanModule(webModule);
278: for (URL webInfURL : tempURLs) {
279: tldURLs.add(webInfURL);
280: }
281:
282: // 4. All TLD files in all META-INF(s)
283: tempURLs.clear();
284: try {
285: Enumeration<URL> enumURLs = webModule.getEarContext()
286: .getClassLoader().getResources("META-INF");
287: while (enumURLs.hasMoreElements()) {
288: URL enumURL = enumURLs.nextElement();
289: tempURLs = scanDirectory(enumURL);
290: for (URL metaInfURL : tempURLs) {
291: tldURLs.add(metaInfURL);
292: }
293: tempURLs.clear();
294: }
295: } catch (IOException ioe) {
296: throw new DeploymentException(
297: "Could not locate TLD files located in META-INF(s) "
298: + ioe.getMessage(), ioe);
299: }
300:
301: log.debug("getTldFiles() Exit: URL[" + tldURLs.size() + "]: "
302: + tldURLs.toString());
303: return tldURLs;
304: }
305:
306: /**
307: * scanModule(): Scan the module being deployed for JAR files or TLD files in the WEB-INF
308: * directory
309: *
310: * @param webModule module being deployed
311: * @return list of the URL(s) for the TLD files in the module
312: * @throws DeploymentException if module cannot be scanned
313: */
314: private List<URL> scanModule(WebModule webModule)
315: throws DeploymentException {
316: log.debug("scanModule( " + webModule.getName() + " ): Entry");
317:
318: List<URL> modURLs = new ArrayList<URL>();
319: try {
320: Enumeration<JarEntry> entries = webModule.getModuleFile()
321: .entries();
322: while (entries.hasMoreElements()) {
323: JarEntry jarEntry = entries.nextElement();
324: if (jarEntry.getName().startsWith("WEB-INF/")
325: && jarEntry.getName().endsWith(".tld")) {
326: File targetFile = webModule.getEarContext()
327: .getTargetFile(
328: createURI(jarEntry.getName()));
329: if (targetFile != null) {
330: modURLs.add(targetFile.toURL());
331: }
332: }
333: if (jarEntry.getName().startsWith("WEB-INF/lib/")
334: && jarEntry.getName().endsWith(".jar")) {
335: File targetFile = webModule.getEarContext()
336: .getTargetFile(
337: createURI(jarEntry.getName()));
338: List<URL> jarUrls = scanJAR(
339: new JarFile(targetFile), null);
340: for (URL jarURL : jarUrls) {
341: modURLs.add(jarURL);
342: }
343: }
344: }
345: } catch (IOException ioe) {
346: throw new DeploymentException(
347: "Could not scan module for TLD files: "
348: + webModule.getName() + " "
349: + ioe.getMessage(), ioe);
350: } catch (Exception e) {
351: throw new DeploymentException(
352: "Could not scan module for TLD files: "
353: + webModule.getName() + " "
354: + e.getMessage(), e);
355: }
356:
357: log.debug("scanModule() Exit: URL[" + modURLs.size() + "]: "
358: + modURLs.toString());
359: return modURLs;
360: }
361:
362: /**
363: * scanJAR(): Scan a JAR files looking for all TLD
364: *
365: * @param jarFile jar file to scan
366: * @param prefix Optional prefix to limit the search to a specific subdirectory in the JAR file
367: * @return list of the URL(s) for the TLD files in the JAR file
368: * @throws DeploymentException if jar file cannot be scanned
369: */
370: private List<URL> scanJAR(JarFile jarFile, String prefix)
371: throws DeploymentException {
372: log.debug("scanJAR( " + jarFile.getName() + " ): Entry");
373:
374: List<URL> jarURLs = new ArrayList<URL>();
375: try {
376: Enumeration<JarEntry> entries = jarFile.entries();
377: while (entries.hasMoreElements()) {
378: JarEntry jarEntry = entries.nextElement();
379: URL tempURL = null;
380: if (prefix != null) {
381: if (jarEntry.getName().endsWith(".tld")
382: && jarEntry.getName().startsWith(prefix)) {
383: tempURL = new URL("jar:file:"
384: + jarFile.getName() + "!/"
385: + jarEntry.getName());
386: }
387: } else {
388: if (jarEntry.getName().endsWith(".tld")) {
389: tempURL = new URL("jar:file:"
390: + jarFile.getName() + "!/"
391: + jarEntry.getName());
392: }
393: }
394: if (tempURL != null) {
395: jarURLs.add(tempURL);
396: }
397: }
398: } catch (MalformedURLException mfe) {
399: throw new DeploymentException(
400: "Could not scan JAR file for TLD files: "
401: + jarFile.getName() + " "
402: + mfe.getMessage(), mfe);
403: } catch (Exception e) {
404: throw new DeploymentException(
405: "Could not scan JAR file for TLD files: "
406: + jarFile.getName() + " " + e.getMessage(),
407: e);
408: }
409:
410: log.debug("scanJAR() Exit: URL[" + jarURLs.size() + "]: "
411: + jarURLs.toString());
412: return jarURLs;
413: }
414:
415: /**
416: * scanDirectory(): Scan a directory for all TLD files
417: *
418: * @param url URL for the directory to be scanned
419: * @return list of the URL(s) for the TLD files in the directory
420: * @throws DeploymentException if directory cannot be scanned
421: */
422: private List<URL> scanDirectory(URL url) throws DeploymentException {
423: log.debug("scanDirectory( " + url.toString() + " ): Entry");
424:
425: List<URL> dirURLs = new ArrayList<URL>();
426: File directory;
427: if (url != null) {
428: if (url.toString().startsWith("jar:file:")) {
429: try {
430: JarURLConnection jarConnection = (JarURLConnection) url
431: .openConnection();
432: URL urlJC = jarConnection.getJarFileURL();
433: URI baseURI = createURI(urlJC.toString());
434: directory = new File(baseURI);
435: if (directory.isDirectory()) {
436: if (directory.canRead()) {
437: JarFile temp = new JarFile(directory);
438: List<URL> tempURLs = scanJAR(temp,
439: "META-INF");
440: for (URL jarURL : tempURLs) {
441: dirURLs.add(jarURL);
442: }
443: } else {
444: log.warn("Cannot read JAR file: "
445: + url.toString());
446: }
447: }
448: } catch (Exception e) {
449: throw new DeploymentException(
450: "Could not scan directory for TLD files: "
451: + url.toString() + " "
452: + e.getMessage(), e);
453: }
454: } else if (url.toString().startsWith("file:")) {
455: try {
456: URI baseURI = createURI(url.toString());
457: directory = new File(baseURI);
458: if (directory.isDirectory() && directory.canRead()) {
459: File[] children = directory.listFiles();
460: for (File child : children) {
461: if (child.getName().endsWith(".tld")) {
462: dirURLs.add(child.toURL());
463: }
464: }
465: } else {
466: log.warn("Cannot read directory: "
467: + url.toString());
468: }
469: } catch (Exception e) {
470: throw new DeploymentException(
471: "Could not scan directory for TLD files: "
472: + url.toString() + " "
473: + e.getMessage(), e);
474: }
475: } else if (url.toString().startsWith("jar:")) {
476: log.warn("URL type not accounted for: "
477: + url.toString());
478: }
479: }
480:
481: log.debug("scanDirectory() Exit: URL[" + dirURLs.size() + "]: "
482: + dirURLs.toString());
483: return dirURLs;
484: }
485:
486: private List<Class> getListenerClasses(WebAppType webApp,
487: WebModule webModule, List<URL> urls,
488: Set<String> listenerNames) throws DeploymentException {
489: if (log.isDebugEnabled()) {
490: log.debug("getListenerClasses( " + webApp.toString() + ","
491: + '\n' + webModule.getName() + " ): Entry");
492: }
493:
494: // Get the classloader from the module's EARContext
495: ClassLoader classLoader = webModule.getEarContext()
496: .getClassLoader();
497: List<Class> classes = new ArrayList<Class>();
498:
499: for (URL url : urls) {
500: parseTldFile(url, classLoader, classes, listenerNames);
501: }
502:
503: if (log.isDebugEnabled()) {
504: log.debug("getListenerClasses() Exit: Classes["
505: + classes.size() + "]: " + classes.toString());
506: }
507: return classes;
508: }
509:
510: private void parseTldFile(URL url, ClassLoader classLoader,
511: List<Class> classes, Set<String> listenerNames)
512: throws DeploymentException {
513: log.debug("parseTLDFile( " + url.toString() + " ): Entry");
514:
515: try {
516: XmlObject xml = XmlBeansUtil.parse(url, null);
517: TaglibDocument tld = convertToTaglibSchema(xml);
518: TldTaglibType tl = tld.getTaglib();
519:
520: // Get all the listeners from the TLD file
521: ListenerType[] listeners = tl.getListenerArray();
522: for (ListenerType listener : listeners) {
523: FullyQualifiedClassType cls = listener
524: .getListenerClass();
525: String className = cls.getStringValue().trim();
526: listenerNames.add(className);
527: try {
528: Class clas = classLoader.loadClass(className);
529: classes.add(clas);
530: } catch (ClassNotFoundException e) {
531: log
532: .warn("JspModuleBuilderExtension: Could not load listener class: "
533: + className
534: + " mentioned in TLD file at "
535: + url.toString());
536: }
537: }
538:
539: // Get all the tags from the TLD file
540: TagType[] tags = tl.getTagArray();
541: for (TagType tag : tags) {
542: FullyQualifiedClassType cls = tag.getTagClass();
543: String className = cls.getStringValue().trim();
544: try {
545: Class clas = classLoader.loadClass(className);
546: classes.add(clas);
547: } catch (ClassNotFoundException e) {
548: log
549: .warn("JspModuleBuilderExtension: Could not load tag class: "
550: + className
551: + " mentioned in TLD file at "
552: + url.toString());
553: }
554: }
555: } catch (XmlException xmle) {
556: throw new DeploymentException(
557: "Could not parse TLD file at " + url.toString(),
558: xmle);
559: } catch (IOException ioe) {
560: throw new DeploymentException("Could not find TLD file at "
561: + url.toString(), ioe);
562: }
563:
564: log.debug("parseTLDFile(): Exit");
565: }
566:
567: /**
568: * convertToTaglibSchema(): Convert older TLD files based on the 1.1 and 1.2 DTD or the 2.0 XSD
569: * schemas
570: *
571: * <p><strong>Note(s):</strong>
572: * <ul>
573: * <li>Those tags from the 1.1 and 1.2 DTD that are no longer valid (e.g., jsp-version) are
574: * removed
575: * <li>Valid tags from the 1.1 and 1.2 DTD are converted (e.g., tlibversion to
576: * tlib-version)
577: * <li>The <taglib> root and the <tag> root elements are reordered as necessary (i.e.,
578: * description, display-name)
579: * <li>The <rtexprvalue> tag is inserted in the <attribute> tag if necessary since it was
580: * not required to preceed <type> in 2.0 schema. Default value of false is used.
581: * </ul>
582: *
583: * @param xmlObject possibly old-style tag lib document
584: * @return converted TagLibDocument in the new shiny schema
585: * @throws XmlException if something goes horribly wrong
586: */
587: protected static TaglibDocument convertToTaglibSchema(
588: XmlObject xmlObject) throws XmlException {
589: if (log.isDebugEnabled()) {
590: log.debug("convertToTaglibSchema( " + xmlObject.toString()
591: + " ): Entry");
592: }
593:
594: XmlCursor cursor = xmlObject.newCursor();
595: XmlCursor moveable = xmlObject.newCursor();
596: try {
597: cursor.toStartDoc();
598: cursor.toFirstChild();
599: if (SchemaConversionUtils.JAVAEE_NAMESPACE.equals(cursor
600: .getName().getNamespaceURI())) {
601: log.debug("Nothing to do");
602: } else if (SchemaConversionUtils.J2EE_NAMESPACE
603: .equals(cursor.getName().getNamespaceURI())) {
604: log.debug("Converting XSD 2.0 to 2.1 schema");
605: SchemaConversionUtils.convertSchemaVersion(cursor,
606: SchemaConversionUtils.JAVAEE_NAMESPACE,
607: SCHEMA_LOCATION_URL, VERSION);
608: cursor.toStartDoc();
609: cursor.toChild(SchemaConversionUtils.JAVAEE_NAMESPACE,
610: "taglib");
611: cursor.toFirstChild();
612: do {
613: String name = cursor.getName().getLocalPart();
614: if ("tag".equals(name)) {
615: cursor.push();
616: cursor.toFirstChild();
617: SchemaConversionUtils
618: .convertToDescriptionGroup(
619: SchemaConversionUtils.JAVAEE_NAMESPACE,
620: cursor, moveable);
621: do {
622: name = cursor.getName().getLocalPart();
623: boolean rtexprvalueFound = false;
624: boolean typeFound = false;
625: if ("attribute".equals(name)) {
626: cursor.push();
627: cursor.toFirstChild();
628: do {
629: name = cursor.getName()
630: .getLocalPart();
631: if ("rtexprvalue".equals(name)) {
632: rtexprvalueFound = true;
633: }
634: if ("type".equals(name)) {
635: typeFound = true;
636: }
637: } while (cursor.toNextSibling());
638: cursor.pop();
639: if (typeFound && !rtexprvalueFound) {
640: //--------------------------------------------------------------
641: // Handle the case where the <type> tag must now be preceded by
642: // the <rtexprvalue> tag in the 2.1 schema. Cases are:
643: // 1: Only type found:
644: // We are currently positioned directly after the attribute
645: // tag (via the pop) so just insert the rtexprvalue tag
646: // with the default value. The tags will be properly
647: // ordered below.
648: // 2: Both type and rtexprvalue found:
649: // The tags will be properly ordered below with the
650: // convertToAttributeGroup() call, so nothing to do
651: // 3: Only rtexprvalue found:
652: // Nothing to do
653: // 4: Neither found:
654: // Nothing to do
655: //--------------------------------------------------------------
656: cursor.push();
657: cursor.toFirstChild();
658: cursor
659: .insertElementWithText(
660: "rtexprvalue",
661: SchemaConversionUtils.JAVAEE_NAMESPACE,
662: "false");
663: cursor.pop();
664: }
665: cursor.push();
666: cursor.toFirstChild();
667: SchemaConversionUtils
668: .convertToTldAttribute(
669: SchemaConversionUtils.JAVAEE_NAMESPACE,
670: cursor, moveable);
671: cursor.pop();
672: }
673: } while (cursor.toNextSibling());
674: cursor.pop();
675: // Do this conversion last after the other tags have been converted
676: SchemaConversionUtils.convertToTldTag(
677: SchemaConversionUtils.JAVAEE_NAMESPACE,
678: cursor, moveable);
679: }
680: } while (cursor.toNextSibling());
681: } else {
682: log.debug("Converting DTD to 2.1 schema");
683: SchemaConversionUtils.convertToSchema(cursor,
684: SchemaConversionUtils.JAVAEE_NAMESPACE,
685: SCHEMA_LOCATION_URL, VERSION);
686: cursor.toStartDoc();
687: cursor.toChild(SchemaConversionUtils.JAVAEE_NAMESPACE,
688: "taglib");
689: cursor.toFirstChild();
690: SchemaConversionUtils.convertToDescriptionGroup(
691: SchemaConversionUtils.JAVAEE_NAMESPACE, cursor,
692: moveable);
693: do {
694: String name = cursor.getName().getLocalPart();
695: if ("jsp-version".equals(name)
696: || "jspversion".equals(name)
697: || "info".equals(name)) {
698: cursor.removeXmlContents();
699: cursor.removeXml();
700: }
701: if ("tlibversion".equals(name)) {
702: cursor.setName(TLIB_VERSION);
703: }
704: if ("tlibversion".equals(name)) {
705: cursor.setName(TLIB_VERSION);
706: }
707: if ("shortname".equals(name)) {
708: cursor.setName(SHORT_NAME);
709: }
710: if ("tag".equals(name)) {
711: cursor.push();
712: cursor.toFirstChild();
713: SchemaConversionUtils
714: .convertToDescriptionGroup(
715: SchemaConversionUtils.JAVAEE_NAMESPACE,
716: cursor, moveable);
717: boolean bodyContentFound = false;
718: do {
719: name = cursor.getName().getLocalPart();
720: if ("tagclass".equals(name)) {
721: cursor.setName(TAG_CLASS);
722: }
723: if ("teiclass".equals(name)) {
724: cursor.setName(TEI_CLASS);
725: }
726: if ("bodycontent".equals(name)) {
727: cursor.setName(BODY_CONTENT);
728: bodyContentFound = true;
729: }
730: if ("body-content".equals(name)) {
731: bodyContentFound = true;
732: }
733: if ("attribute".equals(name)) {
734: cursor.push();
735: cursor.toFirstChild();
736: SchemaConversionUtils
737: .convertToTldAttribute(
738: SchemaConversionUtils.JAVAEE_NAMESPACE,
739: cursor, moveable);
740: cursor.pop();
741: }
742: if ("variable".equals(name)) {
743: cursor.push();
744: cursor.toFirstChild();
745: SchemaConversionUtils
746: .convertToTldVariable(
747: SchemaConversionUtils.JAVAEE_NAMESPACE,
748: cursor, moveable);
749: cursor.pop();
750: }
751: if ("info".equals(name)) {
752: cursor.removeXmlContents();
753: cursor.removeXml();
754: }
755: } while (cursor.toNextSibling());
756: cursor.pop();
757: if (!bodyContentFound) {
758: //--------------------------------------------------------------
759: // Handle the case where the <body-content> tag is missing. We
760: // are currently positioned directly after the <tag> attribute
761: // (via the pop) so just insert the <body-content> tag with the
762: // default value. The tags will be properly ordered below.
763: //--------------------------------------------------------------
764: cursor.push();
765: cursor.toFirstChild();
766: cursor
767: .insertElementWithText(
768: "body-content",
769: SchemaConversionUtils.JAVAEE_NAMESPACE,
770: "scriptless");
771: cursor.pop();
772: }
773: // Do this conversion last after the other tags have been converted
774: cursor.push();
775: cursor.toFirstChild();
776: SchemaConversionUtils.convertToTldTag(
777: SchemaConversionUtils.JAVAEE_NAMESPACE,
778: cursor, moveable);
779: cursor.pop();
780: }
781: if ("validator".equals(name)) {
782: cursor.push();
783: cursor.toFirstChild();
784: SchemaConversionUtils.convertToTldValidator(
785: SchemaConversionUtils.JAVAEE_NAMESPACE,
786: cursor, moveable);
787: cursor.pop();
788: }
789: } while (cursor.toNextSibling());
790: }
791: } finally {
792: cursor.dispose();
793: moveable.dispose();
794: }
795: XmlObject result = xmlObject.changeType(TaglibDocument.type);
796: if (result != null) {
797: try {
798: XmlBeansUtil.validateDD(result);
799: } catch (XmlException e) {
800: log.warn("Invalid transformed taglib", e);
801: }
802: if (log.isDebugEnabled()) {
803: log.debug("convertToTaglibSchema( " + result.toString()
804: + " ): Exit 1");
805: }
806: return (TaglibDocument) result;
807: }
808: try {
809: XmlBeansUtil.validateDD(xmlObject);
810: } catch (XmlException e) {
811: log.warn("Invalid transformed taglib", e);
812: }
813: if (log.isDebugEnabled()) {
814: log.debug("convertToTaglibSchema( " + xmlObject.toString()
815: + " ): Exit 2");
816: }
817: return (TaglibDocument) xmlObject;
818: }
819:
820: private URI createURI(String path) throws URISyntaxException {
821: path = path.replaceAll(" ", "%20");
822: return new URI(path);
823: }
824:
825: public static final GBeanInfo GBEAN_INFO;
826:
827: static {
828: GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(
829: JspModuleBuilderExtension.class,
830: NameFactory.MODULE_BUILDER);
831: infoBuilder.addAttribute("defaultEnvironment",
832: Environment.class, true, true);
833: infoBuilder.addReference("NamingBuilders", NamingBuilder.class,
834: NameFactory.MODULE_BUILDER);
835:
836: infoBuilder.setConstructor(new String[] { "defaultEnvironment",
837: "NamingBuilders" });
838: GBEAN_INFO = infoBuilder.getBeanInfo();
839: }
840:
841: public static GBeanInfo getGBeanInfo() {
842: return GBEAN_INFO;
843: }
844: }
|