1 17 package com.sun.syndication.feed.impl; 18 19 import java.beans.PropertyDescriptor ; 20 import java.io.Serializable ; 21 import java.lang.reflect.Array ; 22 import java.lang.reflect.Method ; 23 import java.lang.reflect.Modifier ; 24 import java.util.*; 25 26 35 public class CloneableBean implements Serializable , Cloneable { 36 37 private static final Class [] NO_PARAMS_DEF = new Class [0]; 38 private static final Object [] NO_PARAMS = new Object [0]; 39 40 private Object _obj; 41 private Set _ignoreProperties; 42 43 50 protected CloneableBean() { 51 _obj = this; 52 } 53 54 77 public CloneableBean(Object obj) { 78 this(obj,null); 79 } 80 81 95 public CloneableBean(Object obj,Set ignoreProperties) { 96 _obj = obj; 97 _ignoreProperties = (ignoreProperties!=null) ? ignoreProperties : Collections.EMPTY_SET; 98 } 99 100 111 public Object clone() throws CloneNotSupportedException { 112 return beanClone(); 113 } 114 115 125 public Object beanClone() throws CloneNotSupportedException { 126 Object clonedBean; 127 try { 128 clonedBean = _obj.getClass().newInstance(); 129 PropertyDescriptor [] pds = BeanIntrospector.getPropertyDescriptors(_obj.getClass()); 130 if (pds!=null) { 131 for (int i=0;i<pds.length;i++) { 132 Method pReadMethod = pds[i].getReadMethod(); 133 Method pWriteMethod = pds[i].getWriteMethod(); 134 if (pReadMethod!=null && pWriteMethod!=null && !_ignoreProperties.contains(pds[i].getName()) && pReadMethod.getDeclaringClass()!=Object .class && pReadMethod.getParameterTypes().length==0) { Object value = pReadMethod.invoke(_obj,NO_PARAMS); 139 if (value!=null) { 140 value = doClone(value); 141 pWriteMethod.invoke(clonedBean,new Object []{value}); 142 } 143 } 144 } 145 } 146 } 147 catch (CloneNotSupportedException cnsEx) { 148 throw cnsEx; 149 } 150 catch (Exception ex) { 151 System.out.println(ex); 152 ex.printStackTrace(System.out); 153 throw new CloneNotSupportedException ("Cannot clone a "+_obj.getClass()+" object"); 154 } 155 return clonedBean; 156 } 157 158 private Object doClone(Object value) throws Exception { 159 if (value!=null) { 160 Class vClass = value.getClass(); 161 if (vClass.isArray()) { 162 value = cloneArray(value); 163 } 164 else 165 if (value instanceof Collection) { 166 value = cloneCollection((Collection)value); 167 } 168 else 169 if (value instanceof Map) { 170 value = cloneMap((Map)value); 171 } 172 else 173 if (isBasicType(vClass)) { 174 } 176 else 177 if (value instanceof Cloneable ) { 178 Method cloneMethod = vClass.getMethod("clone",NO_PARAMS_DEF); 179 if (Modifier.isPublic(cloneMethod.getModifiers())) { 180 value = cloneMethod.invoke(value,NO_PARAMS); 181 } 182 else { 183 throw new CloneNotSupportedException ("Cannot clone a "+value.getClass()+" object, clone() is not public"); 184 } 185 } 186 else { 187 throw new CloneNotSupportedException ("Cannot clone a "+vClass.getName()+" object"); 188 } 189 } 190 return value; 191 } 192 193 private Object cloneArray(Object array) throws Exception { 194 Class elementClass = array.getClass().getComponentType(); 195 int length = Array.getLength(array); 196 Object newArray = Array.newInstance(elementClass,length); 197 for (int i=0;i<length;i++) { 198 Object element = doClone(Array.get(array,i)); 199 Array.set(newArray,i,element); 200 } 201 return newArray; 202 } 203 204 private Object cloneCollection(Collection collection) throws Exception { 205 Class mClass = collection.getClass(); 206 Collection newColl = (Collection) mClass.newInstance(); 207 Iterator i = collection.iterator(); 208 while (i.hasNext()) { 209 Object element = doClone(i.next()); 210 newColl.add(element); 211 } 212 return newColl; 213 } 214 215 private Object cloneMap(Map map) throws Exception { 216 Class mClass = map.getClass(); 217 Map newMap = (Map) mClass.newInstance(); 218 Iterator entries = map.entrySet().iterator(); 219 while (entries.hasNext()) { 220 Map.Entry entry = (Map.Entry) entries.next(); 221 Object key = doClone(entry.getKey()); 222 Object value = doClone(entry.getValue()); 223 newMap.put(key,value); 224 } 225 return newMap; 226 } 227 228 private static final Set BASIC_TYPES = new HashSet(); 229 230 static { 231 BASIC_TYPES.add(Boolean .class); 232 BASIC_TYPES.add(Byte .class); 233 BASIC_TYPES.add(Character .class); 234 BASIC_TYPES.add(Double .class); 235 BASIC_TYPES.add(Float .class); 236 BASIC_TYPES.add(Integer .class); 237 BASIC_TYPES.add(Long .class); 238 BASIC_TYPES.add(Short .class); 239 BASIC_TYPES.add(String .class); 240 } 241 242 private static final Map CONSTRUCTOR_BASIC_TYPES = new HashMap(); 243 244 static { 245 CONSTRUCTOR_BASIC_TYPES.put(Boolean .class,new Class []{Boolean.TYPE}); 246 CONSTRUCTOR_BASIC_TYPES.put(Byte .class,new Class []{Byte.TYPE}); 247 CONSTRUCTOR_BASIC_TYPES.put(Character .class,new Class []{Character.TYPE}); 248 CONSTRUCTOR_BASIC_TYPES.put(Double .class,new Class []{Double.TYPE}); 249 CONSTRUCTOR_BASIC_TYPES.put(Float .class,new Class []{Float.TYPE}); 250 CONSTRUCTOR_BASIC_TYPES.put(Integer .class,new Class []{Integer.TYPE}); 251 CONSTRUCTOR_BASIC_TYPES.put(Long .class,new Class []{Long.TYPE}); 252 CONSTRUCTOR_BASIC_TYPES.put(Short .class,new Class []{Short.TYPE}); 253 CONSTRUCTOR_BASIC_TYPES.put(String .class,new Class []{String .class}); 254 } 255 256 private boolean isBasicType(Class vClass) { 257 return BASIC_TYPES.contains(vClass); 258 } 259 260 270 271 } 272 273 | Popular Tags |