geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rmannibu...@apache.org
Subject svn commit: r1831698 - in /geronimo/components/config/trunk/impl/src: main/java/org/apache/geronimo/config/ main/java/org/apache/geronimo/config/cdi/ test/java/org/apache/geronimo/config/test/internal/
Date Wed, 16 May 2018 10:55:28 GMT
Author: rmannibucau
Date: Wed May 16 10:55:28 2018
New Revision: 1831698

URL: http://svn.apache.org/viewvc?rev=1831698&view=rev
Log:
proxy based impl

Added:
    geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/AnyLiteral.java
      - copied, changed from r1831697, geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/DefaultLiteral.java
    geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigurationHandler.java
    geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ProxyBean.java
    geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/PoxyTest.java
      - copied, changed from r1831697, geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
Modified:
    geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java
    geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java

Modified: geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java?rev=1831698&r1=1831697&r2=1831698&view=diff
==============================================================================
--- geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java
(original)
+++ geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/ConfigImpl.java
Wed May 16 10:55:28 2018
@@ -156,7 +156,7 @@ public class ConfigImpl implements Confi
     public synchronized void addConfigSources(List<ConfigSource> configSourcesToAdd)
{
         List<ConfigSource> allConfigSources = new ArrayList<>(configSources);
 
-        configSourcesToAdd.forEach(cs -> cs.setOnAttributeChange(this::reportConfigChange));
+        // TODO(To Be Fixed): configSourcesToAdd.forEach(cs -> cs.setOnAttributeChange(this::reportConfigChange));
         allConfigSources.addAll(configSourcesToAdd);
 
         // finally put all the configSources back into the map
@@ -181,7 +181,7 @@ public class ConfigImpl implements Confi
         converters.put(type, converter);
     }
 
