Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2003-2013 the original author or authors.
*
* Licensed 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.*;
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 James Strachan
* @author Andres Almiray
* @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_COMPARATOR = new Comparator() {
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 - o1.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 ThreadLocal>> contexts = new ThreadLocal>>();
protected LinkedList attributeDelegates = new LinkedList(); //
private List disposalClosures = new ArrayList(); // because of reverse iteration use ArrayList
private Map factories = new HashMap();
private Closure nameMappingClosure;
private ThreadLocal localProxyBuilder = new ThreadLocal();
private FactoryBuilderSupport globalProxyBuilder;
protected LinkedList preInstantiateDelegates = new LinkedList();
protected LinkedList postInstantiateDelegates = new LinkedList();
protected LinkedList postNodeCompletionDelegates = new LinkedList();
protected Closure methodMissingDelegate;
protected Closure propertyMissingDelegate;
protected Map explicitProperties = new HashMap();
protected Map explicitMethods = new HashMap();
protected Map> registrationGroup = new HashMap>();
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());
if (init) {
autoRegisterNodes();
}
}
private Set getRegistrationGroup(String name) {
Set group = registrationGroup.get(name);
if (group == null ) {
group = new TreeSet();
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());
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 getFactories() {
return Collections.unmodifiableMap(getProxyBuilder().factories);
}
/**
* @return the explicit methods map (Unmodifiable Map).
*/
public Map getExplicitMethods() {
return Collections.unmodifiableMap(getProxyBuilder().explicitMethods);
}
/**
* @return the explicit properties map (Unmodifiable Map).
*/
public Map getExplicitProperties() {
return Collections.unmodifiableMap(getProxyBuilder().explicitProperties);
}
/**
* @return the factory map (Unmodifiable Map).
*/
public Map getLocalFactories() {
return Collections.unmodifiableMap(factories);
}
/**
* @return the explicit methods map (Unmodifiable Map).
*/
public Map getLocalExplicitMethods() {
return Collections.unmodifiableMap(explicitMethods);
}
/**
* @return the explicit properties map (Unmodifiable Map).
*/
public Map getLocalExplicitProperties() {
return Collections.unmodifiableMap(explicitProperties);
}
public Set getRegistrationGroups() {
return Collections.unmodifiableSet(registrationGroup.keySet());
}
public Set getRegistrationGroupItems(String group) {
Set groupSet = registrationGroup.get(group);
if (groupSet != null) {
return Collections.unmodifiableSet(groupSet);
} else {
return Collections.emptySet();
}
}
public List getAttributeDelegates() {
return Collections.unmodifiableList(attributeDelegates);
}
public List getPreInstantiateDelegates() {
return Collections.unmodifiableList(preInstantiateDelegates);
}
public List getPostInstantiateDelegates() {
return Collections.unmodifiableList(postInstantiateDelegates);
}
public List 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 getContext() {
LinkedList