TOMEE-1847 classpath-api config
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/e386526f Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/e386526f Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/e386526f Branch: refs/heads/master Commit: e386526f1a1528d18a70f216f5fc1c584ae27873 Parents: a5d08be Author: Romain manni-Bucau <rmannibu...@gmail.com> Authored: Fri Jun 17 12:40:30 2016 +0200 Committer: Romain manni-Bucau <rmannibu...@gmail.com> Committed: Fri Jun 17 12:40:30 2016 +0200 ---------------------------------------------------------------------- .../openejb/assembler/classic/Assembler.java | 22 ++++++- .../openejb/assembler/classic/ServiceInfo.java | 1 + .../openejb/config/ConfigurationFactory.java | 3 + .../java/org/apache/openejb/config/Service.java | 2 + .../openejb/config/sys/AbstractService.java | 17 +++++ .../apache/openejb/config/sys/StackHandler.java | 3 + .../openejb/resource/ClasspathAPITest.java | 69 ++++++++++++++++++++ 7 files changed, 115 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/e386526f/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java index d316dac..ff32a27 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java @@ -48,8 +48,8 @@ import org.apache.openejb.assembler.classic.event.AssemblerDestroyed; import org.apache.openejb.assembler.classic.event.BeforeStartEjbs; import org.apache.openejb.assembler.classic.event.ContainerSystemPostCreate; import org.apache.openejb.assembler.classic.event.ContainerSystemPreDestroy; -import org.apache.openejb.assembler.classic.event.ResourceCreated; import org.apache.openejb.assembler.classic.event.ResourceBeforeDestroyed; +import org.apache.openejb.assembler.classic.event.ResourceCreated; import org.apache.openejb.assembler.classic.util.ServiceInfos; import org.apache.openejb.assembler.monitoring.JMXContainer; import org.apache.openejb.async.AsynchronousPool; @@ -2958,9 +2958,27 @@ public class Assembler extends AssemblerTool implements org.apache.openejb.spi.A throw new OpenEJBException("Unable to create a classloader for " + serviceInfo.id, e); } + if (!customLoader && serviceInfo.classpathAPI != null) { + throw new IllegalArgumentException("custom-api provided but not classpath used for " + serviceInfo.id); + } + Object service = serviceRecipe.create(loader); if (customLoader) { - final Collection<Class<?>> apis = new ArrayList<Class<?>>(Arrays.asList(service.getClass().getInterfaces())); + final Collection<Class<?>> apis; + if (serviceInfo.classpathAPI == null) { + apis = new ArrayList<Class<?>>(Arrays.asList(service.getClass().getInterfaces())); + } else { + final String[] split = serviceInfo.classpathAPI.split(" *, *"); + apis = new ArrayList<>(split.length); + final ClassLoader apiLoader = Thread.currentThread().getContextClassLoader(); + for (final String fqn : split) { + try { + apis.add(apiLoader.loadClass(fqn)); + } catch (final ClassNotFoundException e) { + throw new IllegalArgumentException(fqn + " not usable as API for " + serviceInfo.id, e); + } + } + } if (apis.size() - (apis.contains(Serializable.class) ? 1 : 0) - (apis.contains(Externalizable.class) ? 1 : 0) > 0) { service = Proxy.newProxyInstance(loader, apis.toArray(new Class<?>[apis.size()]), new ClassLoaderAwareHandler(null, service, loader)); http://git-wip-us.apache.org/repos/asf/tomee/blob/e386526f/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java index bd55d12..21bc831 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ServiceInfo.java @@ -32,6 +32,7 @@ public class ServiceInfo extends InfoObject { public String className; public String codebase; public URI[] classpath; + public String classpathAPI; public Properties properties; public final List<String> constructorArgs = new ArrayList<>(); public Properties unsetProperties; // keep it in the model to be able to investigate it dumping Infos http://git-wip-us.apache.org/repos/asf/tomee/blob/e386526f/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java index e9fd1d1..873a092 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java @@ -798,6 +798,8 @@ public class ConfigurationFactory implements OpenEjbConfigurationFactory { service.setClasspath(cp); } + service.setClasspathAPI(map.remove("classpath-api")); + if (object instanceof Resource) { final Resource resource = Resource.class.cast(object); final String aliases = map.remove("aliases"); @@ -1281,6 +1283,7 @@ public class ConfigurationFactory implements OpenEjbConfigurationFactory { if (service.getClasspath() != null && service.getClasspath().length() > 0) { info.classpath = resolveClasspath(service.getClasspath()); } + info.classpathAPI = service.getClasspathAPI(); specialProcessing(info); http://git-wip-us.apache.org/repos/asf/tomee/blob/e386526f/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java b/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java index 58d9792..c0b4c16 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/Service.java @@ -66,6 +66,8 @@ public interface Service { String getClasspath(); + String getClasspathAPI(); + String getPropertiesProvider(); String getTemplate(); http://git-wip-us.apache.org/repos/asf/tomee/blob/e386526f/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java index 5771632..5e0690f 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/AbstractService.java @@ -51,17 +51,25 @@ public abstract class AbstractService implements Service { @XmlValue @XmlJavaTypeAdapter(PropertiesAdapter.class) protected Properties properties; + @XmlAttribute(required = true) protected String id; + @XmlAttribute protected String jar; + @XmlAttribute protected String provider; + @XmlAttribute protected String type; + @XmlAttribute protected String classpath; + @XmlAttribute(name = "classpath-api") + protected String classpathAPI; + /** * Mutually exclusive with 'provider' */ @@ -205,6 +213,15 @@ public abstract class AbstractService implements Service { this.className = className; } + @Override + public String getClasspathAPI() { + return classpathAPI; + } + + public void setClasspathAPI(final String classpathAPI) { + this.classpathAPI = classpathAPI; + } + public String getConstructor() { return constructor; } http://git-wip-us.apache.org/repos/asf/tomee/blob/e386526f/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java index 9f14676..63da4dc 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/sys/StackHandler.java @@ -183,6 +183,9 @@ public class StackHandler extends DefaultHandler { if (attributes.getValue("classpath") != null) { service.setClasspath(attributes.getValue("classpath")); } + if (attributes.getValue("classpath-api") != null) { + service.setClasspathAPI(attributes.getValue("classpath-api")); + } checkAttributes(attributes, getAttributes()); } http://git-wip-us.apache.org/repos/asf/tomee/blob/e386526f/container/openejb-core/src/test/java/org/apache/openejb/resource/ClasspathAPITest.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/test/java/org/apache/openejb/resource/ClasspathAPITest.java b/container/openejb-core/src/test/java/org/apache/openejb/resource/ClasspathAPITest.java new file mode 100644 index 0000000..068ee4b --- /dev/null +++ b/container/openejb-core/src/test/java/org/apache/openejb/resource/ClasspathAPITest.java @@ -0,0 +1,69 @@ +/* + * 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.openejb.resource; + +import org.apache.openejb.junit.ApplicationComposer; +import org.apache.openejb.testing.Classes; +import org.apache.openejb.testing.Configuration; +import org.apache.openejb.testng.PropertiesBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.annotation.Resource; +import java.util.Properties; +import java.util.concurrent.Callable; + +import static org.apache.openejb.loader.JarLocation.jarLocation; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +@Classes +@RunWith(ApplicationComposer.class) +public class ClasspathAPITest { + @Configuration + public Properties config() { + return new PropertiesBuilder() + .p("r", "new://Resource?class-name=org.apache.openejb.resource.ClasspathAPITest$MyImpl&" + + "classpath-api=java.util.concurrent.Callable&" + + "classpath=" + jarLocation(ClasspathAPITest.class).toURI().toASCIIString()) + .build(); + } + + @Resource(name = "r") + private Callable<String> impl; + + @Test + public void check() throws Exception { + assertTrue(Callable.class.isInstance(impl)); + assertFalse(Runnable.class.isInstance(impl)); + assertEquals("ok", impl.call()); + } + + public static class MyImpl implements Runnable, Callable<String> { + @Override + public void run() { + fail(); + } + + @Override + public String call() throws Exception { + return "ok"; + } + } +}