You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ri...@apache.org on 2014/09/08 14:39:05 UTC

[05/14] git commit: Adds ItemLister for getting entities etc

Adds ItemLister for getting entities etc


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

Branch: refs/heads/master
Commit: af85653292522a6b5cff59939a28dbdfdc8b7ef8
Parents: c92b175
Author: Aled Sage <al...@gmail.com>
Authored: Wed Aug 13 14:00:16 2014 +0100
Committer: Martin Harris <gi...@nakomis.com>
Committed: Mon Sep 8 11:20:33 2014 +0100

----------------------------------------------------------------------
 .../main/java/brooklyn/basic/BrooklynTypes.java |   2 +-
 .../brooklyn/cli/itemlister/ClassFinder.java    | 130 ++++++++++++++++
 .../cli/itemlister/ItemDescriptors.java         | 104 +++++++++++++
 .../brooklyn/cli/itemlister/ItemLister.java     | 156 +++++++++++++++++++
 .../rest/transform/EntityTransformer.java       |   2 +-
 5 files changed, 392 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/af856532/core/src/main/java/brooklyn/basic/BrooklynTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/BrooklynTypes.java b/core/src/main/java/brooklyn/basic/BrooklynTypes.java
index 246e519..1a0049c 100644
--- a/core/src/main/java/brooklyn/basic/BrooklynTypes.java
+++ b/core/src/main/java/brooklyn/basic/BrooklynTypes.java
@@ -76,7 +76,7 @@ public class BrooklynTypes {
         return (EntityDynamicType) BrooklynTypes.getDefinedBrooklynType(entityClass);
     }
 
