http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/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/10110145/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/10110145/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:[email protected]">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/10110145/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:[email protected]">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/10110145/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:[email protected]">James Strachan</a> - * @author <a href="mailto:[email protected]">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/10110145/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/10110145/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
