Browse Source
# Conflicts: # spring-context-support/src/main/java/org/springframework/scheduling/commonj/WorkManagerTaskExecutor.java # spring-core/src/main/java/org/springframework/core/task/SimpleAsyncTaskExecutor.java # spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java # spring-tx/src/main/java/org/springframework/jca/work/SimpleTaskWorkManager.java # spring-tx/src/main/java/org/springframework/jca/work/WorkManagerTaskExecutor.javapull/28011/head
18 changed files with 449 additions and 51 deletions
@ -0,0 +1,330 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2003,2004 The Apache Software Foundation |
||||||
|
* |
||||||
|
* 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.springframework.cglib.beans; |
||||||
|
|
||||||
|
import java.security.ProtectionDomain; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collection; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
import org.springframework.asm.ClassVisitor; |
||||||
|
import org.springframework.cglib.core.AbstractClassGenerator; |
||||||
|
import org.springframework.cglib.core.KeyFactory; |
||||||
|
import org.springframework.cglib.core.ReflectUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* A <code>Map</code>-based view of a JavaBean. The default set of keys is the |
||||||
|
* union of all property names (getters or setters). An attempt to set |
||||||
|
* a read-only property will be ignored, and write-only properties will |
||||||
|
* be returned as <code>null</code>. Removal of objects is not a |
||||||
|
* supported (the key set is fixed). |
||||||
|
* @author Chris Nokleberg |
||||||
|
*/ |
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"}) |
||||||
|
abstract public class BeanMap implements Map { |
||||||
|
/** |
||||||
|
* Limit the properties reflected in the key set of the map |
||||||
|
* to readable properties. |
||||||
|
* @see BeanMap.Generator#setRequire |
||||||
|
*/ |
||||||
|
public static final int REQUIRE_GETTER = 1; |
||||||
|
|
||||||
|
/** |
||||||
|
* Limit the properties reflected in the key set of the map |
||||||
|
* to writable properties. |
||||||
|
* @see BeanMap.Generator#setRequire |
||||||
|
*/ |
||||||
|
public static final int REQUIRE_SETTER = 2; |
||||||
|
|
||||||
|
/** |
||||||
|
* Helper method to create a new <code>BeanMap</code>. For finer |
||||||
|
* control over the generated instance, use a new instance of |
||||||
|
* <code>BeanMap.Generator</code> instead of this static method. |
||||||
|
* @param bean the JavaBean underlying the map |
||||||
|
* @return a new <code>BeanMap</code> instance |
||||||
|
*/ |
||||||
|
public static BeanMap create(Object bean) { |
||||||
|
Generator gen = new Generator(); |
||||||
|
gen.setBean(bean); |
||||||
|
return gen.create(); |
||||||
|
} |
||||||
|
|
||||||
|
public static class Generator extends AbstractClassGenerator { |
||||||
|
private static final Source SOURCE = new Source(BeanMap.class.getName()); |
||||||
|
|
||||||
|
private static final BeanMapKey KEY_FACTORY = |
||||||
|
(BeanMapKey)KeyFactory.create(BeanMapKey.class, KeyFactory.CLASS_BY_NAME); |
||||||
|
|
||||||
|
interface BeanMapKey { |
||||||
|
public Object newInstance(Class type, int require); |
||||||
|
} |
||||||
|
|
||||||
|
private Object bean; |
||||||
|
private Class beanClass; |
||||||
|
private int require; |
||||||
|
|
||||||
|
public Generator() { |
||||||
|
super(SOURCE); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the bean that the generated map should reflect. The bean may be swapped |
||||||
|
* out for another bean of the same type using {@link #setBean}. |
||||||
|
* Calling this method overrides any value previously set using {@link #setBeanClass}. |
||||||
|
* You must call either this method or {@link #setBeanClass} before {@link #create}. |
||||||
|
* @param bean the initial bean |
||||||
|
*/ |
||||||
|
public void setBean(Object bean) { |
||||||
|
this.bean = bean; |
||||||
|
if (bean != null) { |
||||||
|
beanClass = bean.getClass(); |
||||||
|
setContextClass(beanClass); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the class of the bean that the generated map should support. |
||||||
|
* You must call either this method or {@link #setBeanClass} before {@link #create}. |
||||||
|
* @param beanClass the class of the bean |
||||||
|
*/ |
||||||
|
public void setBeanClass(Class beanClass) { |
||||||
|
this.beanClass = beanClass; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Limit the properties reflected by the generated map. |
||||||
|
* @param require any combination of {@link #REQUIRE_GETTER} and |
||||||
|
* {@link #REQUIRE_SETTER}; default is zero (any property allowed) |
||||||
|
*/ |
||||||
|
public void setRequire(int require) { |
||||||
|
this.require = require; |
||||||
|
} |
||||||
|
|
||||||
|
protected ClassLoader getDefaultClassLoader() { |
||||||
|
return beanClass.getClassLoader(); |
||||||
|
} |
||||||
|
|
||||||
|
protected ProtectionDomain getProtectionDomain() { |
||||||
|
return ReflectUtils.getProtectionDomain(beanClass); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new instance of the <code>BeanMap</code>. An existing |
||||||
|
* generated class will be reused if possible. |
||||||
|
*/ |
||||||
|
public BeanMap create() { |
||||||
|
if (beanClass == null) |
||||||
|
throw new IllegalArgumentException("Class of bean unknown"); |
||||||
|
setNamePrefix(beanClass.getName()); |
||||||
|
return (BeanMap)super.create(KEY_FACTORY.newInstance(beanClass, require)); |
||||||
|
} |
||||||
|
|
||||||
|
public void generateClass(ClassVisitor v) throws Exception { |
||||||
|
new BeanMapEmitter(v, getClassName(), beanClass, require); |
||||||
|
} |
||||||
|
|
||||||
|
protected Object firstInstance(Class type) { |
||||||
|
return ((BeanMap)ReflectUtils.newInstance(type)).newInstance(bean); |
||||||
|
} |
||||||
|
|
||||||
|
protected Object nextInstance(Object instance) { |
||||||
|
return ((BeanMap)instance).newInstance(bean); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new <code>BeanMap</code> instance using the specified bean. |
||||||
|
* This is faster than using the {@link #create} static method. |
||||||
|
* @param bean the JavaBean underlying the map |
||||||
|
* @return a new <code>BeanMap</code> instance |
||||||
|
*/ |
||||||
|
abstract public BeanMap newInstance(Object bean); |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the type of a property. |
||||||
|
* @param name the name of the JavaBean property |
||||||
|
* @return the type of the property, or null if the property does not exist |
||||||
|
*/ |
||||||
|
abstract public Class getPropertyType(String name); |
||||||
|
|
||||||
|
protected Object bean; |
||||||
|
|
||||||
|
protected BeanMap() { |
||||||
|
} |
||||||
|
|
||||||
|
protected BeanMap(Object bean) { |
||||||
|
setBean(bean); |
||||||
|
} |
||||||
|
|
||||||
|
public Object get(Object key) { |
||||||
|
return get(bean, key); |
||||||
|
} |
||||||
|
|
||||||
|
public Object put(Object key, Object value) { |
||||||
|
return put(bean, key, value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the property of a bean. This allows a <code>BeanMap</code> |
||||||
|
* to be used statically for multiple beans--the bean instance tied to the |
||||||
|
* map is ignored and the bean passed to this method is used instead. |
||||||
|
* @param bean the bean to query; must be compatible with the type of |
||||||
|
* this <code>BeanMap</code> |
||||||
|
* @param key must be a String |
||||||
|
* @return the current value, or null if there is no matching property |
||||||
|
*/ |
||||||
|
abstract public Object get(Object bean, Object key); |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the property of a bean. This allows a <code>BeanMap</code> |
||||||
|
* to be used statically for multiple beans--the bean instance tied to the |
||||||
|
* map is ignored and the bean passed to this method is used instead. |
||||||
|
* @param key must be a String |
||||||
|
* @return the old value, if there was one, or null |
||||||
|
*/ |
||||||
|
abstract public Object put(Object bean, Object key, Object value); |
||||||
|
|
||||||
|
/** |
||||||
|
* Change the underlying bean this map should use. |
||||||
|
* @param bean the new JavaBean |
||||||
|
* @see #getBean |
||||||
|
*/ |
||||||
|
public void setBean(Object bean) { |
||||||
|
this.bean = bean; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the bean currently in use by this map. |
||||||
|
* @return the current JavaBean |
||||||
|
* @see #setBean |
||||||
|
*/ |
||||||
|
public Object getBean() { |
||||||
|
return bean; |
||||||
|
} |
||||||
|
|
||||||
|
public void clear() { |
||||||
|
throw new UnsupportedOperationException(); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean containsKey(Object key) { |
||||||
|
return keySet().contains(key); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean containsValue(Object value) { |
||||||
|
for (Iterator it = keySet().iterator(); it.hasNext();) { |
||||||
|
Object v = get(it.next()); |
||||||
|
if (((value == null) && (v == null)) || (value != null && value.equals(v))) |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public int size() { |
||||||
|
return keySet().size(); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isEmpty() { |
||||||
|
return size() == 0; |
||||||
|
} |
||||||
|
|
||||||
|
public Object remove(Object key) { |
||||||
|
throw new UnsupportedOperationException(); |
||||||
|
} |
||||||
|
|
||||||
|
public void putAll(Map t) { |
||||||
|
for (Iterator it = t.keySet().iterator(); it.hasNext();) { |
||||||
|
Object key = it.next(); |
||||||
|
put(key, t.get(key)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public boolean equals(Object o) { |
||||||
|
if (o == null || !(o instanceof Map)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
Map other = (Map)o; |
||||||
|
if (size() != other.size()) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
for (Iterator it = keySet().iterator(); it.hasNext();) { |
||||||
|
Object key = it.next(); |
||||||
|
if (!other.containsKey(key)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
Object v1 = get(key); |
||||||
|
Object v2 = other.get(key); |
||||||
|
if (!((v1 == null) ? v2 == null : v1.equals(v2))) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public int hashCode() { |
||||||
|
int code = 0; |
||||||
|
for (Iterator it = keySet().iterator(); it.hasNext();) { |
||||||
|
Object key = it.next(); |
||||||
|
Object value = get(key); |
||||||
|
code += ((key == null) ? 0 : key.hashCode()) ^ |
||||||
|
((value == null) ? 0 : value.hashCode()); |
||||||
|
} |
||||||
|
return code; |
||||||
|
} |
||||||
|
|
||||||
|
// TODO: optimize
|
||||||
|
public Set entrySet() { |
||||||
|
HashMap copy = new HashMap(); |
||||||
|
for (Iterator it = keySet().iterator(); it.hasNext();) { |
||||||
|
Object key = it.next(); |
||||||
|
copy.put(key, get(key)); |
||||||
|
} |
||||||
|
return Collections.unmodifiableMap(copy).entrySet(); |
||||||
|
} |
||||||
|
|
||||||
|
public Collection values() { |
||||||
|
Set keys = keySet(); |
||||||
|
List values = new ArrayList(keys.size()); |
||||||
|
for (Iterator it = keys.iterator(); it.hasNext();) { |
||||||
|
values.add(get(it.next())); |
||||||
|
} |
||||||
|
return Collections.unmodifiableCollection(values); |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
* @see java.util.AbstractMap#toString |
||||||
|
*/ |
||||||
|
public String toString() |
||||||
|
{ |
||||||
|
StringBuffer sb = new StringBuffer(); |
||||||
|
sb.append('{'); |
||||||
|
for (Iterator it = keySet().iterator(); it.hasNext();) { |
||||||
|
Object key = it.next(); |
||||||
|
sb.append(key); |
||||||
|
sb.append('='); |
||||||
|
sb.append(get(key)); |
||||||
|
if (it.hasNext()) { |
||||||
|
sb.append(", "); |
||||||
|
} |
||||||
|
} |
||||||
|
sb.append('}'); |
||||||
|
return sb.toString(); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,10 @@ |
|||||||
|
/** |
||||||
|
* Spring's repackaging of the |
||||||
|
* <a href="http://cglib.sourceforge.net">CGLIB</a> beans package
|
||||||
|
* (for internal use only). |
||||||
|
* |
||||||
|
* <p>As this repackaging happens at the class file level, sources |
||||||
|
* and javadocs are not available here... except for a few files |
||||||
|
* that have been patched for Spring's purposes on JDK 9-17. |
||||||
|
*/ |
||||||
|
package org.springframework.cglib.beans; |
||||||
Loading…
Reference in new issue