METRON-1515: Errors loading stellar functions currently bomb the entire 
topology, they should be recoverable closes apache/incubator-metron#985


Project: http://git-wip-us.apache.org/repos/asf/metron/repo
Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/3fcbf8b4
Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/3fcbf8b4
Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/3fcbf8b4

Branch: refs/heads/feature/METRON-1090-stellar-assignment
Commit: 3fcbf8b4e4e38f9c50842b8af857092b091c7c40
Parents: 1d3e7fc
Author: cstella <ceste...@gmail.com>
Authored: Mon Apr 16 15:12:11 2018 -0400
Committer: cstella <ceste...@gmail.com>
Committed: Mon Apr 16 15:12:11 2018 -0400

----------------------------------------------------------------------
 .../resolver/ClasspathFunctionResolver.java     | 45 +++++++++++++++-----
 .../resolver/ClasspathFunctionResolverTest.java | 30 +++++++++++++
 2 files changed, 65 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/metron/blob/3fcbf8b4/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/resolver/ClasspathFunctionResolver.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/resolver/ClasspathFunctionResolver.java
 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/resolver/ClasspathFunctionResolver.java
index 85aa015..b17233a 100644
--- 
a/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/resolver/ClasspathFunctionResolver.java
+++ 
b/metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/resolver/ClasspathFunctionResolver.java
@@ -34,6 +34,7 @@ import org.apache.metron.stellar.dsl.Context;
 import org.apache.metron.stellar.dsl.Stellar;
 import org.apache.metron.stellar.dsl.StellarFunction;
 
+import org.atteo.classindex.ClassFilter;
 import org.atteo.classindex.ClassIndex;
 import org.reflections.util.FilterBuilder;
 
@@ -219,6 +220,17 @@ public class ClasspathFunctionResolver extends 
BaseFunctionResolver {
     }
   }
 
+  protected Iterable<Class<?>> getStellarClasses(ClassLoader cl) {
+    return ClassIndex.getAnnotated(Stellar.class, cl);
+  }
+
+  protected boolean includeClass(Class<?> c, FilterBuilder filterBuilder)
+  {
+    boolean isAssignable = StellarFunction.class.isAssignableFrom(c);
+    boolean isFiltered = filterBuilder.apply(c.getCanonicalName());
+    return isAssignable && isFiltered;
+  }
+
   /**
    * Returns a set of classes that should undergo further interrogation for 
resolution
    * (aka discovery) of Stellar functions.
@@ -254,16 +266,29 @@ public class ClasspathFunctionResolver extends 
BaseFunctionResolver {
     Set<String> classes = new HashSet<>();
     Set<Class<? extends StellarFunction>> ret = new HashSet<>();
     for(ClassLoader cl : cls) {
-      for(Class<?> c : ClassIndex.getAnnotated(Stellar.class, cl)) {
-        LOG.debug("{}: Found class: {}", cl.getClass().getCanonicalName(), 
c.getCanonicalName());
-        boolean isAssignable = StellarFunction.class.isAssignableFrom(c);
-        boolean isFiltered = filterBuilder.apply(c.getCanonicalName());
-        if( isAssignable && isFiltered ) {
-          String className = c.getName();
-          if(!classes.contains(className)) {
-            LOG.debug("{}: Added class: {}", cl.getClass().getCanonicalName(), 
className);
-            ret.add((Class<? extends StellarFunction>) c);
-            classes.add(className);
+      for(Class<?> c : getStellarClasses(cl)) {
+        try {
+          LOG.debug("{}: Found class: {}", cl.getClass().getCanonicalName(), 
c.getCanonicalName());
+          if (includeClass(c, filterBuilder)) {
+            String className = c.getName();
+            if (!classes.contains(className)) {
+              LOG.debug("{}: Added class: {}", 
cl.getClass().getCanonicalName(), className);
+              ret.add((Class<? extends StellarFunction>) c);
+              classes.add(className);
+            }
+          }
+        }
+        catch(Error le) {
+          //we have had some error loading a stellar function.  This could 
mean that
+          //the classpath is unstable (e.g. old copies of jars are on the 
classpath).
+          try {
+            LOG.error("Skipping class " + c.getName() + ": " + le.getMessage()
+                    + ", please check that there are not old versions of 
stellar functions on the classpath.", le);
+          }
+          catch(Error ie) {
+            //it's possible that getName() will throw an exception if the 
class is VERY malformed.
+            LOG.error("Skipping class: " + le.getMessage()
+                    + ", please check that there are not old versions of 
stellar functions on the classpath.", le);
           }
         }
       }

http://git-wip-us.apache.org/repos/asf/metron/blob/3fcbf8b4/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/resolver/ClasspathFunctionResolverTest.java
----------------------------------------------------------------------
diff --git 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/resolver/ClasspathFunctionResolverTest.java
 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/resolver/ClasspathFunctionResolverTest.java
index 1d37f99..cc5bc7c 100644
--- 
a/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/resolver/ClasspathFunctionResolverTest.java
+++ 
b/metron-stellar/stellar-common/src/test/java/org/apache/metron/stellar/dsl/functions/resolver/ClasspathFunctionResolverTest.java
@@ -18,20 +18,27 @@
 
 package org.apache.metron.stellar.dsl.functions.resolver;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import org.apache.commons.vfs2.FileSystemException;
 import org.apache.metron.stellar.dsl.Context;
+import org.apache.metron.stellar.dsl.StellarFunction;
 import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
 import org.junit.Test;
+import org.reflections.util.FilterBuilder;
 
 import java.io.File;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Properties;
+import java.util.Set;
 
 import static 
org.apache.metron.stellar.dsl.functions.resolver.ClasspathFunctionResolver.Config.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 public class ClasspathFunctionResolverTest {
 
@@ -121,4 +128,27 @@ public class ClasspathFunctionResolverTest {
     Assert.assertTrue(functions.contains("NOW"));
   }
 
+  @Test
+  public void testInvalidStellarClass() throws Exception {
+    StellarFunction goodFunc = mock(StellarFunction.class);
+    StellarFunction badFunc = mock(StellarFunction.class);
+    ClasspathFunctionResolver resolver = new ClasspathFunctionResolver() {
+      @Override
+      protected Iterable<Class<?>> getStellarClasses(ClassLoader cl) {
+        return ImmutableList.of(goodFunc.getClass(), badFunc.getClass());
+      }
+
+      @Override
+      protected boolean includeClass(Class<?> c, FilterBuilder filterBuilder) {
+        if(c != goodFunc.getClass()) {
+          throw new LinkageError("failed!");
+        }
+        return true;
+      }
+    };
+    Set<Class<? extends StellarFunction>> funcs = resolver.resolvables();
+    Assert.assertEquals(1, funcs.size());
+    Assert.assertEquals(goodFunc.getClass(), Iterables.getFirst(funcs, null));
+  }
+
 }

Reply via email to