Author: adrianc Date: Wed Oct 23 19:29:47 2013 New Revision: 1535126 URL: http://svn.apache.org/r1535126 Log: Added a new classes to simplify OFBiz URL generation and eliminate redundant code.
Added: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/OfbizUrlBuilder.java (with props) ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/WebAppUtil.java (with props) Modified: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ConfigXMLReader.java Added: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/OfbizUrlBuilder.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/OfbizUrlBuilder.java?rev=1535126&view=auto ============================================================================== --- ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/OfbizUrlBuilder.java (added) +++ ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/OfbizUrlBuilder.java Wed Oct 23 19:29:47 2013 @@ -0,0 +1,190 @@ +/******************************************************************************* + * 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.ofbiz.webapp; + +import java.io.IOException; +import java.net.URL; + +import javax.servlet.http.HttpServletRequest; + +import org.ofbiz.base.component.ComponentConfig.WebappInfo; +import org.ofbiz.base.util.Assert; +import org.ofbiz.base.util.Debug; +import org.ofbiz.base.util.UtilMisc; +import org.ofbiz.entity.Delegator; +import org.ofbiz.entity.GenericEntityException; +import org.ofbiz.entity.GenericValue; +import org.ofbiz.webapp.control.ConfigXMLReader; +import org.ofbiz.webapp.control.ConfigXMLReader.ControllerConfig; +import org.ofbiz.webapp.control.ConfigXMLReader.RequestMap; +import org.ofbiz.webapp.control.WebAppConfigurationException; +import org.ofbiz.webapp.website.WebSiteProperties; +import org.xml.sax.SAXException; + +/** + * OFBiz URL builder. + */ +public final class OfbizUrlBuilder { + + public static final String module = OfbizUrlBuilder.class.getName(); + + /** + * Returns an <code>OfbizUrlBuilder</code> instance. The instance can be reused in + * the supplied request. + * + * @param request + * @throws GenericEntityException + * @throws WebAppConfigurationException + */ + public static OfbizUrlBuilder from(HttpServletRequest request) throws GenericEntityException, WebAppConfigurationException { + Assert.notNull("request", request); + WebSiteProperties webSiteProps = (WebSiteProperties) request.getAttribute("_WEBSITE_PROPS_"); + if (webSiteProps == null) { + webSiteProps = WebSiteProperties.from(request); + request.setAttribute("_WEBSITE_PROPS_", webSiteProps); + } + URL url = ConfigXMLReader.getControllerConfigURL(request.getServletContext()); + ControllerConfig config = ConfigXMLReader.getControllerConfig(url); + String servletPath = (String) request.getAttribute("_CONTROL_PATH_"); + return new OfbizUrlBuilder(config, webSiteProps, servletPath); + } + + /** + * Returns an <code>OfbizUrlBuilder</code> instance. Use this method when you + * don't have a <code>HttpServletRequest</code> object - like in scheduled jobs. + * + * @param webAppInfo + * @param delegator + * @throws WebAppConfigurationException + * @throws IOException + * @throws SAXException + * @throws GenericEntityException + */ + public static OfbizUrlBuilder from(WebappInfo webAppInfo, Delegator delegator) throws WebAppConfigurationException, IOException, SAXException, GenericEntityException { + Assert.notNull("webAppInfo", webAppInfo, "delegator", delegator); + WebSiteProperties webSiteProps = null; + String webSiteId = WebAppUtil.getWebSiteId(webAppInfo); + if (webSiteId != null) { + GenericValue webSiteValue = delegator.findOne("WebSite", UtilMisc.toMap("webSiteId", webSiteId), true); + if (webSiteValue != null) { + webSiteProps = WebSiteProperties.from(webSiteValue); + } + } + if (webSiteProps == null) { + webSiteProps = WebSiteProperties.defaults(); + } + ControllerConfig config = ConfigXMLReader.getControllerConfig(webAppInfo); + String servletPath = WebAppUtil.getControlServletPath(webAppInfo); + return new OfbizUrlBuilder(config, webSiteProps, servletPath); + } + + private final ControllerConfig config; + private final WebSiteProperties webSiteProps; + private final String servletPath; + + private OfbizUrlBuilder(ControllerConfig config, WebSiteProperties webSiteProps, String servletPath) { + this.config = config; + this.webSiteProps = webSiteProps; + this.servletPath = servletPath; + } + + /** + * Builds a full URL - including scheme, host, and servlet path. + * + * @param buffer + * @param url + * @param useSSL Default value to use - will be replaced by request-map setting + * if one is found. + * @return + * @throws WebAppConfigurationException + * @throws IOException + */ + public boolean buildFullUrl(Appendable buffer, String url, boolean useSSL) throws WebAppConfigurationException, IOException { + boolean makeSecure = buildHostPart(buffer, url, useSSL); + buildPathPart(buffer, url); + return makeSecure; + } + + /** + * Builds a partial URL - including the scheme and host, but not the servlet path or resource. + * + * @param buffer + * @param url + * @param useSSL Default value to use - will be replaced by request-map setting + * if one is found. + * @return + * @throws WebAppConfigurationException + * @throws IOException + */ + public boolean buildHostPart(Appendable buffer, String url, boolean useSSL) throws WebAppConfigurationException, IOException { + boolean makeSecure = useSSL; + String[] pathElements = url.split("/"); + String requestMapUri = pathElements[0]; + int queryIndex = requestMapUri.indexOf("?"); + if (queryIndex != -1) { + requestMapUri = requestMapUri.substring(0, queryIndex); + } + RequestMap requestMap = config.getRequestMapMap().get(requestMapUri); + if (requestMap != null) { + makeSecure = requestMap.securityHttps; + } + makeSecure = webSiteProps.getEnableHttps() & makeSecure; + if (makeSecure) { + String server = webSiteProps.getHttpsHost(); + if (server.isEmpty()) { + server = "localhost"; + } + buffer.append("https://"); + buffer.append(server); + if (!webSiteProps.getHttpsPort().isEmpty()) { + buffer.append(":").append(webSiteProps.getHttpsPort()); + } + } else { + String server = webSiteProps.getHttpHost(); + if (server.isEmpty()) { + server = "localhost"; + } + buffer.append("http://"); + buffer.append(server); + if (!webSiteProps.getHttpPort().isEmpty()) { + buffer.append(":").append(webSiteProps.getHttpPort()); + } + } + if (Debug.warningOn() && requestMap == null) { + Debug.logWarning("The request-map URI '" + requestMapUri + "' was not found in controller.xml", module); + } + return makeSecure; + } + + /** + * Builds a partial URL - including the servlet path and resource, but not the scheme or host. + * + * @param buffer + * @param url + * @throws WebAppConfigurationException + * @throws IOException + */ + public void buildPathPart(Appendable buffer, String url) throws WebAppConfigurationException, IOException { + buffer.append(servletPath); + if (!url.startsWith("/")) { + buffer.append("/"); + } + buffer.append(url); + } +} Propchange: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/OfbizUrlBuilder.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/OfbizUrlBuilder.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Rev URL Added: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/WebAppUtil.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/WebAppUtil.java?rev=1535126&view=auto ============================================================================== --- ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/WebAppUtil.java (added) +++ ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/WebAppUtil.java Wed Oct 23 19:29:47 2013 @@ -0,0 +1,158 @@ +/******************************************************************************* + * 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.ofbiz.webapp; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map.Entry; + +import org.apache.catalina.deploy.ServletDef; +import org.apache.catalina.deploy.WebXml; +import org.apache.catalina.startup.DigesterFactory; +import org.apache.catalina.startup.WebRuleSet; +import org.apache.tomcat.util.digester.Digester; +import org.ofbiz.base.component.ComponentConfig.WebappInfo; +import org.ofbiz.base.util.Assert; +import org.ofbiz.base.util.Debug; +import org.ofbiz.base.util.UtilXml.LocalErrorHandler; +import org.ofbiz.base.util.UtilXml.LocalResolver; +import org.ofbiz.base.util.cache.UtilCache; +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(); + 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.ofbiz.webapp.control.ControlServlet".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.ofbiz.webapp.control.ControlServlet mapping not found in " + webAppInfo.getLocation() + webAppFileName); + } + servletMapping = servletMapping.replace("*", ""); + String servletPath = webAppInfo.contextRoot.concat(servletMapping); + return servletPath; + } + + /** + * 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"); + } + + /** + * Returns a <code>WebXml</code> instance that models the web application's <code>web.xml</code> file. + * + * @param webAppInfo + * @throws IOException + * @throws SAXException + */ + public 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 + */ + public 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; + InputStream is = new FileInputStream(file); + result = new WebXml(); + LocalResolver lr = new LocalResolver(new DefaultHandler()); + ErrorHandler handler = new LocalErrorHandler(webXmlFileLocation, lr); + Digester digester = DigesterFactory.newDigester(validate, namespaceAware, new WebRuleSet()); + digester.getParser(); + digester.push(result); + digester.setErrorHandler(handler); + try { + digester.parse(new InputSource(is)); + } finally { + digester.reset(); + if (is != null) { + try { + is.close(); + } catch (Throwable t) { + Debug.logError(t, "Exception thrown while parsing " + webXmlFileLocation + ": ", module); + } + } + } + result = webXmlCache.putIfAbsentAndGet(webXmlFileLocation, result); + } + return result; + } + + private WebAppUtil() {} +} Propchange: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/WebAppUtil.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/WebAppUtil.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Rev URL Modified: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ConfigXMLReader.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ConfigXMLReader.java?rev=1535126&r1=1535125&r2=1535126&view=diff ============================================================================== --- ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ConfigXMLReader.java (original) +++ ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ConfigXMLReader.java Wed Oct 23 19:29:47 2013 @@ -32,9 +32,11 @@ import javolution.util.FastList; import javolution.util.FastMap; import javolution.util.FastSet; +import org.ofbiz.base.component.ComponentConfig.WebappInfo; import org.ofbiz.base.location.FlexibleLocation; import org.ofbiz.base.metrics.Metrics; import org.ofbiz.base.metrics.MetricsFactory; +import org.ofbiz.base.util.Assert; import org.ofbiz.base.util.Debug; import org.ofbiz.base.util.FileUtil; import org.ofbiz.base.util.GeneralException; @@ -127,6 +129,13 @@ public class ConfigXMLReader { } } + public static ControllerConfig getControllerConfig(WebappInfo webAppInfo) throws WebAppConfigurationException, MalformedURLException { + Assert.notNull("webAppInfo", webAppInfo); + String filePath = webAppInfo.getLocation().concat(controllerXmlFileName); + File configFile = new File(filePath); + return getControllerConfig(configFile.toURI().toURL()); + } + public static ControllerConfig getControllerConfig(URL url) throws WebAppConfigurationException { ControllerConfig controllerConfig = controllerCache.get(url); if (controllerConfig == null) {