| /******************************************************************************* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| *******************************************************************************/ |
| package org.apache.ofbiz.webapp; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| import javax.servlet.ServletContext; |
| import javax.servlet.ServletRequest; |
| |
| import org.apache.ofbiz.base.util.UtilValidate; |
| import org.apache.ofbiz.entity.Delegator; |
| import org.apache.ofbiz.entity.DelegatorFactory; |
| import org.apache.ofbiz.security.Security; |
| import org.apache.ofbiz.security.SecurityConfigurationException; |
| import org.apache.ofbiz.security.SecurityFactory; |
| import org.apache.ofbiz.service.LocalDispatcher; |
| import org.apache.ofbiz.service.ServiceContainer; |
| import org.apache.ofbiz.webapp.event.RequestBodyMapHandlerFactory; |
| import org.apache.ofbiz.base.component.ComponentConfig; |
| import org.apache.ofbiz.base.component.ComponentConfig.WebappInfo; |
| import org.apache.ofbiz.base.util.Assert; |
| import org.apache.ofbiz.base.util.Debug; |
| import org.apache.ofbiz.base.util.UtilXml.LocalErrorHandler; |
| import org.apache.ofbiz.base.util.UtilXml.LocalResolver; |
| import org.apache.ofbiz.base.util.cache.UtilCache; |
| |
| import org.apache.tomcat.util.digester.Digester; |
| import org.apache.tomcat.util.descriptor.DigesterFactory; |
| import org.apache.tomcat.util.descriptor.web.ServletDef; |
| import org.apache.tomcat.util.descriptor.web.WebRuleSet; |
| import org.apache.tomcat.util.descriptor.web.WebXml; |
| import org.xml.sax.ErrorHandler; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.helpers.DefaultHandler; |
| |
| /** |
| * Web application utilities. |
| * <p>This class reuses some of the Tomcat/Catalina classes for convenience, but |
| * OFBiz does not need to be running on Tomcat for this to work.</p> |
| */ |
| public final class WebAppUtil { |
| |
| public static final String module = WebAppUtil.class.getName(); |
| public static final String CONTROL_MOUNT_POINT = "control"; |
| private static final String webAppFileName = "/WEB-INF/web.xml"; |
| private static final UtilCache<String, WebXml> webXmlCache = UtilCache.createUtilCache("webapp.WebXml"); |
| |
| /** |
| * Returns the control servlet path. The path consists of the web application's mount-point |
| * specified in the <code>ofbiz-component.xml</code> file and the servlet mapping specified |
| * in the web application's <code>web.xml</code> file. |
| * |
| * @param webAppInfo |
| * @throws IOException |
| * @throws SAXException |
| */ |
| public static String getControlServletPath(WebappInfo webAppInfo) throws IOException, SAXException { |
| Assert.notNull("webAppInfo", webAppInfo); |
| String servletMapping = null; |
| WebXml webXml = getWebXml(webAppInfo); |
| for (ServletDef servletDef : webXml.getServlets().values()) { |
| if ("org.apache.ofbiz.webapp.control.ControlServlet".equals(servletDef.getServletClass()) || "org.apache.ofbiz.product.category.SeoControlServlet".equals(servletDef.getServletClass())) { |
| String servletName = servletDef.getServletName(); |
| // Catalina servlet mappings: key = url-pattern, value = servlet-name. |
| for (Entry<String, String> entry : webXml.getServletMappings().entrySet()) { |
| if (servletName.equals(entry.getValue())) { |
| servletMapping = entry.getKey(); |
| break; |
| } |
| } |
| break; |
| } |
| } |
| if (servletMapping == null) { |
| throw new IllegalArgumentException("org.apache.ofbiz.webapp.control.ControlServlet mapping not found in " + webAppInfo.getLocation() + webAppFileName); |
| } |
| servletMapping = servletMapping.replace("*", ""); |
| String servletPath = webAppInfo.contextRoot.concat(servletMapping); |
| return servletPath; |
| } |
| |
| /** |
| * Returns the <code>WebappInfo</code> instance associated to the specified web site ID. |
| * Throws <code>IllegalArgumentException</code> if the web site ID was not found. |
| * |
| * @param webSiteId |
| * @throws IOException |
| * @throws SAXException |
| */ |
| public static WebappInfo getWebappInfoFromWebsiteId(String webSiteId) throws IOException, SAXException { |
| Assert.notNull("webSiteId", webSiteId); |
| for (WebappInfo webAppInfo : ComponentConfig.getAllWebappResourceInfos()) { |
| if (webSiteId.equals(WebAppUtil.getWebSiteId(webAppInfo))) { |
| return webAppInfo; |
| } |
| } |
| throw new IllegalArgumentException("Web site ID '" + webSiteId + "' not found."); |
| } |
| |
| /** |
| * Returns the web site ID - as configured in the web application's <code>web.xml</code> file, |
| * or <code>null</code> if no web site ID was found. |
| * |
| * @param webAppInfo |
| * @throws IOException |
| * @throws SAXException |
| */ |
| public static String getWebSiteId(WebappInfo webAppInfo) throws IOException, SAXException { |
| Assert.notNull("webAppInfo", webAppInfo); |
| WebXml webXml = getWebXml(webAppInfo); |
| return webXml.getContextParams().get("webSiteId"); |
| } |
| |
| public static LocalDispatcher getDispatcher(ServletContext servletContext) { |
| LocalDispatcher dispatcher = (LocalDispatcher) servletContext.getAttribute("dispatcher"); |
| if (dispatcher == null) { |
| Delegator delegator = getDelegator(servletContext); |
| dispatcher = makeWebappDispatcher(servletContext, delegator); |
| servletContext.setAttribute("dispatcher", dispatcher); |
| } |
| return dispatcher; |
| } |
| |
| public static void setAttributesFromRequestBody(ServletRequest request) { |
| // read the body (for JSON requests) and set the parameters as attributes: |
| Map<String, Object> requestBodyMap = null; |
| try { |
| requestBodyMap = RequestBodyMapHandlerFactory.extractMapFromRequestBody(request); |
| } catch (IOException ioe) { |
| Debug.logWarning(ioe, module); |
| } |
| if (requestBodyMap != null) { |
| Set<String> parameterNames = requestBodyMap.keySet(); |
| for (String parameterName: parameterNames) { |
| request.setAttribute(parameterName, requestBodyMap.get(parameterName)); |
| } |
| } |
| } |
| |
| /** This method only sets up a dispatcher for the current webapp and passed in delegator, it does not save it to the ServletContext or anywhere else, just returns it */ |
| public static LocalDispatcher makeWebappDispatcher(ServletContext servletContext, Delegator delegator) { |
| if (delegator == null) { |
| Debug.logError("[ContextFilter.init] ERROR: delegator not defined.", module); |
| return null; |
| } |
| // get the unique name of this dispatcher |
| String dispatcherName = servletContext.getInitParameter("localDispatcherName"); |
| |
| if (dispatcherName == null) { |
| Debug.logError("No localDispatcherName specified in the web.xml file", module); |
| dispatcherName = delegator.getDelegatorName(); |
| } |
| |
| LocalDispatcher dispatcher = ServiceContainer.getLocalDispatcher(dispatcherName, delegator); |
| if (dispatcher == null) { |
| Debug.logError("[ContextFilter.init] ERROR: dispatcher could not be initialized.", module); |
| } |
| |
| return dispatcher; |
| } |
| |
| public static Delegator getDelegator(ServletContext servletContext) { |
| Delegator delegator = (Delegator) servletContext.getAttribute("delegator"); |
| if (delegator == null) { |
| String delegatorName = servletContext.getInitParameter("entityDelegatorName"); |
| |
| if (UtilValidate.isEmpty(delegatorName)) { |
| delegatorName = "default"; |
| } |
| if (Debug.verboseOn()) Debug.logVerbose("Setup Entity Engine Delegator with name " + delegatorName, module); |
| delegator = DelegatorFactory.getDelegator(delegatorName); |
| servletContext.setAttribute("delegator", delegator); |
| if (delegator == null) { |
| Debug.logError("[ContextFilter.init] ERROR: delegator factory returned null for delegatorName \"" + delegatorName + "\"", module); |
| } |
| } |
| return delegator; |
| } |
| |
| public static Security getSecurity(ServletContext servletContext) { |
| Security security = (Security) servletContext.getAttribute("security"); |
| if (security == null) { |
| Delegator delegator = (Delegator) servletContext.getAttribute("delegator"); |
| |
| if (delegator != null) { |
| try { |
| security = SecurityFactory.getInstance(delegator); |
| } catch (SecurityConfigurationException e) { |
| Debug.logError(e, "Unable to obtain an instance of the security object.", module); |
| } |
| } |
| servletContext.setAttribute("security", security); |
| if (security == null) { |
| Debug.logError("An invalid (null) Security object has been set in the servlet context.", module); |
| } |
| } |
| return security; |
| } |
| |
| /** |
| * Returns a <code>WebXml</code> instance that models the web application's <code>web.xml</code> file. |
| * |
| * @param webAppInfo |
| * @throws IOException |
| * @throws SAXException |
| */ |
| private static WebXml getWebXml(WebappInfo webAppInfo) throws IOException, SAXException { |
| Assert.notNull("webAppInfo", webAppInfo); |
| String webXmlFileLocation = webAppInfo.getLocation().concat(webAppFileName); |
| return parseWebXmlFile(webXmlFileLocation, true); |
| } |
| |
| /** |
| * Parses the specified <code>web.xml</code> file into a <code>WebXml</code> instance. |
| * |
| * @param webXmlFileLocation |
| * @param validate |
| * @throws IOException |
| * @throws SAXException |
| */ |
| private static WebXml parseWebXmlFile(String webXmlFileLocation, boolean validate) throws IOException, SAXException { |
| Assert.notEmpty("webXmlFileLocation", webXmlFileLocation); |
| WebXml result = webXmlCache.get(webXmlFileLocation); |
| if (result == null) { |
| File file = new File(webXmlFileLocation); |
| if (!file.exists()) { |
| throw new IllegalArgumentException(webXmlFileLocation + " does not exist."); |
| } |
| boolean namespaceAware = true; |
| result = new WebXml(); |
| LocalResolver lr = new LocalResolver(new DefaultHandler()); |
| ErrorHandler handler = new LocalErrorHandler(webXmlFileLocation, lr); |
| Digester digester = DigesterFactory.newDigester(validate, namespaceAware, new WebRuleSet(), false); |
| digester.getParser(); |
| digester.push(result); |
| digester.setErrorHandler(handler); |
| try (InputStream is = new FileInputStream(file)) { |
| digester.parse(new InputSource(is)); |
| } finally { |
| digester.reset(); |
| } |
| result = webXmlCache.putIfAbsentAndGet(webXmlFileLocation, result); |
| } |
| return result; |
| } |
| |
| private WebAppUtil() {} |
| } |