Search for referenced values in external classes (either through imports or fully qualified)

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@618322 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/PropertyHandler.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/PropertyHandler.java
index 6194c15..f8cab9d 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/PropertyHandler.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/PropertyHandler.java
@@ -46,7 +46,7 @@
      * @param component
      * @param ocd
      */
-    public void doProperty(JavaTag property, String name, Component component, OCD ocd, JavaField javaField)
+    protected void doProperty(JavaTag property, String name, Component component, OCD ocd, JavaField javaField)
     throws MojoExecutionException {
         final Property prop = new Property(property);
         prop.setName(name);
@@ -167,7 +167,7 @@
      * @param defaultName
      * @return The name of the property or the defaultName
      */
-    public String getPropertyName(JavaTag property, String defaultName) {
+    protected String getPropertyName(JavaTag property, String defaultName) {
         final String name = property.getNamedParameter(Constants.PROPERTY_NAME);
         if (!StringUtils.isEmpty(name)) {
             return name;
@@ -176,7 +176,7 @@
         return defaultName;
     }
 
-    public void setPropertyValueRef(final JavaTag tag, Property property, String valueRef)
+    protected void setPropertyValueRef(final JavaTag tag, Property property, String valueRef)
     throws MojoExecutionException {
         final String[] values = this.getPropertyValueRef(tag, property, valueRef);
         if ( values != null && values.length == 1 ) {
@@ -186,43 +186,45 @@
         }
     }
 
-    public String[] getPropertyValueRef(final JavaTag tag, Property prop, String valueRef)
+    protected String[] getPropertyValueRef(final JavaTag tag, Property prop, String valueRef)
     throws MojoExecutionException {
         int classSep = valueRef.lastIndexOf('.');
+        JavaField field = null;
         if ( classSep == -1 ) {
             // local variable
-            // TODO - This could be a static import!
-            final JavaField field = tag.getJavaClassDescription().getFieldByName(valueRef);
-            if ( field == null ) {
-                throw new MojoExecutionException("Property references unknown field " + valueRef + " in class " + tag.getJavaClassDescription().getName());
-            }
-            // determine type (if not set explicitly)
-            if ( prop.getType() == null ) {
-                final String type = field.getType();
-                if ( "java.lang.String".equals(type) ) {
-                    prop.setType("String");
-                } else if ("java.lang.Long".equals(type) || "long".equals(type) ) {
-                    prop.setType("Long");
-                } else if ("java.lang.Double".equals(type) || "double".equals(type) ) {
-                    prop.setType("Double");
-                } else if ("java.lang.Float".equals(type) || "float".equals(type) ) {
-                    prop.setType("Float");
-                } else if ("java.lang.Integer".equals(type) || "int".equals(type) ) {
-                    prop.setType("Integer");
-                } else if ("java.lang.Byte".equals(type) || "byte".equals(type) ) {
-                    prop.setType("Byte");
-                } else if ("java.lang.Character".equals(type) || "char".equals(type) ) {
-                    prop.setType("Char");
-                } else if ("java.lang.Boolean".equals(type) || "boolean".equals(type) ) {
-                    prop.setType("Boolean");
-                } else if ("java.lang.Short".equals(type) || "short".equals(type) ) {
-                    prop.setType("Short");
-                }
-
-            }
-            return field.getInitializationExpression();
+            field = tag.getJavaClassDescription().getFieldByName(valueRef);
         }
-        throw new MojoExecutionException("Referencing values from foreign classes not supported yet.");
+        if ( field == null ) {
+            field = tag.getJavaClassDescription().getExternalFieldByName(valueRef);
+        }
+        if ( field == null ) {
+            throw new MojoExecutionException("Property references unknown field " + valueRef + " in class " + tag.getJavaClassDescription().getName());
+        }
+        // determine type (if not set explicitly)
+        if ( prop.getType() == null ) {
+            final String type = field.getType();
+            if ( "java.lang.String".equals(type) ) {
+                prop.setType("String");
+            } else if ("java.lang.Long".equals(type) || "long".equals(type) ) {
+                prop.setType("Long");
+            } else if ("java.lang.Double".equals(type) || "double".equals(type) ) {
+                prop.setType("Double");
+            } else if ("java.lang.Float".equals(type) || "float".equals(type) ) {
+                prop.setType("Float");
+            } else if ("java.lang.Integer".equals(type) || "int".equals(type) ) {
+                prop.setType("Integer");
+            } else if ("java.lang.Byte".equals(type) || "byte".equals(type) ) {
+                prop.setType("Byte");
+            } else if ("java.lang.Character".equals(type) || "char".equals(type) ) {
+                prop.setType("Char");
+            } else if ("java.lang.Boolean".equals(type) || "boolean".equals(type) ) {
+                prop.setType("Boolean");
+            } else if ("java.lang.Short".equals(type) || "short".equals(type) ) {
+                prop.setType("Short");
+            }
+
+        }
+        return field.getInitializationExpression();
     }
 
     public void testProperty(JavaTag property, String defaultName, JavaField field, boolean isInspectedClass)
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescription.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescription.java
index 963fca4..724a395 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescription.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/JavaClassDescription.java
@@ -66,8 +66,16 @@
      */
     JavaField[] getFields();
 
+    /**
+     * Get the field with the name.
+     * @param name The name of the field
+     * @return The field with the name or null.
+     * @throws MojoExecutionException
+     */
     JavaField getFieldByName(String name) throws MojoExecutionException;
 
+    JavaField getExternalFieldByName(String name) throws MojoExecutionException;
+
     /**
      * Returns an array of the implemented interfaces of this class.
      * @return An array containing the interfaces or an empty array
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
index 0755a6a..432be47 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/cl/ClassLoaderJavaClassDescription.java
@@ -81,6 +81,14 @@
     }
 
     /**
+     * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getExternalFieldByName(java.lang.String)
+     */
+    public JavaField getExternalFieldByName(String name)
+    throws MojoExecutionException {
+        throw new MojoExecutionException("getExternalFieldByName not support for this class.");
+    }
+
+    /**
      * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getImplementedInterfaces()
      */
     public JavaClassDescription[] getImplementedInterfaces() throws MojoExecutionException {
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java
index 1861789..ee3d4d5 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/tags/qdox/QDoxJavaClassDescription.java
@@ -141,6 +141,51 @@
     }
 
     /**
+     * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getExternalFieldByName(java.lang.String)
+     */
+    public JavaField getExternalFieldByName(String name)
+    throws MojoExecutionException {
+        JavaField field = this.searchExternalFieldByName(name);
+        if ( field == null ) {
+            field = this.searchExternalFieldByName(this.javaClass.getSource().getPackage() + '.' + name);
+        }
+        return field;
+    }
+
+    protected JavaField searchExternalFieldByName(String name)
+    throws MojoExecutionException {
+        int sep = name.lastIndexOf('.');
+        final String className = name.substring(0, sep);
+        final String constantName = name.substring(sep+1);
+        // we know that the name is external, so let's scan imports first
+        // for a fully qualified static import
+        boolean isStatic = this.searchImport(name);
+        if ( isStatic ) {
+            final JavaClassDescription jcd = this.manager.getJavaClassDescription(className);
+            if ( jcd != null ) {
+                return jcd.getFieldByName(constantName);
+            }
+        }
+        final JavaClassDescription jcd = this.manager.getJavaClassDescription(className);
+        if ( jcd != null ) {
+            return jcd.getFieldByName(constantName);
+        }
+        return null;
+    }
+
+    protected boolean searchImport(String name) {
+        final String[] imports = this.javaClass.getSource().getImports();
+        if ( imports != null ) {
+            for(int i=0; i<imports.length; i++ ) {
+                if ( imports[i].equals(name) ) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
      * @see org.apache.felix.scrplugin.tags.JavaClassDescription#getImplementedInterfaces()
      */
     public JavaClassDescription[] getImplementedInterfaces()