Author: adrianc
Date: Mon Jan  5 19:22:56 2015
New Revision: 1649620

URL: http://svn.apache.org/r1649620
Log:
New Feature: EntityClassLoader. This should be a better solution than the 
current EntityProperties implementation. Includes example usage in 
ControlServlet.java (commented out for now).

Added:
    
ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityClassLoader.java
Modified:
    
ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ControlServlet.java

Added: 
ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityClassLoader.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityClassLoader.java?rev=1649620&view=auto
==============================================================================
--- 
ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityClassLoader.java 
(added)
+++ 
ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityClassLoader.java 
Mon Jan  5 19:22:56 2015
@@ -0,0 +1,212 @@
+/*
+ * 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.entity.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+
+import org.ofbiz.base.util.Assert;
+import org.ofbiz.base.util.cache.UtilCache;
+import org.ofbiz.entity.Delegator;
+import org.ofbiz.entity.DelegatorFactory;
+import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.condition.EntityCondition;
+import org.ofbiz.entity.condition.EntityOperator;
+
+/**
+ * A class loader that retrieves Java resources from the
+ * <b>JavaResource</b> entity. The entity is searched for the
+ * resource(s), and if it is not found, searching is delegated
+ * to the parent class loader.
+ *
+ */
+public final class EntityClassLoader extends ClassLoader {
+
+    private static final ThreadLocal<Boolean> inFind = new 
ThreadLocal<Boolean>(); // Guards against infinite recursion
+    private static final URLStreamHandler streamHandler = new 
EntityURLStreamHandler();
+    private static final UtilCache<String, String> misses = 
UtilCache.createUtilCache("entity.classloader.misses", 500, 0, true);
+
+    public static ClassLoader getInstance(String delegatorName, ClassLoader 
parent) {
+        Assert.notNull("delegatorName", delegatorName, "parent", parent);
+        if (parent instanceof EntityClassLoader) {
+            EntityClassLoader ecl = (EntityClassLoader) parent;
+            if (delegatorName.equals(ecl.delegatorName)) {
+                return ecl;
+            }
+            return new EntityClassLoader(delegatorName, ecl.getParent());
+        }
+        return new EntityClassLoader(delegatorName, parent);
+    }
+
+    private final String delegatorName;
+
+    private EntityClassLoader(String delegatorName, ClassLoader parent) {
+        super(parent);
+        this.delegatorName = delegatorName;
+    }
+
+    @Override
+    protected URL findResource(String name) {
+        URL url = null;
+        if (!isInFind()) {
+            String key = delegatorName.concat(":").concat(name);
+            if (misses.containsKey(key)) {
+                return null;
+            }
+            try {
+                inFind.set(Boolean.TRUE);
+                Delegator delegator = 
DelegatorFactory.getDelegator(delegatorName);
+                GenericValue resourceValue = delegator.findOne("JavaResource", 
true, "resourceName", name);
+                if (resourceValue != null) {
+                    url = makeUrl(resourceValue);
+                } else {
+                    misses.put(key, key);
+                }
+            } catch (Exception e) {
+                throw new EntityClassLoaderException(e);
+            } finally {
+                inFind.set(Boolean.FALSE);
+            }
+        }
+        return url;
+    }
+
+    @Override
+    protected Enumeration<URL> findResources(String name) throws IOException {
+        Enumeration<URL> urlEnum = null;
+        if (!isInFind()) {
+            String key = delegatorName.concat(":").concat(name);
+            if (misses.containsKey(key)) {
+                return null;
+            }
+            try {
+                inFind.set(Boolean.TRUE);
+                Delegator delegator = 
DelegatorFactory.getDelegator(delegatorName);
+                EntityCondition condition = 
EntityCondition.makeCondition("resourceName", EntityOperator.LIKE, name);
+                List<GenericValue> resourceValues = 
delegator.findList("JavaResource", condition, null, null, null, true);
+                if (!resourceValues.isEmpty()) {
+                    List<URL> urls = new ArrayList<URL>(resourceValues.size());
+                    for (GenericValue resourceValue : resourceValues) {
+                        urls.add(makeUrl(resourceValue));
+                    }
+                    urlEnum = Collections.enumeration(urls);
+                } else {
+                    misses.put(key, key);
+                }
+            } catch (Exception e) {
+                throw new EntityClassLoaderException(e);
+            } finally {
+                inFind.set(Boolean.FALSE);
+            }
+        }
+        return urlEnum;
+    }
+
+    public String getDelegatorName() {
+        return delegatorName;
+    }
+
+    @Override
+    public URL getResource(String name) {
+        Assert.notEmpty("name", name);
+        URL url = findResource(name);
+        if (url == null) {
+            url = getParent().getResource(name);
+        }
+        return url;
+    }
+
+    @Override
+    public Enumeration<URL> getResources(String name) throws IOException {
+        Assert.notEmpty("name", name);
+        Enumeration<URL> urlEnum = findResources(name);
+        if (urlEnum == null) {
+            urlEnum = getParent().getResources(name);
+        }
+        return urlEnum;
+    }
+
+    private boolean isInFind() {
+        Boolean inFindValue = inFind.get();
+        if (inFindValue == null) {
+            inFindValue = Boolean.FALSE;
+            inFind.set(inFindValue);
+        }
+        return inFindValue;
+    }
+
+    private URL makeUrl(GenericValue resourceValue) throws 
MalformedURLException {
+        return new URL("entity", 
resourceValue.getDelegator().getDelegatorName(), -1, "/".concat(resourceValue
+                .getString("resourceName")), streamHandler);
+    }
+
+    private static class EntityURLStreamHandler extends URLStreamHandler {
+
+        @Override
+        protected URLConnection openConnection(URL url) throws IOException {
+            Assert.notNull("url", url);
+            try {
+                Delegator delegator = 
DelegatorFactory.getDelegator(url.getHost());
+                String resourceName = url.getFile();
+                if (resourceName.startsWith("/")) {
+                    resourceName = resourceName.substring(1);
+                }
+                GenericValue resourceValue = delegator.findOne("JavaResource", 
true, "resourceName", resourceName);
+                return new EntityURLConnection(url, 
resourceValue.getBytes("resourceValue"));
+            } catch (Exception e) {
+                throw new EntityClassLoaderException(e);
+            }
+        }
+    }
+
+    private static class EntityURLConnection extends URLConnection {
+
+        private final byte[] data;
+
+        private EntityURLConnection(URL url, byte[] data) {
+            super(url);
+            this.data = data;
+        }
+
+        @Override
+        public InputStream getInputStream() throws IOException {
+            return new ByteArrayInputStream(data);
+        }
+
+        @Override
+        public void connect() throws IOException {
+        }
+    }
+
+    @SuppressWarnings("serial")
+    public static class EntityClassLoaderException extends RuntimeException {
+        public EntityClassLoaderException(Throwable cause) {
+            super(cause);
+        }
+    }
+}

Modified: 
ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ControlServlet.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ControlServlet.java?rev=1649620&r1=1649619&r2=1649620&view=diff
==============================================================================
--- 
ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ControlServlet.java 
(original)
+++ 
ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ControlServlet.java 
Mon Jan  5 19:22:56 2015
@@ -47,6 +47,7 @@ import org.ofbiz.security.Security;
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.webapp.stats.ServerHitBin;
 import org.ofbiz.webapp.stats.VisitHandler;
+import org.ofbiz.entity.util.EntityClassLoader;
 
 /**
  * ControlServlet.java - Master servlet for the web application.
@@ -164,6 +165,10 @@ public class ControlServlet extends Http
             request.setAttribute("delegator", delegator);
             // always put this in the session too so that session events can 
use the delegator
             session.setAttribute("delegatorName", 
delegator.getDelegatorName());
+            /* Uncomment this to enable the EntityClassLoader
+            ClassLoader loader = 
EntityClassLoader.getInstance(delegator.getDelegatorName(), 
Thread.currentThread().getContextClassLoader());
+            Thread.currentThread().setContextClassLoader(loader);
+            */
         }
 
         LocalDispatcher dispatcher = (LocalDispatcher) 
session.getAttribute("dispatcher");


Reply via email to