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