You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2017/12/20 04:29:12 UTC
[04/47] groovy git commit: Move source files to proper packages
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/DelegatingScript.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/DelegatingScript.java b/src/main/groovy/util/DelegatingScript.java
deleted file mode 100644
index 959c8e8..0000000
--- a/src/main/groovy/util/DelegatingScript.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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 groovy.util;
-
-import groovy.lang.Binding;
-import groovy.lang.GroovyObject;
-import groovy.lang.MetaClass;
-import groovy.lang.MissingMethodException;
-import groovy.lang.MissingPropertyException;
-import groovy.lang.Script;
-import org.codehaus.groovy.runtime.InvokerHelper;
-
-/**
- * {@link Script} that performs method invocations and property access like {@link groovy.lang.Closure} does.
- *
- * <p>
- * {@link DelegatingScript} is a convenient basis for loading a custom-defined DSL as a {@link Script}, then execute it.
- * The following sample code illustrates how to do it:
- *
- * <pre>
- * class MyDSL {
- * public void foo(int x, int y, Closure z) { ... }
- * public void setBar(String a) { ... }
- * }
- *
- * CompilerConfiguration cc = new CompilerConfiguration();
- * cc.setScriptBaseClass(DelegatingScript.class.getName());
- * GroovyShell sh = new GroovyShell(cl,new Binding(),cc);
- * DelegatingScript script = (DelegatingScript)sh.parse(new File("my.dsl"))
- * script.setDelegate(new MyDSL());
- * script.run();
- * </pre>
- *
- * <p>
- * <tt>my.dsl</tt> can look like this:
- *
- * <pre>
- * foo(1,2) {
- * ....
- * }
- * bar = ...;
- * </pre>
- *
- * <p>
- * {@link DelegatingScript} does this by delegating property access and method invocation to the <tt>delegate</tt> object.
- *
- * <p>
- * More formally speaking, given the following script:
- *
- * <pre>
- * a = 1;
- * b(2);
- * </pre>
- *
- * <p>
- * Using {@link DelegatingScript} as the base class, the code will run as:
- *
- * <pre>
- * delegate.a = 1;
- * delegate.b(2);
- * </pre>
- *
- * ... whereas in plain {@link Script}, this will be run as:
- *
- * <pre>
- * binding.setProperty("a",1);
- * ((Closure)binding.getProperty("b")).call(2);
- * </pre>
- *
- * @author Kohsuke Kawaguchi
- */
-public abstract class DelegatingScript extends Script {
- private Object delegate;
- private MetaClass metaClass;
-
- protected DelegatingScript() {
- super();
- }
-
- protected DelegatingScript(Binding binding) {
- super(binding);
- }
-
- /**
- * Sets the delegation target.
- */
- public void setDelegate(Object delegate) {
- this.delegate = delegate;
- this.metaClass = InvokerHelper.getMetaClass(delegate.getClass());
- }
-
- @Override
- public Object invokeMethod(String name, Object args) {
- try {
- if (delegate instanceof GroovyObject) {
- return ((GroovyObject) delegate).invokeMethod(name, args);
- }
- return metaClass.invokeMethod(delegate, name, args);
- } catch (MissingMethodException mme) {
- return super.invokeMethod(name, args);
- }
- }
-
- @Override
- public Object getProperty(String property) {
- try {
- return metaClass.getProperty(delegate,property);
- } catch (MissingPropertyException e) {
- return super.getProperty(property);
- }
- }
-
- @Override
- public void setProperty(String property, Object newValue) {
- try {
- metaClass.setProperty(delegate,property,newValue);
- } catch (MissingPropertyException e) {
- super.setProperty(property,newValue);
- }
- }
-
- public Object getDelegate() {
- return delegate;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/Eval.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/Eval.java b/src/main/groovy/util/Eval.java
deleted file mode 100644
index 87f9295..0000000
--- a/src/main/groovy/util/Eval.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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 groovy.util;
-
-import groovy.lang.Binding;
-import groovy.lang.GroovyShell;
-import org.codehaus.groovy.control.CompilationFailedException;
-
-/**
- * Allow easy integration from Groovy into Java through convenience methods.
- * <p>
- * This class is a simple helper on top of GroovyShell. You can use it to evaluate small
- * Groovy scripts that don't need large Binding objects. For example, this script
- * executes with no errors:
- * <pre class="groovyTestCase">
- * assert Eval.me(' 2 * 4 + 2') == 10
- * assert Eval.x(2, ' x * 4 + 2') == 10
- * </pre>
- *
- * @see GroovyShell
- * @author Dierk Koenig
- */
-
-public class Eval {
- /**
- * Evaluates the specified String expression and returns the result. For example:
- * <pre class="groovyTestCase">
- * assert Eval.me(' 2 * 4 + 2') == 10
- * </pre>
- * @param expression the Groovy expression to evaluate
- * @return the result of the expression
- * @throws CompilationFailedException if expression is not valid Groovy
- */
- public static Object me(final String expression) throws CompilationFailedException {
- return me(null, null, expression);
- }
-
- /**
- * Evaluates the specified String expression and makes the parameter available inside
- * the script, returning the result. For example, this code binds the 'x' variable:
- * <pre class="groovyTestCase">
- * assert Eval.me('x', 2, ' x * 4 + 2') == 10
- * </pre>
- * @param expression the Groovy expression to evaluate
- * @return the result of the expression
- * @throws CompilationFailedException if expression is not valid Groovy
- */
- public static Object me(final String symbol, final Object object, final String expression) throws CompilationFailedException {
- Binding b = new Binding();
- b.setVariable(symbol, object);
- GroovyShell sh = new GroovyShell(b);
- return sh.evaluate(expression);
- }
-
- /**
- * Evaluates the specified String expression and makes the parameter available inside
- * the script bound to a variable named 'x', returning the result. For example, this
- * code executes without failure:
- * <pre class="groovyTestCase">
- * assert Eval.x(2, ' x * 4 + 2') == 10
- * </pre>
- * @param expression the Groovy expression to evaluate
- * @return the result of the expression
- * @throws CompilationFailedException if expression is not valid Groovy
- */
- public static Object x(final Object x, final String expression) throws CompilationFailedException {
- return me("x", x, expression);
- }
-
- /**
- * Evaluates the specified String expression and makes the first two parameters available inside
- * the script bound to variables named 'x' and 'y' respectively, returning the result. For example,
- * this code executes without failure:
- * <pre class="groovyTestCase">
- * assert Eval.xy(2, 4, ' x * y + 2') == 10
- * </pre>
- * @param expression the Groovy expression to evaluate
- * @return the result of the expression
- * @throws CompilationFailedException if expression is not valid Groovy
- */
- public static Object xy(final Object x, final Object y, final String expression) throws CompilationFailedException {
- Binding b = new Binding();
- b.setVariable("x", x);
- b.setVariable("y", y);
- GroovyShell sh = new GroovyShell(b);
- return sh.evaluate(expression);
- }
-
- /**
- * Evaluates the specified String expression and makes the first three parameters available inside
- * the script bound to variables named 'x', 'y', and 'z' respectively, returning the result. For
- * example, this code executes without failure:
- * <pre class="groovyTestCase">
- * assert Eval.xyz(2, 4, 2, ' x * y + z') == 10
- * </pre>
- * @param expression the Groovy expression to evaluate
- * @return the result of the expression
- * @throws CompilationFailedException if expression is not valid Groovy
- */
- public static Object xyz(final Object x, final Object y, final Object z, final String expression) throws CompilationFailedException {
- Binding b = new Binding();
- b.setVariable("x", x);
- b.setVariable("y", y);
- b.setVariable("z", z);
- GroovyShell sh = new GroovyShell(b);
- return sh.evaluate(expression);
- }
-}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/Expando.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/Expando.java b/src/main/groovy/util/Expando.java
deleted file mode 100644
index f009551..0000000
--- a/src/main/groovy/util/Expando.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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 groovy.util;
-
-import groovy.lang.Closure;
-import groovy.lang.GroovyObjectSupport;
-import groovy.lang.GroovyRuntimeException;
-import groovy.lang.MetaExpandoProperty;
-import groovy.lang.MissingPropertyException;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-
-/**
- * Represents a dynamically expandable bean.
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- * @author Hein Meling
- * @author Pilho Kim
- */
-public class Expando extends GroovyObjectSupport {
-
- private Map expandoProperties;
-
- public Expando() {
- }
-
- public Expando(Map expandoProperties) {
- this.expandoProperties = expandoProperties;
- }
-
- /**
- * @return the dynamically expanded properties
- */
- public Map getProperties() {
- if (expandoProperties == null) {
- expandoProperties = createMap();
- }
- return expandoProperties;
- }
-
- public List getMetaPropertyValues() {
- // run through all our current properties and create MetaProperty objects
- List ret = new ArrayList();
- for (Object o : getProperties().entrySet()) {
- Entry entry = (Entry) o;
- ret.add(new MetaExpandoProperty(entry));
- }
-
- return ret;
- }
-
- public Object getProperty(String property) {
- // always use the expando properties first
- Object result = getProperties().get(property);
- if (result != null) return result;
- try {
- return super.getProperty(property);
- }
- catch (MissingPropertyException e) {
- // IGNORE
- }
- return null;
- }
-
- public void setProperty(String property, Object newValue) {
- // always use the expando properties
- getProperties().put(property, newValue);
- }
-
- public Object invokeMethod(String name, Object args) {
- try {
- return super.invokeMethod(name, args);
- }
- catch (GroovyRuntimeException e) {
- // br should get a "native" property match first. getProperty includes such fall-back logic
- Object value = this.getProperty(name);
- if (value instanceof Closure) {
- Closure closure = (Closure) value;
- closure = (Closure) closure.clone();
- closure.setDelegate(this);
- return closure.call((Object[]) args);
- } else {
- throw e;
- }
- }
-
- }
-
- /**
- * This allows toString to be overridden by a closure <i>field</i> method attached
- * to the expando object.
- *
- * @see java.lang.Object#toString()
- */
- public String toString() {
- Object method = getProperties().get("toString");
- if (method != null && method instanceof Closure) {
- // invoke overridden toString closure method
- Closure closure = (Closure) method;
- closure.setDelegate(this);
- return closure.call().toString();
- } else {
- return expandoProperties.toString();
- }
- }
-
- /**
- * This allows equals to be overridden by a closure <i>field</i> method attached
- * to the expando object.
- *
- * @see java.lang.Object#equals(java.lang.Object)
- */
- public boolean equals(Object obj) {
- Object method = getProperties().get("equals");
- if (method != null && method instanceof Closure) {
- // invoke overridden equals closure method
- Closure closure = (Closure) method;
- closure.setDelegate(this);
- Boolean ret = (Boolean) closure.call(obj);
- return ret.booleanValue();
- } else {
- return super.equals(obj);
- }
- }
-
- /**
- * This allows hashCode to be overridden by a closure <i>field</i> method attached
- * to the expando object.
- *
- * @see java.lang.Object#hashCode()
- */
- public int hashCode() {
- Object method = getProperties().get("hashCode");
- if (method != null && method instanceof Closure) {
- // invoke overridden hashCode closure method
- Closure closure = (Closure) method;
- closure.setDelegate(this);
- Integer ret = (Integer) closure.call();
- return ret.intValue();
- } else {
- return super.hashCode();
- }
- }
-
- /**
- * Factory method to create a new Map used to store the expando properties map
- *
- * @return a newly created Map implementation
- */
- protected Map createMap() {
- return new HashMap();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/Factory.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/Factory.java b/src/main/groovy/util/Factory.java
deleted file mode 100644
index 8ab85b4..0000000
--- a/src/main/groovy/util/Factory.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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 groovy.util;
-
-import groovy.lang.Closure;
-
-import java.util.Map;
-
-/**
- * @author <a href="mailto:aalmiray@users.sourceforge.com">Andres Almiray</a>
- * @author Danno Ferrin
- */
-public interface Factory {
- /**
- *
- * @return true if no child closures should be processed
- */
- boolean isLeaf();
-
- /**
- * Does this factory "Own" it's child closure.
- *
- * @return true if the factory should have onContentClosure() called,
- * false if the builder should handle it
- */
- boolean isHandlesNodeChildren();
-
- /**
- * Called when a factory is registered to a builder
- * @param builder the build the factory has been registered to
- * @param registeredName the name the factory has been registered under
- */
- void onFactoryRegistration(FactoryBuilderSupport builder, String registeredName, String registeredGroupName);
-
- /**
- * @param builder the FactoryBuilder
- * @param name the name of the node being built
- * @param value the 'value' argument in the build node
- * @param attributes the attributes of the build arg
- * @return the object created for the builder
- * @throws InstantiationException if attempting to instantiate an interface or abstract class
- * @throws IllegalAccessException if the instance can't be created due to a security violation
- */
- Object newInstance( FactoryBuilderSupport builder, Object name, Object value, Map attributes )
- throws InstantiationException, IllegalAccessException;
-
- /**
- * @param builder the FactoryBuilder
- * @param node the node (returned from newINstance) to consider the attributes for
- * @param attributes the attributes, a mutable set
- * @return true if the factory builder should use standard bean property matching for the remaining attributes
- */
- boolean onHandleNodeAttributes( FactoryBuilderSupport builder, Object node, Map attributes );
-
- /**
- * Only called if it isLeaf is false and isHandlesNodeChildren is true
- * @param builder the FactoryBuilder
- * @param node the node (returned from newINstance) to consider the attributes for
- * @param childContent the child content closure of the builder
- * @return true if the factory builder should apply default node processing to the content child
- */
- boolean onNodeChildren( FactoryBuilderSupport builder, Object node, Closure childContent);
-
- /**
- * @param builder the FactoryBuilder
- * @param parent the parent node (null if 'root')
- * @param node the node just completed
- */
- void onNodeCompleted( FactoryBuilderSupport builder, Object parent, Object node );
-
- void setParent( FactoryBuilderSupport builder, Object parent, Object child );
-
- void setChild( FactoryBuilderSupport builder, Object parent, Object child );
-}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/FactoryBuilderSupport.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/FactoryBuilderSupport.java b/src/main/groovy/util/FactoryBuilderSupport.java
deleted file mode 100644
index 8dbcff0..0000000
--- a/src/main/groovy/util/FactoryBuilderSupport.java
+++ /dev/null
@@ -1,1363 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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 groovy.util;
-
-import groovy.lang.Binding;
-import groovy.lang.Closure;
-import groovy.lang.DelegatingMetaClass;
-import groovy.lang.GroovyClassLoader;
-import groovy.lang.MetaClass;
-import groovy.lang.MissingMethodException;
-import groovy.lang.MissingPropertyException;
-import groovy.lang.Reference;
-import groovy.lang.Script;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.MetaClassHelper;
-import org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Mix of BuilderSupport and SwingBuilder's factory support.
- *
- * Warning: this implementation is not thread safe and should not be used
- * across threads in a multi-threaded environment. A locking mechanism
- * should be implemented by the subclass if use is expected across
- * multiple threads.
- *
- * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
- * @author <a href="mailto:aalmiray@users.sourceforge.com">Andres Almiray</a>
- * @author Danno Ferrin
- */
-public abstract class FactoryBuilderSupport extends Binding {
- public static final String CURRENT_FACTORY = "_CURRENT_FACTORY_";
- public static final String PARENT_FACTORY = "_PARENT_FACTORY_";
- public static final String PARENT_NODE = "_PARENT_NODE_";
- public static final String CURRENT_NODE = "_CURRENT_NODE_";
- public static final String PARENT_CONTEXT = "_PARENT_CONTEXT_";
- public static final String PARENT_NAME = "_PARENT_NAME_";
- public static final String CURRENT_NAME = "_CURRENT_NAME_";
- public static final String OWNER = "owner";
- public static final String PARENT_BUILDER = "_PARENT_BUILDER_";
- public static final String CURRENT_BUILDER = "_CURRENT_BUILDER_";
- public static final String CHILD_BUILDER = "_CHILD_BUILDER_";
- public static final String SCRIPT_CLASS_NAME = "_SCRIPT_CLASS_NAME_";
- private static final Logger LOG = Logger.getLogger(FactoryBuilderSupport.class.getName());
- private static final Comparator<Method> METHOD_COMPARATOR = new Comparator<Method>() {
- public int compare(final Method o1, final Method o2) {
- int cmp = o1.getName().compareTo(o2.getName());
- if (cmp != 0) return cmp;
- cmp = o1.getParameterTypes().length - o2.getParameterTypes().length;
- return cmp;
- }
- };
-
- /**
- * Throws an exception if value is null.
- *
- * @param value the node's value
- * @param name the node's name
- */
- public static void checkValueIsNull(Object value, Object name) {
- if (value != null) {
- throw new RuntimeException("'" + name + "' elements do not accept a value argument.");
- }
- }
-
- /**
- * Checks type of value against builder type
- *
- * @param value the node's value
- * @param name the node's name
- * @param type a Class that may be assignable to the value's class
- * @return true if type is assignable to the value's class, false if value
- * is null.
- */
- public static boolean checkValueIsType(Object value, Object name, Class type) {
- if (value != null) {
- if (type.isAssignableFrom(value.getClass())) {
- return true;
- } else {
- throw new RuntimeException("The value argument of '" + name + "' must be of type "
- + type.getName() + ". Found: " + value.getClass());
- }
- } else {
- return false;
- }
- }
-
- /**
- * Checks values against factory's type
- *
- * @param value the node's value
- * @param name the node's name
- * @param type a Class that may be assignable to the value's class
- * @return Returns true if type is assignable to the value's class, false if value is
- * null or a String.
- */
- public static boolean checkValueIsTypeNotString(Object value, Object name, Class type) {
- if (value != null) {
- if (type.isAssignableFrom(value.getClass())) {
- return true;
- } else if (value instanceof String) {
- return false;
- } else {
- throw new RuntimeException("The value argument of '" + name + "' must be of type "
- + type.getName() + " or a String. Found: " + value.getClass());
- }
- } else {
- return false;
- }
- }
-
- private final ThreadLocal<LinkedList<Map<String, Object>>> contexts = new ThreadLocal<LinkedList<Map<String, Object>>>();
- protected LinkedList<Closure> attributeDelegates = new LinkedList<Closure>(); //
- private final List<Closure> disposalClosures = new ArrayList<Closure>(); // because of reverse iteration use ArrayList
- private final Map<String, Factory> factories = new HashMap<String, Factory>();
- private Closure nameMappingClosure;
- private final ThreadLocal<FactoryBuilderSupport> localProxyBuilder = new ThreadLocal<FactoryBuilderSupport>();
- private FactoryBuilderSupport globalProxyBuilder;
- protected LinkedList<Closure> preInstantiateDelegates = new LinkedList<Closure>();
- protected LinkedList<Closure> postInstantiateDelegates = new LinkedList<Closure>();
- protected LinkedList<Closure> postNodeCompletionDelegates = new LinkedList<Closure>();
- protected Closure methodMissingDelegate;
- protected Closure propertyMissingDelegate;
- protected Map<String, Closure[]> explicitProperties = new HashMap<String, Closure[]>();
- protected Map<String, Closure> explicitMethods = new HashMap<String, Closure>();
- protected Map<String, Set<String>> registrationGroup = new HashMap<String, Set<String>>();
- protected String registrationGroupName = ""; // use binding to store?
-
- protected boolean autoRegistrationRunning = false;
- protected boolean autoRegistrationComplete = false;
-
- public FactoryBuilderSupport() {
- this(false);
- }
-
- public FactoryBuilderSupport(boolean init) {
- globalProxyBuilder = this;
- registrationGroup.put(registrationGroupName, new TreeSet<String>());
- if (init) {
- autoRegisterNodes();
- }
- }
-
- private Set<String> getRegistrationGroup(String name) {
- Set<String> group = registrationGroup.get(name);
- if (group == null ) {
- group = new TreeSet<String>();
- registrationGroup.put(name, group);
- }
- return group;
- }
-
- /**
- * Ask the nodes to be registered
- */
- public void autoRegisterNodes() {
- // if java did atomic blocks, this would be one
- synchronized (this) {
- if (autoRegistrationRunning || autoRegistrationComplete) {
- // registration already done or in process, abort
- return;
- }
- }
- autoRegistrationRunning = true;
- try {
- callAutoRegisterMethods(getClass());
- } finally {
- autoRegistrationComplete = true;
- autoRegistrationRunning = false;
- }
- }
-
- private void callAutoRegisterMethods(Class declaredClass) {
- if (declaredClass == null) {
- return;
- }
- callAutoRegisterMethods(declaredClass.getSuperclass());
-
- Method[] declaredMethods = declaredClass.getDeclaredMethods();
- Arrays.sort(declaredMethods, METHOD_COMPARATOR);
- for (Method method : declaredMethods) {
- if (method.getName().startsWith("register") && method.getParameterTypes().length == 0) {
- registrationGroupName = method.getName().substring("register".length());
- registrationGroup.put(registrationGroupName, new TreeSet<String>());
- try {
- if (Modifier.isPublic(method.getModifiers())) {
- method.invoke(this);
- }
- } catch (IllegalAccessException e) {
- throw new RuntimeException("Could not init " + getClass().getName() + " because of an access error in " + declaredClass.getName() + "." + method.getName(), e);
- } catch (InvocationTargetException e) {
- throw new RuntimeException("Could not init " + getClass().getName() + " because of an exception in " + declaredClass.getName() + "." + method.getName(), e);
- } finally {
- registrationGroupName = "";
- }
- }
- }
- }
-
- /**
- * @param name the name of the variable to lookup
- * @return the variable value
- */
- public Object getVariable(String name) {
- try {
- return getProxyBuilder().doGetVariable(name);
- } catch(MissingPropertyException mpe) {
- if(mpe.getProperty().equals(name) && propertyMissingDelegate != null) {
- return propertyMissingDelegate.call(new Object[]{name});
- }
- throw mpe;
- }
- }
-
- private Object doGetVariable(String name) {
- return super.getVariable(name);
- }
-
- /**
- * Sets the value of the given variable
- *
- * @param name the name of the variable to set
- * @param value the new value for the given variable
- */
- public void setVariable(String name, Object value) {
- getProxyBuilder().doSetVariable(name, value);
- }
-
- private void doSetVariable(String name, Object value) {
- super.setVariable(name, value);
- }
-
- public Map getVariables() {
- return getProxyBuilder().doGetVariables();
- }
-
- private Map doGetVariables() {
- return super.getVariables();
- }
-
- /**
- * Overloaded to make variables appear as bean properties or via the subscript operator
- */
- public Object getProperty(String property) {
- try {
- return getProxyBuilder().doGetProperty(property);
- } catch (MissingPropertyException mpe) {
- if ((getContext() != null) && (getContext().containsKey(property))) {
- return getContext().get(property);
- } else {
- try {
- return getMetaClass().getProperty(this, property);
- } catch(MissingPropertyException mpe2) {
- if(mpe2.getProperty().equals(property) && propertyMissingDelegate != null) {
- return propertyMissingDelegate.call(new Object[]{property});
- }
- throw mpe2;
- }
- }
- }
- }
-
- private Object doGetProperty(String property) {
- Closure[] accessors = resolveExplicitProperty(property);
- if (accessors != null) {
- if (accessors[0] == null) {
- // write only property
- throw new MissingPropertyException(property + " is declared as write only");
- } else {
- return accessors[0].call();
- }
- } else {
- return super.getProperty(property);
- }
- }
-
- /**
- * Overloaded to make variables appear as bean properties or via the subscript operator
- */
- public void setProperty(String property, Object newValue) {
- getProxyBuilder().doSetProperty(property, newValue);
- }
-
- private void doSetProperty(String property, Object newValue) {
- Closure[] accessors = resolveExplicitProperty(property);
- if (accessors != null) {
- if (accessors[1] == null) {
- // read only property
- throw new MissingPropertyException(property + " is declared as read only");
- } else {
- accessors[1].call(newValue);
- }
- } else {
- super.setProperty(property, newValue);
- }
- }
-
- /**
- * @return the factory map (Unmodifiable Map).
- */
- public Map<String, Factory> getFactories() {
- return Collections.unmodifiableMap(getProxyBuilder().factories);
- }
-
- /**
- * @return the explicit methods map (Unmodifiable Map).
- */
- public Map<String, Closure> getExplicitMethods() {
- return Collections.unmodifiableMap(getProxyBuilder().explicitMethods);
- }
-
- /**
- * @return the explicit properties map (Unmodifiable Map).
- */
- public Map<String, Closure[]> getExplicitProperties() {
- return Collections.unmodifiableMap(getProxyBuilder().explicitProperties);
- }
-
- /**
- * @return the factory map (Unmodifiable Map).
- */
- public Map<String, Factory> getLocalFactories() {
- return Collections.unmodifiableMap(factories);
- }
-
- /**
- * @return the explicit methods map (Unmodifiable Map).
- */
- public Map<String, Closure> getLocalExplicitMethods() {
- return Collections.unmodifiableMap(explicitMethods);
- }
-
- /**
- * @return the explicit properties map (Unmodifiable Map).
- */
- public Map<String, Closure[]> getLocalExplicitProperties() {
- return Collections.unmodifiableMap(explicitProperties);
- }
-
- public Set<String> getRegistrationGroups() {
- return Collections.unmodifiableSet(registrationGroup.keySet());
- }
-
- public Set<String> getRegistrationGroupItems(String group) {
- Set<String> groupSet = registrationGroup.get(group);
- if (groupSet != null) {
- return Collections.unmodifiableSet(groupSet);
- } else {
- return Collections.emptySet();
- }
- }
-
- public List<Closure> getAttributeDelegates() {
- return Collections.unmodifiableList(attributeDelegates);
- }
-
- public List<Closure> getPreInstantiateDelegates() {
- return Collections.unmodifiableList(preInstantiateDelegates);
- }
-
- public List<Closure> getPostInstantiateDelegates() {
- return Collections.unmodifiableList(postInstantiateDelegates);
- }
-
- public List<Closure> getPostNodeCompletionDelegates() {
- return Collections.unmodifiableList(postNodeCompletionDelegates);
- }
-
- public Closure getMethodMissingDelegate() {
- return methodMissingDelegate;
- }
-
- public void setMethodMissingDelegate(Closure delegate) {
- methodMissingDelegate = delegate;
- }
-
- public Closure getPropertyMissingDelegate() {
- return propertyMissingDelegate;
- }
-
- public void setPropertyMissingDelegate(Closure delegate) {
- propertyMissingDelegate = delegate;
- }
-
- /**
- * @return the context of the current node.
- */
- public Map<String, Object> getContext() {
- LinkedList<Map<String, Object>> contexts = getProxyBuilder().contexts.get();
- if (contexts != null && !contexts.isEmpty()) {
- return contexts.getFirst();
- }
- return null;
- }
-
- /**
- * @return the current node being built.
- */
- public Object getCurrent() {
- return getContextAttribute(CURRENT_NODE);
- }
-
- /**
- * @return the factory that built the current node.
- */
- public Factory getCurrentFactory() {
- return (Factory) getContextAttribute(CURRENT_FACTORY);
- }
-
- /**
- * @return the factory of the parent of the current node.
- */
- public String getCurrentName() {
- return (String) getContextAttribute(CURRENT_NAME);
- }
-
- /**
- * @return the builder that built the current node.
- */
- public FactoryBuilderSupport getCurrentBuilder() {
- return (FactoryBuilderSupport) getContextAttribute(CURRENT_BUILDER);
- }
-
- /**
- * @return the node of the parent of the current node.
- */
- public Object getParentNode() {
- return getContextAttribute(PARENT_NODE);
- }
-
- /**
- * @return the factory of the parent of the current node.
- */
- public Factory getParentFactory() {
- return (Factory) getContextAttribute(PARENT_FACTORY);
- }
-
- /**
- * @return the context of the parent of the current node.
- */
- public Map getParentContext() {
- return (Map) getContextAttribute(PARENT_CONTEXT);
- }
-
- /**
- * @return the name of the parent of the current node.
- */
- public String getParentName() {
- return (String) getContextAttribute(PARENT_NAME);
- }
-
- public FactoryBuilderSupport getChildBuilder() {
- return (FactoryBuilderSupport) getContextAttribute(CHILD_BUILDER);
- }
-
- public Object getContextAttribute(String key) {
- Map context = getContext();
- if (context != null) {
- return context.get(key);
- }
- return null;
- }
-
- /**
- * Convenience method when no arguments are required
- *
- * @param methodName the name of the method to invoke
- * @return the result of the call
- */
- public Object invokeMethod(String methodName) {
- return getProxyBuilder().invokeMethod(methodName, null);
- }
-
- public Object invokeMethod(String methodName, Object args) {
- Object name = getProxyBuilder().getName(methodName);
- Object result;
- Object previousContext = getProxyBuilder().getContext();
- try {
- result = getProxyBuilder().doInvokeMethod(methodName, name, args);
- } catch (RuntimeException e) {
- // remove contexts created after we started
- if (getContexts().contains(previousContext)) {
- Map<String, Object> context = getProxyBuilder().getContext();
- while (context != null && context != previousContext) {
- getProxyBuilder().popContext();
- context = getProxyBuilder().getContext();
- }
- }
- throw e;
- }
- return result;
- }
-
- /**
- * Add an attribute delegate so it can intercept attributes being set.
- * Attribute delegates are fired in a FILO pattern, so that nested delegates
- * get first crack.
- *
- * @param attrDelegate the closure to be called
- * @return attrDelegate
- */
- public Closure addAttributeDelegate(Closure attrDelegate) {
- getProxyBuilder().attributeDelegates.addFirst(attrDelegate);
- return attrDelegate;
- }
-
- /**
- * Remove the most recently added instance of the attribute delegate.
- *
- * @param attrDelegate the instance of the closure to be removed
- */
- public void removeAttributeDelegate(Closure attrDelegate) {
- getProxyBuilder().attributeDelegates.remove(attrDelegate);
- }
-
- /**
- * Add a preInstantiate delegate so it can intercept nodes before they are
- * created. PreInstantiate delegates are fired in a FILO pattern, so that
- * nested delegates get first crack.
- *
- * @param delegate the closure to invoke
- * @return delegate
- */
- public Closure addPreInstantiateDelegate(Closure delegate) {
- getProxyBuilder().preInstantiateDelegates.addFirst(delegate);
- return delegate;
- }
-
- /**
- * Remove the most recently added instance of the preInstantiate delegate.
- *
- * @param delegate the closure to invoke
- */
- public void removePreInstantiateDelegate(Closure delegate) {
- getProxyBuilder().preInstantiateDelegates.remove(delegate);
- }
-
- /**
- * Add a postInstantiate delegate so it can intercept nodes after they are
- * created. PostInstantiate delegates are fired in a FILO pattern, so that
- * nested delegates get first crack.
- *
- * @param delegate the closure to invoke
- * @return delegate
- */
- public Closure addPostInstantiateDelegate(Closure delegate) {
- getProxyBuilder().postInstantiateDelegates.addFirst(delegate);
- return delegate;
- }
-
- /**
- * Remove the most recently added instance of the postInstantiate delegate.
- *
- * @param delegate the closure to invoke
- */
- public void removePostInstantiateDelegate(Closure delegate) {
- getProxyBuilder().postInstantiateDelegates.remove(delegate);
- }
-
- /**
- * Add a nodeCompletion delegate so it can intercept nodes after they done
- * with building. NodeCompletion delegates are fired in a FILO pattern, so
- * that nested delegates get first crack.
- *
- * @param delegate the closure to invoke
- * @return delegate
- */
- public Closure addPostNodeCompletionDelegate(Closure delegate) {
- getProxyBuilder().postNodeCompletionDelegates.addFirst(delegate);
- return delegate;
- }
-
- /**
- * Remove the most recently added instance of the nodeCompletion delegate.
- *
- * @param delegate the closure to be removed
- */
- public void removePostNodeCompletionDelegate(Closure delegate) {
- getProxyBuilder().postNodeCompletionDelegates.remove(delegate);
- }
-
- public void registerExplicitProperty(String name, Closure getter, Closure setter) {
- registerExplicitProperty(name, registrationGroupName, getter, setter);
- }
-
- public void registerExplicitProperty(String name, String groupName, Closure getter, Closure setter) {
- // set the delegate to FBS so the closure closes over the builder
- if (getter != null) getter.setDelegate(this);
- if (setter != null) setter.setDelegate(this);
- explicitProperties.put(name, new Closure[]{getter, setter});
- String methodNameBase = MetaClassHelper.capitalize(name);
- if (getter != null) {
- getRegistrationGroup(groupName).add("get" + methodNameBase);
- }
- if (setter != null) {
- getRegistrationGroup(groupName).add("set" + methodNameBase);
- }
- }
-
- public void registerExplicitMethod(String name, Closure closure) {
- registerExplicitMethod(name, registrationGroupName, closure);
- }
-
- public void registerExplicitMethod(String name, String groupName, Closure closure) {
- // set the delegate to FBS so the closure closes over the builder
- closure.setDelegate(this);
- explicitMethods.put(name, closure);
- getRegistrationGroup(groupName).add(name);
- }
-
- /**
- * Registers a factory for a JavaBean.<br>
- * The JavaBean class should have a no-args constructor.
- *
- * @param theName name of the node
- * @param beanClass the factory to handle the name
- */
- public void registerBeanFactory(String theName, Class beanClass) {
- registerBeanFactory(theName, registrationGroupName, beanClass);
- }
-
- /**
- * Registers a factory for a JavaBean.<br>
- * The JavaBean class should have a no-args constructor.
- *
- * @param theName name of the node
- * @param groupName thr group to register this node in
- * @param beanClass the factory to handle the name
- */
- public void registerBeanFactory(String theName, String groupName, final Class beanClass) {
- getProxyBuilder().registerFactory(theName, new AbstractFactory() {
- public Object newInstance(FactoryBuilderSupport builder, Object name, Object value,
- Map properties) throws InstantiationException, IllegalAccessException {
- if (checkValueIsTypeNotString(value, name, beanClass)) {
- return value;
- } else {
- return beanClass.newInstance();
- }
- }
- });
- getRegistrationGroup(groupName).add(theName);
- }
-
- /**
- * Registers a factory for a node name.
- *
- * @param name the name of the node
- * @param factory the factory to return the values
- */
- public void registerFactory(String name, Factory factory) {
- registerFactory(name, registrationGroupName, factory);
- }
-
- /**
- * Registers a factory for a node name.
- *
- * @param name the name of the node
- * @param groupName thr group to register this node in
- * @param factory the factory to return the values
- */
- public void registerFactory(String name, String groupName, Factory factory) {
- getProxyBuilder().factories.put(name, factory);
- getRegistrationGroup(groupName).add(name);
- factory.onFactoryRegistration(this, name, groupName);
- }
-
- /**
- * This method is responsible for instantiating a node and configure its
- * properties.
- *
- * @param name the name of the node
- * @param attributes the attributes for the node
- * @param value the value arguments for the node
- * @return the object return from the factory
- */
- protected Object createNode(Object name, Map attributes, Object value) {
- Object node;
-
- Factory factory = getProxyBuilder().resolveFactory(name, attributes, value);
- if (factory == null) {
- LOG.log(Level.WARNING, "Could not find match for name '" + name + "'");
- throw new MissingMethodExceptionNoStack((String) name, Object.class, new Object[]{attributes, value});
- //return null;
- }
- getProxyBuilder().getContext().put(CURRENT_FACTORY, factory);
- getProxyBuilder().getContext().put(CURRENT_NAME, String.valueOf(name));
- getProxyBuilder().preInstantiate(name, attributes, value);
- try {
- node = factory.newInstance(getProxyBuilder().getChildBuilder(), name, value, attributes);
- if (node == null) {
- LOG.log(Level.WARNING, "Factory for name '" + name + "' returned null");
- return null;
- }
-
- if (LOG.isLoggable(Level.FINE)) {
- LOG.fine("For name: " + name + " created node: " + node);
- }
- } catch (Exception e) {
- throw new RuntimeException("Failed to create component for '" + name + "' reason: "
- + e, e);
- }
- getProxyBuilder().postInstantiate(name, attributes, node);
- getProxyBuilder().handleNodeAttributes(node, attributes);
- return node;
- }
-
- /**
- * This is a hook for subclasses to plugin a custom strategy for mapping
- * names to factories.
- *
- * @param name the name of the factory
- * @param attributes the attributes from the node
- * @param value value arguments from te node
- * @return the Factory associated with name.<br>
- */
- protected Factory resolveFactory(Object name, Map attributes, Object value) {
- getProxyBuilder().getContext().put(CHILD_BUILDER, getProxyBuilder());
- return getProxyBuilder().getFactories().get(name);
- }
-
- /**
- * This is a hook for subclasses to plugin a custom strategy for mapping
- * names to explicit methods.
- *
- * @param methodName the name of the explicit method
- * @param args the arguments for the method
- * @return the closure for the matched explicit method.<br>
- */
- @SuppressWarnings({"UnusedDeclaration"})
- protected Closure resolveExplicitMethod(String methodName, Object args) {
- return getExplicitMethods().get(methodName);
- }
-
- /**
- * This is a hook for subclasses to plugin a custom strategy for mapping
- * names to property methods.
- *
- * @param propertyName the name of the explicit method
- * @return the get and set closures (in that order) for the matched explicit property.<br>
- */
- protected Closure[] resolveExplicitProperty(String propertyName) {
- return getExplicitProperties().get(propertyName);
- }
-
- /**
- * This method is the workhorse of the builder.
- *
- * @param methodName the name of the method being invoked
- * @param name the name of the node
- * @param args the arguments passed into the node
- * @return the object from the factory
- */
- private Object doInvokeMethod(String methodName, Object name, Object args) {
- Reference explicitResult = new Reference();
- if (checkExplicitMethod(methodName, args, explicitResult)) {
- return explicitResult.get();
- } else {
- try {
- return dispatchNodeCall(name, args);
- } catch(MissingMethodException mme) {
- if(mme.getMethod().equals(methodName) && methodMissingDelegate != null) {
- return methodMissingDelegate.call(new Object[]{methodName, args});
- }
- throw mme;
- }
- }
- }
-
- protected boolean checkExplicitMethod(String methodName, Object args, Reference result) {
- Closure explicitMethod = resolveExplicitMethod(methodName, args);
- if (explicitMethod != null) {
- if (args instanceof Object[]) {
- result.set(explicitMethod.call((Object[]) args));
- } else {
- //todo push through InvokerHelper.asList?
- result.set(explicitMethod.call(args));
- }
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Use {@link FactoryBuilderSupport#dispatchNodeCall(Object, Object)} instead.
- */
- @Deprecated
- protected Object dispathNodeCall(Object name, Object args) {
- return dispatchNodeCall(name, args);
- }
-
- protected Object dispatchNodeCall(Object name, Object args) {
- Object node;
- Closure closure = null;
- List list = InvokerHelper.asList(args);
-
- final boolean needToPopContext;
- if (getProxyBuilder().getContexts().isEmpty()) {
- // should be called on first build method only
- getProxyBuilder().newContext();
- needToPopContext = true;
- } else {
- needToPopContext = false;
- }
-
- try {
- Map namedArgs = Collections.EMPTY_MAP;
-
- // the arguments come in like [named_args?, args..., closure?]
- // so peel off a hashmap from the front, and a closure from the
- // end and presume that is what they meant, since there is
- // no way to distinguish node(a:b,c,d) {..} from
- // node([a:b],[c,d], {..}), i.e. the user can deliberately confuse
- // the builder and there is nothing we can really do to prevent
- // that
-
- if ((!list.isEmpty())
- && (list.get(0) instanceof LinkedHashMap)) {
- namedArgs = (Map) list.get(0);
- list = list.subList(1, list.size());
- }
- if ((!list.isEmpty())
- && (list.get(list.size() - 1) instanceof Closure)) {
- closure = (Closure) list.get(list.size() - 1);
- list = list.subList(0, list.size() - 1);
- }
- Object arg;
- if (list.isEmpty()) {
- arg = null;
- } else if (list.size() == 1) {
- arg = list.get(0);
- } else {
- arg = list;
- }
- node = getProxyBuilder().createNode(name, namedArgs, arg);
-
- Object current = getProxyBuilder().getCurrent();
- if (current != null) {
- getProxyBuilder().setParent(current, node);
- }
-
- if (closure != null) {
- Factory parentFactory = getProxyBuilder().getCurrentFactory();
- if (parentFactory.isLeaf()) {
- throw new RuntimeException("'" + name + "' doesn't support nesting.");
- }
- boolean processContent = true;
- if (parentFactory.isHandlesNodeChildren()) {
- processContent = parentFactory.onNodeChildren(this, node, closure);
- }
- if (processContent) {
- // push new node on stack
- String parentName = getProxyBuilder().getCurrentName();
- Map parentContext = getProxyBuilder().getContext();
- getProxyBuilder().newContext();
- try {
- getProxyBuilder().getContext().put(OWNER, closure.getOwner());
- getProxyBuilder().getContext().put(CURRENT_NODE, node);
- getProxyBuilder().getContext().put(PARENT_FACTORY, parentFactory);
- getProxyBuilder().getContext().put(PARENT_NODE, current);
- getProxyBuilder().getContext().put(PARENT_CONTEXT, parentContext);
- getProxyBuilder().getContext().put(PARENT_NAME, parentName);
- getProxyBuilder().getContext().put(PARENT_BUILDER, parentContext.get(CURRENT_BUILDER));
- getProxyBuilder().getContext().put(CURRENT_BUILDER, parentContext.get(CHILD_BUILDER));
- // lets register the builder as the delegate
- getProxyBuilder().setClosureDelegate(closure, node);
- closure.call();
- } finally {
- getProxyBuilder().popContext();
- }
- }
- }
-
- getProxyBuilder().nodeCompleted(current, node);
- node = getProxyBuilder().postNodeCompletion(current, node);
- } finally {
- if (needToPopContext) {
- // pop the first context
- getProxyBuilder().popContext();
- }
- }
- return node;
- }
-
- /**
- * A hook to allow names to be converted into some other object such as a
- * QName in XML or ObjectName in JMX.
- *
- * @param methodName the name of the desired method
- * @return the object representing the name
- */
- public Object getName(String methodName) {
- if (getProxyBuilder().nameMappingClosure != null) {
- return getProxyBuilder().nameMappingClosure.call(methodName);
- }
- return methodName;
- }
-
- /**
- * Proxy builders are useful for changing the building context, thus
- * enabling mix & match builders.
- *
- * @return the current builder that serves as a proxy.<br>
- */
- protected FactoryBuilderSupport getProxyBuilder() {
- FactoryBuilderSupport proxy = localProxyBuilder.get();
- if (proxy == null) {
- return globalProxyBuilder;
- } else {
- return proxy;
- }
- }
-
- /**
- * Sets the builder to be used as a proxy.
- *
- * @param proxyBuilder the new proxy
- */
- protected void setProxyBuilder(FactoryBuilderSupport proxyBuilder) {
- globalProxyBuilder = proxyBuilder;
- }
-
- public Closure getNameMappingClosure() {
- return nameMappingClosure;
- }
-
- public void setNameMappingClosure(Closure nameMappingClosure) {
- this.nameMappingClosure = nameMappingClosure;
- }
-
- /**
- * Assigns any existing properties to the node.<br>
- * It will call attributeDelegates before passing control to the factory
- * that built the node.
- *
- * @param node the object returned by tne node factory
- * @param attributes the attributes for the node
- */
- protected void handleNodeAttributes(Object node, Map attributes) {
- // first, short circuit
- if (node == null) {
- return;
- }
-
- for (Closure attrDelegate : getProxyBuilder().getAttributeDelegates()) {
- FactoryBuilderSupport builder = this;
- if (attrDelegate.getOwner() instanceof FactoryBuilderSupport) {
- builder = (FactoryBuilderSupport) attrDelegate.getOwner();
- } else if (attrDelegate.getDelegate() instanceof FactoryBuilderSupport) {
- builder = (FactoryBuilderSupport) attrDelegate.getDelegate();
- }
-
- attrDelegate.call(new Object[]{builder, node, attributes});
- }
-
- if (getProxyBuilder().getCurrentFactory().onHandleNodeAttributes(getProxyBuilder().getChildBuilder(), node, attributes)) {
- getProxyBuilder().setNodeAttributes(node, attributes);
- }
- }
-
- /**
- * Pushes a new context on the stack.
- */
- protected void newContext() {
- getContexts().addFirst(new HashMap<String, Object>());
- }
-
- /**
- * A hook to allow nodes to be processed once they have had all of their
- * children applied.
- *
- * @param node the current node being processed
- * @param parent the parent of the node being processed
- */
- protected void nodeCompleted(Object parent, Object node) {
- getProxyBuilder().getCurrentFactory().onNodeCompleted(getProxyBuilder().getChildBuilder(), parent, node);
- }
-
- /**
- * Removes the last context from the stack.
- *
- * @return the content just removed
- */
- protected Map<String, Object> popContext() {
- if (!getProxyBuilder().getContexts().isEmpty()) {
- return getProxyBuilder().getContexts().removeFirst();
- }
- return null;
- }
-
- /**
- * A hook after the factory creates the node and before attributes are set.<br>
- * It will call any registered postInstantiateDelegates, if you override
- * this method be sure to call this impl somewhere in your code.
- *
- * @param name the name of the node
- * @param attributes the attributes for the node
- * @param node the object created by the node factory
- */
- protected void postInstantiate(Object name, Map attributes, Object node) {
- for (Closure postInstantiateDelegate : getProxyBuilder().getPostInstantiateDelegates()) {
- (postInstantiateDelegate).call(new Object[]{this, attributes, node});
- }
- }
-
- /**
- * A hook to allow nodes to be processed once they have had all of their
- * children applied and allows the actual node object that represents the
- * Markup element to be changed.<br>
- * It will call any registered postNodeCompletionDelegates, if you override
- * this method be sure to call this impl at the end of your code.
- *
- * @param node the current node being processed
- * @param parent the parent of the node being processed
- * @return the node, possibly new, that represents the markup element
- */
- protected Object postNodeCompletion(Object parent, Object node) {
- for (Closure postNodeCompletionDelegate : getProxyBuilder().getPostNodeCompletionDelegates()) {
- (postNodeCompletionDelegate).call(new Object[]{this, parent, node});
- }
-
- return node;
- }
-
- /**
- * A hook before the factory creates the node.<br>
- * It will call any registered preInstantiateDelegates, if you override this
- * method be sure to call this impl somewhere in your code.
- *
- * @param name the name of the node
- * @param attributes the attributes of the node
- * @param value the value argument(s) of the node
- */
- protected void preInstantiate(Object name, Map attributes, Object value) {
- for (Closure preInstantiateDelegate : getProxyBuilder().getPreInstantiateDelegates()) {
- (preInstantiateDelegate).call(new Object[]{this, attributes, value});
- }
- }
-
- /**
- * Clears the context stack.
- */
- protected void reset() {
- getProxyBuilder().getContexts().clear();
- }
-
- /**
- * A strategy method to allow derived builders to use builder-trees and
- * switch in different kinds of builders. This method should call the
- * setDelegate() method on the closure which by default passes in this but
- * if node is-a builder we could pass that in instead (or do something wacky
- * too)
- *
- * @param closure the closure on which to call setDelegate()
- * @param node the node value that we've just created, which could be a
- * builder
- */
- @SuppressWarnings({"UnusedDeclaration"})
- protected void setClosureDelegate(Closure closure, Object node) {
- closure.setDelegate(this);
- }
-
- /**
- * Maps attributes key/values to properties on node.
- *
- * @param node the object from the node
- * @param attributes the attributes to be set
- */
- protected void setNodeAttributes(Object node, Map attributes) {
- // set the properties
- //noinspection unchecked
- for (Map.Entry entry : (Set<Map.Entry>) attributes.entrySet()) {
- String property = entry.getKey().toString();
- Object value = entry.getValue();
- InvokerHelper.setProperty(node, property, value);
- }
- }
-
- /**
- * Strategy method to establish parent/child relationships.
- *
- * @param parent the object from the parent node
- * @param child the object from the child node
- */
- protected void setParent(Object parent, Object child) {
- getProxyBuilder().getCurrentFactory().setParent(getProxyBuilder().getChildBuilder(), parent, child);
- Factory parentFactory = getProxyBuilder().getParentFactory();
- if (parentFactory != null) {
- parentFactory.setChild(getProxyBuilder().getCurrentBuilder(), parent, child);
- }
- }
-
- /**
- * @return the stack of available contexts.
- */
- protected LinkedList<Map<String, Object>> getContexts() {
- LinkedList<Map<String, Object>> contexts = getProxyBuilder().contexts.get();
- if (contexts == null) {
- contexts = new LinkedList<Map<String, Object>>();
- getProxyBuilder().contexts.set(contexts);
- }
- return contexts;
- }
-
- /**
- * Stores the thread local states in a Map that can be passed across threads
- * @return the map
- */
- protected Map<String, Object> getContinuationData() {
- Map<String, Object> data = new HashMap<String, Object>();
- data.put("proxyBuilder", localProxyBuilder.get());
- data.put("contexts", contexts.get());
- return data;
- }
-
- /**
- * Restores the state of the current builder to the same state as an older build.
- *
- * Caution, this will destroy rather than merge the current build context if there is any,
- * @param data the data retrieved from a compatible getContinuationData call
- */
- protected void restoreFromContinuationData(Map<String, Object> data) {
- //noinspection unchecked
- localProxyBuilder.set((FactoryBuilderSupport) data.get("proxyBuilder"));
- //noinspection unchecked
- contexts.set((LinkedList<Map<String, Object>>) data.get("contexts"));
- }
-
- public Object build(Class viewClass) {
- if (Script.class.isAssignableFrom(viewClass)) {
- Script script = InvokerHelper.createScript(viewClass, this);
- return build(script);
- } else {
- throw new RuntimeException("Only scripts can be executed via build(Class)");
- }
- }
-
- public Object build(Script script) {
- // this used to be synchronized, but we also used to remove the
- // metaclass. Since adding the metaclass is now a side effect, we
- // don't need to ensure the meta-class won't be observed and don't
- // need to hide the side effect.
- MetaClass scriptMetaClass = script.getMetaClass();
- script.setMetaClass(new FactoryInterceptorMetaClass(scriptMetaClass, this));
- script.setBinding(this);
- Object oldScriptName = getProxyBuilder().getVariables().get(SCRIPT_CLASS_NAME);
- try {
- getProxyBuilder().setVariable(SCRIPT_CLASS_NAME, script.getClass().getName());
- return script.run();
- } finally {
- if(oldScriptName != null) {
- getProxyBuilder().setVariable(SCRIPT_CLASS_NAME, oldScriptName);
- } else {
- getProxyBuilder().getVariables().remove(SCRIPT_CLASS_NAME);
- }
- }
- }
-
- public Object build(final String script, GroovyClassLoader loader) {
- return build(loader.parseClass(script));
- }
-
- /**
- * Switches the builder's proxyBuilder during the execution of a closure.<br>
- * This is useful to temporary change the building context to another builder
- * without the need for a contrived setup. It will also take care of restoring
- * the previous proxyBuilder when the execution finishes, even if an exception
- * was thrown from inside the closure.
- *
- * @param builder the temporary builder to switch to as proxyBuilder.
- * @param closure the closure to be executed under the temporary builder.
- * @return the execution result of the closure.
- * @throws RuntimeException - any exception the closure might have thrown during
- * execution.
- */
- public Object withBuilder(FactoryBuilderSupport builder, Closure closure) {
- if (builder == null || closure == null) {
- return null;
- }
-
- Object result = null;
- Object previousContext = getProxyBuilder().getContext();
- FactoryBuilderSupport previousProxyBuilder = localProxyBuilder.get();
- try {
- localProxyBuilder.set(builder);
- closure.setDelegate(builder);
- result = closure.call();
- }
- catch (RuntimeException e) {
- // remove contexts created after we started
- localProxyBuilder.set(previousProxyBuilder);
- if (getProxyBuilder().getContexts().contains(previousContext)) {
- Map<String, Object> context = getProxyBuilder().getContext();
- while (context != null && context != previousContext) {
- getProxyBuilder().popContext();
- context = getProxyBuilder().getContext();
- }
- }
- throw e;
- }
- finally {
- localProxyBuilder.set(previousProxyBuilder);
- }
-
- return result;
- }
-
- /**
- * Switches the builder's proxyBuilder during the execution of a closure.<br>
- * This is useful to temporary change the building context to another builder
- * without the need for a contrived setup. It will also take care of restoring
- * the previous proxyBuilder when the execution finishes, even if an exception
- * was thrown from inside the closure. Additionally it will use the closure's
- * result as the value for the node identified by 'name'.
- *
- * @param builder the temporary builder to switch to as proxyBuilder.
- * @param name the node to build on the 'parent' builder.
- * @param closure the closure to be executed under the temporary builder.
- * @return a node that responds to value of name with the closure's result as its
- * value.
- * @throws RuntimeException - any exception the closure might have thrown during
- * execution.
- */
- public Object withBuilder(FactoryBuilderSupport builder, String name, Closure closure) {
- if (name == null) {
- return null;
- }
- Object result = getProxyBuilder().withBuilder(builder, closure);
- return getProxyBuilder().invokeMethod(name, new Object[]{result});
- }
-
- /**
- * Switches the builder's proxyBuilder during the execution of a closure.<br>
- * This is useful to temporary change the building context to another builder
- * without the need for a contrived setup. It will also take care of restoring
- * the previous proxyBuilder when the execution finishes, even if an exception
- * was thrown from inside the closure. Additionally it will use the closure's
- * result as the value for the node identified by 'name' and assign any attributes
- * that might have been set.
- *
- * @param attributes additional properties for the node on the parent builder.
- * @param builder the temporary builder to switch to as proxyBuilder.
- * @param name the node to build on the 'parent' builder.
- * @param closure the closure to be executed under the temporary builder.
- * @return a node that responds to value of name with the closure's result as its
- * value.
- * @throws RuntimeException - any exception the closure might have thrown during
- * execution.
- */
- public Object withBuilder(Map attributes, FactoryBuilderSupport builder, String name, Closure closure) {
- if (name == null) {
- return null;
- }
- Object result = getProxyBuilder().withBuilder(builder, closure);
- return getProxyBuilder().invokeMethod(name, new Object[]{attributes, result});
- }
-
- public void addDisposalClosure(Closure closure) {
- disposalClosures.add(closure);
- }
-
- public List<Closure> getDisposalClosures() {
- return Collections.unmodifiableList(disposalClosures);
- }
-
- public void dispose() {
- for (int i = disposalClosures.size() - 1; i >= 0; i--) {
- disposalClosures.get(i).call();
- }
- }
-}
-
-class FactoryInterceptorMetaClass extends DelegatingMetaClass {
-
- FactoryBuilderSupport builder;
-
- public FactoryInterceptorMetaClass(MetaClass delegate, FactoryBuilderSupport builder) {
- super(delegate);
- this.builder = builder;
- }
-
- public Object invokeMethod(Object object, String methodName, Object arguments) {
- try {
- return delegate.invokeMethod(object, methodName, arguments);
- } catch (MissingMethodException mme) {
- // attempt builder resolution
- try {
- if (builder.getMetaClass().respondsTo(builder, methodName).isEmpty()) {
- // dispatch to factories if it is not a literal method
- return builder.invokeMethod(methodName, arguments);
- } else {
- return InvokerHelper.invokeMethod(builder, methodName, arguments);
- }
- } catch (MissingMethodException mme2) {
- // chain secondary exception
- Throwable root = mme;
- while (root.getCause() != null) {
- root = root.getCause();
- }
- root.initCause(mme2);
- // throw original
- throw mme;
- }
- }
- }
-
- public Object invokeMethod(Object object, String methodName, Object[] arguments) {
- try {
- return delegate.invokeMethod(object, methodName, arguments);
- } catch (MissingMethodException mme) {
- // attempt builder resolution
- try {
- if (builder.getMetaClass().respondsTo(builder, methodName).isEmpty()) {
- // dispatch to factories if it is not a literal method
- return builder.invokeMethod(methodName, arguments);
- } else {
- return InvokerHelper.invokeMethod(builder, methodName, arguments);
- }
- } catch (MissingMethodException mme2) {
- // chain secondary exception
- Throwable root = mme;
- while (root.getCause() != null) {
- root = root.getCause();
- }
- root.initCause(mme2);
- // throw original
- throw mme;
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/FileNameByRegexFinder.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/FileNameByRegexFinder.groovy b/src/main/groovy/util/FileNameByRegexFinder.groovy
deleted file mode 100644
index fbb16e7..0000000
--- a/src/main/groovy/util/FileNameByRegexFinder.groovy
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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 groovy.util
-
-/**
- * Find files according to a base directory and an includes and excludes pattern.
- * The include and exclude patterns conform to regex conventions.
- *
- * @author Dierk Koenig
- * @author Paul King
- */
-class FileNameByRegexFinder implements IFileNameFinder {
-
- List<String> getFileNames(String basedir, String pattern) {
- getFileNames(basedir, pattern, "")
- }
-
- List<String> getFileNames(String basedir, String pattern, String excludesPattern) {
- def result = []
- new File(basedir).eachFileRecurse {
- if (it.path =~ pattern && (!excludesPattern || !(it.path =~ excludesPattern))) {
- result << it.absolutePath
- }
- }
- return result
- }
-}
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/util/FileTreeBuilder.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/FileTreeBuilder.groovy b/src/main/groovy/util/FileTreeBuilder.groovy
deleted file mode 100644
index f76c95a..0000000
--- a/src/main/groovy/util/FileTreeBuilder.groovy
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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 groovy.util
-
-import groovy.transform.CompileStatic
-
-/**
- * A builder dedicated at generating a file directory structure from a
- * specification. For example, imagine that you want to create the following tree:
- * <pre>
- * src/
- * |--- main
- * | |--- groovy
- * | |--- Foo.groovy
- * |--- test
- * |--- groovy
- * |--- FooTest.groovy
- *
- * </pre>
- *
- * <p>Then you can create the structure using:</p>
- * <pre><code>
- * def tree = new FileTreeBuilder()
- * tree.dir('src') {
- * dir('main') {
- * dir('groovy') {
- * file('Foo.groovy', 'println "Hello"')
- * }
- * }
- * dir('test') {
- * dir('groovy') {
- * file('FooTest.groovy', 'class FooTest extends GroovyTestCase {}')
- * }
- * }
- * }
- * </code></pre>
- *
- * <p>or with this shorthand syntax:</p>
- * <pre><code>
- * def tree = new FileTreeBuilder()
- * tree.src {
- * main {
- * groovy {
- * 'Foo.groovy'('println "Hello"')
- * }
- * }
- * test {
- * groovy {
- * 'FooTest.groovy'('class FooTest extends GroovyTestCase {}')
- * }
- * }
- * }
- * </code></pre>
- *
- * @since 2.4.2
- */
-@CompileStatic
-class FileTreeBuilder {
-
- File baseDir
-
- FileTreeBuilder(File baseDir = new File('.')) {
- this.baseDir = baseDir
- }
-
- /**
- * Creates a file with the specified name and the text contents using the system default encoding.
- * @param name name of the file to be created
- * @param contents the contents of the file, written using the system default encoding
- * @return the file being created
- */
- File file(String name, CharSequence contents) {
- new File(baseDir, name) << contents
- }
-
- /**
- * Creates a file with the specified name and the specified binary contents
- * @param name name of the file to be created
- * @param contents the contents of the file
- * @return the file being created
- */
- File file(String name, byte[] contents) {
- new File(baseDir, name) << contents
- }
-
- /**
- * Creates a file with the specified name and the contents from the source file (copy).
- * @param name name of the file to be created
- * @param contents the contents of the file
- * @return the file being created
- */
- File file(String name, File source) {
- // TODO: Avoid using bytes and prefer streaming copy
- file(name, source.bytes)
- }
-
- /**
- * Creates a new file in the current directory, whose contents is going to be generated in the
- * closure. The delegate of the closure is the file being created.
- * @param name name of the file to create
- * @param spec closure for generating the file contents
- * @return the created file
- */
- File file(String name, @DelegatesTo(value = File, strategy = Closure.DELEGATE_FIRST) Closure spec) {
- def file = new File(baseDir, name)
- def clone = (Closure) spec.clone()
- clone.delegate = file
- clone.resolveStrategy = Closure.DELEGATE_FIRST
- clone(file)
- file
- }
-
- /**
- * Creates a new empty directory
- * @param name the name of the directory to create
- * @return the created directory
- */
- File dir(String name) {
- def f = new File(baseDir, name)
- f.mkdirs()
- f
- }
-
- /**
- * Creates a new directory and allows to specify a subdirectory structure using the closure as a specification
- * @param name name of the directory to be created
- * @param cl specification of the subdirectory structure
- * @return the created directory
- */
- File dir(String name, @DelegatesTo(value = FileTreeBuilder, strategy = Closure.DELEGATE_FIRST) Closure cl) {
- def oldBase = baseDir
- def newBase = dir(name)
- try {
- baseDir = newBase
- cl.delegate = this
- cl.resolveStrategy = Closure.DELEGATE_FIRST
- cl()
- } finally {
- baseDir = oldBase
- }
- newBase
- }
-
- File call(@DelegatesTo(value = FileTreeBuilder, strategy = Closure.DELEGATE_FIRST) Closure spec) {
- def clone = (Closure) spec.clone()
- clone.delegate = this
- clone.resolveStrategy = Closure.DELEGATE_FIRST
- clone.call()
- baseDir
- }
-
-
- def methodMissing(String name, args) {
- if (args instanceof Object[] && ((Object[]) args).length == 1) {
- def arg = ((Object[]) args)[0]
- if (arg instanceof Closure) {
- dir(name, arg)
- } else if (arg instanceof CharSequence) {
- file(name, arg.toString())
- } else if (arg instanceof byte[]) {
- file(name, arg)
- } else if (arg instanceof File) {
- file(name, arg)
- }
- }
- }
-}
\ No newline at end of file