-    @Override
+    // TODO(to be fixed) @Override
     public void registerConfigChangedListener(Consumer<Set<String>> configChangedListener)
{
         configListenerLock.writeLock().lock();
         try {

Copied: geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/AnyLiteral.java
(from r1831697, geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/DefaultLiteral.java)
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/AnyLiteral.java?p2=geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/AnyLiteral.java&p1=geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/DefaultLiteral.java&r1=1831697&r2=1831698&rev=1831698&view=diff
==============================================================================
--- geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/DefaultLiteral.java
(original)
+++ geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/AnyLiteral.java
Wed May 16 10:55:28 2018
@@ -19,9 +19,9 @@
 
 package org.apache.geronimo.config.cdi;
 
-import javax.enterprise.inject.Default;
+import javax.enterprise.inject.Any;
 import javax.enterprise.util.AnnotationLiteral;
 
-class DefaultLiteral extends AnnotationLiteral<Default> implements Default {
-    public static Default INSTANCE = new DefaultLiteral();
+class AnyLiteral extends AnnotationLiteral<Any> implements Any {
+    public static Any INSTANCE = new AnyLiteral();
 }

Modified: geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java?rev=1831698&r1=1831697&r2=1831698&view=diff
==============================================================================
--- geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
(original)
+++ geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigExtension.java
Wed May 16 10:55:28 2018
@@ -16,6 +16,8 @@
  */
 package org.apache.geronimo.config.cdi;
 
+import static java.util.stream.Collectors.toList;
+
 import org.apache.geronimo.config.DefaultConfigProvider;
 import org.eclipse.microprofile.config.Config;
 import org.eclipse.microprofile.config.ConfigProvider;
@@ -29,18 +31,24 @@ import javax.enterprise.inject.spi.Befor
 import javax.enterprise.inject.spi.DeploymentException;
 import javax.enterprise.inject.spi.Extension;
 import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
 import javax.enterprise.inject.spi.ProcessInjectionPoint;
 import javax.inject.Provider;
+
+import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
@@ -60,6 +68,18 @@ public class ConfigExtension implements
     }
 
     private Set<InjectionPoint> injectionPoints = new HashSet<>();
+    private Set<Class<?>> proxies = new HashSet<>();
+    private List<Class<?>> validProxies;
+    private List<ProxyBean<?>> proxyBeans;
+
+
+    public void findProxies(@Observes ProcessAnnotatedType<?> pat) {
+        final Class<?> javaClass = pat.getAnnotatedType().getJavaClass();
+        if (javaClass.isInterface() &&
+                Stream.of(javaClass.getMethods()).anyMatch(m -> m.isAnnotationPresent(ConfigProperty.class)))
{
+            proxies.add(javaClass);
+        }
+    }
 
 
     public void collectConfigProducer(@Observes ProcessInjectionPoint<?, ?> pip) {
@@ -85,12 +105,24 @@ public class ConfigExtension implements
         types.stream()
                 .map(type -> new ConfigInjectionBean(bm, type))
                 .forEach(abd::addBean);
+
+        validProxies = proxies.stream()
+                .filter(this::isValidProxy)
+                .collect(toList());
+        if (validProxies.size() == proxies.size()) {
+            proxyBeans = validProxies.stream()
+                                     .map((Function<Class<?>, ? extends ProxyBean<?>>)
ProxyBean::new)
+                                     .collect(toList());
+            proxyBeans.forEach(abd::addBean);
+        } // else there are errors
     }
 
     public void validate(@Observes AfterDeploymentValidation add) {
         List<String> deploymentProblems = new ArrayList<>();
 
         config = ConfigProvider.getConfig();
+        proxyBeans.forEach(b -> b.init(config));
+        proxyBeans.clear();
 
         for (InjectionPoint injectionPoint : injectionPoints) {
             Type type = injectionPoint.getType();
@@ -115,12 +147,23 @@ public class ConfigExtension implements
                                                              + String.join("\n", deploymentProblems)));
         }
 
+        if (validProxies.size() != proxies.size()) {
+            proxies.stream()
+                   .filter(p -> !validProxies.contains(p))
+                   .forEach(p -> add.addDeploymentProblem(
+                           new DeploymentException("Invalid proxy: " + p + ". All method
should have @ConfigProperty.")));
+        }
+        proxies.clear();
     }
 
     public void shutdown(@Observes BeforeShutdown bsd) {
         DefaultConfigProvider.instance().releaseConfig(config);
     }
 
+    private boolean isValidProxy(final Class<?> api) {
+        return Stream.of(api.getMethods())
+                     .allMatch(m -> m.isAnnotationPresent(ConfigProperty.class) || Object.class
== m.getDeclaringClass());
+    }
 
     static boolean isDefaultUnset(String defaultValue) {
         return defaultValue.equals(ConfigProperty.UNCONFIGURED_VALUE);

Added: geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigurationHandler.java
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigurationHandler.java?rev=1831698&view=auto
==============================================================================
--- geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigurationHandler.java
(added)
+++ geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ConfigurationHandler.java
Wed May 16 10:55:28 2018
@@ -0,0 +1,104 @@
+/*
+ * 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.geronimo.config.cdi;
+
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.toMap;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+
+public class ConfigurationHandler implements InvocationHandler {
+    private final Config config;
+    private final Map<Method, MethodMeta> methodMetas;
+
+    ConfigurationHandler(final Config config, final Class<?> api) {
+        this.config = config;
+        this.methodMetas = Stream.of(api.getMethods())
+            .filter(m -> m.isAnnotationPresent(ConfigProperty.class))
+            .collect(toMap(identity(), MethodMeta::new));
+    }
+
+    @Override
+    public Object invoke(final Object proxy, final Method method, final Object[] args) throws
Throwable {
+        if (Object.class == method.getDeclaringClass()) {
+            try {
+                return method.invoke(this, args);
+            } catch (final InvocationTargetException ite) {
+                throw ite.getTargetException();
+            }
+        }
+        final MethodMeta methodMeta = methodMetas.get(method);
+        if (methodMeta != null) {
+            return methodMeta.read(config);
+        }
+        return null;
+    }
+
+    // todo: list, set etc handling but config API is not that friendly for now (Class vs
Type)
+    private static class MethodMeta {
+        private final String key;
+        private final Object defaultValue;
+        private final Class type;
+        private final boolean optional;
+
+        private MethodMeta(final Method m) {
+            final ConfigProperty annotation = m.getAnnotation(ConfigProperty.class);
+            optional = Optional.class == m.getReturnType();
+            type = optional ?
+                    Class.class.cast(ParameterizedType.class.cast(m.getGenericReturnType()).getActualTypeArguments()[0])
:
+                    m.getReturnType();
+            key = annotation.name().isEmpty() ? m.getDeclaringClass().getName() + "." + m.getName()
: annotation.name();
+            final boolean hasDefault = !annotation.defaultValue().equals(ConfigProperty.UNCONFIGURED_VALUE);
+            if (type == long.class || type == Long.class) {
+                defaultValue = hasDefault ? Long.parseLong(annotation.defaultValue()) : 0L;
+            } else if (type == int.class || type == Integer.class) {
+                defaultValue = hasDefault ? Integer.parseInt(annotation.defaultValue()) :
0;
+            } else if (type == double.class || type == Double.class) {
+                defaultValue = hasDefault ? Double.parseDouble(annotation.defaultValue())
: 0.;
+            } else if (type == float.class || type == Float.class) {
+                defaultValue = hasDefault ? Float.parseFloat(annotation.defaultValue()) :
0f;
+            } else if (type == short.class || type == Short.class) {
+                defaultValue = hasDefault ? Short.parseShort(annotation.defaultValue()) :
(short) 0;
+            } else if (type == char.class || type == Character.class) {
+                defaultValue = hasDefault ? annotation.defaultValue().charAt(0) : (type ==
char.class ? (char) 0 : null);
+            } else if (type == String.class) {
+                defaultValue = hasDefault ? annotation.defaultValue() : null;
+            } else if (hasDefault) {
+                throw new IllegalArgumentException("Unsupported default for " + m);
+            } else {
+                defaultValue = null;
+            }
+        }
+
+        Object read(final Config config) {
+            final Optional optionalValue = config.getOptionalValue(key, type);
+            if (optional) {
+                return optionalValue;
+            }
+            return optionalValue.orElse(defaultValue);
+        }
+    }
+}

Added: geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ProxyBean.java
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ProxyBean.java?rev=1831698&view=auto
==============================================================================
--- geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ProxyBean.java
(added)
+++ geronimo/components/config/trunk/impl/src/main/java/org/apache/geronimo/config/cdi/ProxyBean.java
Wed May 16 10:55:28 2018
@@ -0,0 +1,119 @@
+/*
+ * 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.geronimo.config.cdi;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptySet;
+
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.PassivationCapable;
+
+import org.eclipse.microprofile.config.Config;
+
+public class ProxyBean<T> implements Bean<T>, PassivationCapable {
+    private static final Set<Annotation> QUALIFIERS = new HashSet<>(
+            asList(DefaultLiteral.INSTANCE, AnyLiteral.INSTANCE));
+    private final Class<T> beanClass;
+    private final Set<Type> types;
+    private final Set<Annotation> qualifiers;
+    private final String id;
+    private Config config;
+
+    ProxyBean(final Class<T> api) {
+        this.beanClass = api;
+        this.qualifiers = QUALIFIERS;
+        this.types = new HashSet<>(asList(api, Serializable.class));
+        this.id = ProxyBean.class.getName() + "[" + api.getName() + "]";
+    }
+
+    void init(final Config config) {
+        this.config = config;
+    }
+
+    @Override
+    public Set<InjectionPoint> getInjectionPoints() {
+        return emptySet();
+    }
+
+    @Override
+    public Class<?> getBeanClass() {
+        return beanClass;
+    }
+
+    @Override
+    public boolean isNullable() {
+        return false;
+    }
+
+    @Override
+    public T create(final CreationalContext<T> context) {
+        return (T) Proxy.newProxyInstance(
+                Thread.currentThread().getContextClassLoader(),
+                new Class<?>[] { beanClass },
+                new ConfigurationHandler(config, beanClass));
+    }
+
+    @Override
+    public void destroy(final T instance, final CreationalContext<T> context) {
+        // no-op
+    }
+
+    @Override
+    public Set<Type> getTypes() {
+        return types;
+    }
+
+    @Override
+    public Set<Annotation> getQualifiers() {
+        return qualifiers;
+    }
+
+    @Override
+    public Class<? extends Annotation> getScope() {
+        return ApplicationScoped.class;
+    }
+
+    @Override
+    public String getName() {
+        return null;
+    }
+
+    @Override
+    public Set<Class<? extends Annotation>> getStereotypes() {
+        return emptySet();
+    }
+
+    @Override
+    public boolean isAlternative() {
+        return false;
+    }
+
+    @Override
+    public String getId() {
+        return id;
+    }
+}

Copied: geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/PoxyTest.java
(from r1831697, geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java)
URL: http://svn.apache.org/viewvc/geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/PoxyTest.java?p2=geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/PoxyTest.java&p1=geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java&r1=1831697&r2=1831698&rev=1831698&view=diff
==============================================================================
--- geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/ProviderTest.java
(original)
+++ geronimo/components/config/trunk/impl/src/test/java/org/apache/geronimo/config/test/internal/PoxyTest.java
Wed May 16 10:55:28 2018
@@ -16,7 +16,8 @@
  */
 package org.apache.geronimo.config.test.internal;
 
-import javax.enterprise.context.RequestScoped;
+import static org.testng.Assert.assertEquals;
+
 import javax.inject.Inject;
 import javax.inject.Provider;
 
@@ -30,15 +31,17 @@ import org.jboss.shrinkwrap.api.spec.Web
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
-public class ProviderTest extends Arquillian {
-    private static final String SOME_KEY = "org.apache.geronimo.config.test.internal.somekey";
+public class PoxyTest extends Arquillian {
+    private static final String SOME_KEY = SomeProxy.class.getName() + ".key";
+    private static final String SOME_OTHER_KEY = SomeProxy.class.getName() + ".key2";
 
     @Deployment
     public static WebArchive deploy() {
-        System.setProperty(SOME_KEY, "someval");
+        System.setProperty(SOME_KEY, "yeah");
+        System.setProperty(SOME_OTHER_KEY, "123");
         JavaArchive testJar = ShrinkWrap
-                .create(JavaArchive.class, "configProviderTest.jar")
-                .addClasses(ProviderTest.class, SomeBean.class)
+                .create(JavaArchive.class, "PoxyTest.jar")
+                .addClasses(PoxyTest.class, SomeProxy.class)
                 .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
 
         return ShrinkWrap
@@ -46,31 +49,28 @@ public class ProviderTest extends Arquil
                 .addAsLibrary(testJar);
     }
 
-    private @Inject SomeBean someBean;
-
+    @Inject
+    private SomeProxy proxy;
 
     @Test
-    public void testConfigProvider() {
-        System.setProperty(SOME_KEY, "someval");
-        String myconfig = someBean.getMyconfig();
-        Assert.assertEquals(myconfig, "someval");
-
-        System.setProperty(SOME_KEY, "otherval");
-        myconfig = someBean.getMyconfig();
-        Assert.assertEquals(myconfig, "otherval");
+    public void test() {
+        assertEquals(proxy.key(), "yeah");
+        assertEquals(proxy.renamed(), "yeah");
+        assertEquals(proxy.key2(), 123);
+        assertEquals(proxy.key3(), "def");
     }
 
+    public interface SomeProxy {
+        @ConfigProperty
+        int key2();
 
-    @RequestScoped
-    public static class SomeBean {
+        @ConfigProperty(defaultValue = "def")
+        String key3();
 
-        @Inject
-        @ConfigProperty(name=SOME_KEY)
-        private Provider<String> myconfig;
-
-        public String getMyconfig() {
-            return myconfig.get();
-        }
+        @ConfigProperty
+        String key();
 
+        @ConfigProperty(name = "org.apache.geronimo.config.test.internal.PoxyTest$SomeProxy.key")
+        String renamed();
     }
 }



Mime
View raw message