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 @@
@@ -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 @@
@@ -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