You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by rm...@apache.org on 2016/11/13 20:13:00 UTC

svn commit: r1769543 - in /openwebbeans/meecrowave/trunk: meecrowave-core/src/main/java/org/apache/meecrowave/ meecrowave-core/src/main/java/org/apache/meecrowave/runner/ meecrowave-core/src/test/java/org/apache/meecrowave/ meecrowave-doc/src/main/java...

Author: rmannibucau
Date: Sun Nov 13 20:13:00 2016
New Revision: 1769543

URL: http://svn.apache.org/viewvc?rev=1769543&view=rev
Log:
Cli extension PoC

Modified:
    openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
    openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/runner/Cli.java
    openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
    openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/CliConfiguration.java
    openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/Configuration.java

Modified: openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java?rev=1769543&r1=1769542&r2=1769543&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java Sun Nov 13 20:13:00 2016
@@ -86,8 +86,6 @@ import java.util.TreeMap;
 import java.util.function.Consumer;
 import java.util.stream.Stream;
 
-import static java.beans.Introspector.decapitalize;
-import static java.lang.Character.toUpperCase;
 import static java.util.Collections.emptyList;
 import static java.util.Collections.emptySet;
 import static java.util.Optional.ofNullable;
@@ -873,10 +871,28 @@ public class Meecrowave implements AutoC
         @CliOption(name = "log4j2-jul-bridge", description = "Should JUL logs be redirected to Log4j2 - only works before JUL usage.")
         private boolean useLog4j2JulLogManager = System.getProperty("java.util.logging.manager") == null;
 
+        private final Map<Class<?>, Object> extensions = new HashMap<>();
+
         public Builder() { // load defaults
             loadFrom("meecrowave.properties");
         }
 
+        public <T> T getExtension(final Class<T> extension) {
+            // in the cli we read the values from the cli but in other mode from properties
+            // to ensure we can do the same in all modes keeping a nice cli
+            return extension.cast(extensions.computeIfAbsent(extension, k -> {
+                try {
+                    return bind(k.newInstance());
+                } catch (final InstantiationException | IllegalAccessException e) {
+                    throw new IllegalArgumentException(e);
+                }
+            }));
+        }
+
+        public void setExtension(final Class<?> type, final Object value) {
+            extensions.put(type, value);
+        }
+
         public String getJsonpBufferStrategy() {
             return jsonpBufferStrategy;
         }
@@ -1548,57 +1564,38 @@ public class Meecrowave implements AutoC
             }
         }
 
