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();