Repository: tomee
Updated Branches:
  refs/heads/master 066da5ed0 -> e386526f1


TOMEE-1846 adding Template API


Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/a5d08be1
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/a5d08be1
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/a5d08be1

Branch: refs/heads/master
Commit: a5d08be10d9ea4b20a9179494fbc9ced140e5439
Parents: 066da5e
Author: Romain manni-Bucau <rmannibu...@gmail.com>
Authored: Fri Jun 17 12:24:19 2016 +0200
Committer: Romain manni-Bucau <rmannibu...@gmail.com>
Committed: Fri Jun 17 12:24:19 2016 +0200

----------------------------------------------------------------------
 .../apache/openejb/api/resource/Template.java   |  29 ++++
 .../openejb/config/ConfigurationFactory.java    | 132 ++++++++++++-------
 .../java/org/apache/openejb/config/Service.java |   2 +
 .../openejb/config/sys/AbstractService.java     |  10 ++
 .../apache/openejb/config/sys/StackHandler.java |   1 +
 .../apache/openejb/resource/TemplateTest.java   |  63 +++++++++
 6 files changed, 189 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tomee/blob/a5d08be1/container/openejb-api/src/main/java/org/apache/openejb/api/resource/Template.java
----------------------------------------------------------------------
diff --git 
a/container/openejb-api/src/main/java/org/apache/openejb/api/resource/Template.java
 
b/container/openejb-api/src/main/java/org/apache/openejb/api/resource/Template.java
new file mode 100644
index 0000000..bb56f28
--- /dev/null
+++ 
b/container/openejb-api/src/main/java/org/apache/openejb/api/resource/Template.java
@@ -0,0 +1,29 @@
+/*
+ * 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.api.resource;
+
+/**
+ * Called to setup a service/resource.
+ *
+ * It is called at the very beginning of resource configuration (ie before 
provider are resolved)
+ * so the resource can be fully configured.
+ *
+ * @param <T> Service or AbstractService or Resource.
+ */
+public interface Template<T> {
+    void configure(T resource);
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/a5d08be1/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 99a91b9..e9fd1d1 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
@@ -22,6 +22,7 @@ import org.apache.openejb.OpenEJBException;
 import org.apache.openejb.Vendor;
 import org.apache.openejb.api.Proxy;
 import org.apache.openejb.api.resource.PropertiesResourceProvider;
+import org.apache.openejb.api.resource.Template;
 import org.apache.openejb.assembler.classic.AppInfo;
 import org.apache.openejb.assembler.classic.Assembler;
 import org.apache.openejb.assembler.classic.BmpEntityContainerInfo;
@@ -790,6 +791,7 @@ public class ConfigurationFactory implements 
OpenEjbConfigurationFactory {
                 service.setConstructor(map.remove("constructor"));
                 service.setFactoryName(map.remove("factory-name"));
                 
service.setPropertiesProvider(map.remove("properties-provider"));
+                service.setTemplate(map.remove("template"));
 
                 final String cp = map.remove("classpath");
                 if (null != cp) {
@@ -1156,30 +1158,23 @@ public class ConfigurationFactory implements 
OpenEjbConfigurationFactory {
                 }
             }
 
-            final String providerType = getProviderType(service);
-
-            final ServiceProvider provider = resolveServiceProvider(service, 
infoType);
-
-            if (provider == null) {
-                final List<ServiceProvider> providers = 
ServiceUtils.getServiceProvidersByServiceType(providerType);
-                final StringBuilder sb = new StringBuilder();
-                final List<String> types = new ArrayList<String>();
-                for (final ServiceProvider p : providers) {
-                    for (final String type : p.getTypes()) {
-                        if (types.contains(type)) {
-                            continue;
-                        }
-                        types.add(type);
-                        sb.append(System.getProperty("line.separator"));
-                        sb.append("  <").append(p.getService());
-                        sb.append(" 
id=\"").append(service.getId()).append('"');
-                        sb.append(" type=\"").append(type).append("\"/>");
-                    }
+            {
+                String template = service.getTemplate();
+                if (template == null) {
+                    template = 
SystemInstance.get().getProperty(Template.class.getName());
+                }
+                if (template != null) {
+                    template = unaliasPropertiesProvider(template);
+
+                    // don't trim them, user wants to handle it himself, let 
him do it
+                    final ObjectRecipe recipe = newObjectRecipe(template);
+                    recipe.setProperty("serviceId", service.getId());
+                    // note: we can also use reflection if needed to limit the 
dependency
+                    Template.class.cast(recipe.create()).configure(service);
                 }
-                final String noProviderMessage = 
messages.format("configureService.noProviderForService", providerType, 
service.getId(), service.getType(), service.getProvider(), sb.toString());
-                throw new NoSuchProviderException(noProviderMessage);
             }
 
+            final ServiceProvider provider = getServiceProvider(service, 
infoType);
             if (service.getId() == null) {
                 service.setId(provider.getId());
             }
@@ -1225,39 +1220,33 @@ public class ConfigurationFactory implements 
OpenEjbConfigurationFactory {
                 props.putAll(provider.getProperties());
             }
 
-            props.putAll(serviceProperties);
-            props.putAll(overrides);
-
-            // force user properties last
-            String propertiesProvider = service.getPropertiesProvider();
-            if (propertiesProvider == null) {
-                propertiesProvider = 
SystemInstance.get().getProperty(PropertiesResourceProvider.class.getName());
+            if (serviceProperties != null) {
+                props.putAll(serviceProperties);
             }
-            if (propertiesProvider != null) {
-                propertiesProvider = 
unaliasPropertiesProvider(propertiesProvider);
-
-                // don't trim them, user wants to handle it himself, let him 
do it
-                final ObjectRecipe recipe = new 
ObjectRecipe(propertiesProvider);
-                recipe.allow(Option.CASE_INSENSITIVE_PROPERTIES);
-                recipe.allow(Option.PRIVATE_PROPERTIES);
-                recipe.allow(Option.FIELD_INJECTION);
-                recipe.allow(Option.NAMED_PARAMETERS);
-                recipe.allow(Option.IGNORE_MISSING_PROPERTIES);
-                recipe.setFactoryMethod("provides");
-                recipe.setProperty("serviceId", service.getId());
-                recipe.setProperties(props);
-                recipe.setProperty("properties", props); // let user get all 
config
-                final Properties p = Properties.class.cast(recipe.create());
+            props.putAll(overrides);
 
-                props.putAll(p);
+            {// force user properties last
+                String propertiesProvider = service.getPropertiesProvider();
+                if (propertiesProvider == null) {
+                    propertiesProvider = 
SystemInstance.get().getProperty(PropertiesResourceProvider.class.getName());
+                }
+                if (propertiesProvider != null) {
+                    propertiesProvider = 
unaliasPropertiesProvider(propertiesProvider);
+
+                    // don't trim them, user wants to handle it himself, let 
him do it
+                    final ObjectRecipe recipe = 
newObjectRecipe(propertiesProvider);
+                    recipe.setFactoryMethod("provides");
+                    recipe.setProperty("serviceId", service.getId());
+                    recipe.setProperties(props);
+                    recipe.setProperty("properties", props); // let user get 
all config
+                    final Properties p = 
Properties.class.cast(recipe.create());
+
+                    props.putAll(p);
+                }
             }
 
             props.remove(IGNORE_DEFAULT_VALUES_PROP);
 
-            if (providerType != null && 
!provider.getService().equals(providerType)) {
-                throw new 
OpenEJBException(messages.format("configureService.wrongProviderType", 
service.getId(), providerType));
-            }
-
             final T info;
             try {
                 info = infoType.newInstance();
@@ -1305,6 +1294,49 @@ public class ConfigurationFactory implements 
OpenEjbConfigurationFactory {
         }
     }
 
+    private <T extends ServiceInfo> ServiceProvider getServiceProvider(
+            final org.apache.openejb.config.Service service,
+            final Class<? extends T> infoType) throws OpenEJBException {
+        final String providerType = getProviderType(service);
+
+        final ServiceProvider provider = resolveServiceProvider(service, 
infoType);
+
+        if (provider == null) {
+            final List<ServiceProvider> providers = 
ServiceUtils.getServiceProvidersByServiceType(providerType);
+            final StringBuilder sb = new StringBuilder();
+            final List<String> types = new ArrayList<String>();
+            for (final ServiceProvider p : providers) {
+                for (final String type : p.getTypes()) {
+                    if (types.contains(type)) {
+                        continue;
+                    }
+                    types.add(type);
+                    sb.append(System.getProperty("line.separator"));
+                    sb.append("  <").append(p.getService());
+                    sb.append(" id=\"").append(service.getId()).append('"');
+                    sb.append(" type=\"").append(type).append("\"/>");
+                }
+            }
+            final String noProviderMessage = 
messages.format("configureService.noProviderForService", providerType, 
service.getId(), service.getType(), service.getProvider(), sb.toString());
+            throw new NoSuchProviderException(noProviderMessage);
+        }
+
+        if (!provider.getService().equals(providerType)) {
+            throw new 
OpenEJBException(messages.format("configureService.wrongProviderType", 
service.getId(), providerType));
+        }
+        return provider;
+    }
+
+    private ObjectRecipe newObjectRecipe(final String template) {
+        final ObjectRecipe recipe = new ObjectRecipe(template);
+        recipe.allow(Option.CASE_INSENSITIVE_PROPERTIES);
+        recipe.allow(Option.PRIVATE_PROPERTIES);
+        recipe.allow(Option.FIELD_INJECTION);
+        recipe.allow(Option.NAMED_PARAMETERS);
+        recipe.allow(Option.IGNORE_MISSING_PROPERTIES);
+        return recipe;
+    }
+
     private static String unaliasPropertiesProvider(final String 
propertiesProvider) {
         switch (propertiesProvider.toLowerCase(Locale.ENGLISH)) {
             case "heroku":
@@ -1318,6 +1350,10 @@ public class ConfigurationFactory implements 
OpenEjbConfigurationFactory {
         }
     }
 
+    private static String unaliasTemplate(final String value) {
+        return value;
+    }
+
     /**
      * Takes a raw unparsed string expected to be in jvm classpath syntax
      * and parses it, producing a collection of URIs representing the absolute

http://git-wip-us.apache.org/repos/asf/tomee/blob/a5d08be1/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 7ca596d..58d9792 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
@@ -67,4 +67,6 @@ public interface Service {
     String getClasspath();
 
     String getPropertiesProvider();
+
+    String getTemplate();
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/a5d08be1/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 6181df5..5771632 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
@@ -83,6 +83,8 @@ public abstract class AbstractService implements Service {
     @XmlAttribute(name = "properties-provider")
     private String propertiesProvider;
 
+    @XmlAttribute(name = "template")
+    private String template;
 
     protected AbstractService(final String id) {
         this(id, null, null);
@@ -227,6 +229,14 @@ public abstract class AbstractService implements Service {
         this.classpath = classpath;
     }
 
+    public String getTemplate() {
+        return template;
+    }
+
+    public void setTemplate(final String template) {
+        this.template = template;
+    }
+
     @Override
     public boolean equals(final Object o) {
         if (this == o) {

http://git-wip-us.apache.org/repos/asf/tomee/blob/a5d08be1/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 965c2b5..9f14676 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
@@ -224,6 +224,7 @@ public class StackHandler extends DefaultHandler {
             service.setJndi(attributes.getValue("jndi"));
             service.setPostConstruct(attributes.getValue("post-construct"));
             service.setPreDestroy(attributes.getValue("pre-destroy"));
+            service.setTemplate(attributes.getValue("template"));
             
service.setPropertiesProvider(attributes.getValue("property-provider"));
             if (service.getPropertiesProvider() == null) {
                 
service.setPropertiesProvider(attributes.getValue("properties-provider"));

http://git-wip-us.apache.org/repos/asf/tomee/blob/a5d08be1/container/openejb-core/src/test/java/org/apache/openejb/resource/TemplateTest.java
----------------------------------------------------------------------
diff --git 
a/container/openejb-core/src/test/java/org/apache/openejb/resource/TemplateTest.java
 
b/container/openejb-core/src/test/java/org/apache/openejb/resource/TemplateTest.java
new file mode 100644
index 0000000..9ad1eff
--- /dev/null
+++ 
b/container/openejb-core/src/test/java/org/apache/openejb/resource/TemplateTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.api.resource.Template;
+import org.apache.openejb.config.sys.AbstractService;
+import org.apache.openejb.junit.ApplicationComposer;
+import org.apache.openejb.testing.Classes;
+import org.apache.openejb.testing.Configuration;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.annotation.Resource;
+import java.util.Properties;
+
+import static org.junit.Assert.assertEquals;
+
+@Classes
+@RunWith(ApplicationComposer.class)
+public class TemplateTest {
+    @Resource(name = "r1")
+    private MyResource r1;
+
+    @Test
+    public void validAliases() {
+        assertEquals("r1", r1.value);
+    }
+
+    @Configuration
+    public Properties config() {
+        final Properties p = new Properties();
+        p.put("r1", 
"new://Resource?template=org.apache.openejb.resource.TemplateTest$MyTemplate");
+        return p;
+    }
+
+    public static class MyResource {
+        private String value;
+    }
+
+    public static class MyTemplate implements Template<AbstractService> {
+        private String serviceId;
+
+        @Override
+        public void configure(final AbstractService resource) {
+            resource.setClassName(MyResource.class.getName());
+            resource.getProperties().put("value", serviceId);
+        }
+    }
+}

Reply via email to