You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2014/07/04 11:51:15 UTC

[33/45] git commit: use an OSGi cache, and connect catalog items to OsgiManager class loading

use an OSGi cache, and connect catalog items to OsgiManager class loading


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

Branch: refs/heads/master
Commit: 13aa4af9447fc2536da660ff592fb0c0175b1d0d
Parents: d4d17b7
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Jul 3 15:06:28 2014 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Jul 3 15:06:28 2014 +0100

----------------------------------------------------------------------
 .../catalog/internal/BasicBrooklynCatalog.java  |  3 +-
 .../catalog/internal/CatalogItemDo.java         | 34 ++++++++++--
 .../brooklyn/management/ha/OsgiManager.java     | 57 +++++++++++++++-----
 .../creation/BrooklynEntityClassResolver.java   | 39 +++++++++-----
 4 files changed, 100 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/13aa4af9/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
index f924869..f4f0150 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -134,8 +134,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         // revert to legacy mechanism
         try {
             if (loadedItem.getJavaType()!=null) {
-                @SuppressWarnings({ "deprecation" })
-                SpecT specT = (SpecT) Reflections.findMethod(specType, "create", Class.class).invoke(null, loadedItem.getJavaClass());
+                SpecT specT = (SpecT) Reflections.findMethod(specType, "create", Class.class).invoke(null, loadedItem.loadJavaClass(mgmt));
                 spec = specT;
             }
         } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/13aa4af9/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index d1d8d82..65133fe 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -1,10 +1,16 @@
 package brooklyn.catalog.internal;
 
+import java.util.List;
+
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import brooklyn.catalog.CatalogItem;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.ha.OsgiManager;
+import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
 
 import com.google.common.base.Preconditions;
 
