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");