private void deploy(WebApp webApp) { Bundle bundle = webApp.getBundle(); String contextName = webApp.getContextName(); eventDispatcher.webEvent( new WebEvent(WebEvent.DEPLOYING, "/" + contextName, bundle, bundleContext.getBundle())); if (!contexts.containsKey(contextName)) { LinkedList<WebApp> queue = new LinkedList<WebApp>(); contexts.put(contextName, queue); queue.add(webApp); // let the publisher set the deployment state and send web event m_publisher.publish(webApp, eventDispatcher, bundleContext); } else { LinkedList<WebApp> queue = contexts.get(contextName); queue.add(webApp); Collection<Long> duplicateIds = new LinkedList<Long>(); for (WebApp duplicateWebApp : queue) { duplicateIds.add(duplicateWebApp.getBundle().getBundleId()); } webApp.setDeploymentState(WebApp.WAITING_STATE); eventDispatcher.webEvent( new WebEvent( WebEvent.WAITING, "/" + contextName, bundle, bundleContext.getBundle(), duplicateIds)); } }
public int stop(long bundleId) { WebApp webApp = webApps.get(bundleId); if (webApp == null) { return WAR_NOT_FOUND; } if (webApp.getDeploymentState() == WebApp.UNDEPLOYED_STATE) { return ALREADY_STOPPED; } undeploy(webApp); return SUCCESS; }
/** * Parses servlets and servlet mappings out of web.xml. * * @param rootElement web.xml root element * @param webApp web app for web.xml */ private static void parseServlets(final Element rootElement, final WebApp webApp) { final Element[] elements = getChildren(rootElement, "servlet"); if (elements != null && elements.length > 0) { for (Element element : elements) { final WebAppServlet servlet = new WebAppServlet(); servlet.setServletName(getTextContent(getChild(element, "servlet-name"))); String servletClass = getTextContent(getChild(element, "servlet-class")); if (servletClass != null) { servlet.setServletClass(servletClass); webApp.addServlet(servlet); } else { String jspFile = getTextContent(getChild(element, "jsp-file")); if (jspFile != null) { WebAppJspServlet jspServlet = new WebAppJspServlet(); jspServlet.setServletName(getTextContent(getChild(element, "servlet-name"))); jspServlet.setJspPath(jspFile); webApp.addServlet(jspServlet); } } servlet.setLoadOnStartup(getTextContent(getChild(element, "load-on-startup"))); servlet.setAsyncSupported(getTextContent(getChild(element, "async-supported"))); final Element[] initParamElements = getChildren(element, "init-param"); if (initParamElements != null && initParamElements.length > 0) { for (Element initParamElement : initParamElements) { final WebAppInitParam initParam = new WebAppInitParam(); initParam.setParamName(getTextContent(getChild(initParamElement, "param-name"))); initParam.setParamValue(getTextContent(getChild(initParamElement, "param-value"))); servlet.addInitParam(initParam); } } } } final Element[] mappingElements = getChildren(rootElement, "servlet-mapping"); if (mappingElements != null && mappingElements.length > 0) { for (Element mappingElement : mappingElements) { // starting with servlet 2.5 url-patern can be specified more // times // for the earlier version only one entry will be returned final String servletName = getTextContent(getChild(mappingElement, "servlet-name")); final Element[] urlPatternsElements = getChildren(mappingElement, "url-pattern"); if (urlPatternsElements != null && urlPatternsElements.length > 0) { for (Element urlPatternElement : urlPatternsElements) { final WebAppServletMapping servletMapping = new WebAppServletMapping(); servletMapping.setServletName(servletName); servletMapping.setUrlPattern(getTextContent(urlPatternElement)); webApp.addServletMapping(servletMapping); } } } } }
public int start(long bundleId, String contextName) { WebApp webApp = webApps.get(bundleId); if (webApp == null) { return WAR_NOT_FOUND; } if (webApp.getDeploymentState() != WebApp.UNDEPLOYED_STATE) { return ALREADY_STARTED; } if (contextName != null) { webApp.setContextName(contextName); } deploy(webApp); return SUCCESS; }
private void undeploy(WebApp webApp) { String contextName = webApp.getContextName(); LinkedList<WebApp> queue = contexts.get(contextName); if (queue != null) { // Are we the published web app?? if (queue.get(0) == webApp) { webApp.setDeploymentState(WebApp.UNDEPLOYED_STATE); eventDispatcher.webEvent( new WebEvent( WebEvent.UNDEPLOYING, "/" + contextName, webApp.getBundle(), bundleContext.getBundle())); m_publisher.unpublish(webApp); eventDispatcher.webEvent( new WebEvent( WebEvent.UNDEPLOYED, "/" + contextName, webApp.getBundle(), bundleContext.getBundle())); queue.removeFirst(); // Below checks if another webapp is waiting for the context, if so the webapp is published. LOG.debug("Check for a waiting webapp."); if (!queue.isEmpty()) { LOG.debug("Found another bundle waiting for the context"); WebApp next = queue.getFirst(); eventDispatcher.webEvent( new WebEvent( WebEvent.DEPLOYING, "/" + contextName, next.getBundle(), bundleContext.getBundle())); // let the publisher set the deployment state and send web event m_publisher.publish(next, eventDispatcher, bundleContext); } else { contexts.remove(contextName); } } else if (queue.remove(webApp)) { webApp.setDeploymentState(WebApp.UNDEPLOYED_STATE); eventDispatcher.webEvent( new WebEvent( WebEvent.UNDEPLOYED, "/" + contextName, webApp.getBundle(), bundleContext.getBundle())); } else { LOG.debug("Web application was not in the deployment queue"); } } else { LOG.debug(String.format("No web application published under context: %s", contextName)); } }
/** * Parses filters and filter mappings out of web.xml. * * @param rootElement web.xml root element * @param webApp web app for web.xml */ private static void parseFilters(final Element rootElement, final WebApp webApp) { final Element[] elements = getChildren(rootElement, "filter"); if (elements != null && elements.length > 0) { for (Element element : elements) { final WebAppFilter filter = new WebAppFilter(); filter.setFilterName(getTextContent(getChild(element, "filter-name"))); filter.setFilterClass(getTextContent(getChild(element, "filter-class"))); webApp.addFilter(filter); final Element[] initParamElements = getChildren(element, "init-param"); if (initParamElements != null && initParamElements.length > 0) { for (Element initParamElement : initParamElements) { final WebAppInitParam initParam = new WebAppInitParam(); initParam.setParamName(getTextContent(getChild(initParamElement, "param-name"))); initParam.setParamValue(getTextContent(getChild(initParamElement, "param-value"))); filter.addInitParam(initParam); } } } } final Element[] mappingElements = getChildren(rootElement, "filter-mapping"); if (mappingElements != null && mappingElements.length > 0) { for (Element mappingElement : mappingElements) { // starting with servlet 2.5 url-patern / servlet-names can be // specified more times // for the earlier version only one entry will be returned final String filterName = getTextContent(getChild(mappingElement, "filter-name")); final Element[] urlPatternsElements = getChildren(mappingElement, "url-pattern"); if (urlPatternsElements != null && urlPatternsElements.length > 0) { for (Element urlPatternElement : urlPatternsElements) { final WebAppFilterMapping filterMapping = new WebAppFilterMapping(); filterMapping.setFilterName(filterName); filterMapping.setUrlPattern(getTextContent(urlPatternElement)); webApp.addFilterMapping(filterMapping); } } final Element[] servletNamesElements = getChildren(mappingElement, "servlet-name"); if (servletNamesElements != null && servletNamesElements.length > 0) { for (Element servletNameElement : servletNamesElements) { final WebAppFilterMapping filterMapping = new WebAppFilterMapping(); filterMapping.setFilterName(filterName); filterMapping.setServletName(getTextContent(servletNameElement)); webApp.addFilterMapping(filterMapping); } } } } }
/** * Parses mime mappings out of web.xml. * * @param rootElement web.xml root element * @param webApp web app for web.xml */ private static void parseMimeMappings(final Element rootElement, final WebApp webApp) { final Element[] elements = getChildren(rootElement, "mime-mapping"); if (elements != null && elements.length > 0) { for (Element element : elements) { final WebAppMimeMapping mimeMapping = new WebAppMimeMapping(); mimeMapping.setExtension(getTextContent(getChild(element, "extension"))); mimeMapping.setMimeType(getTextContent(getChild(element, "mime-type"))); webApp.addMimeMapping(mimeMapping); } } }
/** * Parses welcome files out of web.xml. * * @param rootElement web.xml root element * @param webApp web app for web.xml */ private static void parseWelcomeFiles(final Element rootElement, final WebApp webApp) { final Element listElement = getChild(rootElement, "welcome-file-list"); if (listElement != null) { final Element[] elements = getChildren(listElement, "welcome-file"); if (elements != null && elements.length > 0) { for (Element element : elements) { webApp.addWelcomeFile(getTextContent(element)); } } } }
/** * Parses session config out of web.xml. * * @param rootElement web.xml root element * @param webApp web app for web.xml */ private static void parseSessionConfig(final Element rootElement, final WebApp webApp) { final Element scElement = getChild(rootElement, "session-config"); if (scElement != null) { final Element stElement = getChild(scElement, "session-timeout"); // Fix // for // PAXWEB-201 if (stElement != null) { webApp.setSessionTimeout(getTextContent(stElement)); } } }
/** * Parses context params out of web.xml. * * @param rootElement web.xml root element * @param webApp web app for web.xml */ private static void parseContextParams(final Element rootElement, final WebApp webApp) { final Element[] elements = getChildren(rootElement, "context-param"); if (elements != null && elements.length > 0) { for (Element element : elements) { final WebAppInitParam initParam = new WebAppInitParam(); initParam.setParamName(getTextContent(getChild(element, "param-name"))); initParam.setParamValue(getTextContent(getChild(element, "param-value"))); webApp.addContextParam(initParam); } } }
/** * Parses error pages out of web.xml. * * @param rootElement web.xml root element * @param webApp web app for web.xml */ private static void parseErrorPages(final Element rootElement, final WebApp webApp) { final Element[] elements = getChildren(rootElement, "error-page"); if (elements != null && elements.length > 0) { for (Element element : elements) { final WebAppErrorPage errorPage = new WebAppErrorPage(); errorPage.setErrorCode(getTextContent(getChild(element, "error-code"))); errorPage.setExceptionType(getTextContent(getChild(element, "exception-type"))); errorPage.setLocation(getTextContent(getChild(element, "location"))); webApp.addErrorPage(errorPage); } } }
/** * Unregisters registered web app once that the bundle that contains the web.xml gets stopped. The * list of web.xml's is expected to contain only one entry (only first will be used). * * @throws NullArgumentException if bundle or list of web xmls is null * @throws PreConditionException if the list of web xmls is empty or more then one xml * @see BundleObserver#removingEntries(Bundle,List) */ public void removingEntries(final Bundle bundle, final List<URL> entries) { WebApp webApp = webApps.remove(bundle.getBundleId()); if (webApp != null && webApp.getDeploymentState() != WebApp.UNDEPLOYED_STATE) { undeploy(webApp); } }
/** * Parse the web.xml and publish the corresponding web app. The received list is expected to * contain one URL of an web.xml (only first is used. The web.xml will be parsed and resulting web * application structure will be registered with the http service. * * @throws NullArgumentException if bundle or list of web xmls is null * @throws PreConditionException if the list of web xmls is empty or more then one xml * @see BundleObserver#addingEntries(Bundle,List) */ public void addingEntries(final Bundle bundle, final List<URL> entries) { NullArgumentException.validateNotNull(bundle, "Bundle"); NullArgumentException.validateNotNull(entries, "List of *.xml's"); // Context name is also needed for some of the pre-condition checks, therefore it is retrieved // here. String contextName = extractContextName(bundle); LOG.info(String.format("Using [%s] as web application context name", contextName)); List<String> virtualHostList = extractVirtualHostList(bundle); LOG.info(String.format("[%d] virtual hosts defined in bundle header", virtualHostList.size())); List<String> connectorList = extractConnectorList(bundle); LOG.info(String.format("[%d] connectors defined in bundle header", connectorList.size())); // try-catch only to inform framework and listeners of an event. try { // PreConditionException.validateLesserThan( entries.size(), 3, "Number of xml's" ); PreConditionException.validateEqualTo( "WEB-INF".compareToIgnoreCase(Path.getDirectParent(entries.get(0))), 0, "Direct parent of web.xml"); } catch (PreConditionException pce) { LOG.error(pce.getMessage(), pce); eventDispatcher.webEvent( new WebEvent(WebEvent.FAILED, "/" + contextName, bundle, bundleContext.getBundle(), pce)); throw pce; } if (webApps.containsKey(bundle.getBundleId())) { LOG.debug( String.format("Already found a web application in bundle %d", bundle.getBundleId())); return; } URL webXmlURL = null; // = entries.get( 0 ); URL jettyWebXmlURL = null; for (URL url : entries) { if (isJettyWebXml(url)) { // it's the jetty-web.xml jettyWebXmlURL = url; } else if (isWebXml(url)) { // it's the web.xml webXmlURL = url; } else { // just another one } } if (webXmlURL == null) { PreConditionException pce = new PreConditionException("no web.xml configured in web-application"); LOG.error(pce.getMessage(), pce); eventDispatcher.webEvent( new WebEvent(WebEvent.FAILED, "/" + contextName, bundle, bundleContext.getBundle(), pce)); throw pce; } LOG.debug("Parsing a web application from [" + webXmlURL + "]"); String rootPath = extractRootPath(bundle); LOG.info(String.format("Using [%s] as web application root path", rootPath)); InputStream is = null; try { is = webXmlURL.openStream(); final WebApp webApp = m_parser.parse(bundle, is); if (webApp != null) { LOG.debug("Parsed web app [" + webApp + "]"); webApp.setWebXmlURL(webXmlURL); webApp.setJettyWebXmlURL(jettyWebXmlURL); webApp.setVirtualHostList(virtualHostList); webApp.setConnectorList(connectorList); webApp.setBundle(bundle); webApp.setContextName(contextName); webApp.setRootPath(rootPath); webApp.setDeploymentState(WebApp.UNDEPLOYED_STATE); webApps.put(bundle.getBundleId(), webApp); // The Webapp-Deploy header controls if the app is deployed on // startup. if ("true".equals(opt(getHeader(bundle, "Webapp-Deploy"), "true"))) { deploy(webApp); } else { eventDispatcher.webEvent( new WebEvent( WebEvent.UNDEPLOYED, "/" + webApp.getContextName(), webApp.getBundle(), bundleContext.getBundle())); } } } catch (Exception ignore) { LOG.error("Could not parse web.xml", ignore); eventDispatcher.webEvent( new WebEvent( WebEvent.FAILED, "/" + contextName, bundle, bundleContext.getBundle(), ignore)); } finally { if (is != null) { try { is.close(); } catch (IOException ignore) { // just ignore } } } }
/** @see WebXmlParser#parse(InputStream) */ public WebApp parse(final Bundle bundle, final InputStream inputStream) { final WebApp webApp = new WebApp(); // changed to final because of inner // class. try { final Element rootElement = getRootElement(inputStream); if (rootElement != null) { // webApp = new WebApp(); // web-app attributes String version = getAttribute(rootElement, "version"); Integer majorVersion = null; if (version != null && !version.isEmpty() && version.length() > 2) { LOG.debug("version found in web.xml - " + version); try { majorVersion = Integer.parseInt(version.split("\\.")[0]); } catch (NumberFormatException nfe) { // munch do nothing here stay with null therefore // annotation scanning is disabled. } } else if (version != null && !version.isEmpty() && version.length() > 0) { try { majorVersion = Integer.parseInt(version); } catch (NumberFormatException e) { // munch do nothing here stay with null.... } } Boolean metaDataComplete = Boolean.parseBoolean(getAttribute(rootElement, "metadata-complete", "false")); webApp.setMetaDataComplete(metaDataComplete); LOG.debug("metadata-complete is: " + metaDataComplete); // web-app elements webApp.setDisplayName(getTextContent(getChild(rootElement, "display-name"))); parseContextParams(rootElement, webApp); parseSessionConfig(rootElement, webApp); parseServlets(rootElement, webApp); parseFilters(rootElement, webApp); parseListeners(rootElement, webApp); parseErrorPages(rootElement, webApp); parseWelcomeFiles(rootElement, webApp); parseMimeMappings(rootElement, webApp); parseSecurity(rootElement, webApp); LOG.debug("scanninf for ServletContainerInitializers"); ServiceLoader<ServletContainerInitializer> serviceLoader = ServiceLoader.load( ServletContainerInitializer.class, bundle.getClass().getClassLoader()); if (serviceLoader != null) { LOG.debug("ServletContainerInitializers found"); while (serviceLoader.iterator().hasNext()) { // for (ServletContainerInitializer service : // serviceLoader) { ServletContainerInitializer service = null; try { bundle.loadClass(ServletContainerInitializer.class.getName()); Object obj = serviceLoader.iterator().next(); if (obj instanceof ServletContainerInitializer) service = (ServletContainerInitializer) obj; else continue; } catch (ServiceConfigurationError e) { LOG.error("ServiceConfigurationError loading ServletContainerInitializer", e); continue; } catch (ClassNotFoundException e) { LOG.error("ServiceConfigurationError loading ServletContainerInitializer", e); continue; } WebAppServletContainerInitializer webAppServletContainerInitializer = new WebAppServletContainerInitializer(); webAppServletContainerInitializer.setServletContainerInitializer(service); if (!webApp.getMetaDataComplete() && majorVersion != null && majorVersion >= 3) { HandlesTypes annotation = service.getClass().getAnnotation(HandlesTypes.class); Class[] classes; if (annotation != null) { // add annotated classes to service classes = annotation.value(); webAppServletContainerInitializer.setClasses(classes); } } webApp.addServletContainerInitializer(webAppServletContainerInitializer); } } if (!webApp.getMetaDataComplete() && majorVersion != null && majorVersion >= 3) { LOG.debug("metadata-complete is either false or not set"); LOG.debug("scanning for annotated classes"); Enumeration<?> clazzes = bundle.findEntries("/", "*.class", true); for (; clazzes.hasMoreElements(); ) { URL clazzUrl = (URL) clazzes.nextElement(); Class<?> clazz; String clazzFile = clazzUrl.getFile(); LOG.debug("Class file found at :" + clazzFile); if (clazzFile.startsWith("/WEB-INF/classes")) clazzFile = clazzFile.replaceFirst("/WEB-INF/classes", ""); else if (clazzFile.startsWith("/WEB-INF/lib")) clazzFile = clazzFile.replaceFirst("/WEB-INF/lib", ""); String clazzName = clazzFile.replaceAll("/", ".").replaceAll(".class", "").replaceFirst(".", ""); try { clazz = bundle.loadClass(clazzName); } catch (ClassNotFoundException e) { LOG.debug("Class {} not found", clazzName); continue; } if (clazz.isAnnotationPresent(WebServlet.class)) { LOG.debug("found WebServlet annotation on class: " + clazz); WebServletAnnotationScanner annonScanner = new WebServletAnnotationScanner(bundle, clazz.getCanonicalName()); annonScanner.scan(webApp); } else if (clazz.isAnnotationPresent(WebFilter.class)) { LOG.debug("found WebFilter annotation on class: " + clazz); WebFilterAnnotationScanner filterScanner = new WebFilterAnnotationScanner(bundle, clazz.getCanonicalName()); filterScanner.scan(webApp); } else if (clazz.isAnnotationPresent(WebListener.class)) { LOG.debug("found WebListener annotation on class: " + clazz); addWebListener(webApp, clazz.getSimpleName()); } } LOG.debug("class scanning done"); } // special handling for finding JSF Context listeners wrapped in // *.tld files Enumeration tldEntries = bundle.getResources("*.tld"); // Enumeration tldEntries = bundle.findEntries("/", "*.tld", // true); while (tldEntries != null && tldEntries.hasMoreElements()) { URL url = (URL) tldEntries.nextElement(); Element rootTld = getRootElement(url.openStream()); if (rootTld != null) { parseListeners(rootTld, webApp); } } } else { LOG.warn("The parsed web.xml does not have a root element"); return null; } } catch (ParserConfigurationException ignore) { LOG.error("Cannot parse web.xml", ignore); } catch (IOException ignore) { LOG.error("Cannot parse web.xml", ignore); } catch (SAXException ignore) { LOG.error("Cannot parse web.xml", ignore); } return webApp; }
/** * @param webApp * @param clazz */ private static void addWebListener(final WebApp webApp, String clazz) { final WebAppListener listener = new WebAppListener(); listener.setListenerClass(clazz); webApp.addListener(listener); }
/** * Parses security-constraint, login-configuration and security-role out of web.xml * * @param rootElement web.xml root element * @param webApp web app for web.xml */ private static void parseSecurity(final Element rootElement, final WebApp webApp) { final Element[] securityConstraint = getChildren(rootElement, "security-constraint"); if (securityConstraint != null && securityConstraint.length > 0) { try { for (Element scElement : securityConstraint) { final WebAppSecurityConstraint webSecurityConstraint = new WebAppSecurityConstraint(); final Element authConstraintElement = getChild(scElement, "auth-constraint"); if (authConstraintElement != null) { webSecurityConstraint.setAuthenticate(true); final Element[] roleElemnts = getChildren(authConstraintElement, "role-name"); if (roleElemnts != null && roleElemnts.length > 0) { for (Element roleElement : roleElemnts) { String roleName = getTextContent(roleElement); webSecurityConstraint.addRole(roleName); } } } final Element userDataConstraintsElement = getChild(scElement, "user-data-constraint"); if (userDataConstraintsElement != null) { String guarantee = getTextContent(getChild(userDataConstraintsElement, "transport-guarantee")) .trim() .toUpperCase(); webSecurityConstraint.setDataConstraint(guarantee); } final Element[] webResourceElements = getChildren(scElement, "web-resource-collection"); if (webResourceElements != null && webResourceElements.length > 0) { for (Element webResourceElement : webResourceElements) { WebAppConstraintMapping webConstraintMapping = new WebAppConstraintMapping(); WebAppSecurityConstraint sc = (WebAppSecurityConstraint) webSecurityConstraint.clone(); String constraintName = getTextContent(getChild(webResourceElement, "web-resource-name")); webConstraintMapping.setConstraintName(constraintName); Element[] urlPatternElemnts = getChildren(webResourceElement, "url-pattern"); for (Element urlPattern : urlPatternElemnts) { String url = getTextContent(urlPattern); Element[] httpMethodElements = getChildren(urlPattern, "http-method"); if (httpMethodElements != null && httpMethodElements.length > 0) { for (Element httpMethodElement : httpMethodElements) { webConstraintMapping.setMapping(getTextContent(httpMethodElement)); webConstraintMapping.setUrl(url); webConstraintMapping.setSecurityConstraints(sc); } } else { webConstraintMapping.setUrl(url); webConstraintMapping.setSecurityConstraints(sc); } webApp.addConstraintMapping(webConstraintMapping); } } } } } catch (CloneNotSupportedException e) { LOG.warn("", e); } } final Element[] securityRoleElements = getChildren(rootElement, "security-role"); if (securityRoleElements != null && securityRoleElements.length > 0) { for (Element securityRoleElement : securityRoleElements) { final WebAppSecurityRole webSecurityRole = new WebAppSecurityRole(); Element[] roleElements = getChildren(securityRoleElement, "role-name"); if (roleElements != null && roleElements.length > 0) { for (Element roleElement : roleElements) { String roleName = getTextContent(roleElement); webSecurityRole.addRoleName(roleName); } } webApp.addSecurityRole(webSecurityRole); } } final Element[] loginConfigElements = getChildren(rootElement, "login-config"); if (loginConfigElements != null && loginConfigElements.length > 0) { for (Element loginConfigElement : loginConfigElements) { final WebAppLoginConfig webLoginConfig = new WebAppLoginConfig(); webLoginConfig.setAuthMethod(getTextContent(getChild(loginConfigElement, "auth-method"))); String realmName = getTextContent(getChild(loginConfigElement, "realm-name")); webLoginConfig.setRealmName(realmName == null ? "default" : realmName); if ("FORM".equalsIgnoreCase(webLoginConfig.getAuthMethod())) { // FORM // authorization Element formLoginConfigElement = getChild(loginConfigElement, "form-login-config"); webLoginConfig.setFormLoginPage( getTextContent(getChild(formLoginConfigElement, "form-login-page"))); webLoginConfig.setFormErrorPage( getTextContent(getChild(formLoginConfigElement, "form-error-page"))); } webApp.addLoginConfig(webLoginConfig); } } }