001 package railo.runtime.type; 002 003 import java.util.Iterator; 004 import java.util.Set; 005 006 import org.apache.commons.collections.map.ReferenceMap; 007 008 import railo.commons.lang.SerializableObject; 009 import railo.commons.util.mod.ConcurrentHashMapPro; 010 import railo.commons.util.mod.LinkedHashMapPro; 011 import railo.commons.util.mod.MapFactory; 012 import railo.commons.util.mod.MapPro; 013 import railo.commons.util.mod.MapProWrapper; 014 import railo.commons.util.mod.SyncMap; 015 import railo.commons.util.mod.WeakHashMapPro; 016 import railo.runtime.config.NullSupportHelper; 017 import railo.runtime.exp.ExpressionException; 018 import railo.runtime.exp.PageException; 019 import railo.runtime.op.Duplicator; 020 import railo.runtime.op.ThreadLocalDuplication; 021 import railo.runtime.type.Collection.Key; 022 import railo.runtime.type.it.StringIterator; 023 import railo.runtime.type.util.StructSupport; 024 025 /** 026 * CFML data type struct 027 */ 028 public class StructImpl extends StructSupport { 029 private static final long serialVersionUID = 1421746759512286393L; 030 031 private MapPro<Collection.Key,Object> map; 032 033 /** 034 * default constructor 035 */ 036 public StructImpl() { 037 this(TYPE_REGULAR);//asx 038 } 039 040 /** 041 * This implementation spares its clients from the unspecified, 042 * generally chaotic ordering provided by normally Struct , 043 * without incurring the increased cost associated with TreeMap. 044 * It can be used to produce a copy of a map that has the same order as the original 045 * @param doubleLinked 046 */ 047 public StructImpl(int type) { 048 /*if(type==TYPE_LINKED) map=new LinkedHashMapPro<Collection.Key,Object>(); 049 else if(type==TYPE_WEAKED) map=new WeakHashMapPro<Collection.Key,Object>(); 050 else if(type==TYPE_SOFT) map=new MapProWrapper<Collection.Key, Object>(new ReferenceMap(),new Object()); 051 else if(type==TYPE_SYNC) map=new SyncMap<Collection.Key, Object>(new HashMapPro<Collection.Key,Object>()); 052 else map=new SyncMap<Collection.Key,Object>(); 053 */ 054 if(type==TYPE_LINKED) map=new SyncMap<Collection.Key, Object>(new LinkedHashMapPro<Collection.Key,Object>()); 055 else if(type==TYPE_WEAKED) map=new SyncMap<Collection.Key, Object>(new WeakHashMapPro<Collection.Key,Object>()); 056 else if(type==TYPE_SOFT) map=new SyncMap<Collection.Key, Object>(new MapProWrapper<Collection.Key, Object>(new ReferenceMap(),new SerializableObject())); 057 //else if(type==TYPE_SYNC) map=new ConcurrentHashMapPro<Collection.Key,Object>); 058 else map=MapFactory.getConcurrentMap();//new ConcurrentHashMapPro<Collection.Key,Object>(); 059 } 060 061 private int getType(){ 062 MapPro m = map; 063 if(map instanceof SyncMap) 064 m=((SyncMap)map).getMap(); 065 066 if(map instanceof LinkedHashMapPro) return TYPE_LINKED; 067 if(map instanceof WeakHashMapPro) return TYPE_WEAKED; 068 //if(map instanceof SyncMap) return TYPE_SYNC; 069 if(map instanceof MapProWrapper) return TYPE_SOFT; 070 return TYPE_REGULAR; 071 } 072 073 074 @Override 075 public Object get(Collection.Key key, Object defaultValue) { 076 if(NullSupportHelper.full())return map.g(key, defaultValue); 077 078 Object rtn=map.get(key); 079 if(rtn!=null) return rtn; 080 return defaultValue; 081 } 082 083 084 public Object g(Collection.Key key, Object defaultValue) { 085 return map.g(key, defaultValue); 086 } 087 public Object g(Collection.Key key) throws PageException { 088 return map.g(key); 089 } 090 091 @Override 092 public Object get(Collection.Key key) throws PageException { 093 if(NullSupportHelper.full()) return map.g(key); 094 095 Object rtn=map.get(key); 096 if(rtn!=null) return rtn; 097 throw StructSupport.invalidKey(this,key); 098 } 099 100 @Override 101 public Object set(Collection.Key key, Object value) throws PageException { 102 map.put(key,value); 103 return value; 104 } 105 106 @Override 107 public Object setEL(Collection.Key key, Object value) { 108 map.put(key,value); 109 return value; 110 } 111 112 @Override 113 public int size() { 114 return map.size(); 115 } 116 117 public Collection.Key[] keys() { 118 try { 119 return map.keySet().toArray(new Key[map.size()]); 120 } 121 catch(Throwable t) { 122 MapPro<Key, Object> old = map; 123 try{ 124 map = new railo.commons.util.mod.SyncMap(map); 125 Set<Key> set = map.keySet(); 126 Collection.Key[] keys = new Collection.Key[size()]; 127 synchronized(map){ 128 Iterator<Key> it = set.iterator(); 129 int count=0; 130 while(it.hasNext() && keys.length>count) { 131 keys[count++]=KeyImpl.toKey(it.next(), null); 132 } 133 return keys; 134 } 135 } 136 finally { 137 map=old; 138 } 139 } 140 } 141 142 @Override 143 public Object remove(Collection.Key key) throws PageException { 144 if(NullSupportHelper.full())return map.r(key); 145 Object obj= map.remove(key); 146 if(obj==null) throw new ExpressionException("can't remove key ["+key+"] from struct, key doesn't exist"); 147 return obj; 148 } 149 150 @Override 151 public Object removeEL(Collection.Key key) { 152 return map.remove(key); 153 } 154 155 @Override 156 public void clear() { 157 map.clear(); 158 } 159 160 161 @Override 162 public Collection duplicate(boolean deepCopy) { 163 Struct sct=new StructImpl(getType()); 164 copy(this,sct,deepCopy); 165 return sct; 166 } 167 168 public static void copy(Struct src,Struct trg,boolean deepCopy) { 169 ThreadLocalDuplication.set(src,trg); 170 try{ 171 Iterator<Entry<Key, Object>> it = src.entryIterator(); 172 Entry<Key, Object> e; 173 while(it.hasNext()) { 174 e = it.next(); 175 if(!deepCopy) trg.setEL(e.getKey(),e.getValue()); 176 else trg.setEL(e.getKey(),Duplicator.duplicate(e.getValue(),deepCopy)); 177 } 178 } 179 finally { 180 //ThreadLocalDuplication.remove(src); 181 } 182 } 183 184 185 186 @Override 187 public Iterator<Collection.Key> keyIterator() { 188 return map.keySet().iterator(); 189 } 190 191 @Override 192 public Iterator<String> keysAsStringIterator() { 193 return new StringIterator(keys()); 194 } 195 196 197 public Iterator<Entry<Key, Object>> entryIterator() { 198 return this.map.entrySet().iterator(); 199 } 200 201 @Override 202 public Iterator<Object> valueIterator() { 203 return map.values().iterator(); 204 } 205 206 @Override 207 public boolean containsKey(Collection.Key key) { 208 return map.containsKey(key); 209 } 210 211 @Override 212 public boolean containsValue(Object value) { 213 return map.containsValue(value); 214 } 215 216 @Override 217 public java.util.Collection<Object> values() { 218 return map.values(); 219 } 220 221 @Override 222 public int hashCode() { 223 return map.hashCode(); 224 } 225 226 @Override 227 public boolean equals(Object obj) { 228 return map.equals(obj); 229 } 230 }