-    private static BrooklynDynamicType<?,?> getDefinedBrooklynType(Class<? extends BrooklynObject> brooklynClass) {
+    public static BrooklynDynamicType<?,?> getDefinedBrooklynType(Class<? extends BrooklynObject> brooklynClass) {
         BrooklynDynamicType<?,?> t = cache.get(brooklynClass);
         if (t!=null) return t;
         return loadDefinedBrooklynType(brooklynClass);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/af856532/usage/cli/src/main/java/brooklyn/cli/itemlister/ClassFinder.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/brooklyn/cli/itemlister/ClassFinder.java b/usage/cli/src/main/java/brooklyn/cli/itemlister/ClassFinder.java
new file mode 100644
index 0000000..18888ac
--- /dev/null
+++ b/usage/cli/src/main/java/brooklyn/cli/itemlister/ClassFinder.java
@@ -0,0 +1,130 @@
+package brooklyn.cli.itemlister;
+
+import java.io.File;
+import java.lang.annotation.Annotation;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import org.reflections.Reflections;
+import org.reflections.scanners.FieldAnnotationsScanner;
+import org.reflections.scanners.SubTypesScanner;
+import org.reflections.scanners.TypeAnnotationsScanner;
+import org.reflections.util.ConfigurationBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.basic.BrooklynObject;
+import brooklyn.enricher.basic.AbstractEnricher;
+import brooklyn.entity.Application;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.AbstractApplication;
+import brooklyn.entity.basic.AbstractEntity;
+import brooklyn.entity.basic.SoftwareProcessImpl;
+import brooklyn.policy.Enricher;
+import brooklyn.policy.Policy;
+import brooklyn.policy.basic.AbstractPolicy;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.javalang.UrlClassLoader;
+import brooklyn.util.net.Urls;
+import brooklyn.util.os.Os;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+public class ClassFinder {
+
+    private static final Logger log = LoggerFactory.getLogger(ClassFinder.class);
+
+    private static final Collection<Class<?>> BORING = ImmutableList.<Class<?>>of(
+            Entity.class,
+            AbstractEntity.class,
+            SoftwareProcessImpl.class,
+            Application.class,
+            AbstractApplication.class,
+            Policy.class,
+            Enricher.class,
+            AbstractPolicy.class,
+            AbstractEnricher.class);
+
+    public static Predicate<Class<?>> notBoring() {
+        return new Predicate<Class<?>>() {
+            public boolean apply(Class<?> input) {
+                return (input != null && !BORING.contains(input));
+            }
+        };
+    }
+    
+    public static Predicate<Class<?>> withAnnotation(final Class<? extends Annotation> annotation) {
+        return new Predicate<Class<?>>() {
+            public boolean apply(Class<?> input) {
+                return (input != null && input.getAnnotation(annotation) != null);
+            }
+        };
+    }
+    
+    public static Predicate<? super Class<? extends BrooklynObject>> withClassNameMatching(final String typeRegex) {
+        return new Predicate<Class<?>>() {
+            public boolean apply(Class<?> input) {
+                return (input != null && input.getName() != null && input.getName().matches(typeRegex));
+            }
+        };
+    }
+    
+    public static List<URL> toJarUrls(String url) throws MalformedURLException {
+        if (url==null) throw new NullPointerException("Cannot read from null");
+        if (url=="") throw new NullPointerException("Cannot read from empty string");
+        
+        List<URL> result = Lists.newArrayList();
+        
+        String protocol = Urls.getProtocol(url);
+        if (protocol!=null) {
+            // it's a URL - easy
+            if ("file".equals(protocol)) {
+                url = ResourceUtils.tidyFileUrl(url);
+            }
+            result.add(new URL(url));
+        } else {
+            // treat as file
+            String tidiedPath = Os.tidyPath(url);
+            File tidiedFile = new File(tidiedPath);
+            if (tidiedFile.isDirectory()) {
+                List<File> toscan = Lists.newLinkedList();
+                toscan.add(tidiedFile);
+                while (toscan.size() > 0) {
+                    File file = toscan.remove(0);
+                    if (file.isFile()) {
+                        if (file.getName().toLowerCase().endsWith(".jar")) {
+                            result.add(new URL("file://"+file.getAbsolutePath()));
+                        }
+                    } else if (file.isDirectory()) {
+                        for (File subfile : file.listFiles()) {
+                            toscan.add(subfile);
+                        }
+                    } else {
+                        log.info("Cannot read "+file+"; not a file or directory");
+                    }
+                }
+            }
+        }
+        
+        return result;
+    }
+
+    public static <T extends BrooklynObject> Set<Class<? extends T>> findClasses(Collection<URL> urls, Class<T> clazz) {
+        ClassLoader classLoader = new UrlClassLoader(urls.toArray(new URL[urls.size()]));
+        
+        Reflections reflections = new ConfigurationBuilder()
+                .addClassLoader(classLoader)
+                .addScanners(new SubTypesScanner(), new TypeAnnotationsScanner(), new FieldAnnotationsScanner())
+                .addUrls(urls)
+                .build();
+        
+        Set<Class<? extends T>> types = reflections.getSubTypesOf(clazz);
+        
+        return types;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/af856532/usage/cli/src/main/java/brooklyn/cli/itemlister/ItemDescriptors.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/brooklyn/cli/itemlister/ItemDescriptors.java b/usage/cli/src/main/java/brooklyn/cli/itemlister/ItemDescriptors.java
new file mode 100644
index 0000000..a3929ee
--- /dev/null
+++ b/usage/cli/src/main/java/brooklyn/cli/itemlister/ItemDescriptors.java
@@ -0,0 +1,104 @@
+package brooklyn.cli.itemlister;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import brooklyn.basic.BrooklynDynamicType;
+import brooklyn.basic.BrooklynObject;
+import brooklyn.basic.BrooklynType;
+import brooklyn.basic.BrooklynTypes;
+import brooklyn.catalog.Catalog;
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.Effector;
+import brooklyn.entity.EntityType;
+import brooklyn.entity.basic.BrooklynConfigKeys;
+import brooklyn.event.Sensor;
+import brooklyn.location.LocationResolver;
+import brooklyn.rest.domain.EffectorSummary;
+import brooklyn.rest.domain.EntityConfigSummary;
+import brooklyn.rest.domain.SensorSummary;
+import brooklyn.rest.domain.SummaryComparators;
+import brooklyn.rest.transform.EffectorTransformer;
+import brooklyn.rest.transform.EntityTransformer;
+import brooklyn.rest.transform.SensorTransformer;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+public class ItemDescriptors {
+
+    public static List<Map<String, Object>> toItemDescriptors(Iterable<? extends Class<? extends BrooklynObject>> types, boolean headingsOnly) {
+        List<Map<String, Object>> itemDescriptors = Lists.newArrayList();
+        
+        for (Class<? extends BrooklynObject> type : types) {
+            Map<String, Object> itemDescriptor = toItemDescriptor(type, headingsOnly);
+            itemDescriptors.add(itemDescriptor);
+        }
+        
+        return itemDescriptors;
+    }
+    
+    public static Map<String,Object> toItemDescriptor(Class<? extends BrooklynObject> clazz, boolean headingsOnly) {
+        BrooklynDynamicType<?, ?> dynamicType = BrooklynTypes.getDefinedBrooklynType(clazz);
+        BrooklynType type = dynamicType.getSnapshot();
+        ConfigKey<?> version = dynamicType.getConfigKey(BrooklynConfigKeys.SUGGESTED_VERSION.getName());
+        
+        Map<String,Object> result = Maps.newLinkedHashMap();
+        
+        result.put("type", clazz.getName());
+        if (version != null) {
+            result.put("defaultVersion", version.getDefaultValue());
+        }
+        
+        Catalog catalogAnnotation = clazz.getAnnotation(Catalog.class);
+        if (catalogAnnotation != null) {
+            result.put("name", catalogAnnotation.name());
+            result.put("description", catalogAnnotation.description());
+            result.put("iconUrl", catalogAnnotation.iconUrl());
+        }
+        
+        Deprecated deprecatedAnnotation = clazz.getAnnotation(Deprecated.class);
+        if (deprecatedAnnotation != null) {
+            result.put("deprecated", true);
+        }
+        
+        if (!headingsOnly) {
+            Set<EntityConfigSummary> config = Sets.newTreeSet(SummaryComparators.nameComparator());
+            Set<SensorSummary> sensors = Sets.newTreeSet(SummaryComparators.nameComparator());
+            Set<EffectorSummary> effectors = Sets.newTreeSet(SummaryComparators.nameComparator());
+
+            for (ConfigKey<?> x: type.getConfigKeys()) {
+                config.add(EntityTransformer.entityConfigSummary(x, dynamicType.getConfigKeyField(x.getName())));
+            }
+            result.put("config", config);
+            
+            if (type instanceof EntityType) {
+                for (Sensor<?> x: ((EntityType)type).getSensors())
+                    sensors.add(SensorTransformer.sensorSummaryForCatalog(x));
+                result.put("sensors", sensors);
+                
+                for (Effector<?> x: ((EntityType)type).getEffectors())
+                    effectors.add(EffectorTransformer.effectorSummaryForCatalog(x));
+                result.put("effectors", effectors);
+            }
+        }
+        
+        return result;
+    }
+    
+    public static Object toItemDescriptors(List<LocationResolver> resolvers) {
+        List<Object> result = Lists.newArrayList();
+        for (LocationResolver resolver : resolvers) {
+            result.add(toItemDescriptor(resolver));
+        }
+        return result;
+    }
+
+    public static Object toItemDescriptor(LocationResolver resolver) {
+        // TODO Get javadoc of LocationResolver? Could use docklet? But that would give dependency here
+        // on com.sun.javadoc.*
+        return resolver.getPrefix();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/af856532/usage/cli/src/main/java/brooklyn/cli/itemlister/ItemLister.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/brooklyn/cli/itemlister/ItemLister.java b/usage/cli/src/main/java/brooklyn/cli/itemlister/ItemLister.java
new file mode 100644
index 0000000..bc3782d
--- /dev/null
+++ b/usage/cli/src/main/java/brooklyn/cli/itemlister/ItemLister.java
@@ -0,0 +1,156 @@
+package brooklyn.cli.itemlister;
+
+import io.airlift.command.Cli;
+import io.airlift.command.Cli.CliBuilder;
+import io.airlift.command.Command;
+import io.airlift.command.Option;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+import brooklyn.basic.BrooklynObject;
+import brooklyn.catalog.Catalog;
+import brooklyn.cli.AbstractMain;
+import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.ImplementedBy;
+import brooklyn.location.Location;
+import brooklyn.location.LocationResolver;
+import brooklyn.policy.Enricher;
+import brooklyn.policy.Policy;
+import brooklyn.util.collections.MutableSet;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+
+public class ItemLister extends AbstractMain {
+
+    public static void main(String... args) {
+        new ItemLister().execCli(args);
+    }
+
+    @Command(name = "all", description = "Lists everything")
+    public static class ListAllCommand extends BrooklynCommandCollectingArgs {
+
+        @Option(name = { "--jars" }, title = "Jars", description = "jars to scan. If a file (not a url) pointing at a directory, will include all files in that directory")
+        public List<String> jars;
+
+        @Option(name = { "--type-regex" }, title = "Regex for types to list")
+        public String typeRegex = null;
+
+        @Option(name = { "--catalog-only" }, title = "Whether to only list items annotated with @Catalog")
+        public boolean catalogOnly;
+
+        @Option(name = { "--ignore-impls" }, title = "Ignore Entity implementations, where there is an Entity interface with @ImplementedBy")
+        public boolean ignoreImpls;
+
+        @Option(name = { "--headings-only" }, title = "Whether to only show name/type, and not config keys etc")
+        public boolean headingsOnly;
+
+        @Override
+        public Void call() throws Exception {
+            List<URL> urls = getUrls();
+            
+            // TODO Remove duplication from separate ListPolicyCommand etc
+            List<Class<? extends Entity>> entityTypes = getTypes(urls, Entity.class);
+            List<Class<? extends Policy>> policyTypes = getTypes(urls, Policy.class);
+            List<Class<? extends Enricher>> enricherTypes = getTypes(urls, Enricher.class);
+            List<Class<? extends Location>> locationTypes = getTypes(urls, Location.class, Boolean.FALSE);
+
+            Map<String, Object> result = ImmutableMap.<String, Object>builder()
+                    .put("entities", ItemDescriptors.toItemDescriptors(entityTypes, headingsOnly))
+                    .put("policies", ItemDescriptors.toItemDescriptors(policyTypes, headingsOnly))
+                    .put("enrichers", ItemDescriptors.toItemDescriptors(enricherTypes, headingsOnly))
+                    .put("locations", ItemDescriptors.toItemDescriptors(locationTypes, headingsOnly))
+                    .put("locationResolvers", ItemDescriptors.toItemDescriptors(ImmutableList.copyOf(ServiceLoader.load(LocationResolver.class))))
+                    .build();
+            
+            System.out.println(toJson(result));
+            return null;
+        }
+
+        protected List<URL> getUrls() throws MalformedURLException {
+            List<URL> urls = Lists.newArrayList();
+            for (String jar : jars) {
+                urls.addAll(ClassFinder.toJarUrls(jar));
+            }
+            return urls;
+        }
+
+        private <T extends BrooklynObject> List<Class<? extends T>> getTypes(List<URL> urls, Class<T> type) {
+            return getTypes(urls, type, null);
+        }
+        
+        private <T extends BrooklynObject> List<Class<? extends T>> getTypes(List<URL> urls, Class<T> type, Boolean catalogOnlyOverride) {
+            FluentIterable<Class<? extends T>> fluent = FluentIterable.from(ClassFinder.findClasses(urls, type));
+            if (typeRegex != null) {
+                fluent = fluent.filter(ClassFinder.withClassNameMatching(typeRegex));
+            }
+            if (catalogOnlyOverride == null ? catalogOnly : catalogOnlyOverride) {
+                fluent = fluent.filter(ClassFinder.withAnnotation(Catalog.class));
+            }
+            ImmutableList<Class<? extends T>> result = fluent.toList();
+            if (ignoreImpls) {
+                MutableSet<Class<? extends T>> mutableResult = MutableSet.copyOf(result);
+                for (Class<? extends T> clazz : result) {
+                    ImplementedBy implementedBy = clazz.getAnnotation(ImplementedBy.class);
+                    if (implementedBy != null) {
+                        mutableResult.remove(implementedBy.value());
+                    }
+                }
+                return ImmutableList.copyOf(mutableResult);
+            } else {
+                return result;
+            }
+        }
+        
+        private String toJson(Object obj) throws JsonProcessingException {
+            ObjectMapper objectMapper = new ObjectMapper()
+                    .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
+                    .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+                    .enable(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS)
+                    .enable(SerializationFeature.INDENT_OUTPUT)
+                    .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
+                    .setSerializationInclusion(JsonInclude.Include.ALWAYS)
+            
+                    // Only serialise annotated fields
+                    .setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE)
+                    .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
+            
+            return objectMapper.writeValueAsString(obj);
+        }
+    }
+
+    /** method intended for overriding when the script filename is different 
+     * @return the name of the script the user has invoked */
+    protected String cliScriptName() {
+        return "item-lister";
+    }
+
+    /** method intended for overriding when a different {@link Cli} is desired,
+     * or when the subclass wishes to change any of the arguments */
+    protected CliBuilder<BrooklynCommand> cliBuilder() {
+        @SuppressWarnings({ "unchecked" })
+        CliBuilder<BrooklynCommand> builder = Cli.<BrooklynCommand>builder(cliScriptName())
+                .withDescription("Brooklyn Management Service")
+                .withDefaultCommand(ListAllCommand.class)
+                .withCommands(
+                        HelpCommand.class,
+                        InfoCommand.class,
+                        ListAllCommand.class
+                );
+
+        return builder;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/af856532/usage/rest-server/src/main/java/brooklyn/rest/transform/EntityTransformer.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/transform/EntityTransformer.java b/usage/rest-server/src/main/java/brooklyn/rest/transform/EntityTransformer.java
index cebdf86..23107c5 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/transform/EntityTransformer.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/transform/EntityTransformer.java
@@ -127,7 +127,7 @@ public class EntityTransformer {
         return applicationUri(entity.getApplication()) + "/entities/" + entity.getId();
     }
     
-    protected static EntityConfigSummary entityConfigSummary(ConfigKey<?> config, Field configKeyField) {
+    public static EntityConfigSummary entityConfigSummary(ConfigKey<?> config, Field configKeyField) {
         CatalogConfig catalogConfig = configKeyField!=null ? configKeyField.getAnnotation(CatalogConfig.class) : null;
         String label = catalogConfig==null ? null : catalogConfig.label();
         Double priority = catalogConfig==null ? null : catalogConfig.priority();