aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2010-10-25 14:00:04 -0700
committerTor Norbye <tnorbye@google.com>2010-10-26 10:17:23 -0700
commit912d8df0ed1a06c559efeefb1a0958ba989178e3 (patch)
treed541cf8bfed6d10dc7472375e49565186282ab25
parent3a480e2d770105c302b0d14be411dbfde42349a5 (diff)
downloadsdk-912d8df0ed1a06c559efeefb1a0958ba989178e3.zip
sdk-912d8df0ed1a06c559efeefb1a0958ba989178e3.tar.gz
sdk-912d8df0ed1a06c559efeefb1a0958ba989178e3.tar.bz2
Support 3rd party layout rule loading, and rip out Groovy support
Add support for loading 3rd party .jars providing additional layout rules. This can be configured by adding a property referencing the jars to be loaded as part of your build.properties, like this: default.properties: ... layoutrules.jars=chart-rules.jar:graph-rules.jar ... This will create a class loader referencing chart-rules.jar and graph-rules.jar (as well as the visual editor's plugin class loader as a fallback), and this class loader is used to load IViewRule implementations. In addition, this plugin rips out the various remaining Groovy hooks and references that were earlier used to load Groovy scripts as layout rules, and removes groovy from the load path and build symlinking scripts. Change-Id: Ia17a60259559ec86270726add258382a879117dc
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/.classpath1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/about.html3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/build.properties1
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/api/IViewRule.java11
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/BaseLayout.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ExplodedRenderingHelper.java2
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DynamicContextMenu.java6
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java2
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java8
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeFactory.java2
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeProxy.java4
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java380
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/.classpath1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/build.properties1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/AllTests.java11
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/GroovyTestsSuite.java46
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/UnitTests.java3
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/TestGroovy.java175
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/compile_error.groovy34
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/invalid_interface.groovy24
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/simple_test.groovy85
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngineTest.java33
-rwxr-xr-xeclipse/scripts/build_server.sh4
-rwxr-xr-xeclipse/scripts/create_adt_symlinks.sh6
-rwxr-xr-xeclipse/scripts/create_test_symlinks.sh6
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java4
28 files changed, 136 insertions, 721 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/.classpath b/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
index 72ca4ed..2f2f6a9 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
@@ -5,7 +5,6 @@
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="lib" path="libs/androidprefs.jar" sourcepath="/AndroidPrefs"/>
<classpathentry kind="lib" path="libs/commons-compress-1.0.jar"/>
- <classpathentry kind="lib" path="libs/groovy-all-1.7.0.jar" sourcepath="/GroovySrc/groovy-src-1.7.0.zip"/>
<classpathentry kind="lib" path="libs/kxml2-2.3.0.jar"/>
<classpathentry kind="lib" path="libs/layoutlib_api.jar"/>
<classpathentry kind="lib" path="libs/layoutlib_utils.jar"/>
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
index 1f66e2a..6145db2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
@@ -10,7 +10,6 @@ Bundle-ClassPath: .,
libs/ninepatch.jar,
libs/sdkstats.jar,
libs/commons-compress-1.0.jar,
- libs/groovy-all-1.7.0.jar,
libs/kxml2-2.3.0.jar,
libs/layoutlib_api.jar,
libs/layoutlib_utils.jar
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/about.html b/eclipse/plugins/com.android.ide.eclipse.adt/about.html
index 2892e5d..baa6af1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/about.html
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/about.html
@@ -13,7 +13,6 @@
<pre>
Note: kxml2-2.3.0.jar is under the BSD license rather than the EPL. You can find a copy of the BSD License at http://www.opensource.org/licenses/bsd-license.php
- Note: groovy-all-1.7.0.jar is under a BSD/Apache license rather than the EPL. For details, please see http://groovy.codehaus.org/faq.html#licence .
Eclipse Public License - v 1.0
@@ -106,4 +105,4 @@ This Agreement is governed by the laws of the State of New York and the intellec
</pre>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/build.properties b/eclipse/plugins/com.android.ide.eclipse.adt/build.properties
index fdd7c71..9eb0d29 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/build.properties
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/build.properties
@@ -4,7 +4,6 @@ bin.includes = plugin.xml,\
.,\
templates/,\
about.ini,\
- gscripts/,\
libs/,\
about.properties,\
NOTICE,\
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/api/IViewRule.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/api/IViewRule.java
index 71c14e3..13699b4 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/api/IViewRule.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/api/IViewRule.java
@@ -24,13 +24,12 @@ import java.util.Map;
* An {@link IViewRule} describes the GLE rules that apply to a given Layout or View object
* in the Graphical Layout Editor (GLE).
* <p/>
- * Such a rule is implemented using a Groovy script located in the
- * com.android.ide.eclipse.adt.internal.editors.layout.gre package or in a
- * projects' /gscript folder for custom views.
+ * Such a rule is implemented by builtin layout helpers, or 3rd party layout rule implementations
+ * provided with or for a given 3rd party widget.
* <p/>
- * The Groovy script must be named using the fully qualified class name of the View or Layout,
- * e.g. "android.widget.LinearLayout.groovy". If the rule engine can't find a groovy script
- * for a given element, it will use the closest matching parent (e.g. View instead of ViewGroup).
+ * A 3rd party layout rule should use the same fully qualified class name as the layout it
+ * represents, plus "Rule" as a suffix. For example, the layout rule for the
+ * LinearLayout class is LinearLayoutRule, in the same package.
* <p/>
* Rule instances are stateless. They are created once per View class to handle and are shared
* across platforms or editor instances. As such, rules methods should never cache editor-specific
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/BaseLayout.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/BaseLayout.java
index 13b335e..2a2102a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/BaseLayout.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/BaseLayout.java
@@ -81,7 +81,7 @@ public class BaseLayout extends BaseView {
* The default behavior for pasting in a layout with a specific child target
* is to simulate a drop right above the top left of the given child target.
* <p/>
- * This method is invoked by BaseView.groovy when onPaste() is called --
+ * This method is invoked by BaseView when onPaste() is called --
* views don't generally accept children and instead use the target node as
* a hint to paste "before" it.
*/
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ExplodedRenderingHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ExplodedRenderingHelper.java
index be882a7..e06ad40 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ExplodedRenderingHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ExplodedRenderingHelper.java
@@ -44,7 +44,7 @@ import java.util.Map.Entry;
*
* TODO
* - find a better class name :)
- * - move the logic for each layout to groovy scripts?
+ * - move the logic for each layout to the layout rule classes?
* - support custom classes (by querying JDT for its super class and reverting to its behavior)
*/
public final class ExplodedRenderingHelper {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DynamicContextMenu.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DynamicContextMenu.java
index 2e53806..fb7ccfa 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DynamicContextMenu.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DynamicContextMenu.java
@@ -45,7 +45,7 @@ import java.util.regex.Pattern;
/**
* Helper class that is responsible for adding and managing the dynamic menu items
- * contributed by the {@link IViewRule} groovy instances, based on the current selection
+ * contributed by the {@link IViewRule} instances, based on the current selection
* on the {@link LayoutCanvas}.
* <p/>
* This class is tied to a specific {@link LayoutCanvas} instance and a root {@link MenuManager}.
@@ -68,7 +68,7 @@ import java.util.regex.Pattern;
/**
* Creates a new helper responsible for adding and managing the dynamic menu items
- * contributed by the {@link IViewRule} groovy instances, based on the current selection
+ * contributed by the {@link IViewRule} instances, based on the current selection
* on the {@link LayoutCanvas}.
*
* @param canvas The {@link LayoutCanvas} providing the selection, the node factory and
@@ -269,7 +269,7 @@ import java.util.regex.Pattern;
}
/**
- * Returns the menu actions computed by the groovy rule associated with this view.
+ * Returns the menu actions computed by the rule associated with this view.
*/
public List<MenuAction> getMenuActions(CanvasViewInfo vi) {
if (vi == null) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
index 883a40b..2c77c9b 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
@@ -172,7 +172,7 @@ public class GraphicalEditorPart extends EditorPart
/** The layout canvas displayed to the right of the sash. */
private LayoutCanvasViewer mCanvasViewer;
- /** The Groovy Rules Engine associated with this editor. It is project-specific. */
+ /** The Rules Engine associated with this editor. It is project-specific. */
private RulesEngine mRulesEngine;
/** Styled text displaying the most recent error in the error view. */
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java
index 3e5bdcf..44a2e74 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java
@@ -154,7 +154,7 @@ class LayoutCanvas extends Canvas implements ISelectionProvider {
/** The layout editor that uses this layout canvas. */
private final LayoutEditor mLayoutEditor;
- /** The Groovy Rules Engine, associated with the current project. */
+ /** The Rules Engine, associated with the current project. */
private RulesEngine mRulesEngine;
/** SWT clipboard instance. */
@@ -459,12 +459,12 @@ class LayoutCanvas extends Canvas implements ISelectionProvider {
return mLastValidViewInfoRoot == null;
}
- /** Returns the Groovy Rules Engine, associated with the current project. */
+ /** Returns the Rules Engine, associated with the current project. */
/* package */ RulesEngine getRulesEngine() {
return mRulesEngine;
}
- /** Sets the Groovy Rules Engine, associated with the current project. */
+ /** Sets the Rules Engine, associated with the current project. */
/* package */ void setRulesEngine(RulesEngine rulesEngine) {
mRulesEngine = rulesEngine;
}
@@ -1964,7 +1964,7 @@ class LayoutCanvas extends Canvas implements ISelectionProvider {
* copy, cut, paste and show in > explorer. This is created by
* {@link #setupStaticMenuActions(IMenuManager)}.
* <p/>
- * There's also a dynamic part that is populated by the groovy rules of the
+ * There's also a dynamic part that is populated by the rules of the
* selected elements, created by {@link DynamicContextMenu}.
*/
private void createContextMenu() {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeFactory.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeFactory.java
index 022d233..f4ebc23 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeFactory.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeFactory.java
@@ -46,7 +46,7 @@ public class NodeFactory {
/**
* Returns an {@link INode} proxy based on a given {@link UiViewElementNode} that
- * is not yet part of the canvas, typically those created by groovy scripts
+ * is not yet part of the canvas, typically those created by layout rules
* when generating new XML.
*/
public NodeProxy create(UiViewElementNode uiNode) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeProxy.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeProxy.java
index 30782bf..c6c84a7 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeProxy.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeProxy.java
@@ -362,7 +362,7 @@ public class NodeProxy implements INode {
* Helper methods that returns a {@link ViewElementDescriptor} for the requested FQCN.
* Will return null if we can't find that FQCN or we lack the editor/data/descriptors info
* (which shouldn't really happen since at this point the SDK should be fully loaded and
- * isn't reloading, or we wouldn't be here editing XML for a groovy script.)
+ * isn't reloading, or we wouldn't be here editing XML for a layout rule.)
*/
private ViewElementDescriptor getFqcnViewDescritor(String fqcn) {
AndroidXmlEditor editor = mNode.getEditor();
@@ -375,7 +375,7 @@ public class NodeProxy implements INode {
private void warnPrintf(String msg, Object...params) {
AdtPlugin.printToConsole(
- mNode == null ? "Groovy" : mNode.getDescriptor().getXmlLocalName() + ".groovy",
+ mNode == null ? "" : mNode.getDescriptor().getXmlLocalName(),
String.format(msg, params)
);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java
index d492a7a..8de095d 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngine.java
@@ -27,117 +27,119 @@ import com.android.ide.common.api.MenuAction;
import com.android.ide.common.api.Point;
import com.android.ide.common.layout.ViewRule;
import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.AndroidConstants;
import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SimpleElement;
import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
-import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor;
-import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IFolderListener;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
+import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
-import com.android.sdklib.annotations.VisibleForTesting;
-import com.android.sdklib.annotations.VisibleForTesting.Visibility;
-
-import org.codehaus.groovy.control.CompilationFailedException;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.CompilerConfiguration;
-import org.codehaus.groovy.control.Phases;
-import org.codehaus.groovy.control.SourceUnit;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IFolder;
+import com.android.sdklib.internal.project.ProjectProperties;
+
import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.Window;
-import groovy.lang.ExpandoMetaClass;
-import groovy.lang.GroovyClassLoader;
-import groovy.lang.GroovyCodeSource;
-import groovy.lang.GroovyObject;
-import groovy.lang.GroovyResourceLoader;
-
-import java.io.InputStream;
-import java.io.InputStreamReader;
+import java.io.File;
import java.net.MalformedURLException;
-import java.net.URI;
import java.net.URL;
-import java.nio.charset.Charset;
-import java.security.CodeSource;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
/**
- * The rule engine manages the groovy rules files and interacts with them.
+ * The rule engine manages the layout rules and interacts with them.
* There's one {@link RulesEngine} instance per layout editor.
- * Each instance has 2 sets of scripts: the static ADT rules (shared across all instances)
+ * Each instance has 2 sets of rules: the static ADT rules (shared across all instances)
* and the project specific rules (local to the current instance / layout editor).
*/
public class RulesEngine {
+ private final IProject mProject;
+ private final Map<Object, IViewRule> mRulesCache = new HashMap<Object, IViewRule>();
/**
- * The project folder where the scripts are located.
- * This is for both our unique ADT project folder and the user projects folders.
- */
- @VisibleForTesting(visibility=Visibility.PRIVATE)
- public static final String FD_GSCRIPTS = "gscripts"; //$NON-NLS-1$
- /**
- * The extension we expect for the groovy scripts.
+ * Class loader (or null) used to load user/project-specific IViewRule
+ * classes
*/
- private static final String SCRIPT_EXT = ".groovy"; //$NON-NLS-1$
+ private ClassLoader mUserClassLoader;
+
/**
- * The package we expect for our groovy scripts.
- * User scripts do not need to use the same (and in fact should probably not.)
+ * Flag set when we've attempted to initialize the {@link #mUserClassLoader}
+ * already
*/
- private static final String SCRIPT_PACKAGE = "com.android.adt.gscripts"; //$NON-NLS-1$
-
- private final GroovyClassLoader mClassLoader;
- private final IProject mProject;
- private final Map<Object, IViewRule> mRulesCache = new HashMap<Object, IViewRule>();
- private ProjectFolderListener mProjectFolderListener;
-
+ private boolean mUserClassLoaderInited;
/**
* Creates a new {@link RulesEngine} associated with the selected project.
* <p/>
- * The rules engine will look in the projects "/gscripts" folder for custom view rules.
+ * The rules engine will look in the project for a tools jar to load custom view rules.
*
* @param project A non-null open project.
*/
public RulesEngine(IProject project) {
mProject = project;
- ClassLoader cl = getClass().getClassLoader();
-
- // Note: we could use the CompilerConfiguration to add an output log collector
- CompilerConfiguration cc = new CompilerConfiguration();
- cc.setDefaultScriptExtension(SCRIPT_EXT);
+ }
- mClassLoader = new GreGroovyClassLoader(cl, cc);
+ /**
+ * Find out whether the given project has 3rd party ViewRules, and if so
+ * return a ClassLoader which can locate them. If not, return null.
+ * @param project The project to load user rules from
+ * @return A class loader which can user view rules, or otherwise null
+ */
+ private static ClassLoader computeUserClassLoader(IProject project) {
+ // Default place to locate layout rules. The user may also add to this
+ // path by defining a config property specifying
+ // additional .jar files to search via a the layoutrules.jars property.
+ ProjectState state = Sdk.getProjectState(project);
+ ProjectProperties projectProperties = state.getProperties();
+
+ // Ensure we have the latest & greatest version of the properties.
+ // This allows users to reopen editors in a running Eclipse instance
+ // to get updated view rule jars
+ projectProperties.reload();
+
+ String path = projectProperties.getProperty(
+ ProjectProperties.PROPERTY_RULES_PATH);
+
+ if (path != null && path.length() > 0) {
+ List<URL> urls = new ArrayList<URL>();
+ String[] pathElements = path.split(File.pathSeparator);
+ for (String pathElement : pathElements) {
+ pathElement = pathElement.trim(); // Avoid problems with trailing whitespace etc
+ File pathFile = new File(pathElement);
+ if (!pathFile.isAbsolute()) {
+ pathFile = new File(project.getLocation().toFile(), pathElement);
+ }
+ // Directories and jar files are okay. Do we need to
+ // validate the files here as .jar files?
+ if (pathFile.isFile() || pathFile.isDirectory()) {
+ URL url;
+ try {
+ url = pathFile.toURI().toURL();
+ urls.add(url);
+ } catch (MalformedURLException e) {
+ AdtPlugin.log(IStatus.WARNING,
+ "Invalid URL: %1$s", //$NON-NLS-1$
+ e.toString());
+ }
+ }
+ }
- // Add the project's gscript folder to the classpath, if it exists.
- IResource f = project.findMember(FD_GSCRIPTS);
- if ((f instanceof IFolder) && f.exists()) {
- URI uri = ((IFolder) f).getLocationURI();
- try {
- URL url = uri.toURL();
- mClassLoader.addURL(url);
- } catch (MalformedURLException e) {
- // ignore; it's not a valid URL, we obviously won't use it
- // in the class path.
+ if (urls.size() > 0) {
+ return new URLClassLoader(urls.toArray(new URL[urls.size()]),
+ RulesEngine.class.getClassLoader());
}
}
- mProjectFolderListener = new ProjectFolderListener();
- GlobalProjectMonitor.getMonitor().addFolderListener(
- mProjectFolderListener,
- IResourceDelta.ADDED | IResourceDelta.REMOVED | IResourceDelta.CHANGED);
+ return null;
}
/**
@@ -152,10 +154,6 @@ public class RulesEngine {
* This frees some resources, such as the project's folder monitor.
*/
public void dispose() {
- if (mProjectFolderListener != null) {
- GlobalProjectMonitor.getMonitor().removeFolderListener(mProjectFolderListener);
- mProjectFolderListener = null;
- }
clearCache();
}
@@ -172,7 +170,7 @@ public class RulesEngine {
*
* @param element The view element to target. Can be null.
* @return Null if the rule failed, there's no rule or the rule does not want to override
- * the display name. Otherwise, a string as returned by the groovy script.
+ * the display name. Otherwise, a string as returned by the rule.
*/
public String callGetDisplayName(UiViewElementNode element) {
// try to find a rule for this element's FQCN
@@ -418,16 +416,6 @@ public class RulesEngine {
return null;
}
- private class ProjectFolderListener implements IFolderListener {
- public void folderChanged(IFolder folder, int kind) {
- if (folder.getProject() == mProject &&
- FD_GSCRIPTS.equals(folder.getName())) {
- // Clear our whole rules cache, to not have to deal with dependencies.
- clearCache();
- }
- }
- }
-
/**
* Clear the Rules cache. Calls onDispose() on each rule.
*/
@@ -525,11 +513,11 @@ public class RulesEngine {
* Once a rule is found (or not), it is stored in a cache using its target FQCN
* so we don't try to reload it.
* <p/>
- * The real FQCN is the actual groovy filename we're loading, e.g. "android.view.View.groovy"
+ * The real FQCN is the actual rule class we're loading, e.g. "android.view.View"
* where target FQCN is the class we were initially looking for, which might be the same as
* the real FQCN or might be a derived class, e.g. "android.widget.TextView".
*
- * @param realFqcn The FQCN of the groovy rule actually being loaded.
+ * @param realFqcn The FQCN of the rule class actually being loaded.
* @param targetFqcn The FQCN of the class actually processed, which might be different from
* the FQCN of the rule being loaded.
*/
@@ -545,32 +533,53 @@ public class RulesEngine {
return rule;
}
- // Look for class via reflection first
+ // Look for class via reflection
try {
- int dotIndex = realFqcn.lastIndexOf('.');
- String baseName = realFqcn.substring(dotIndex+1);
-
// For now, we package view rules for the builtin Android views and
// widgets with the tool in a special package, so look there rather
// than in the same package as the widgets.
- String packageName;
+ String ruleClassName;
+ ClassLoader classLoader;
if (realFqcn.startsWith("android.")) { //$NON-NLS-1$
// This doesn't handle a case where there are name conflicts
// (e.g. where there are multiple different views with the same
// class name and only differing in package names, but that's a
// really bad practice in the first place, and if that situation
// should come up in the API we can enhance this algorithm.
- packageName = ViewRule.class.getName();
+ String packageName = ViewRule.class.getName();
packageName = packageName.substring(0, packageName.lastIndexOf('.'));
+ classLoader = RulesEngine.class.getClassLoader();
+ int dotIndex = realFqcn.lastIndexOf('.');
+ String baseName = realFqcn.substring(dotIndex+1);
+ ruleClassName = packageName + "." + //$NON-NLS-1$
+ baseName + "Rule"; //$NON-NLS-1$
+
} else {
+ // Initialize the user-classpath for 3rd party IViewRules, if necessary
+ if (mUserClassLoader == null) {
+ // Only attempt to load rule paths once (per RulesEngine instance);
+ if (!mUserClassLoaderInited) {
+ mUserClassLoaderInited = true;
+ mUserClassLoader = computeUserClassLoader(mProject);
+ }
+
+ if (mUserClassLoader == null) {
+ // The mUserClassLoader can be null; this is the typical scenario,
+ // when the user is only using builtin layout rules.
+ // This means however we can't resolve this fqcn since it's not
+ // in the name space of the builtin rules.
+ mRulesCache.put(realFqcn, null);
+ return null;
+ }
+ }
+
// For other (3rd party) widgets, look in the same package (though most
// likely not in the same jar!)
- packageName = realFqcn.substring(0, dotIndex);
+ ruleClassName = realFqcn + "Rule"; //$NON-NLS-1$
+ classLoader = mUserClassLoader;
}
- String ruleClassName = packageName + "." + //$NON-NLS-1$
- baseName + "Rule"; //$NON-NLS-1$
- Class<?> clz = Class.forName(ruleClassName);
+ Class<?> clz = Class.forName(ruleClassName, true, classLoader);
rule = (IViewRule) clz.newInstance();
return initializeRule(rule, targetFqcn);
} catch (ClassNotFoundException ex) {
@@ -584,39 +593,6 @@ public class RulesEngine {
logError("load rule error (%s): %s", realFqcn, e.toString());
}
- // Look for the file in ADT first.
- // That means a project can't redefine any of the rules we define.
- String filename = realFqcn + SCRIPT_EXT;
-
- try {
- InputStream is = AdtPlugin.readEmbeddedFileAsStream(
- FD_GSCRIPTS + AndroidConstants.WS_SEP + filename);
- rule = loadStream(is, realFqcn, "ADT"); //$NON-NLS-1$
- if (rule != null) {
- return initializeRule(rule, targetFqcn);
- }
- } catch (Exception e) {
- logError("load rule error (%s): %s", filename, e.toString());
- }
-
-
- // Then look for the file in the project
- IResource r = mProject.findMember(FD_GSCRIPTS);
- if (r != null && r.getType() == IResource.FOLDER) {
- r = ((IFolder) r).findMember(filename);
- if (r != null && r.getType() == IResource.FILE) {
- try {
- InputStream is = ((IFile) r).getContents();
- rule = loadStream(is, realFqcn, mProject.getName());
- if (rule != null) {
- return initializeRule(rule, targetFqcn);
- }
- } catch (Exception e) {
- logError("load rule error (%s): %s", filename, e.getMessage());
- }
- }
- }
-
// Memorize in the cache that we couldn't find a rule for this real FQCN
mRulesCache.put(realFqcn, null);
return null;
@@ -629,7 +605,7 @@ public class RulesEngine {
* Contract: the rule is not in the {@link #mRulesCache} yet and this method will
* cache it using the target FQCN if the rule is accepted.
* <p/>
- * The real FQCN is the actual groovy filename we're loading, e.g. "android.view.View.groovy"
+ * The real FQCN is the actual rule class we're loading, e.g. "android.view.View"
* where target FQCN is the class we were initially looking for, which might be the same as
* the real FQCN or might be a derived class, e.g. "android.widget.TextView".
*
@@ -641,10 +617,6 @@ public class RulesEngine {
private IViewRule initializeRule(IViewRule rule, String targetFqcn) {
try {
- if (rule instanceof GroovyObject) {
- initializeMetaClass((GroovyObject) rule, targetFqcn);
- }
-
if (rule.onInitialize(targetFqcn, new ClientRulesEngineImpl(targetFqcn))) {
// Add it to the cache and return it
mRulesCache.put(targetFqcn, rule);
@@ -662,73 +634,6 @@ public class RulesEngine {
}
/**
- * Initializes a custom meta class for the given {@link GroovyObject}.
- * This is used to add a meta "_rules_engine" property to the {@link IViewRule} instances.
- *
- * @param instance The {@link IViewRule} groovy object to modify.
- * @param targetFqcn The FQCN for the new {@link IClientRulesEngine}.
- */
- private void initializeMetaClass(GroovyObject instance, final String targetFqcn) {
-
- final ClientRulesEngineImpl mClient = new ClientRulesEngineImpl(targetFqcn);
-
- ExpandoMetaClass mc = new ExpandoMetaClass(instance.getClass(), false) {
- @Override
- public Object getProperty(Object object, String name) {
- if (IViewRule.RULES_ENGINE.equals(name)) {
- return mClient;
- }
- return super.getProperty(object, name);
- }
- };
- mc.initialize();
-
- instance.setMetaClass(mc);
- }
-
- /**
- * Actually load a groovy script and instantiate an {@link IViewRule} from it.
- * On error, outputs (hopefully meaningful) groovy error messages.
- *
- * @param is The input stream for the groovy script. Can be null.
- * @param fqcn The class name, for display purposes only.
- * @param codeBase A string eventually passed to {@link CodeSource} to define some kind
- * of security permission. Quite irrelevant in our case since it all
- * comes from an input stream. However this method uses it to print
- * the origin of the source in the exception errors.
- * @return A new {@link IViewRule} or null if loading failed for any reason.
- */
- private IViewRule loadStream(InputStream is, String fqcn, String codeBase) {
- try {
- if (is == null) {
- // We handle this case for convenience. It typically means that the
- // input stream couldn't be opened because the file was not found.
- // Since we expect this to be a common case, we don't log it as an error.
- return null;
- }
-
- // We don't really now the character encoding, we're going to assume UTF-8.
- InputStreamReader reader = new InputStreamReader(is, Charset.forName("UTF-8"));
- GroovyCodeSource source = new GroovyCodeSource(reader, fqcn, codeBase);
-
- // Create a groovy class from it. Can fail to compile.
- Class<?> c = mClassLoader.parseClass(source);
-
- // Get an instance. This might throw ClassCastException.
- return (IViewRule) c.newInstance();
-
- } catch (CompilationFailedException e) {
- logError("Compilation error in %1$s:%2$s.groovy: %3$s", codeBase, fqcn, e.toString());
- } catch (ClassCastException e) {
- logError("Script %1$s:%2$s.groovy does not implement IViewRule", codeBase, fqcn);
- } catch (Exception e) {
- logError("Failed to use %1$s:%2$s.groovy: %3$s", codeBase, fqcn, e.toString());
- }
-
- return null;
- }
-
- /**
* Logs an error to the console.
*
* @param format A format string following the format specified by
@@ -740,83 +645,6 @@ public class RulesEngine {
AdtPlugin.printErrorToConsole(mProject, s);
}
- // -----
-
- /**
- * A custom {@link GroovyClassLoader} that lets us override the {@link CompilationUnit}
- * and the {@link GroovyResourceLoader}.
- */
- private static class GreGroovyClassLoader extends GroovyClassLoader {
-
- public GreGroovyClassLoader(ClassLoader cl, CompilerConfiguration cc) {
- super(cl, cc);
-
- // Override the resource loader: when a class is not found, we try to find a class
- // defined in our internal ADT groovy script, assuming it has our special package.
- // Note that these classes do not have to implement IViewRule. That means we can
- // create utility classes in groovy used by the other groovy rules.
- final GroovyResourceLoader resLoader = getResourceLoader();
- setResourceLoader(new GroovyResourceLoader() {
- public URL loadGroovySource(String filename) throws MalformedURLException {
- URL url = resLoader.loadGroovySource(filename);
- if (url == null) {
- // We only try to load classes in our own groovy script package
- String p = SCRIPT_PACKAGE + "."; //$NON-NLS-1$
-
- if (filename.startsWith(p)) {
- filename = filename.substring(p.length());
-
- // This will return null if the file doesn't exists.
- // The groovy resolver will actually load and verify the class
- // implemented matches the one it was expecting in the first place,
- // so we don't have anything to do here besides returning the URL to
- // the source file.
- url = AdtPlugin.getEmbeddedFileUrl(
- AndroidConstants.WS_SEP +
- FD_GSCRIPTS +
- AndroidConstants.WS_SEP +
- filename +
- SCRIPT_EXT);
- }
- }
- return url;
- }
- });
- }
-
- @Override
- protected CompilationUnit createCompilationUnit(
- CompilerConfiguration config,
- CodeSource source) {
- return new GreCompilationUnit(config, source, this);
- }
- }
-
- /**
- * A custom {@link CompilationUnit} that lets us add default import for our base classes
- * using the base package of {@link IViewRule} (e.g. "import com.android...gscripts.*")
- */
- private static class GreCompilationUnit extends CompilationUnit {
-
- public GreCompilationUnit(
- CompilerConfiguration config,
- CodeSource source,
- GroovyClassLoader loader) {
- super(config, source, loader);
-
- SourceUnitOperation op = new SourceUnitOperation() {
- @Override
- public void call(SourceUnit source) throws CompilationFailedException {
- // add the equivalent of "import com.android...gscripts.*" to the source.
- String p = IViewRule.class.getPackage().getName();
- source.getAST().addStarImport(p + "."); //$NON-NLS-1$
- }
- };
-
- addPhaseOperation(op, Phases.CONVERSION);
- }
- }
-
/**
* Implementation of {@link IClientRulesEngine}. This provide {@link IViewRule} clients
* with a few methods they can use to use functionality from this {@link RulesEngine}.
@@ -835,7 +663,7 @@ public class RulesEngine {
public void debugPrintf(String msg, Object... params) {
AdtPlugin.printToConsole(
- mFqcn == null ? "Groovy" : mFqcn,
+ mFqcn == null ? "<unknown>" : mFqcn,
String.format(msg, params)
);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/.classpath b/eclipse/plugins/com.android.ide.eclipse.tests/.classpath
index 1f2b3ec..9164986 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/.classpath
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/.classpath
@@ -6,7 +6,6 @@
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="lib" path="layoutlib.jar"/>
<classpathentry kind="lib" path="kxml2-2.3.0.jar"/>
- <classpathentry kind="lib" path="groovy-all-1.7.0.jar"/>
<classpathentry kind="lib" path="easymock.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/ddmlib"/>
<classpathentry combineaccessrules="false" kind="src" path="/ddmuilib"/>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
index 549611f..36e25e0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
@@ -10,5 +10,4 @@ Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ClassPath: kxml2-2.3.0.jar,
.,
layoutlib.jar,
- groovy-all-1.7.0.jar,
easymock.jar
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/build.properties b/eclipse/plugins/com.android.ide.eclipse.tests/build.properties
index 7c9915c..eece9f2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/build.properties
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/build.properties
@@ -11,6 +11,5 @@ bin.includes = META-INF/,\
unittests/com/android/sdklib/testdata/,\
unittests/com/android/layoutlib/testdata/,\
unittests/com/android/ide/eclipse/testdata/,\
- groovy-all-1.7.0.jar,\
easymock.jar
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/AllTests.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/AllTests.java
index ee79336..5386142 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/AllTests.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/AllTests.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- *
+ *
* Licensed under the Eclipse Public License, Version 1.0 (the "License"); you
* may not use this file except in compliance with the License. You may obtain a
* copy of the License at
- *
+ *
* http://www.eclipse.org/org/documents/epl-v10.php
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -24,9 +24,9 @@ import junit.framework.TestSuite;
public class AllTests extends TestSuite {
public AllTests() {
-
+
}
-
+
/**
* Returns a suite of test cases to be run.
*/
@@ -34,7 +34,6 @@ public class AllTests extends TestSuite {
TestSuite suite = new TestSuite();
suite.addTest(FuncTests.suite());
suite.addTest(UnitTests.suite());
- suite.addTest(GroovyTestsSuite.suite());
return suite;
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/GroovyTestsSuite.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/GroovyTestsSuite.java
deleted file mode 100755
index affc7ec..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/GroovyTestsSuite.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.0 (the "License"); you
- * may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.eclipse.org/org/documents/epl-v10.php
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.android.ide.eclipse.tests;
-
-import com.android.ide.eclipse.tests.groovytests.TestGroovy;
-
-import junit.framework.TestSuite;
-
-/**
- * Container TestSuite for groovy tests to be run
- */
-
-public class GroovyTestsSuite extends TestSuite {
-
- static final String GROOVY_TEST_PACKAGE = "com.android.ide.eclipse.tests.groovytests";
-
- public GroovyTestsSuite() {
-
- }
-
- /**
- * Returns a suite of test cases to be run.
- * Needed for JUnit3 compliant command line test runner
- */
- public static TestSuite suite() {
- TestSuite suite = new TestSuite();
-
- suite.addTestSuite(TestGroovy.class);
-
- return suite;
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/UnitTests.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/UnitTests.java
index 2d74f82..15d3871 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/UnitTests.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/UnitTests.java
@@ -55,8 +55,7 @@ public class UnitTests {
@Override
protected boolean isTestClass(Class<?> testClass) {
return super.isTestClass(testClass) &&
- !testClass.getPackage().getName().startsWith(FuncTests.FUNC_TEST_PACKAGE) &&
- !testClass.getPackage().getName().startsWith(GroovyTestsSuite.GROOVY_TEST_PACKAGE);
+ !testClass.getPackage().getName().startsWith(FuncTests.FUNC_TEST_PACKAGE);
}
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/TestGroovy.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/TestGroovy.java
deleted file mode 100755
index 556bce6..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/TestGroovy.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.eclipse.org/org/documents/epl-v10.php
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ide.eclipse.tests.groovytests;
-
-import org.codehaus.groovy.control.CompilationFailedException;
-import org.eclipse.swt.graphics.Rectangle;
-
-import groovy.lang.GroovyClassLoader;
-
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-
-import junit.framework.TestCase;
-
-/**
- * Tests we can invoke a groovy script that implements a given interface.
- */
-public class TestGroovy extends TestCase {
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- /**
- * This is the interface that we want our Groovy script to implement.
- */
- public static interface AdtTestInterface {
-
- /** Method that returns a boolean. */
- public boolean acceptDrag(String xmlName);
- /** Method that returns an SWT Rectangle. */
- public Rectangle acceptDrop(String xmlName);
-
- /** Method that returns some Groovy object (opaque for us). */
- public Object returnGroovyObject();
- /** Method that accepts the Groovy object back. */
- public boolean testGroovyObject(Object o);
- }
-
- /**
- * Loads a groovy script that defines one class that implements the {@link AdtTestInterface}.
- *
- * @param filename The name of the script to load, that must be located in this Java package.
- * @return A non-null instance of the groovy class on success.
- * @throws CompilationFailedException if the groovy script failed to compile (e.g. syntax
- * errors or it doesn't completely implement the interface.)
- * @throws ClassCastException if the groovy script does not implement our interface.
- * @throws FileNotFoundException if the groovy script does not exist.
- * @throws InstantiationException
- * @throws IllegalAccessException
- */
- @SuppressWarnings("unchecked")
- private AdtTestInterface loadScript(String filename)
- throws CompilationFailedException, ClassCastException,
- InstantiationException, IllegalAccessException,
- FileNotFoundException {
- // Get the input source from the sources or the JAR.
- InputStream myGroovyStream = getClass().getResourceAsStream(filename);
-
- // The stream is null if the file does not exists.
- if (myGroovyStream == null) {
- throw new FileNotFoundException(filename);
- }
-
- // Create a groovy class from it. Can fail to compile.
- ClassLoader cl = getClass().getClassLoader();
- GroovyClassLoader gcl = new GroovyClassLoader(cl);
- Class gClass = gcl.parseClass(myGroovyStream, filename);
-
- // Get an instance. This might throw ClassCastException.
- return (AdtTestInterface) gClass.newInstance();
- }
-
- /**
- * Tests that a {@link FileNotFoundException} is thrown if when trying
- * to load a missing script.
- */
- public void testMissingScript() throws Exception {
- try {
- @SuppressWarnings("unused")
- AdtTestInterface instance = loadScript("not_an_existing_script.groovy");
- fail("loadScript should not succeed, FileNotFoundException expected.");
- } catch (FileNotFoundException e) {
- assertEquals("not_an_existing_script.groovy", e.getMessage());
- return; // succeed
- }
-
- fail("Script failed to throw an exception on missing groovy file.");
- }
-
- /**
- * Tests that a {@link ClassCastException} is thrown if the script does not
- * implement our interface.
- */
- public void testInvalidInterface() throws Exception {
- try {
- @SuppressWarnings("unused")
- AdtTestInterface instance = loadScript("invalid_interface.groovy");
- fail("loadScript should not succeed, ClassCastException expected.");
- } catch(ClassCastException e) {
- // This has to fail because the script does not implement our interface
- // The message explains why but we're not harcoding the message in the test.
- assertNotNull(e.getMessage());
- return; // succeed
- }
-
- fail("Script failed to throw a ClassCastException.");
- }
-
- /**
- * Tests that a {@link CompilationFailedException} is thrown if the script
- * is not valid.
- */
- public void testCompilationError() throws Exception {
- try {
- @SuppressWarnings("unused")
- AdtTestInterface instance = loadScript("compile_error.groovy");
- fail("loadScript should not succeed, CompilationFailedException expected.");
- } catch (CompilationFailedException e) {
- // This script does not compile, the message explains why but we're not
- // harcoding the message in the test.
- assertNotNull(e.getMessage());
- return; // succeed
- }
-
- fail("Script failed to throw a compilation error.");
- }
-
- /**
- * Tests a valid script scenario with only some basic methods
- */
- public void testSimpleMethods() throws Exception {
- AdtTestInterface instance = loadScript("simple_test.groovy");
-
- assertTrue(instance.acceptDrag("LinearLayout"));
- assertFalse(instance.acceptDrag("RelativeLayout"));
- assertNull(instance.acceptDrop("none"));
-
- Rectangle r = instance.acceptDrop("LinearLayout");
- assertNotNull(r);
- assertEquals(new Rectangle(1, 2, 3, 4), r);
- }
-
- /**
- * Tests a valid script scenario with some methods providing some callbacks.
- */
- public void testCallback() throws Exception {
- AdtTestInterface instance = loadScript("simple_test.groovy");
-
- // The groovy method returns an object. We should treat it as an opaque object
- // which purpose is just to give it back to groovy later.
- Object o = instance.returnGroovyObject();
- assertNotNull(o);
-
- // Let the groovy script get back the object and play with it
- assertTrue(instance.testGroovyObject(o));
- }
-
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/compile_error.groovy b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/compile_error.groovy
deleted file mode 100755
index 6516c45..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/compile_error.groovy
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.eclipse.org/org/documents/epl-v10.php
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ide.eclipse.tests.groovytests;
-
-
-import com.android.ide.eclipse.tests.groovytests.TestGroovy.AdtTestInterface;
-
-import org.eclipse.swt.graphics.Rectangle;
-
-class CompileError implements AdtTestInterface {
-
- public boolean acceptDrag(String xmlName) {
- // missing return value (implicit in Groovy so not really an error)
- }
-
- // invalid syntax
- public Rectangle accept(])
-
- // missing method: public Rectangle acceptDrop(String xmlName)
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/invalid_interface.groovy b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/invalid_interface.groovy
deleted file mode 100755
index 0fa1a86..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/invalid_interface.groovy
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.eclipse.org/org/documents/epl-v10.php
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ide.eclipse.tests.groovytests;
-
-class InvalidInterface implements Runnable {
-
- public void run() {
- // pass
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/simple_test.groovy b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/simple_test.groovy
deleted file mode 100755
index 7dd96bd..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/groovytests/simple_test.groovy
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.eclipse.org/org/documents/epl-v10.php
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ide.eclipse.tests.groovytests;
-
-import com.android.ide.eclipse.tests.groovytests.TestGroovy.AdtTestInterface;
-
-import org.eclipse.swt.graphics.Rectangle;
-
-
-class AdtGroovyTest implements AdtTestInterface {
-
- /** Returns a true if the argument is LinearLayout. */
- public boolean acceptDrag(String xmlName) {
- if (xmlName == "LinearLayout") {
- return true;
- }
-
- return false;
- }
-
- /** Returns a new SWT Rectangle if LinearLayout or null. */
- public Rectangle acceptDrop(String xmlName) {
- if (xmlName == "LinearLayout") {
- return new Rectangle(1, 2, 3, 4);
- }
-
- return null;
- }
-
- /** Always throw an assert. */
- public void testAssert() {
- assert true == false
- }
-
- /**
- * Returns some Groovy object, in this case a map with some info and a closure.
- * The caller will return this object to testGroovyObject.
- */
- public Object returnGroovyObject() {
-
- return [
- TheInstance: this,
- SomeRect: new Rectangle(1, 2, 3, 4),
- SomeClosure: { int x, int y -> x + y }
- ]
- }
-
- /** Returns true if the object is the same as the one created by returnGroovyObject. */
- public boolean testGroovyObject(Object o) {
- // Input argument should be a map
- assert o.getClass() == LinkedHashMap
-
- // We expected these keys
- assert o.containsKey("TheInstance")
- assert o.containsKey("SomeRect")
- assert o.containsKey("SomeClosure")
-
- // Check the values
- assert o.TheInstance.is(this) // check identity, not equality
- assert o.SomeRect == new Rectangle(1, 2, 3, 4)
- assert o.SomeClosure != null
-
- // Execute the closure
- assert o.SomeClosure(42, 3) == 45
-
- // Everything succeeded
- return true
- }
-
-}
-
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngineTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngineTest.java
index f6a2ff1..d9a1a3d 100755
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngineTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gre/RulesEngineTest.java
@@ -30,37 +30,8 @@ public class RulesEngineTest extends TestCase {
super.tearDown();
}
-
- public void testCreate() {
-// DISABLED to fix the build. EasyMock dependency not found on the build server,
-// will be fixed in next CL.
-// // Creating a RulesEngine from a given project should ask for the location
-// // of the projects' /gscripts folder.
-// IProject projectMock = EasyMock.createMock(IProject.class);
-// EasyMock.expect(projectMock.findMember(RulesEngine.FD_GSCRIPTS)).andReturn(null);
-// EasyMock.replay(projectMock);
-//
-// RulesEngine r = new RulesEngine(projectMock);
-// assertNotNull(r);
-//
-// EasyMock.verify(projectMock);
+ public void testDummy() {
+ // Here to avoid warning that RulesEngineTest is empty
}
- public void testCallGetDisplayName() {
-// DISABLED to fix the build. EasyMock dependency not found on the build server,
-// will be fixed in next CL.
-// IProject projectMock = EasyMock.createMock(IProject.class);
-// EasyMock.expect(projectMock.findMember(RulesEngine.FD_GSCRIPTS)).andReturn(null);
-// EasyMock.expect(projectMock.getName()).andReturn("unit-test");
-// EasyMock.replay(projectMock);
-//
-// RulesEngine r = new RulesEngine(projectMock);
-//
-// ViewElementDescriptor ved = new ViewElementDescriptor("view", SdkConstants.CLASS_VIEW);
-// UiViewElementNode uiv = new UiViewElementNode(ved);
-//
-// // TODO: this test is not ready. We need a way to override
-// // String result = r.callGetDisplayName(uiv);
-// // assertEquals("com.example.MyJavaClass", result);
- }
}
diff --git a/eclipse/scripts/build_server.sh b/eclipse/scripts/build_server.sh
index aa63b18..12e4472 100755
--- a/eclipse/scripts/build_server.sh
+++ b/eclipse/scripts/build_server.sh
@@ -61,8 +61,8 @@ function check_params() {
function build_libs() {
MAKE_OPT="-j8"
- echo "*** Building: make $MAKE_OPT dx ping ddms androidprefs groovy-all-1.7.0 layoutlib layoutlib_api layoutlib_utils ninepatch sdklib sdkuilib"
- make $MAKE_OPT dx ping ddms androidprefs groovy-all-1.7.0 layoutlib layoutlib_api layoutlib_utils ninepatch sdklib sdkuilib
+ echo "*** Building: make $MAKE_OPT dx ping ddms androidprefs layoutlib layoutlib_api layoutlib_utils ninepatch sdklib sdkuilib"
+ make $MAKE_OPT dx ping ddms androidprefs layoutlib layoutlib_api layoutlib_utils ninepatch sdklib sdkuilib
}
function build_plugin {
diff --git a/eclipse/scripts/create_adt_symlinks.sh b/eclipse/scripts/create_adt_symlinks.sh
index 4fd99fb..fef0761 100755
--- a/eclipse/scripts/create_adt_symlinks.sh
+++ b/eclipse/scripts/create_adt_symlinks.sh
@@ -31,7 +31,6 @@ if [ "$HOST" == "Linux" ]; then
done
ln -svf $BACK/out/host/linux-x86/framework/kxml2-2.3.0.jar "$DEST/"
ln -svf $BACK/out/host/linux-x86/framework/commons-compress-1.0.jar "$DEST/"
- ln -svf $BACK/out/host/linux-x86/framework/groovy-all-1.7.0.jar "$DEST/"
elif [ "$HOST" == "Darwin" ]; then
for LIB in $LIBS; do
@@ -39,7 +38,6 @@ elif [ "$HOST" == "Darwin" ]; then
done
ln -svf $BACK/out/host/darwin-x86/framework/kxml2-2.3.0.jar "$DEST/"
ln -svf $BACK/out/host/darwin-x86/framework/commons-compress-1.0.jar "$DEST/"
- ln -svf $BACK/out/host/darwin-x86/framework/groovy-all-1.7.0.jar "$DEST/"
elif [ "${HOST:0:6}" == "CYGWIN" ]; then
for LIB in $LIBS; do
@@ -54,10 +52,6 @@ elif [ "${HOST:0:6}" == "CYGWIN" ]; then
cp -v "prebuilt/common/commons-compress/commons-compress-1.0.jar" "$DEST/"
fi
- if [ ! -f "$DEST/groovy-all-1.7.0.jar" ]; then
- cp -v "prebuilt/common/groovy/groovy-all-1.7.0.jar" "$DEST/"
- fi
-
chmod -v a+rx "$DEST"/*.jar
else
echo "Unsupported platform ($HOST). Nothing done."
diff --git a/eclipse/scripts/create_test_symlinks.sh b/eclipse/scripts/create_test_symlinks.sh
index 9a9849a..dca9bf3 100755
--- a/eclipse/scripts/create_test_symlinks.sh
+++ b/eclipse/scripts/create_test_symlinks.sh
@@ -49,7 +49,6 @@ if [ "$HOST" == "Linux" ]; then
done
ln -svf $BACK/out/host/linux-x86/framework/kxml2-2.3.0.jar "$DEST/"
ln -svf $BACK/out/host/linux-x86/framework/layoutlib.jar "$DEST/"
- ln -svf $BACK/out/host/linux-x86/framework/groovy-all-1.7.0.jar "$DEST/"
elif [ "$HOST" == "Darwin" ]; then
for LIB in $LIBS; do
@@ -57,7 +56,6 @@ elif [ "$HOST" == "Darwin" ]; then
done
ln -svf $BACK/out/host/darwin-x86/framework/kxml2-2.3.0.jar "$DEST/"
ln -svf $BACK/out/host/darwin-x86/framework/layoutlib.jar "$DEST/"
- ln -svf $BACK/out/host/darwin-x86/framework/groovy-all-1.7.0.jar "$DEST/"
elif [ "${HOST:0:6}" == "CYGWIN" ]; then
for LIB in $LIBS; do
@@ -67,10 +65,6 @@ elif [ "${HOST:0:6}" == "CYGWIN" ]; then
cp -v "prebuilt/common/kxml2/kxml2-2.3.0.jar" "$DEST/"
fi
- if [ ! -f "$DEST/groovy-all-1.7.0.jar" ]; then
- cp -v "prebuilt/common/groovy/groovy-all-1.7.0.jar" "$DEST/"
- fi
-
LIBS="layoutlib.jar"
NEED_MAKE="yes"
for LIB in $LIBS ; do
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java
index 4fe574b..19cad00 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java
@@ -61,6 +61,7 @@ public class ProjectProperties {
private final static String PROPERTY_LIB_REF_REGEX = "android.library.reference.\\d+";
public final static String PROPERTY_PROGUARD_CONFIG = "proguard.config";
+ public final static String PROPERTY_RULES_PATH = "layoutrules.jars";
public final static String PROPERTY_SDK = "sdk.dir";
// LEGACY - Kept so that we can actually remove it from local.properties.
@@ -87,7 +88,8 @@ public class ProjectProperties {
}, null),
DEFAULT(SdkConstants.FN_DEFAULT_PROPERTIES, DEFAULT_HEADER, new String[] {
PROPERTY_TARGET, PROPERTY_LIBRARY, PROPERTY_LIB_REF_REGEX,
- PROPERTY_KEY_STORE, PROPERTY_KEY_ALIAS, PROPERTY_PROGUARD_CONFIG
+ PROPERTY_KEY_STORE, PROPERTY_KEY_ALIAS, PROPERTY_PROGUARD_CONFIG,
+ PROPERTY_RULES_PATH
}, null),
LOCAL(SdkConstants.FN_LOCAL_PROPERTIES, LOCAL_HEADER, new String[] {
PROPERTY_SDK