svn commit: r1854429 - in /ofbiz/ofbiz-framework/trunk: framework/base/src/main/java/org/apache/ofbiz/base/component/ framework/webapp/src/main/java/org/apache/ofbiz/webapp/ framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ themes/rainbow...

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r1854429 - in /ofbiz/ofbiz-framework/trunk: framework/base/src/main/java/org/apache/ofbiz/base/component/ framework/webapp/src/main/java/org/apache/ofbiz/webapp/ framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ themes/rainbow...

mthl
Author: mthl
Date: Tue Feb 26 22:47:58 2019
New Revision: 1854429

URL: http://svn.apache.org/viewvc?rev=1854429&view=rev
Log:
Improved: Add ‘WebAppCache’ (OFBIZ-10606)

This improves the cohesion of the ‘ComponentConfig’ class by
extracting the webapps cache related methods into a separate
‘WebAppCache’ class.

Added:
    ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/WebAppCache.java   (with props)
Modified:
    ofbiz/ofbiz-framework/trunk/framework/base/src/main/java/org/apache/ofbiz/base/component/ComponentConfig.java
    ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java
    ofbiz/ofbiz-framework/trunk/themes/rainbowstone/template/includes/HomeMenu.ftl
    ofbiz/ofbiz-framework/trunk/themes/rainbowstone/template/includes/TopAppBar.ftl

Modified: ofbiz/ofbiz-framework/trunk/framework/base/src/main/java/org/apache/ofbiz/base/component/ComponentConfig.java
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/base/src/main/java/org/apache/ofbiz/base/component/ComponentConfig.java?rev=1854429&r1=1854428&r2=1854429&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/base/src/main/java/org/apache/ofbiz/base/component/ComponentConfig.java (original)
+++ ofbiz/ofbiz-framework/trunk/framework/base/src/main/java/org/apache/ofbiz/base/component/ComponentConfig.java Tue Feb 26 22:47:58 2019
@@ -25,12 +25,10 @@ import java.security.KeyStore;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.TreeMap;
 
 import org.apache.ofbiz.base.container.ContainerConfig;
 import org.apache.ofbiz.base.container.ContainerConfig.Configuration;