@@ -79,20 +85,38 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
      * new items should use {@link #getYaml()} */
     @Deprecated
     public Class<T> getJavaClass() {
-        if (javaClass==null) loadJavaClass();
+        if (javaClass==null) loadJavaClass(null);
         return javaClass;
     }
     
     @SuppressWarnings("unchecked")
-    protected Class<? extends T> loadJavaClass() {
+    protected Class<? extends T> loadJavaClass(ManagementContext mgmt) {
+        Maybe<Class<Object>> clazz = null;
         try {
             if (javaClass!=null) return javaClass;
-            
-            // TODO use OSGi
+
+            if (mgmt!=null) {
+                Maybe<OsgiManager> osgi = ((ManagementContextInternal)mgmt).getOsgiManager();
+                if (osgi.isPresent()) {
+                    List<String> bundles = getLibraries().getBundles();
+                    if (bundles!=null && !bundles.isEmpty()) {
+                        clazz = osgi.get().tryResolveClass(getJavaType(), bundles);
+                        if (clazz.isPresent()) {
+                            return (Class<? extends T>) clazz.get();
+                        }
+                    }
+                }
+            }
             
             javaClass = (Class<T>) catalog.getRootClassLoader().loadClass(getJavaType());
             return javaClass;
-        } catch (ClassNotFoundException e) {
+        } catch (Throwable e) {
+            Exceptions.propagateIfFatal(e);
+            if (clazz!=null) {
+                // if OSGi bundles were defined and failed, then prefer to throw its error message
+                clazz.get();
+            }
+            // else throw the java error
             throw Exceptions.propagate(e);
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/13aa4af9/core/src/main/java/brooklyn/management/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/OsgiManager.java b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
index a968660..709bf34 100644
--- a/core/src/main/java/brooklyn/management/ha/OsgiManager.java
+++ b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
@@ -1,12 +1,14 @@
 package brooklyn.management.ha;
 
 import java.io.File;
+import java.util.Arrays;
+import java.util.Map;
 
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.launch.Framework;
-
-import com.google.common.base.Throwables;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import brooklyn.config.BrooklynServerConfig;
 import brooklyn.config.ConfigKey;
@@ -16,14 +18,19 @@ import brooklyn.util.guava.Maybe;
 import brooklyn.util.os.Os;
 import brooklyn.util.osgi.Osgis;
 
+import com.google.common.base.Throwables;
+
 public class OsgiManager {
 
+    private static final Logger log = LoggerFactory.getLogger(OsgiManager.class);
+    
     public static final ConfigKey<Boolean> USE_OSGI = BrooklynServerConfig.USE_OSGI;
     
     /* see Osgis for info on starting framework etc */
     
     protected Framework framework;
     protected File osgiTempDir;
+    protected Map<String,String> bundleUrlToNameVersionString = MutableMap.of();
     
     public void start() {
         try {
@@ -51,24 +58,48 @@ public class OsgiManager {
 
     public void registerBundle(String bundleUrl) {
         try {
-            Osgis.install(framework, bundleUrl);
+            String nv = bundleUrlToNameVersionString.get(bundleUrl);
+            if (nv!=null) {
+                if (Osgis.getBundle(framework, nv).isPresent()) {
+                    log.debug("Bundle from "+bundleUrl+" already installed as "+nv+"; not re-registering");
+                    return;
+                }
+            }
+            Bundle b = Osgis.install(framework, bundleUrl);
+            log.debug("Bundle from "+bundleUrl+" successfully installed as "+nv);
+            bundleUrlToNameVersionString.put(bundleUrl, b.getSymbolicName()+":"+b.getVersion().toString());
         } catch (BundleException e) {
+            log.debug("Bundle from "+bundleUrl+" failed to install (rethrowing): "+e);
             throw Throwables.propagate(e);
         }
     }
 
-    public <T> Maybe<Class<T>> tryResolveClass(String bundleUrl, String type) {
-        try {
-            Maybe<Bundle> bundle = Osgis.getBundle(framework, bundleUrl);
-            if (bundle.isPresent()) {
-                Class<T> clazz = (Class<T>) bundle.get().loadClass(type);
-                return Maybe.of(clazz);
-            } else {
-                return Maybe.absent("No bundle found in " + framework + " at URL: " + bundleUrl);
+    public <T> Maybe<Class<T>> tryResolveClass(String type, String... bundleUrlsOrNameVersionString) {
+        return tryResolveClass(type, Arrays.asList(bundleUrlsOrNameVersionString));
+    }
+    public <T> Maybe<Class<T>> tryResolveClass(String type, Iterable<String> bundleUrlsOrNameVersionString) {
+        Map<String,Throwable> bundleProblems = MutableMap.of();
+        for (String bundleUrlOrNameVersionString: bundleUrlsOrNameVersionString) {
+            try {
+                String bundleNameVersion = bundleUrlToNameVersionString.get(bundleUrlOrNameVersionString);
+                if (bundleNameVersion==null) {
+                    bundleNameVersion = bundleUrlOrNameVersionString;
+                }
+                
+                Maybe<Bundle> bundle = Osgis.getBundle(framework, bundleNameVersion);
+                if (bundle.isPresent()) {
+                    @SuppressWarnings("unchecked")
+                    Class<T> clazz = (Class<T>) bundle.get().loadClass(type);
+                    return Maybe.of(clazz);
+                } else {
+                    bundleProblems.put(bundleUrlOrNameVersionString, new IllegalStateException("Unable to find bundle "+bundleUrlOrNameVersionString));
+                }
+            } catch (Throwable e) {
+                Exceptions.propagateIfFatal(e);
+                bundleProblems.put(bundleUrlOrNameVersionString, e);
             }
-        } catch (ClassNotFoundException e) {
-            return Maybe.absent(e);
         }
+        return Maybe.absent("Unable to resolve class "+type+": "+bundleProblems);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/13aa4af9/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
index df096dc..97df227 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
@@ -2,6 +2,7 @@ package io.brooklyn.camp.brooklyn.spi.creation;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.NoSuchElementException;
@@ -39,16 +40,18 @@ public class BrooklynEntityClassResolver {
      */
     public static <T extends Entity> Class<T> resolveEntity(String entityTypeName, ManagementContext mgmt, List<String> context) {
         checkNotNull(mgmt, "management context");
-        Maybe<Class<T>> entityClazz = Maybe.absent();
-        // TODO: What if context not empty but class not found? Throw?
-        if (context != null) {
-            for (String bundleUrl : context) {
-                entityClazz = tryLoadEntityFromBundle(entityTypeName, bundleUrl, mgmt);
-                if (entityClazz.isPresent()) {
-                    break;
-                }
+        Maybe<Class<T>> entityClazz = Maybe.absent("No bundles defined");
+        Maybe<Class<T>> bestError = null;
+        
+        if (context!=null && !context.isEmpty()) {
+            entityClazz = tryLoadEntityFromBundle(entityTypeName, mgmt, context);
+            if (!entityClazz.isPresent()) {
+                LOG.warn("Unable to find class "+entityTypeName+" in suggested bundles "+context+"; continuing other mechanisms");
+                // we should prefer the error message from above if context is non-empty but class can't be found
+                bestError = entityClazz;
             }
         }
+        
 
         if (!entityClazz.isPresent()) {
             entityClazz = tryLoadEntityFromCatalogue(entityTypeName, mgmt);
@@ -64,19 +67,29 @@ public class BrooklynEntityClassResolver {
             LOG.warn("Found class {} on classpath but it is not assignable to {}", entityTypeName, Entity.class);
             throw new IllegalStateException("Unable to load class "+ entityTypeName +" (extending Entity) from catalogue or classpath: wrong type "+entityClazz.get());
         }
+        if (!entityClazz.isPresent() && bestError!=null) {
+            // prefer best error if not found
+            bestError.get();
+        }
         return entityClazz.get();
     }
 
+    // TODO deprecate the ones below, make them protected or private
+    
     /** Tries to load the entity with the given class name from the given bundle. */
-    public static <T extends Entity> Maybe<Class<T>> tryLoadEntityFromBundle(String entityTypeName, String bundleUrl, ManagementContext mgmt) {
-        LOG.debug("Trying to resolve class {} from bundle {}", entityTypeName, bundleUrl);
+    public static <T extends Entity> Maybe<Class<T>> tryLoadEntityFromBundle(String entityTypeName, ManagementContext mgmt, String... bundleUrls) {
+        return tryLoadEntityFromBundle(entityTypeName, mgmt, Arrays.asList(bundleUrls));
+    }
+    public static <T extends Entity> Maybe<Class<T>> tryLoadEntityFromBundle(String entityTypeName, ManagementContext mgmt, Iterable<String> bundleUrls) {
+        LOG.debug("Trying to resolve class {} from bundle {}", entityTypeName, bundleUrls);
         Maybe<OsgiManager> osgiManager = ((ManagementContextInternal) mgmt).getOsgiManager();
         if (!osgiManager.isPresentAndNonNull()) {
-            LOG.debug("Asked to resolve class {} from bundle {} but osgi manager is unavailable in context {}",
-                    new Object[]{entityTypeName, bundleUrl, mgmt});
+            if (LOG.isDebugEnabled())
+                LOG.debug("Asked to resolve class {} from bundles {} but osgi manager is unavailable in context {}",
+                    new Object[]{entityTypeName, bundleUrls, mgmt});
             return Maybe.absent();
         }
-        Maybe<Class<T>> clazz = osgiManager.get().tryResolveClass(bundleUrl, entityTypeName);
+        Maybe<Class<T>> clazz = osgiManager.get().tryResolveClass(entityTypeName, bundleUrls);
         if (!clazz.isPresent() || !Entity.class.isAssignableFrom(clazz.get())) {
             return Maybe.absent();
         }