/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.osgi.web.servlet.context.helper.internal.definition; import com.liferay.portal.kernel.util.ArrayUtil; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.ListUtil; import com.liferay.portal.kernel.util.StringBundler; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.osgi.web.servlet.context.helper.definition.FilterDefinition; import com.liferay.portal.osgi.web.servlet.context.helper.definition.ListenerDefinition; import com.liferay.portal.osgi.web.servlet.context.helper.definition.ServletDefinition; import com.liferay.portal.osgi.web.servlet.context.helper.definition.WebResourceCollectionDefinition; import com.liferay.portal.osgi.web.servlet.context.helper.definition.WebXMLDefinition; import com.liferay.portal.osgi.web.servlet.context.helper.internal.JspServletWrapper; import com.liferay.portal.osgi.web.servlet.context.helper.internal.order.OrderImpl; import com.liferay.portal.osgi.web.servlet.context.helper.internal.order.OrderUtil; import com.liferay.portal.osgi.web.servlet.context.helper.order.Order; import com.liferay.portal.osgi.web.servlet.context.helper.order.Order.Path; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.EnumMap; import java.util.Enumeration; import java.util.EventListener; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Stack; import javax.servlet.DispatcherType; import javax.servlet.Filter; import javax.servlet.Servlet; import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebListener; import javax.servlet.annotation.WebServlet; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.apache.felix.utils.log.Logger; import org.osgi.framework.Bundle; import org.osgi.framework.wiring.BundleWiring; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; /** * @author Raymond Augé * @author Miguel Pastor */ public class WebXMLDefinitionLoader extends DefaultHandler { public WebXMLDefinitionLoader( Bundle bundle, SAXParserFactory saxParserFactory, Logger logger) { _bundle = bundle; _saxParserFactory = saxParserFactory; _logger = logger; _webXMLDefinition = new WebXMLDefinition(); } @Override public void characters(char[] c, int start, int length) { if (_stack.empty()) { return; } StringBuilder stringBuilder = _stack.peek(); stringBuilder.append(c, start, length); } @Override public void endElement(String uri, String localName, String qName) { if (qName.equals("absolute-ordering")) { if (_othersAbsoluteOrderingSet && (_absoluteOrderingNames != null)) { _absoluteOrderingNames.add(Order.OTHERS); } List<String> absoluteOrderingNames = _webXMLDefinition.getAbsoluteOrderingNames(); absoluteOrderingNames.addAll(_absoluteOrderingNames); _absoluteOrderingNames = null; _othersAbsoluteOrderingSet = false; } else if (qName.equals("after")) { _after = false; _afterName = _name; _name = null; } else if (qName.equals("async-supported")) { boolean asyncSupported = GetterUtil.getBoolean(_stack.pop()); if (_filterDefinition != null) { _filterDefinition.setAsyncSupported(asyncSupported); } else if (_servletDefinition != null) { _servletDefinition.setAsyncSupported(asyncSupported); } } else if (qName.equals("before")) { _before = false; _beforeName = _name; _name = null; } else if (qName.equals("context-param")) { _webXMLDefinition.setContextParameter( _parameterName, _parameterValue); _parameterName = null; _parameterValue = null; } else if (qName.equals("dispatcher")) { String dispatcher = String.valueOf(_stack.pop()); dispatcher = StringUtil.toUpperCase(dispatcher); dispatcher = dispatcher.trim(); _filterMapping.dispatchers.add(dispatcher); } else if (qName.equals("filter")) { if (_filterDefinition.getFilter() != null) { _webXMLDefinition.setFilterDefinition( _filterDefinition.getName(), _filterDefinition); } _filterDefinition = null; } else if (qName.equals("filter-class")) { String filterClassName = String.valueOf(_stack.pop()); _setFilter(_filterDefinition, filterClassName.trim()); } else if (qName.equals("filter-mapping")) { Map<String, FilterDefinition> filterDefinitions = _webXMLDefinition.getFilterDefinitions(); FilterDefinition filterDefinition = filterDefinitions.get( _filterMapping.filterName); if (filterDefinition != null) { filterDefinition.setDispatchers(_filterMapping.dispatchers); if (_filterMapping.servletName != null) { List<String> servletNames = filterDefinition.getServletNames(); servletNames.add(_filterMapping.servletName); } _addURLPatterns(filterDefinition, _filterMapping.urlPatterns); } _filterMapping = null; } else if (qName.equals("filter-name")) { if (_filterMapping != null) { String filterName = String.valueOf(_stack.pop()); _filterMapping.filterName = filterName.trim(); } else if (_filterDefinition != null) { String filterName = String.valueOf(_stack.pop()); _filterDefinition.setName(filterName.trim()); } } else if (qName.equals("http-method")) { if (_webResourceCollection != null) { String httpMethod = String.valueOf(_stack.pop()); _webResourceCollection.httpMethods.add(httpMethod.trim()); } } else if (qName.equals("http-method-exception")) { if (_webResourceCollection != null) { String httpMethodException = String.valueOf(_stack.pop()); _webResourceCollection.httpMethodExceptions.add( httpMethodException.trim()); } } else if (qName.equals("init-param")) { if (_filterDefinition != null) { _filterDefinition.setInitParameter( _parameterName, _parameterValue); } else if (_servletDefinition != null) { _servletDefinition.setInitParameter( _parameterName, _parameterValue); } _parameterName = null; _parameterValue = null; } else if (qName.equals("jsp-config")) { _webXMLDefinition.setJspTaglibMappings(_jspConfig.mappings); _jspConfig = null; } else if (qName.equals("jsp-file")) { String jspFile = String.valueOf(_stack.pop()); _servletDefinition.setJSPFile(jspFile); _servletDefinition.setServlet(new JspServletWrapper(jspFile)); } else if (qName.equals("listener")) { if (_listenerDefinition.getEventListener() != null) { _webXMLDefinition.addListenerDefinition(_listenerDefinition); } _listenerDefinition = null; } else if (qName.equals("listener-class")) { String listenerClassName = String.valueOf(_stack.pop()); _setEventListener(_listenerDefinition, listenerClassName); } else if (qName.equals("name")) { String name = String.valueOf(_stack.pop()); if (_absoluteOrderingNames != null) { _absoluteOrderingNames.add(name); } else if (!_after && !_before) { _webXMLDefinition.setFragmentName(name); } else { _name = name; } } else if (qName.equals("ordering")) { if (_order == null) { return; } EnumMap<Path, String[]> routes = _order.getRoutes(); List<String> beforeNames = new ArrayList<>(2); if (_beforeName != null) { beforeNames.add(_beforeName); } if (_othersBeforeSet) { beforeNames.add(Order.OTHERS); } if (ListUtil.isNotEmpty(beforeNames)) { routes.put(Path.BEFORE, beforeNames.toArray(new String[0])); } List<String> afterNames = new ArrayList<>(2); if (_afterName != null) { afterNames.add(_afterName); } if (_othersAfterSet) { afterNames.add(Order.OTHERS); } if (ListUtil.isNotEmpty(afterNames)) { routes.put(Path.AFTER, afterNames.toArray(new String[0])); } _order.setRoutes(routes); _webXMLDefinition.setOrder(_order); _afterName = null; _beforeName = null; _order = null; _othersAfterSet = false; _othersBeforeSet = false; } else if (qName.equals("others")) { if (_absoluteOrderingNames != null) { _othersAbsoluteOrderingSet = true; } if (_after) { _othersAfterSet = true; } else if (_before) { _othersBeforeSet = true; } } else if (qName.equals("param-name")) { _parameterName = String.valueOf(_stack.pop()); _parameterName = _parameterName.trim(); } else if (qName.equals("param-value")) { _parameterValue = String.valueOf(_stack.pop()); _parameterValue = _parameterValue.trim(); } else if (qName.equals("role-name") || qName.equals("transport-guarantee")) { _logger.log( Logger.LOG_WARNING, qName + " from web.xml in bundle " + _bundle + " is not supported"); } else if (qName.equals("servlet")) { _webXMLDefinition.setServletDefinition( _servletDefinition.getName(), _servletDefinition); _servletDefinition = null; } else if (qName.equals("servlet-class")) { String servletClassName = String.valueOf(_stack.pop()); _setServlet(_servletDefinition, servletClassName.trim()); } else if (qName.equals("servlet-mapping")) { Map<String, ServletDefinition> servletDefinitions = _webXMLDefinition.getServletDefinitions(); ServletDefinition servletDefinition = servletDefinitions.get( _servletMapping.servletName); if (servletDefinition != null) { _addURLPatterns(servletDefinition, _servletMapping.urlPatterns); } _servletMapping = null; } else if (qName.equals("servlet-name")) { if (_filterMapping != null) { String servletName = String.valueOf(_stack.pop()); _filterMapping.servletName = servletName.trim(); } else if (_servletDefinition != null) { String servletName = String.valueOf(_stack.pop()); _servletDefinition.setName(servletName.trim()); } else if (_servletMapping != null) { String servletName = String.valueOf(_stack.pop()); _servletMapping.servletName = servletName.trim(); } } else if (qName.equals("taglib")) { _jspConfig.mappings.put(_taglibUri, _taglibLocation); _taglibUri = null; _taglibLocation = null; } else if (qName.equals("taglib-location")) { _taglibLocation = String.valueOf(_stack.pop()); } else if (qName.equals("taglib-uri")) { _taglibUri = String.valueOf(_stack.pop()); } else if (qName.equals("url-pattern")) { if (_filterMapping != null) { String urlPattern = String.valueOf(_stack.pop()); _filterMapping.urlPatterns.add(urlPattern.trim()); } else if (_servletMapping != null) { String urlPattern = String.valueOf(_stack.pop()); _servletMapping.urlPatterns.add(urlPattern.trim()); } else if (_webResourceCollection != null) { String urlPattern = String.valueOf(_stack.pop()); _webResourceCollection.urlPatterns.add(urlPattern.trim()); } } else if (qName.equals("web-resource-collection")) { List<WebResourceCollectionDefinition> webResourceCollectionDefinitions = _webXMLDefinition.getWebResourceCollectionDefinitions(); WebResourceCollectionDefinition webResourceCollectionDefinition = new WebResourceCollectionDefinition( _webResourceCollection.webResourceName); for (String httpMethod : _webResourceCollection.httpMethods) { webResourceCollectionDefinition.addHttpMethod(httpMethod); } for (String httpMethodException : _webResourceCollection.httpMethodExceptions) { webResourceCollectionDefinition.addHttpMethodException( httpMethodException); } for (String urlPattern : _webResourceCollection.urlPatterns) { webResourceCollectionDefinition.addURLPattern(urlPattern); } webResourceCollectionDefinitions.add( webResourceCollectionDefinition); _webResourceCollection = null; } else if (qName.equals("web-resource-name")) { String name = String.valueOf(_stack.pop()); _webResourceCollection.webResourceName = name.trim(); } } @Override public void error(SAXParseException e) { _logger.log(Logger.LOG_ERROR, _bundle + ": " + e.getMessage(), e); } public WebXMLDefinition loadWebXML() throws Exception { WebXMLDefinition webXMLDefinition = loadWebXMLDefinition( _bundle.getEntry("WEB-INF/web.xml")); if (webXMLDefinition.isMetadataComplete()) { return webXMLDefinition; } Enumeration<URL> enumeration = _bundle.getResources( "META-INF/web-fragment.xml"); List<WebXMLDefinition> webXMLDefinitions = new ArrayList<>(); if (enumeration != null) { while (enumeration.hasMoreElements()) { URL url = enumeration.nextElement(); WebXMLDefinitionLoader webXMLDefinitionLoader = new WebXMLDefinitionLoader( _bundle, _saxParserFactory, _logger); webXMLDefinitions.add( webXMLDefinitionLoader.loadWebXMLDefinition(url)); } } BundleWiring bundleWiring = _bundle.adapt(BundleWiring.class); WebXMLDefinition annotationWebXMLDefinition = new WebXMLDefinition(); Collection<String> classResources = bundleWiring.listResources( "/", "*.class", BundleWiring.LISTRESOURCES_RECURSE); if (classResources == null) { classResources = new ArrayList<>(0); } _collectAnnotatedClasses( annotationWebXMLDefinition, _bundle, classResources); webXMLDefinitions.add(annotationWebXMLDefinition); List<WebXMLDefinition> orderedWebXMLDefinitions = new ArrayList<>(); if (ListUtil.isNotEmpty(webXMLDefinitions)) { orderedWebXMLDefinitions = OrderUtil.getOrderedWebXMLDefinitions( webXMLDefinitions, webXMLDefinition.getAbsoluteOrderingNames()); } return _assembleWebXMLDefinition( webXMLDefinition, orderedWebXMLDefinitions); } public WebXMLDefinition loadWebXMLDefinition(URL url) throws Exception { if (url == null) { return _webXMLDefinition; } try (InputStream inputStream = url.openStream()) { SAXParser saxParser = _saxParserFactory.newSAXParser(); XMLReader xmlReader = saxParser.getXMLReader(); xmlReader.setContentHandler(this); xmlReader.parse(new InputSource(inputStream)); return _webXMLDefinition; } catch (SAXParseException saxpe) { String message = saxpe.getMessage(); if (message.contains("DOCTYPE is disallowed")) { throw new Exception( url + " must be updated to the Servlet 3.0 specification"); } throw saxpe; } } @Override public void startElement( String uri, String localName, String qName, Attributes attributes) { if (qName.equals("absolute-ordering")) { _absoluteOrderingNames = new ArrayList<>(); } else if (qName.equals("after")) { _after = true; } else if (qName.equals("before")) { _before = true; } else if (qName.equals("filter")) { _filterDefinition = new FilterDefinition(); } else if (qName.equals("filter-mapping")) { _filterMapping = new FilterMapping(); } else if (qName.equals("jsp-config")) { _jspConfig = new JSPConfig(); } else if (qName.equals("listener")) { _listenerDefinition = new ListenerDefinition(); } else if (qName.equals("ordering")) { _order = new OrderImpl(); } else if (qName.equals("servlet")) { _servletDefinition = new ServletDefinition(); } else if (qName.equals("servlet-mapping")) { _servletMapping = new ServletMapping(); } else if (qName.equals("web-app")) { boolean metadataComplete = GetterUtil.getBoolean( attributes.getValue("metadata-complete")); _webXMLDefinition.setMetadataComplete(metadataComplete); } else if (qName.equals("web-resource-collection")) { _webResourceCollection = new WebResourceCollection(); } else if (Arrays.binarySearch(_LEAVES, qName) > -1) { _stack.push(new StringBuilder()); } } private void _addURLPatterns( FilterDefinition filterDefinition, List<String> value) { if (!ListUtil.isEmpty(value)) { _addURLPatterns( filterDefinition, value.toArray(new String[0]), null); } } private void _addURLPatterns( FilterDefinition filterDefinition, String[] value, String[] urlPatterns) { if (!ArrayUtil.isEmpty(value)) { for (String urlPattern : value) { filterDefinition.addURLPattern(urlPattern); } } if (!ArrayUtil.isEmpty(urlPatterns)) { if (ListUtil.isNotEmpty(filterDefinition.getURLPatterns())) { throw new IllegalStateException( "Both value and URL patterns are declared"); } for (String urlPattern : urlPatterns) { filterDefinition.addURLPattern(urlPattern); } } } private void _addURLPatterns( ServletDefinition servletDefinition, List<String> value) { if (!ListUtil.isEmpty(value)) { _addURLPatterns( servletDefinition, value.toArray(new String[0]), null); } } private void _addURLPatterns( ServletDefinition servletDefinition, String[] value, String[] urlPatterns) { if (!ArrayUtil.isEmpty(value)) { for (String urlPattern : value) { servletDefinition.addURLPattern(urlPattern); } } if (!ArrayUtil.isEmpty(urlPatterns)) { if (ListUtil.isNotEmpty(servletDefinition.getURLPatterns())) { throw new IllegalStateException( "Both value and URL patterns are declared"); } for (String urlPattern : urlPatterns) { servletDefinition.addURLPattern(urlPattern); } } } private void _assembleContextParameters( Map<String, String> assembledContextParameters, Map<String, String> fragmentContextParameters) { for (Entry<String, String> entry : fragmentContextParameters.entrySet()) { String name = entry.getKey(); if (!assembledContextParameters.containsKey(name)) { assembledContextParameters.put(name, entry.getValue()); } } } private void _assembleFilterDefinitions( Map<String, FilterDefinition> webXMLFilterDefinitions, Map<String, FilterDefinition> assembledFilterDefinitions, Map<String, FilterDefinition> fragmentFilterDefinitions) throws Exception { for (Entry<String, FilterDefinition> entry : fragmentFilterDefinitions.entrySet()) { String filterName = entry.getKey(); if (!assembledFilterDefinitions.containsKey(filterName)) { assembledFilterDefinitions.put(filterName, entry.getValue()); continue; } FilterDefinition webXMLFilterDefinition = webXMLFilterDefinitions.get(filterName); Map<String, String> webXMLInitParameters = null; if (webXMLFilterDefinition != null) { webXMLInitParameters = webXMLFilterDefinition.getInitParameters(); } FilterDefinition assembledFilterDefinition = assembledFilterDefinitions.get(filterName); Map<String, String> assembledInitParameters = assembledFilterDefinition.getInitParameters(); FilterDefinition fragmentFilterDefinition = entry.getValue(); Map<String, String> fragmentInitParameters = fragmentFilterDefinition.getInitParameters(); for (Entry<String, String> initParametersEntry : fragmentInitParameters.entrySet()) { String initParameterName = initParametersEntry.getKey(); String webXMLInitParameterValue = null; if (webXMLInitParameters != null) { webXMLInitParameterValue = webXMLInitParameters.get( initParameterName); } String assembledInitParameterValue = assembledInitParameters.get(initParameterName); if (Validator.isNull(assembledInitParameterValue)) { if ((webXMLInitParameterValue == null) && !Objects.equals( assembledInitParameterValue, initParametersEntry.getValue())) { // Servlet 3 spec 8.2.3 throw new Exception( "Init paramter name " + initParameterName + " conflicts with filter name " + filterName); } else { assembledInitParameters.put( initParameterName, initParametersEntry.getValue()); } } } List<String> assembledDispatchers = assembledFilterDefinition.getDispatchers(); List<String> fragmentDispatchers = fragmentFilterDefinition.getDispatchers(); for (String dispatcher : fragmentDispatchers) { if (!assembledDispatchers.contains(dispatcher)) { assembledDispatchers.add(dispatcher); } } List<String> assembledServletNames = assembledFilterDefinition.getServletNames(); List<String> fragmentServletNames = fragmentFilterDefinition.getServletNames(); for (String servletName : fragmentServletNames) { if (!assembledServletNames.contains(servletName)) { assembledServletNames.add(servletName); } } List<String> assembledURLPatterns = assembledFilterDefinition.getURLPatterns(); List<String> fragmentURLPatterns = fragmentFilterDefinition.getURLPatterns(); for (String urlPattern : fragmentURLPatterns) { if (!assembledURLPatterns.contains(urlPattern)) { assembledURLPatterns.add(urlPattern); } } } } private void _assembleListenerDefinitions( List<ListenerDefinition> assembledListenerDefinitions, List<ListenerDefinition> fragmentListenerDefinitions) { for (ListenerDefinition fragmentListenerDefinition : fragmentListenerDefinitions) { if (!assembledListenerDefinitions.contains( fragmentListenerDefinition)) { assembledListenerDefinitions.add(fragmentListenerDefinition); } } } private void _assembleServletDefinitions( Map<String, ServletDefinition> webXMLServletDefinitions, Map<String, ServletDefinition> assembledServletDefinitions, Map<String, ServletDefinition> fragmentServletDefinitions) throws Exception { for (Entry<String, ServletDefinition> entry : fragmentServletDefinitions.entrySet()) { String servletName = entry.getKey(); if (!assembledServletDefinitions.containsKey(servletName)) { assembledServletDefinitions.put(servletName, entry.getValue()); continue; } ServletDefinition webXMLServletDefinition = webXMLServletDefinitions.get(servletName); Map<String, String> webXMLServletInitParameters = null; if (webXMLServletDefinition != null) { webXMLServletInitParameters = webXMLServletDefinition.getInitParameters(); } ServletDefinition assembledServletDefinition = assembledServletDefinitions.get(servletName); Map<String, String> assembledInitInitParameters = assembledServletDefinition.getInitParameters(); ServletDefinition fragmentServletDefinition = entry.getValue(); Map<String, String> fragmentServletInitParameters = fragmentServletDefinition.getInitParameters(); for (Entry<String, String> initParameterEntry : fragmentServletInitParameters.entrySet()) { String initParameterName = initParameterEntry.getKey(); String webXMLInitParameterValue = null; if (webXMLServletInitParameters != null) { webXMLInitParameterValue = webXMLServletInitParameters.get( initParameterName); } String assembledInitParameterValue = assembledInitInitParameters.get(initParameterName); if (Validator.isNull(assembledInitParameterValue)) { if ((webXMLInitParameterValue == null) && !Objects.equals( assembledInitParameterValue, initParameterEntry.getValue())) { // Servlet 3 spec 8.2.3 throw new Exception( "Init paramter name " + initParameterName + " conflicts with servlet name " + servletName); } else { assembledInitInitParameters.put( initParameterName, initParameterEntry.getValue()); } } } List<String> assembledURLPatterns = assembledServletDefinition.getURLPatterns(); List<String> fragmentURLPatterns = fragmentServletDefinition.getURLPatterns(); for (String urlPattern : fragmentURLPatterns) { if (!assembledURLPatterns.contains(urlPattern)) { assembledURLPatterns.add(urlPattern); } } if (Validator.isNull(assembledServletDefinition.getJspFile())) { assembledServletDefinition.setJSPFile( fragmentServletDefinition.getJspFile()); } } } private WebXMLDefinition _assembleWebXMLDefinition( WebXMLDefinition webXMLWebXMLDefinition, List<WebXMLDefinition> fragmentWebXMLDefinitions) throws Exception { Map<String, FilterDefinition> webXMLFilterDefinitions = webXMLWebXMLDefinition.getFilterDefinitions(); Map<String, ServletDefinition> webXMLServletDefinitions = webXMLWebXMLDefinition.getServletDefinitions(); WebXMLDefinition assembledWebXMLDefinition = (WebXMLDefinition)webXMLWebXMLDefinition.clone(); Map<String, String> assembledContextParameters = assembledWebXMLDefinition.getContextParameters(); Map<String, FilterDefinition> assembledFilterDefinitions = assembledWebXMLDefinition.getFilterDefinitions(); List<ListenerDefinition> assembledListenerDefinitions = assembledWebXMLDefinition.getListenerDefinitions(); Map<String, ServletDefinition> assembledServletDefinitions = assembledWebXMLDefinition.getServletDefinitions(); for (WebXMLDefinition fragmentWebXMLDefinition : fragmentWebXMLDefinitions) { Map<String, String> fragmentContextParameters = fragmentWebXMLDefinition.getContextParameters(); _assembleContextParameters( assembledContextParameters, fragmentContextParameters); Map<String, FilterDefinition> fragmentFilterDefinitions = fragmentWebXMLDefinition.getFilterDefinitions(); _assembleFilterDefinitions( webXMLFilterDefinitions, assembledFilterDefinitions, fragmentFilterDefinitions); List<ListenerDefinition> fragmentListenerDefinitions = fragmentWebXMLDefinition.getListenerDefinitions(); _assembleListenerDefinitions( assembledListenerDefinitions, fragmentListenerDefinitions); Map<String, ServletDefinition> fragmentServletDefinitions = fragmentWebXMLDefinition.getServletDefinitions(); _assembleServletDefinitions( webXMLServletDefinitions, assembledServletDefinitions, fragmentServletDefinitions); } return assembledWebXMLDefinition; } private void _collectAnnotatedClasses( WebXMLDefinition webXMLDefinition, Bundle bundle, Collection<String> classResources) throws Exception { for (String classResource : classResources) { _collectAnnotatedClasses(webXMLDefinition, bundle, classResource); } } private void _collectAnnotatedClasses( WebXMLDefinition webXMLDefinition, Bundle bundle, String classResource) throws Exception { URL url = _bundle.getResource(classResource); if (url == null) { return; } String className = classResource.replaceAll("\\.class$", ""); className = className.replaceAll("/", "."); Class<?> clazz = null; try { clazz = bundle.loadClass(className); } catch (Throwable t) { _logger.log(Logger.LOG_DEBUG, t.getMessage()); return; } WebServlet webServlet = null; try { webServlet = clazz.getAnnotation(WebServlet.class); } catch (Exception e) { // See http://bugs.java.com/view_bug.do?bug_id=7183985 and LPS-69679 StringBundler sb = new StringBundler(6); sb.append("Unexpected error retrieving the annotation "); sb.append(WebServlet.class); sb.append("from class "); sb.append(clazz); sb.append(" because a some dependency may not be present in the "); sb.append("classpath"); _logger.log(Logger.LOG_DEBUG, sb.toString(), e); return; } if (webServlet != null) { ServletDefinition servletDefinition = new ServletDefinition(); servletDefinition.setAsyncSupported(webServlet.asyncSupported()); _setInitParameters( webServlet.initParams(), servletDefinition.getInitParameters()); String name = webServlet.name(); if (Validator.isNotNull(name)) { servletDefinition.setName(name); } else { servletDefinition.setName(clazz.getCanonicalName()); } _addURLPatterns( servletDefinition, webServlet.value(), webServlet.urlPatterns()); _setServlet(servletDefinition, clazz.getCanonicalName()); webXMLDefinition.setServletDefinition( servletDefinition.getName(), servletDefinition); } WebFilter webFilter = clazz.getAnnotation(WebFilter.class); if (webFilter != null) { FilterDefinition filterDefinition = new FilterDefinition(); filterDefinition.setAsyncSupported(webFilter.asyncSupported()); DispatcherType[] dispatcherTypes = webFilter.dispatcherTypes(); if (!ArrayUtil.isEmpty(dispatcherTypes)) { for (DispatcherType dispatcherType : dispatcherTypes) { filterDefinition.addDispatcher(dispatcherType.name()); } } _setFilter(filterDefinition, clazz.getCanonicalName()); _setInitParameters( webFilter.initParams(), filterDefinition.getInitParameters()); String filterName = webFilter.filterName(); if (Validator.isNotNull(filterName)) { filterDefinition.setName(filterName); } else { filterDefinition.setName(clazz.getCanonicalName()); } String[] servletNames = webFilter.servletNames(); if (!ArrayUtil.isEmpty(servletNames)) { for (String servletName : servletNames) { filterDefinition.addServletName(servletName); } } _addURLPatterns( filterDefinition, webFilter.value(), webFilter.urlPatterns()); webXMLDefinition.setFilterDefinition( filterDefinition.getName(), filterDefinition); } WebListener webListener = clazz.getAnnotation(WebListener.class); if (webListener != null) { ListenerDefinition listenerDefinition = new ListenerDefinition(); _setEventListener(listenerDefinition, clazz.getCanonicalName()); webXMLDefinition.addListenerDefinition(listenerDefinition); } } private Filter _getFilterInstance(String filterClassName) { try { Class<?> clazz = _bundle.loadClass(filterClassName); Class<? extends Filter> filterClass = clazz.asSubclass( Filter.class); return filterClass.newInstance(); } catch (Exception e) { _logger.log( Logger.LOG_ERROR, "Bundle " + _bundle + " is unable to load filter " + filterClassName); return null; } } private EventListener _getListenerInstance(String listenerClassName) { try { Class<?> clazz = _bundle.loadClass(listenerClassName); Class<? extends EventListener> eventListenerClass = clazz.asSubclass(EventListener.class); return eventListenerClass.newInstance(); } catch (Exception e) { _logger.log( Logger.LOG_ERROR, "Bundle " + _bundle + " is unable to load listener " + listenerClassName); return null; } } private Servlet _getServletInstance(String servletClassName) { try { Class<?> clazz = _bundle.loadClass(servletClassName); Class<? extends Servlet> servletClass = clazz.asSubclass( Servlet.class); return servletClass.newInstance(); } catch (Exception e) { _logger.log( Logger.LOG_ERROR, _bundle + " unable to load servlet " + servletClassName, e); return null; } } private void _setEventListener( ListenerDefinition listenerDefinition, String listenerClassName) { listenerDefinition.setEventListener( _getListenerInstance(listenerClassName)); } private void _setFilter( FilterDefinition filterDefinition, String filterClassName) { filterDefinition.setFilter(_getFilterInstance(filterClassName)); } private void _setInitParameters( WebInitParam[] webInitParams, Map<String, String> initParametersMap) { if (!ArrayUtil.isEmpty(webInitParams)) { for (WebInitParam webInitParam : webInitParams) { initParametersMap.put( webInitParam.name(), webInitParam.value()); } } } private void _setServlet( ServletDefinition servletDefinition, String servletClassName) { servletDefinition.setServlet(_getServletInstance(servletClassName)); } private static final String[] _LEAVES = new String[] { "async-supported", "dispatcher", "error-code", "exception-type", "filter-class", "filter-name", "http-method", "http-method-exception", "jsp-file", "listener-class", "location", "name", "param-name", "param-value", "servlet-class", "servlet-name", "taglib-location", "taglib-uri", "url-pattern", "web-resource-name" }; private List<String> _absoluteOrderingNames; private boolean _after; private String _afterName; private boolean _before; private String _beforeName; private final Bundle _bundle; private FilterDefinition _filterDefinition; private FilterMapping _filterMapping; private JSPConfig _jspConfig; private ListenerDefinition _listenerDefinition; private final Logger _logger; private String _name; private Order _order; private boolean _othersAbsoluteOrderingSet; private boolean _othersAfterSet; private boolean _othersBeforeSet; private String _parameterName; private String _parameterValue; private final SAXParserFactory _saxParserFactory; private ServletDefinition _servletDefinition; private ServletMapping _servletMapping; private final Stack<StringBuilder> _stack = new Stack<>(); private String _taglibLocation; private String _taglibUri; private WebResourceCollection _webResourceCollection; private final WebXMLDefinition _webXMLDefinition; private static class FilterMapping { protected List<String> dispatchers = new ArrayList<>(); protected String filterName; protected String servletName; protected List<String> urlPatterns = new ArrayList<>(); } private static class JSPConfig { protected Map<String, String> mappings = new HashMap<>(); } private static class ServletMapping { protected String servletName; protected List<String> urlPatterns = new ArrayList<>(); } private static class WebResourceCollection { protected List<String> httpMethodExceptions = new ArrayList<>(); protected List<String> httpMethods = new ArrayList<>(); protected List<String> urlPatterns = new ArrayList<>(); protected String webResourceName; } }