@@ -55,12 +53,8 @@ public final class ComponentConfig {
 
     public static final String module = ComponentConfig.class.getName();
     public static final String OFBIZ_COMPONENT_XML_FILENAME = "ofbiz-component.xml";
-    /* Note: These Maps are not UtilCache instances because there is no strategy or implementation for reloading components.
-     * Also, we are using LinkedHashMap to maintain insertion order - which client code depends on. This means
-     * we will need to use synchronization code because there is no concurrent implementation of LinkedHashMap.
-     */
+    // This map is not a UtilCache instance because there is no strategy or implementation for reloading components.
     private static final ComponentConfigCache componentConfigCache = new ComponentConfigCache();
-    private static final Map<String, List<WebappInfo>> serverWebApps = new LinkedHashMap<>();
 
     public static Boolean componentExists(String componentName) {
         Assert.notEmpty("componentName", componentName);
@@ -187,55 +181,6 @@ public final class ComponentConfig {
         return webappInfos;
     }
 
-    public static List<WebappInfo> getAppBarWebInfos(String serverName) {
-        return ComponentConfig.getAppBarWebInfos(serverName, null, null);
-    }
-
-    public static List<WebappInfo> getAppBarWebInfos(String serverName, Comparator<? super String> comp, String menuName) {
-        String serverWebAppsKey = serverName + menuName;
-        List<WebappInfo> webInfos = null;
-        synchronized (serverWebApps) {
-            webInfos = serverWebApps.get(serverWebAppsKey);
-        }
-        if (webInfos == null) {
-            Map<String, WebappInfo> tm = null;
-            // use a TreeMap to sort the components alpha by title
-            if (comp != null) {
-                tm = new TreeMap<>(comp);
-            } else {
-                tm = new TreeMap<>();
-            }
-            for (ComponentConfig cc : getAllComponents()) {
-                for (WebappInfo wInfo : cc.getWebappInfos()) {
-                    String key = UtilValidate.isNotEmpty(wInfo.position) ? wInfo.position : wInfo.title;
-                    if (serverName.equals(wInfo.server) && wInfo.getAppBarDisplay()) {
-                        if (UtilValidate.isNotEmpty(menuName)) {
-                            if (menuName.equals(wInfo.menuName)) {
-                                tm.put(key, wInfo);
-                            }
-                        } else {
-                            tm.put(key, wInfo);
-                        }
-                    } if (!wInfo.getAppBarDisplay() && UtilValidate.isEmpty(menuName)) {
-                        tm.put(key, wInfo);
-                    }
-                }
-            }
-            webInfos = new ArrayList<>(tm.size());
-            webInfos.addAll(tm.values());
-            webInfos = Collections.unmodifiableList(webInfos);
-            synchronized (serverWebApps) {
-                // We are only preventing concurrent modification, we are not guaranteeing a singleton.
-                serverWebApps.put(serverWebAppsKey, webInfos);
-            }
-        }
-        return webInfos;
-    }
-
-    public static List<WebappInfo> getAppBarWebInfos(String serverName, String menuName) {
-        return getAppBarWebInfos(serverName, null, menuName);
-    }
-
     public static ComponentConfig getComponentConfig(String globalName) throws ComponentException {
         // TODO: we need to look up the rootLocation from the container config, or this will blow up
         return getComponentConfig(globalName, null);
@@ -314,21 +259,6 @@ public final class ComponentConfig {
         return info;
     }
     
-    public static WebappInfo getWebappInfo(String serverName, String webAppName) {
-        WebappInfo webappInfo = null;
-        List<WebappInfo> webappsInfo = getAppBarWebInfos(serverName);
-        for(WebappInfo currApp : webappsInfo) {
-            String currWebAppName = currApp.getMountPoint().replace("/", "").replace("*", "");
-            if (webAppName.equals(currWebAppName)) {
-                webappInfo = currApp;
-                break;
-            }
-        }
-        return webappInfo;
-    }    
-
-    
-
     public static boolean isFileResourceLoader(String componentName, String resourceLoaderName) throws ComponentException {
         ComponentConfig cc = getComponentConfig(componentName);
         return cc.isFileResourceLoader(resourceLoaderName);

Added: ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/WebAppCache.java
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/WebAppCache.java?rev=1854429&view=auto
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/WebAppCache.java (added)
+++ ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/WebAppCache.java Tue Feb 26 22:47:58 2019
@@ -0,0 +1,182 @@
+/*
+ * 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.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.function.Supplier;
+
+import org.apache.ofbiz.base.component.ComponentConfig;
+import org.apache.ofbiz.base.component.ComponentConfig.WebappInfo;
+import org.apache.ofbiz.base.util.UtilValidate;
+
+/**
+ * Cache for web applications information retrieved from
+ * {@linkplain ComponentConfig component configurations}.
+ * <p>
+ * This improves performance by avoiding to retrieve web applications from
+ * component configurations each time.
+ * <p>
+ * This is a cache which doesn't implement any invalidation mechanism.  Once a
+ * web applications is defined, it is <b>memoized</b> because it is not meant
+ * to change while OFBiz is running.
+ *
+ * @see <a href="https://en.wikipedia.org/wiki/Memoization">Memoization</a>
+ */
+public class WebAppCache {
+    // Synchronized map storing web applications.
+    // The LinkedHashMap is used to maintain insertion order (which client code depends on).
+    // There is no concurrent implementation of LinkedHashMap, so we are using manual synchronization instead.
+    private final LinkedHashMap<String, List<WebappInfo>> serverWebApps;
+    // Source for retrieving components configurations.
+    private final Supplier<Collection<ComponentConfig>> ccs;
+
+    /**
+     * Constructs an empty web application cache.
+     *
+     * @param supplier the source from which components configurations
+     *        are retrieved
+     */
+    public WebAppCache(Supplier<Collection<ComponentConfig>>supplier) {
+        ccs = supplier;
+        serverWebApps = new LinkedHashMap<>();
+    }
+
+    /**
+     * Retrieves the web applications information that must be visible
+     * in the context of the server {@code serverName}.
+     *
+     * @param serverName the name of the server to match
+     * @return the corresponding web applications information
+     */
+    public List<WebappInfo> getAppBarWebInfos(String serverName) {
+        return getAppBarWebInfos(serverName, null, null);
+    }
+
+    /**
+     * Retrieves the web applications information that must be visible inside
+     * the menu {@code menuName} in the context of the server {@code serverName}.
+     * <p>
+     * When an empty string or {@code null} is used for {@code menuName},
+     * all the web application information corresponding to {@code serverName} are matched.
+     *
+     * @param serverName the name of server to match
+     * @param menuName the name of the menu to match
+     * @return the corresponding web applications information
+     * @throws NullPointerException when {@code serverName} is {@code null}
+     */
+    public List<WebappInfo> getAppBarWebInfos(String serverName, String menuName) {
+        return getAppBarWebInfos(serverName, null, menuName);
+    }
+
+    /**
+     * Retrieves the web applications information that must be visible inside
+     * the menu {@code menuName} in the context of the server {@code serverName}.
+     * <p>
+     * When an empty string or {@code null} is used for {@code menuName},
+     * all the web application information corresponding to {@code serverName} are matched.
+     *
+     * @param serverName the name of server to match
+     * @param comp the comparator used for ordering the results
+     * @param menuName the name of the menu to match
+     * @return the corresponding web applications information
+     * @throws NullPointerException when {@code serverName} is {@code null}
+     */
+    private List<WebappInfo> getAppBarWebInfos(String serverName, Comparator<? super String> comp, String menuName) {
+        String serverWebAppsKey = serverName + menuName;
+        List<WebappInfo> webInfos = null;
+        synchronized (serverWebApps) {
+            webInfos = serverWebApps.get(serverWebAppsKey);
+        }
+        if (webInfos == null) {
+            Map<String, WebappInfo> tm = null;
+            // use a TreeMap to sort the components alpha by title
+            if (comp != null) {
+                tm = new TreeMap<>(comp);
+            } else {
+                tm = new TreeMap<>();
+            }
+            for (ComponentConfig cc : ccs.get()) {
+                for (WebappInfo wInfo : cc.getWebappInfos()) {
+                    String key = UtilValidate.isNotEmpty(wInfo.position) ? wInfo.position : wInfo.title;
+                    if (serverName.equals(wInfo.server) && wInfo.getAppBarDisplay()) {
+                        if (UtilValidate.isNotEmpty(menuName)) {
+                            if (menuName.equals(wInfo.menuName)) {
+                                tm.put(key, wInfo);
+                            }
+                        } else {
+                            tm.put(key, wInfo);
+                        }
+                    } if (!wInfo.getAppBarDisplay() && UtilValidate.isEmpty(menuName)) {
+                        tm.put(key, wInfo);
+                    }
+                }
+            }
+            webInfos = new ArrayList<>(tm.size());
+            webInfos.addAll(tm.values());
+            webInfos = Collections.unmodifiableList(webInfos);
+            synchronized (serverWebApps) {
+                // We are only preventing concurrent modification, we are not guaranteeing a singleton.
+                serverWebApps.put(serverWebAppsKey, webInfos);
+            }
+        }
+        return webInfos;
+    }
+
+    /**
+     * Retrieves the first web application information which mount point correspond to
+     * {@code webAppName} in the context of the server {@code serverName}.
+     *
+     * @param serverName the name of the server to match
+     * @param webAppName the name of the web application to match
+     * @return the corresponding web application information
+     * @throws NullPointerException when {@code serverName} or {@doc webAppName} are {@code null}
+     */
+    public WebappInfo getWebappInfo(String serverName, String webAppName) {
+        WebappInfo webappInfo = null;
+        List<WebappInfo> webappsInfo = getAppBarWebInfos(serverName);
+        for(WebappInfo currApp : webappsInfo) {
+            String currWebAppName = currApp.getMountPoint().replace("/", "").replace("*", "");
+            if (webAppName.equals(currWebAppName)) {
+                webappInfo = currApp;
+                break;
+            }
+        }
+        return webappInfo;
+    }
+
+    // Instance of the cache shared by the loginWorker and Freemarker appbar rendering.
+    // TODO: Find a way to share this cache without relying on a global variable.
+    private static WebAppCache sharedCache = new WebAppCache(ComponentConfig::getAllComponents);
+
+    /**
+     * Provides access to a shared instance of the webapp cache.
+     *
+     * @return the shared webapp cache.
+     */
+    public static WebAppCache getShared() {
+        return sharedCache;
+    }
+}

Propchange: ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/WebAppCache.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/WebAppCache.java
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/WebAppCache.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java?rev=1854429&r1=1854428&r2=1854429&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java (original)
+++ ofbiz/ofbiz-framework/trunk/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/LoginWorker.java Tue Feb 26 22:47:58 2019
@@ -81,6 +81,7 @@ import org.apache.ofbiz.service.GenericS
 import org.apache.ofbiz.service.LocalDispatcher;
 import org.apache.ofbiz.service.ModelService;
 import org.apache.ofbiz.service.ServiceUtil;
+import org.apache.ofbiz.webapp.WebAppCache;
 import org.apache.ofbiz.webapp.WebAppUtil;
 import org.apache.ofbiz.webapp.stats.VisitHandler;
 import org.apache.ofbiz.widget.model.ThemeFactory;
@@ -97,6 +98,7 @@ public class LoginWorker {
     public static final String securityProperties = "security.properties";
 
     private static final String keyValue = UtilProperties.getPropertyValue(securityProperties, "login.secret_key_string");
+    private static final WebAppCache webapps = WebAppCache.getShared();
 
     public static StringWrapper makeLoginUrl(PageContext pageContext) {
         return makeLoginUrl(pageContext, "checkLogin");
@@ -922,9 +924,9 @@ public class LoginWorker {
         Delegator delegator = (Delegator) request.getAttribute("delegator");
         HttpSession session = request.getSession();
         GenericValue userLogin = (GenericValue) session.getAttribute("userLogin");
-        ServletContext context = request.getServletContext();
+        String serverId = (String) request.getServletContext().getAttribute("_serverId");
         String applicationName = UtilHttp.getApplicationName(request);
-        WebappInfo webappInfo = ComponentConfig.getWebappInfo((String) context.getAttribute("_serverId"), applicationName);
+        WebappInfo webappInfo = webapps.getWebappInfo(serverId, applicationName);
                 
         if (userLogin != null &&
                 ((webappInfo != null && webappInfo.isAutologinCookieUsed())
@@ -932,7 +934,7 @@ public class LoginWorker {
             Cookie autoLoginCookie = new Cookie(getAutoLoginCookieName(request), userLogin.getString("userLoginId"));
             autoLoginCookie.setMaxAge(60 * 60 * 24 * 365);
             autoLoginCookie.setDomain(EntityUtilProperties.getPropertyValue("url", "cookie.domain", delegator));
-            autoLoginCookie.setPath( applicationName.equals("root") ? "/" : request.getContextPath());
+            autoLoginCookie.setPath(applicationName.equals("root") ? "/" : request.getContextPath());
             autoLoginCookie.setSecure(true);
             autoLoginCookie.setHttpOnly(true);
             response.addCookie(autoLoginCookie);
@@ -1368,7 +1370,7 @@ public class LoginWorker {
      * user is authorized to access
      */
     public static Collection<ComponentConfig.WebappInfo> getAppBarWebInfos(Security security, GenericValue userLogin, String serverName, String menuName) {
-        Collection<ComponentConfig.WebappInfo> allInfos = ComponentConfig.getAppBarWebInfos(serverName, menuName);
+        Collection<ComponentConfig.WebappInfo> allInfos = webapps.getAppBarWebInfos(serverName, menuName);
         Collection<ComponentConfig.WebappInfo> allowedInfos = new ArrayList<ComponentConfig.WebappInfo>(allInfos.size());
         for (ComponentConfig.WebappInfo info : allInfos) {
             if (hasApplicationPermission(info, security, userLogin)) {

Modified: ofbiz/ofbiz-framework/trunk/themes/rainbowstone/template/includes/HomeMenu.ftl
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/themes/rainbowstone/template/includes/HomeMenu.ftl?rev=1854429&r1=1854428&r2=1854429&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/themes/rainbowstone/template/includes/HomeMenu.ftl (original)
+++ ofbiz/ofbiz-framework/trunk/themes/rainbowstone/template/includes/HomeMenu.ftl Tue Feb 26 22:47:58 2019
@@ -21,8 +21,8 @@ under the License.
 <#if (externalLoginKey)?exists><#assign externalKeyParam = "?externalLoginKey=" + requestAttributes.externalLoginKey?if_exists></#if>
 <#assign ofbizServerName = application.getAttribute("_serverId")?default("default-server")>
 <#assign contextPath = request.getContextPath()>
-<#assign displayApps = Static["org.apache.ofbiz.base.component.ComponentConfig"].getAppBarWebInfos(ofbizServerName, "main")>
-<#assign displaySecondaryApps = Static["org.apache.ofbiz.base.component.ComponentConfig"].getAppBarWebInfos(ofbizServerName, "secondary")>
+<#assign displayApps = Static["org.apache.ofbiz.webapp.WebAppCache"].getShared().getAppBarWebInfos(ofbizServerName, "main")>
+<#assign displaySecondaryApps = Static["org.apache.ofbiz.webapp.WebAppCache"].getShared().getAppBarWebInfos(ofbizServerName, "secondary")>
 <#assign avatarList = EntityQuery.use(delegator).from("PartyContent").where("partyId", person.partyId!, "partyContentTypeId", "LGOIMGURL").queryList()!>
 <#if avatarList?has_content>
     <#assign avatar = Static["org.apache.ofbiz.entity.util.EntityUtil"].getFirst(avatarList)>

Modified: ofbiz/ofbiz-framework/trunk/themes/rainbowstone/template/includes/TopAppBar.ftl
URL: http://svn.apache.org/viewvc/ofbiz/ofbiz-framework/trunk/themes/rainbowstone/template/includes/TopAppBar.ftl?rev=1854429&r1=1854428&r2=1854429&view=diff
==============================================================================
--- ofbiz/ofbiz-framework/trunk/themes/rainbowstone/template/includes/TopAppBar.ftl (original)
+++ ofbiz/ofbiz-framework/trunk/themes/rainbowstone/template/includes/TopAppBar.ftl Tue Feb 26 22:47:58 2019
@@ -20,8 +20,8 @@ under the License.
 <#if (externalLoginKey)?exists><#assign externalKeyParam = "?externalLoginKey=" + requestAttributes.externalLoginKey?if_exists></#if>
 <#assign ofbizServerName = application.getAttribute("_serverId")?default("default-server")>
 <#assign contextPath = request.getContextPath()>
-<#assign displayApps = Static["org.apache.ofbiz.base.component.ComponentConfig"].getAppBarWebInfos(ofbizServerName, "main")>
-<#assign displaySecondaryApps = Static["org.apache.ofbiz.base.component.ComponentConfig"].getAppBarWebInfos(ofbizServerName, "secondary")>
+<#assign displayApps = Static["org.apache.ofbiz.webapp.WebAppCache"].getShared().getAppBarWebInfos(ofbizServerName, "main")>
+<#assign displaySecondaryApps = Static["org.apache.ofbiz.webapp.WebAppCache"].getShared().getAppBarWebInfos(ofbizServerName, "secondary")>
 <#if person?has_content>
     <#assign avatarList = EntityQuery.use(delegator).from("PartyContent").where("partyId",  person.partyId!, "partyContentTypeId", "LGOIMGURL").queryList()!>
     <#if avatarList?has_content>