001 package railo.runtime.op; 002 003 import java.io.Serializable; 004 import java.util.ArrayList; 005 import java.util.Date; 006 import java.util.HashMap; 007 import java.util.Iterator; 008 import java.util.List; 009 import java.util.ListIterator; 010 import java.util.Map; 011 012 import railo.commons.lang.ClassException; 013 import railo.commons.lang.ClassUtil; 014 import railo.commons.lang.StringUtil; 015 import railo.commons.lang.types.RefBoolean; 016 import railo.commons.lang.types.RefBooleanImpl; 017 import railo.runtime.converter.JavaConverter; 018 import railo.runtime.exp.PageException; 019 import railo.runtime.type.Collection; 020 import railo.runtime.type.Duplicable; 021 import railo.runtime.type.UDF; 022 023 024 /** 025 * 026 * 027 * To change the template for this generated type comment go to 028 * Window - Preferences - Java - Code Generation - Code and Comments 029 */ 030 public final class Duplicator { 031 032 /** 033 * primitive value duplication (do nothing, value type must not be duplicated) 034 * @param _boolean boolean value to duplicate 035 * @return duplicated value 036 */ 037 public static boolean duplicate(boolean _boolean) { 038 return _boolean; 039 } 040 041 /** 042 * primitive value duplication (do nothing, value type must not be duplicated) 043 * @param _byte byte value to duplicate 044 * @return duplicated value 045 */ 046 public static byte duplicate(byte _byte) { 047 return _byte; 048 } 049 050 /** 051 * primitive value duplication (do nothing, value type must not be duplicated) 052 * @param _short byte value to duplicate 053 * @return duplicated value 054 */ 055 public static short duplicate(short _short) { 056 return _short; 057 } 058 059 /** 060 * primitive value duplication (do nothing, value type must not be duplicated) 061 * @param _int byte value to duplicate 062 * @return duplicated value 063 */ 064 public static int duplicate(int _int) { 065 return _int; 066 } 067 068 /** 069 * primitive value duplication (do nothing, value type must not be duplicated) 070 * @param _long byte value to duplicate 071 * @return duplicated value 072 */ 073 public static long duplicate(long _long) { 074 return _long; 075 } 076 077 /** 078 * primitive value duplication (do nothing, value type must not be duplicated) 079 * @param _double byte value to duplicate 080 * @return duplicated value 081 */ 082 public static double duplicate(double _double) { 083 return _double; 084 } 085 086 /** 087 * reference type value duplication 088 * @param object object to duplicate 089 * @return duplicated value 090 */ 091 092 public static Object duplicate(Object object, boolean deepCopy) { 093 if(object == null) return null; 094 if(object instanceof Number) return object; 095 if(object instanceof String) return object; 096 if(object instanceof Date) return ((Date)object).clone(); 097 if(object instanceof Boolean) return object; 098 099 RefBoolean before=new RefBooleanImpl(); 100 try{ 101 Object copy = ThreadLocalDuplication.get(object,before); 102 if(copy!=null){ 103 return copy; 104 } 105 106 107 //if(object instanceof CollectionPlus)return ((CollectionPlus)object).duplicate(deepCopy,ThreadLocalDuplication.getMap()); 108 if(object instanceof Collection)return ((Collection)object).duplicate(deepCopy); 109 if(object instanceof Duplicable)return ((Duplicable)object).duplicate(deepCopy); 110 if(object instanceof UDF) return ((UDF)object).duplicate(); 111 if(object instanceof List) return duplicateList((List)object,deepCopy); 112 if(object instanceof Map) return duplicateMap((Map)object,deepCopy); 113 if(object instanceof Serializable) { 114 try { 115 String ser = JavaConverter.serialize((Serializable)object); 116 return JavaConverter.deserialize(ser); 117 118 } catch (Throwable t) {} 119 } 120 } 121 finally { 122 if(!before.toBooleanValue())ThreadLocalDuplication.reset(); 123 } 124 125 return object; 126 } 127 128 public static List duplicateList(List list, boolean deepCopy) { 129 List newList; 130 try { 131 newList=(List) ClassUtil.loadInstance(list.getClass()); 132 } catch (ClassException e) { 133 newList=new ArrayList(); 134 } 135 return duplicateList(list, newList, deepCopy); 136 } 137 138 public static List duplicateList(List list,List newList, boolean deepCopy) { 139 ListIterator it = list.listIterator(); 140 while(it.hasNext()) { 141 if(deepCopy) 142 newList.add(Duplicator.duplicate(it.next(),deepCopy)); 143 else 144 newList.add(it.next()); 145 } 146 return newList; 147 } 148 149 /** 150 * duplicate a map 151 * @param map 152 * @param doKeysLower 153 * @return duplicated Map 154 * @throws PageException 155 */ 156 public static Map duplicateMap(Map map, boolean doKeysLower,boolean deepCopy) throws PageException{ 157 if(doKeysLower) { 158 Map newMap; 159 try { 160 newMap=(Map) ClassUtil.loadInstance(map.getClass()); 161 } catch (ClassException e) { 162 newMap=new HashMap(); 163 } 164 ThreadLocalDuplication.set(map,newMap); 165 Iterator it=map.keySet().iterator(); 166 while(it.hasNext()) { 167 Object key=it.next(); 168 if(deepCopy)newMap.put(StringUtil.toLowerCase(Caster.toString(key)),duplicate(map.get(key), deepCopy)); 169 else newMap.put(StringUtil.toLowerCase(Caster.toString(key)),map.get(key)); 170 } 171 //ThreadLocalDuplication.remove(map); removed "remove" to catch sisters and brothers 172 return newMap; 173 } 174 return duplicateMap(map,deepCopy); 175 } 176 177 public static Map duplicateMap(Map map,boolean deepCopy){ 178 Map other; 179 try { 180 other=(Map) ClassUtil.loadInstance(map.getClass()); 181 } catch (ClassException e) { 182 other=new HashMap(); 183 } 184 ThreadLocalDuplication.set(map,other); 185 duplicateMap(map,other, deepCopy); 186 //ThreadLocalDuplication.remove(map); removed "remove" to catch sisters and brothers 187 return other; 188 } 189 190 public static Map duplicateMap(Map map,Map newMap,boolean deepCopy){ 191 192 193 Iterator it=map.keySet().iterator(); 194 while(it.hasNext()) { 195 Object key=it.next(); 196 if(deepCopy)newMap.put(key,duplicate(map.get(key),deepCopy)); 197 else newMap.put(key,map.get(key)); 198 } 199 return newMap; 200 } 201 } 202 203