All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.groovy.runtime.metaclass.ThreadManagedMetaBeanProperty Maven / Gradle / Ivy

There is a newer version: 1.5.8
Show newest version
/*
 * Copyright 2003-2007 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 org.codehaus.groovy.runtime.metaclass;


import groovy.lang.Closure;
import groovy.lang.MetaBeanProperty;
import groovy.lang.MetaMethod;

import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.WeakHashMap;

import org.codehaus.groovy.reflection.CachedClass;
import org.codehaus.groovy.reflection.ReflectionCache;
import org.codehaus.groovy.reflection.ParameterTypes;

/**
 * This MetaBeanProperty will create a pseudo property whose value is bound to the current
 * Thread using soft references. The values will go out of scope and be garabage collected when
 * the Thread dies or when memory is required by the JVM
 * 

* The property uses an InheritableThreadLocal instance internally so child threads will still be able * to see the property * * @author Graeme Rocher * @since 1.1 */ public class ThreadManagedMetaBeanProperty extends MetaBeanProperty { private static final CachedClass[] ZERO_ARGUMENT_LIST = new CachedClass[0]; private static final ThreadLocal PROPERTY_INSTANCE_HOLDER = new InheritableThreadLocal(); private Class declaringClass; private ThreadBoundGetter getter; private ThreadBoundSetter setter; private Object initialValue; private static final String PROPERTY_SET_PREFIX = "set"; private Closure initialValueCreator; /** * Retrieves the initial value of the ThreadBound property * * @return The initial value */ public synchronized Object getInitialValue() { return getInitialValue(null); } public synchronized Object getInitialValue(Object object) { if (initialValueCreator != null) { return initialValueCreator.call(object); } return initialValue; } /** * Closure responsible for creating the initial value of thread-managed bean properties * * @param callable The closure responsible for creating the initial value */ public void setInitialValueCreator(Closure callable) { this.initialValueCreator = callable; } /** * Constructs a new ThreadManagedBeanProperty for the given arguments * * @param declaringClass The class that declares the property * @param name The name of the property * @param type The type of the property * @param iv The properties initial value */ public ThreadManagedMetaBeanProperty(Class declaringClass, String name, Class type, Object iv) { super(name, type, null, null); this.type = type; this.declaringClass = declaringClass; this.getter = new ThreadBoundGetter(name); this.setter = new ThreadBoundSetter(name); initialValue = iv; } /** * Constructs a new ThreadManagedBeanProperty for the given arguments * * @param declaringClass The class that declares the property * @param name The name of the property * @param type The type of the property * @param initialValueCreator The closure responsible for creating the initial value */ public ThreadManagedMetaBeanProperty(Class declaringClass, String name, Class type, Closure initialValueCreator) { super(name, type, null, null); this.type = type; this.declaringClass = declaringClass; this.getter = new ThreadBoundGetter(name); this.setter = new ThreadBoundSetter(name); this.initialValueCreator = initialValueCreator; } private static Object getThreadBoundPropertyValue(Object obj, String name, Object initialValue) { Map propertyMap = getThreadBoundPropertMap(); String key = System.identityHashCode(obj) + name; if (propertyMap.containsKey(key)) { return propertyMap.get(key); } else { propertyMap.put(key, initialValue); return initialValue; } } private static Map getThreadBoundPropertMap() { Map propertyMap = (Map) PROPERTY_INSTANCE_HOLDER.get(); if (propertyMap == null) { propertyMap = new WeakHashMap(); PROPERTY_INSTANCE_HOLDER.set(propertyMap); } return propertyMap; } private static Object setThreadBoundPropertyValue(Object obj, String name, Object value) { Map propertyMap = getThreadBoundPropertMap(); String key = System.identityHashCode(obj) + name; return propertyMap.put(key, value); } /* (non-Javadoc) * @see groovy.lang.MetaBeanProperty#getGetter() */ public MetaMethod getGetter() { return this.getter; } /* (non-Javadoc) * @see groovy.lang.MetaBeanProperty#getSetter() */ public MetaMethod getSetter() { return this.setter; } /** * Accesses the ThreadBound state of the property as a getter * * @author Graeme Rocher */ class ThreadBoundGetter extends MetaMethod { private final String name, name0; private final ParameterTypes pt = new ParameterTypes(new CachedClass[0]); public ThreadBoundGetter(String name) { this.name = getGetterName(name, type); this.name0 = name; } public int getModifiers() { return Modifier.PUBLIC; } public String getName() { return name; } public Class getReturnType() { return type; } public CachedClass getDeclaringClass() { return ReflectionCache.getCachedClass(declaringClass); } public ParameterTypes getParamTypes() { return pt; } /* (non-Javadoc) * @see groovy.lang.MetaMethod#invoke(java.lang.Object, java.lang.Object[]) */ public Object invoke(Object object, Object[] arguments) { return getThreadBoundPropertyValue(object, name0, getInitialValue()); } } /** * Sets the ThreadBound state of the property like a setter * * @author Graeme Rocher */ private class ThreadBoundSetter extends MetaMethod { private final String name, name0; private ParameterTypes pt = new ParameterTypes(new CachedClass[]{ReflectionCache.getCachedClass(type)}); public ThreadBoundSetter(String name) { this.name = getSetterName(name); this.name0 = name; } public int getModifiers() { return Modifier.PUBLIC; }/* (non-Javadoc) * @see groovy.lang.MetaMethod#getName() */ public String getName() { return name; } public Class getReturnType() { return type; } public CachedClass getDeclaringClass() { return ReflectionCache.getCachedClass(declaringClass); } public ParameterTypes getParamTypes() { return pt; } /* (non-Javadoc) * @see groovy.lang.MetaMethod#invoke(java.lang.Object, java.lang.Object[]) */ public Object invoke(Object object, Object[] arguments) { return setThreadBoundPropertyValue(object, name0, arguments[0]); } } private String getGetterName(String propertyName, Class type) { String prefix = type == boolean.class || type == Boolean.class ? "is" : "get"; return prefix + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1); } private String getSetterName(String propertyName) { return PROPERTY_SET_PREFIX + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy