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 if (log.isDebugEnabled()) {
204 log.debug("getTldFiles( " + webApp.toString() + "," + webModule.getName() + " ): Entry");
205 }
206
207 List<URL> tldURLs = new ArrayList<URL>();
208
209 // 1. web.xml <taglib> entries
210 JspConfigType[] jspConfigs = webApp.getJspConfigArray();
211 for (JspConfigType jspConfig : jspConfigs) {
212 TaglibType[] taglibs = jspConfig.getTaglibArray();
213 for (TaglibType taglib : taglibs) {
214 String uri = taglib.getTaglibUri().getStringValue().trim();
215 String location = taglib.getTaglibLocation().getStringValue().trim();
216 if (!location.equals("")) {
217 if (location.startsWith("/")) {
218 location = location.substring(1);
219 }
220 try {
221 File targetFile = webModule.getEarContext().getTargetFile(createURI(location));
222 if (targetFile!=null) {
223 tldURLs.add(targetFile.toURL());
224 }
225 }
226 catch (MalformedURLException mfe) {
227 throw new DeploymentException("Could not locate TLD file specified in <taglib>: URI: " + uri + " Location: " + location + " " + mfe.getMessage(), mfe);
228 }
229 catch (URISyntaxException use) {
230 throw new DeploymentException("Could not locate TLD file specified in <taglib>: URI: " + uri + " Location: " + location + " " + use.getMessage(), use);
231 }
232 }
233 }
234 }
235
236 // 2. TLD(s) in JAR files in WEB-INF/lib
237 // 3. TLD(s) under WEB-INF
238 List<URL> tempURLs = scanModule(webModule);
239 for (URL webInfURL : tempURLs) {
240 tldURLs.add(webInfURL);
241 }
242
243 // 4. All TLD files in all META-INF(s)
244 tempURLs.clear();
245 try {
246 Enumeration<URL> enumURLs = webModule.getEarContext().getClassLoader().getResources("META-INF");
247 while (enumURLs.hasMoreElements()) {
248 URL enumURL = enumURLs.nextElement();
249 tempURLs = scanDirectory(enumURL);
250 for (URL metaInfURL : tempURLs) {
251 tldURLs.add(metaInfURL);
252 }
253 tempURLs.clear();
254 }
255 }
256 catch (IOException ioe) {
257 throw new DeploymentException("Could not locate TLD files located in META-INF(s) " + ioe.getMessage(), ioe);
258 }
259
260 log.debug("getTldFiles() Exit: URL[" + tldURLs.size() + "]: " + tldURLs.toString());
261 return tldURLs;
262 }
263
264
265 /**
266 * scanModule(): Scan the module being deployed for JAR files or TLD files in the WEB-INF
267 * directory
268 *
269 * @param webModule module being deployed
270 * @return list of the URL(s) for the TLD files in the module
271 * @throws DeploymentException if module cannot be scanned
272 */
273 private List<URL> scanModule(WebModule webModule) throws DeploymentException {
274 log.debug("scanModule( " + webModule.getName() + " ): Entry");
275
276 List<URL> modURLs = new ArrayList<URL>();
277 try {
278 Enumeration<JarEntry> entries = webModule.getModuleFile().entries();
279 while (entries.hasMoreElements()) {
280 JarEntry jarEntry = entries.nextElement();
281 if (jarEntry.getName().startsWith("WEB-INF/") && jarEntry.getName().endsWith(".tld")) {
282 File targetFile = webModule.getEarContext().getTargetFile(createURI(jarEntry.getName()));
283 if (targetFile!=null) {
284 modURLs.add(targetFile.toURL());
285 }
286 }
287 if (jarEntry.getName().startsWith("WEB-INF/lib/") && jarEntry.getName().endsWith(".jar")) {
288 File targetFile = webModule.getEarContext().getTargetFile(createURI(jarEntry.getName()));
289 List<URL> jarUrls = scanJAR(new JarFile(targetFile), null);
290 for (URL jarURL : jarUrls) {
291 modURLs.add(jarURL);
292 }
293 }
294 }
295 }
296 catch (IOException ioe) {
297 throw new DeploymentException("Could not scan module for TLD files: " + webModule.getName() + " " + ioe.getMessage(), ioe);
298 }
299 catch (Exception e) {
300 throw new DeploymentException("Could not scan module for TLD files: " + webModule.getName() + " " + e.getMessage(), e);
301 }
302
303 log.debug("scanModule() Exit: URL[" + modURLs.size() + "]: " + modURLs.toString());
304 return modURLs;
305 }
306
307
308 /**
309 * scanJAR(): Scan a JAR files looking for all TLD
310 *
311 * @param jarFile jar file to scan
312 * @param prefix Optional prefix to limit the search to a specific subdirectory in the JAR file
313 * @return list of the URL(s) for the TLD files in the JAR file
314 * @throws DeploymentException if jar file cannot be scanned
315 */
316 private List<URL> scanJAR(JarFile jarFile, String prefix) throws DeploymentException {
317 log.debug("scanJAR( " + jarFile.getName() + " ): Entry");
318
319 List<URL> jarURLs = new ArrayList<URL>();
320 try {
321 Enumeration<JarEntry> entries = jarFile.entries();
322 while (entries.hasMoreElements()) {
323 JarEntry jarEntry = entries.nextElement();
324 URL tempURL = null;
325 if (prefix != null) {
326 if (jarEntry.getName().endsWith(".tld") && jarEntry.getName().startsWith(prefix)) {
327 tempURL = new URL("jar:file:" + jarFile.getName() + "!/" + jarEntry.getName());
328 }
329 } else {
330 if (jarEntry.getName().endsWith(".tld")) {
331 tempURL = new URL("jar:file:" + jarFile.getName() + "!/" + jarEntry.getName());
332 }
333 }
334 if (tempURL != null) {
335 jarURLs.add(tempURL);
336 }
337 }
338 }
339 catch (MalformedURLException mfe) {
340 throw new DeploymentException("Could not scan JAR file for TLD files: " + jarFile.getName() + " " + mfe.getMessage(), mfe);
341 }
342 catch (Exception e) {
343 throw new DeploymentException("Could not scan JAR file for TLD files: " + jarFile.getName() + " " + e.getMessage(), e);
344 }
345
346 log.debug("scanJAR() Exit: URL[" + jarURLs.size() + "]: " + jarURLs.toString());
347 return jarURLs;
348 }
349
350
351 /**
352 * scanDirectory(): Scan a directory for all TLD files
353 *
354 * @param url URL for the directory to be scanned
355 * @return list of the URL(s) for the TLD files in the directory
356 * @throws DeploymentException if directory cannot be scanned
357 */
358 private List<URL> scanDirectory(URL url) throws DeploymentException {
359 log.debug("scanDirectory( " + url.toString() + " ): Entry");
360
361 List<URL> dirURLs = new ArrayList<URL>();
362 File directory;
363 if (url != null) {
364 if (url.toString().startsWith("jar:file:")) {
365 try {
366 JarURLConnection jarConnection = (JarURLConnection) url.openConnection();
367 URL urlJC = jarConnection.getJarFileURL();
368 URI baseURI = createURI(urlJC.toString());
369 directory = new File(baseURI);
370 if (directory.isDirectory()) {
371 if (directory.canRead()) {
372 JarFile temp = new JarFile(directory);
373 List<URL> tempURLs = scanJAR(temp, "META-INF");
374 for (URL jarURL : tempURLs) {
375 dirURLs.add(jarURL);
376 }
377 } else {
378 log.warn("Cannot read JAR file: " + url.toString());
379 }
380 }
381 }
382 catch (Exception e) {
383 throw new DeploymentException("Could not scan directory for TLD files: " + url.toString() + " " + e.getMessage(), e);
384 }
385 } else if (url.toString().startsWith("file:")) {
386 try {
387 URI baseURI = createURI(url.toString());
388 directory = new File(baseURI);
389 if (directory.isDirectory() && directory.canRead()) {
390 File[] children = directory.listFiles();
391 for (File child : children) {
392 if (child.getName().endsWith(".tld")) {
393 dirURLs.add(child.toURL());
394 }
395 }
396 } else {
397 log.warn("Cannot read directory: " + url.toString());
398 }
399 }
400 catch (Exception e) {
401 throw new DeploymentException("Could not scan directory for TLD files: " + url.toString() + " " + e.getMessage(), e);
402 }
403 } else if (url.toString().startsWith("jar:")) {
404 log.warn("URL type not accounted for: " + url.toString());
405 }
406 }
407
408 log.debug("scanDirectory() Exit: URL[" + dirURLs.size() + "]: " + dirURLs.toString());
409 return dirURLs;
410 }
411
412
413 private List<Class> getListenerClasses(WebAppType webApp, WebModule webModule, List<URL> urls, Set<String> listenerNames) throws DeploymentException {
414 if (log.isDebugEnabled()) {
415 log.debug("getListenerClasses( " + webApp.toString() + "," + '\n' +
416 webModule.getName() + " ): Entry");
417 }
418
419 // Get the classloader from the module's EARContext
420 ClassLoader classLoader = webModule.getEarContext().getClassLoader();
421 List<Class> classes = new ArrayList<Class>();
422
423 for (URL url : urls) {
424 parseTldFile(url, classLoader, classes, listenerNames);
425 }
426
427 if (log.isDebugEnabled()) {
428 log.debug("getListenerClasses() Exit: Classes[" + classes.size() + "]: " + classes.toString());
429 }
430 return classes;
431 }
432
433
434 private void parseTldFile(URL url, ClassLoader classLoader, List<Class> classes, Set<String> listenerNames) throws DeploymentException {
435 log.debug("parseTLDFile( " + url.toString() + " ): Entry");
436
437 try {
438 XmlObject xml = XmlBeansUtil.parse(url, null);
439 TaglibDocument tld = convertToTaglibSchema(xml);
440 TldTaglibType tl = tld.getTaglib();
441
442 // Get all the listeners from the TLD file
443 ListenerType[] listeners = tl.getListenerArray();
444 for (ListenerType listener : listeners) {
445 FullyQualifiedClassType cls = listener.getListenerClass();
446 String className = cls.getStringValue().trim();
447 listenerNames.add(className);
448 try {
449 Class clas = classLoader.loadClass(className);
450 classes.add(clas);
451 }
452 catch (ClassNotFoundException e) {
453 log.warn("JspModuleBuilderExtension: Could not load listener class: " + className + " mentioned in TLD file at " + url.toString());
454 }
455 }
456
457 // Get all the tags from the TLD file
458 TagType[] tags = tl.getTagArray();
459 for (TagType tag : tags) {
460 FullyQualifiedClassType cls = tag.getTagClass();
461 String className = cls.getStringValue().trim();
462 try {
463 Class clas = classLoader.loadClass(className);
464 classes.add(clas);
465 }
466 catch (ClassNotFoundException e) {
467 log.warn("JspModuleBuilderExtension: Could not load tag class: " + className + " mentioned in TLD file at " + url.toString());
468 }
469 }
470 }
471 catch (XmlException xmle) {
472 throw new DeploymentException("Could not parse TLD file at " + url.toString(), xmle);
473 }
474 catch (IOException ioe) {
475 throw new DeploymentException("Could not find TLD file at " + url.toString(), ioe);
476 }
477
478 log.debug("parseTLDFile(): Exit");
479 }
480
481
482 /**
483 * convertToTaglibSchema(): Convert older TLD files based on the 1.1 and 1.2 DTD or the 2.0 XSD
484 * schemas
485 *
486 * <p><strong>Note(s):</strong>
487 * <ul>
488 * <li>Those tags from the 1.1 and 1.2 DTD that are no longer valid (e.g., jsp-version) are
489 * removed
490 * <li>Valid tags from the 1.1 and 1.2 DTD are converted (e.g., tlibversion to
491 * tlib-version)
492 * <li>The <taglib> root and the <tag> root elements are reordered as necessary (i.e.,
493 * description, display-name)
494 * <li>The <rtexprvalue> tag is inserted in the <attribute> tag if necessary since it was
495 * not required to preceed <type> in 2.0 schema. Default value of false is used.
496 * </ul>
497 *
498 * @param xmlObject possibly old-style tag lib document
499 * @return converted TagLibDocument in the new shiny schema
500 * @throws XmlException if something goes horribly wrong
501 */
502 protected static TaglibDocument convertToTaglibSchema(XmlObject xmlObject) throws XmlException {
503 if (log.isDebugEnabled()) {
504 log.debug("convertToTaglibSchema( " + xmlObject.toString() + " ): Entry");
505 }
506
507 XmlCursor cursor = xmlObject.newCursor();
508 XmlCursor moveable = xmlObject.newCursor();
509 try {
510 cursor.toStartDoc();
511 cursor.toFirstChild();
512 if (SchemaConversionUtils.JAVAEE_NAMESPACE.equals(cursor.getName().getNamespaceURI())) {
513 log.debug("Nothing to do");
514 }
515 else if (SchemaConversionUtils.J2EE_NAMESPACE.equals(cursor.getName().getNamespaceURI())) {
516 log.debug("Converting XSD 2.0 to 2.1 schema");
517 SchemaConversionUtils.convertSchemaVersion(cursor, SchemaConversionUtils.JAVAEE_NAMESPACE, SCHEMA_LOCATION_URL, VERSION);
518 cursor.toStartDoc();
519 cursor.toChild(SchemaConversionUtils.JAVAEE_NAMESPACE, "taglib");
520 cursor.toFirstChild();
521 do {
522 String name = cursor.getName().getLocalPart();
523 if ("tag".equals(name)) {
524 cursor.push();
525 cursor.toFirstChild();
526 SchemaConversionUtils.convertToDescriptionGroup(SchemaConversionUtils.JAVAEE_NAMESPACE, cursor, moveable);
527 do {
528 name = cursor.getName().getLocalPart();
529 boolean rtexprvalueFound = false;
530 boolean typeFound = false;
531 if ("attribute".equals(name)) {
532 cursor.push();
533 cursor.toFirstChild();
534 do {
535 name = cursor.getName().getLocalPart();
536 if ("rtexprvalue".equals(name)) {
537 rtexprvalueFound = true;
538 }
539 if ("type".equals(name)) {
540 typeFound = true;
541 }
542 } while (cursor.toNextSibling());
543 cursor.pop();
544 if (typeFound && !rtexprvalueFound) {
545 //--------------------------------------------------------------
546 // Handle the case where the <type> tag must now be preceded by
547 // the <rtexprvalue> tag in the 2.1 schema. Cases are:
548 // 1: Only type found:
549 // We are currently positioned directly after the attribute
550 // tag (via the pop) so just insert the rtexprvalue tag
551 // with the default value. The tags will be properly
552 // ordered below.
553 // 2: Both type and rtexprvalue found:
554 // The tags will be properly ordered below with the
555 // convertToAttributeGroup() call, so nothing to do
556 // 3: Only rtexprvalue found:
557 // Nothing to do
558 // 4: Neither found:
559 // Nothing to do
560 //--------------------------------------------------------------
561 cursor.push();
562 cursor.toFirstChild();
563 cursor.insertElementWithText("rtexprvalue", SchemaConversionUtils.JAVAEE_NAMESPACE, "false");
564 cursor.pop();
565 }
566 cursor.push();
567 cursor.toFirstChild();
568 SchemaConversionUtils.convertToTldAttribute(SchemaConversionUtils.JAVAEE_NAMESPACE, cursor, moveable);
569 cursor.pop();
570 }
571 } while (cursor.toNextSibling());
572 cursor.pop();
573 // Do this conversion last after the other tags have been converted
574 SchemaConversionUtils.convertToTldTag(SchemaConversionUtils.JAVAEE_NAMESPACE, cursor, moveable);
575 }
576 } while (cursor.toNextSibling());
577 }
578 else {
579 log.debug("Converting DTD to 2.1 schema");
580 SchemaConversionUtils.convertToSchema(cursor, SchemaConversionUtils.JAVAEE_NAMESPACE, SCHEMA_LOCATION_URL, VERSION);
581 cursor.toStartDoc();
582 cursor.toChild(SchemaConversionUtils.JAVAEE_NAMESPACE, "taglib");
583 cursor.toFirstChild();
584 SchemaConversionUtils.convertToDescriptionGroup(SchemaConversionUtils.JAVAEE_NAMESPACE, cursor, moveable);
585 do {
586 String name = cursor.getName().getLocalPart();
587 if ("jsp-version".equals(name) ||
588 "jspversion".equals(name) ||
589 "info".equals(name)) {
590 cursor.removeXmlContents();
591 cursor.removeXml();
592 }
593 if ("tlibversion".equals(name)) {
594 cursor.setName(TLIB_VERSION);
595 }
596 if ("tlibversion".equals(name)) {
597 cursor.setName(TLIB_VERSION);
598 }
599 if ("shortname".equals(name)) {
600 cursor.setName(SHORT_NAME);
601 }
602 if ("tag".equals(name)) {
603 cursor.push();
604 cursor.toFirstChild();
605 SchemaConversionUtils.convertToDescriptionGroup(SchemaConversionUtils.JAVAEE_NAMESPACE, cursor, moveable);
606 boolean bodyContentFound = false;
607 do {
608 name = cursor.getName().getLocalPart();
609 if ("tagclass".equals(name)) {
610 cursor.setName(TAG_CLASS);
611 }
612 if ("teiclass".equals(name)) {
613 cursor.setName(TEI_CLASS);
614 }
615 if ("bodycontent".equals(name)) {
616 cursor.setName(BODY_CONTENT);
617 bodyContentFound = true;
618 }
619 if ("body-content".equals(name)) {
620 bodyContentFound = true;
621 }
622 if ("attribute".equals(name)) {
623 cursor.push();
624 cursor.toFirstChild();
625 SchemaConversionUtils.convertToTldAttribute(SchemaConversionUtils.JAVAEE_NAMESPACE, cursor, moveable);
626 cursor.pop();
627 }
628 if ("variable".equals(name)) {
629 cursor.push();
630 cursor.toFirstChild();
631 SchemaConversionUtils.convertToTldVariable(SchemaConversionUtils.JAVAEE_NAMESPACE, cursor, moveable);
632 cursor.pop();
633 }
634 if ("info".equals(name)) {
635 cursor.removeXmlContents();
636 cursor.removeXml();
637 }
638 } while (cursor.toNextSibling());
639 cursor.pop();
640 if (!bodyContentFound) {
641 //--------------------------------------------------------------
642 // Handle the case where the <body-content> tag is missing. We
643 // are currently positioned directly after the <tag> attribute
644 // (via the pop) so just insert the <body-content> tag with the
645 // default value. The tags will be properly ordered below.
646 //--------------------------------------------------------------
647 cursor.push();
648 cursor.toFirstChild();
649 cursor.insertElementWithText("body-content", SchemaConversionUtils.JAVAEE_NAMESPACE, "scriptless");
650 cursor.pop();
651 }
652 // Do this conversion last after the other tags have been converted
653 cursor.push();
654 cursor.toFirstChild();
655 SchemaConversionUtils.convertToTldTag(SchemaConversionUtils.JAVAEE_NAMESPACE, cursor, moveable);
656 cursor.pop();
657 }
658 if ("validator".equals(name)) {
659 cursor.push();
660 cursor.toFirstChild();
661 SchemaConversionUtils.convertToTldValidator(SchemaConversionUtils.JAVAEE_NAMESPACE, cursor, moveable);
662 cursor.pop();
663 }
664 } while (cursor.toNextSibling());
665 }
666 }
667 finally {
668 cursor.dispose();
669 moveable.dispose();
670 }
671 XmlObject result = xmlObject.changeType(TaglibDocument.type);
672 if (result != null) {
673 try {
674 XmlBeansUtil.validateDD(result);
675 } catch (XmlException e) {
676 log.warn("Invalid transformed taglib", e);
677 }
678 if (log.isDebugEnabled()) {
679 log.debug("convertToTaglibSchema( " + result.toString() + " ): Exit 1");
680 }
681 return (TaglibDocument) result;
682 }
683 try {
684 XmlBeansUtil.validateDD(xmlObject);
685 } catch (XmlException e) {
686 log.warn("Invalid transformed taglib", e);
687 }
688 if (log.isDebugEnabled()) {
689 log.debug("convertToTaglibSchema( " + xmlObject.toString() + " ): Exit 2");
690 }
691 return (TaglibDocument) xmlObject;
692 }
693
694
695 private URI createURI(String path) throws URISyntaxException {
696 path = path.replaceAll(" ", "%20");
697 return new URI(path);
698 }
699
700 public static final GBeanInfo GBEAN_INFO;
701
702 static {
703 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(JspModuleBuilderExtension.class, NameFactory.MODULE_BUILDER);
704 infoBuilder.addAttribute("defaultEnvironment", Environment.class, true, true);
705 infoBuilder.addReference("NamingBuilders", NamingBuilder.class, NameFactory.MODULE_BUILDER);
706
707 infoBuilder.setConstructor(new String[]{
708 "defaultEnvironment",
709 "NamingBuilders"});
710 GBEAN_INFO = infoBuilder.getBeanInfo();
711 }
712
713 public static GBeanInfo getGBeanInfo() {
714 return GBEAN_INFO;
715 }
716 }