-        public <T> T bind(final T instance, final String prefix) {
-            ofNullable(properties.stringPropertyNames()).orElse(emptySet()).stream()
-                    .filter(p -> p.startsWith(prefix))
-                    .forEach(p -> {
-                        final String value = properties.getProperty(p);
-
-                        // convert iphen case to camel case (a-simple-sample becomes aSimpleSample)
-                        final int startIdx = prefix.length();
-                        final StringBuilder nameBuilder = new StringBuilder(p.length() /*ok this is wrong but allocates something big enough*/);
-                        nameBuilder.append(decapitalize(p.substring(startIdx, startIdx + 1)));
-                        boolean uppercase = false;
-                        for (int i = 1; i < p.length() - prefix.length(); i++) {
-                            final char c = p.charAt(startIdx + i);
-                            if (c == '-') {
-                                uppercase = true;
-                            } else if (uppercase) {
-                                nameBuilder.append(toUpperCase(c));
-                                uppercase = false;
-                            } else {
-                                nameBuilder.append(c);
+        public <T> T bind(final T instance) {
+            Class<? extends Object> type = instance.getClass();
+            do {
+                Stream.of(type.getDeclaredFields())
+                        .filter(f -> f.isAnnotationPresent(CliOption.class))
+                        .forEach(f -> {
+                            final CliOption annotation = f.getAnnotation(CliOption.class);
+                            final String value = properties.getProperty(annotation.name());
+                            if (value == null) {
+                                return;
                             }
-                        }
 
-                        final String name = nameBuilder.toString();
-                        Class<?> current = instance.getClass();
-                        do {
+                            if (!f.isAccessible()) {
+                                f.setAccessible(true);
+                            }
+                            final Class<?> t = f.getType();
                             try {
-                                final Field f = instance.getClass().getDeclaredField(name);
-                                if (!f.isAccessible()) {
-                                    f.setAccessible(true);
-                                }
-                                final Class<?> type = f.getType();
-                                if (type == String.class) {
+                                if (t == String.class) {
                                     f.set(instance, value);
-                                } else if (type == int.class) {
+                                } else if (t == int.class) {
                                     f.set(instance, Integer.parseInt(value));
-                                } else if (type == boolean.class) {
+                                } else if (t == boolean.class) {
                                     f.set(instance, Boolean.parseBoolean(value));
                                 } else {
-                                    throw new IllegalArgumentException("Unsupported type " + type);
+                                    throw new IllegalArgumentException("Unsupported type " + t);
                                 }
-                                return;
-                            } catch (final NoSuchFieldException e) {
-                                // continue
-                            } catch (final IllegalAccessException e) {
-                                new LogFacade(Meecrowave.class.getName()).warn("Can't set " + value + " to " + name + " on " + instance);
+                            } catch (final IllegalAccessException iae) {
+                                throw new IllegalStateException(iae);
                             }
-                            current = current.getSuperclass();
-                        } while (current != Object.class && current != null);
-                        throw new IllegalArgumentException("Didn't find " + name + " on " + instance);
-                    });
+                        });
+                type = type.getSuperclass();
+            } while (type != Object.class);
             return instance;
         }
     }

Modified: openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/runner/Cli.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/runner/Cli.java?rev=1769543&r1=1769542&r2=1769543&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/runner/Cli.java (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/runner/Cli.java Sun Nov 13 20:13:00 2016
@@ -22,7 +22,6 @@ import org.apache.catalina.connector.Con
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.CommandLineParser;
 import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
 import org.apache.commons.cli.PosixParser;
 import org.apache.meecrowave.Meecrowave;
@@ -36,10 +35,14 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.ServiceLoader;
 import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 import static java.util.Optional.ofNullable;
+import static java.util.function.Function.identity;
 import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
 
 @Vetoed
 public class Cli {
@@ -48,17 +51,23 @@ public class Cli {
     }
 
     public static void main(final String[] args) {
-        final Options options = new Options();
+        final org.apache.commons.cli.Options options = new org.apache.commons.cli.Options();
         options.addOption("help", false, "Show help");
         options.addOption("context", true, "The context to use to deploy the webapp");
         options.addOption("webapp", true, "Location of the webapp, if not set the classpath will be deployed");
         final List<Field> fields = Stream.of(Meecrowave.Builder.class.getDeclaredFields())
                 .filter(f -> f.isAnnotationPresent(CliOption.class))
                 .collect(toList());
+        final Map<Object, List<Field>> propertiesOptions = StreamSupport.stream(ServiceLoader.load(Options.class).spliterator(), false)
+                .collect(toMap(identity(), o -> Stream.of(o.getClass().getDeclaredFields()).filter(f -> f.isAnnotationPresent(CliOption.class)).collect(toList())));
         fields.forEach(f -> {
             final CliOption opt = f.getAnnotation(CliOption.class);
             options.addOption(null, opt.name(), f.getType() != boolean.class, opt.description());
         });
+        propertiesOptions.values().forEach(all -> all.forEach(f -> {
+            final CliOption opt = f.getAnnotation(CliOption.class);
+            options.addOption(null, opt.name(), f.getType() != boolean.class, opt.description());
+        }));
 
         final CommandLineParser parser = new PosixParser();
         final CommandLine line;
@@ -74,7 +83,7 @@ public class Cli {
             return;
         }
 
-        try (final Meecrowave meecrowave = new Meecrowave(buildConfig(line, fields))) {
+        try (final Meecrowave meecrowave = new Meecrowave(buildConfig(line, fields, propertiesOptions))) {
             final String ctx = line.getOptionValue("context", "");
             final String fixedCtx = !ctx.isEmpty() && !ctx.startsWith("/") ? '/' + ctx : ctx;
             final String war = line.getOptionValue("webapp");
@@ -87,8 +96,18 @@ public class Cli {
         }
     }
 
-    private static Meecrowave.Builder buildConfig(final CommandLine line, final List<Field> fields) {
+    private static Meecrowave.Builder buildConfig(final CommandLine line, final List<Field> fields,
+                                                  final Map<Object, List<Field>> propertiesOptions) {
         final Meecrowave.Builder config = new Meecrowave.Builder();
+        bind(line, fields, config);
+        propertiesOptions.forEach((o, f) -> {
+            bind(line, f, o);
+            config.setExtension(o.getClass(), o);
+        });
+        return config;
+    }
+
+    private static void bind(final CommandLine line, final List<Field> fields, final Object config) {
         fields.forEach(f -> {
             final CliOption opt = f.getAnnotation(CliOption.class);
             final String name = opt.name();
@@ -108,7 +127,6 @@ public class Cli {
                         });
             }
         });
-        return config;
     }
 
     private static Object toValue(final String name, final String[] optionValues, final Class<?> type) {
@@ -196,7 +214,10 @@ public class Cli {
         }
     }
 
-    private static void help(final Options options) {
+    private static void help(final org.apache.commons.cli.Options options) {
         new HelpFormatter().printHelp("java -jar meecrowave.jar", options);
     }
+
+    public interface Options {
+    }
 }

Modified: openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java?rev=1769543&r1=1769542&r2=1769543&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/MeecrowaveTest.java Sun Nov 13 20:13:00 2016
@@ -20,6 +20,7 @@ package org.apache.meecrowave;
 
 import org.apache.cxf.helpers.FileUtils;
 import org.apache.meecrowave.io.IO;
+import org.apache.meecrowave.runner.cli.CliOption;
 import org.junit.Test;
 import org.superbiz.app.Endpoint;
 import org.superbiz.app.RsApp;
@@ -48,7 +49,7 @@ public class MeecrowaveTest {
                 .property("my-prefix-a-last-port-value", "9632")
                 .property("my-prefix-passthrough", "any value")
                 .property("my-prefix-bool", "true")
-                .bind(new MyConfig(), "my-prefix-");
+                .bind(new MyConfig());
         assertNotNull(config);
         assertEquals(1234, config.port);
         assertEquals(5678, config.anotherPort);
@@ -134,10 +135,19 @@ public class MeecrowaveTest {
     }
 
     public static class MyConfig {
+        @CliOption(name = "my-prefix-port", description = "")
         private int port;
+
+        @CliOption(name = "my-prefix-another-port", description = "")
         private int anotherPort;
+
+        @CliOption(name = "my-prefix-a-last-port-value", description = "")
         private int aLastPortValue;
+
+        @CliOption(name = "my-prefix-passthrough", description = "")
         private String passthrough;
+
+        @CliOption(name = "my-prefix-bool", description = "")
         private boolean bool;
     }
 }

Modified: openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/CliConfiguration.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/CliConfiguration.java?rev=1769543&r1=1769542&r2=1769543&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/CliConfiguration.java (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/CliConfiguration.java Sun Nov 13 20:13:00 2016
@@ -30,6 +30,7 @@ public class CliConfiguration extends Ba
     protected String generate() {
         return super.tableConfig() + "|===\n|Name|Description\n" +
                 Stream.of(Meecrowave.Builder.class.getDeclaredFields())
+                        .filter(f -> f.isAnnotationPresent(CliOption.class))
                         .sorted((o1, o2) -> o1.getName().compareTo(o2.getName()))
                         .map(f -> f.getAnnotation(CliOption.class))
                         .map(opt -> "|--" + opt.name() + "|" + opt.description())

Modified: openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/Configuration.java
URL: http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/Configuration.java?rev=1769543&r1=1769542&r2=1769543&view=diff
==============================================================================
--- openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/Configuration.java (original)
+++ openwebbeans/meecrowave/trunk/meecrowave-doc/src/main/java/org/apache/meecrowave/doc/generator/Configuration.java Sun Nov 13 20:13:00 2016
@@ -30,8 +30,9 @@ public class Configuration extends BaseG
     protected String generate() {
         return super.tableConfig() + "|===\n|Name|Description\n" +
                 Stream.of(Meecrowave.Builder.class.getDeclaredFields())
-                .sorted((o1, o2) -> o1.getName().compareTo(o2.getName()))
-                .map(f -> "|" + f.getName() + "|" + f.getAnnotation(CliOption.class).description())
-                .collect(joining("\n")) + "\n|===\n";
+                        .filter(f -> f.isAnnotationPresent(CliOption.class))
+                        .sorted((o1, o2) -> o1.getName().compareTo(o2.getName()))
+                        .map(f -> "|" + f.getName() + "|" + f.getAnnotation(CliOption.class).description())
+                        .collect(joining("\n")) + "\n|===\n";
     }
 }