1 29 30 package com.caucho.quercus.env; 31 32 import com.caucho.quercus.Quercus; 33 import com.caucho.quercus.QuercusException; 34 import com.caucho.quercus.program.AbstractFunction; 35 import com.caucho.quercus.program.ClassDef; 36 import com.caucho.quercus.program.UnsetFunction; 37 import com.caucho.util.Crc64; 38 import com.caucho.util.L10N; 39 import com.caucho.util.LruCache; 40 41 import java.lang.ref.SoftReference ; 42 import java.lang.ref.WeakReference ; 43 import java.util.ArrayList ; 44 import java.util.Collections ; 45 import java.util.HashMap ; 46 import java.util.logging.Logger ; 47 48 52 public final class DefinitionState { 53 private static final L10N L = new L10N(DefinitionState.class); 54 private static final Logger log 55 = Logger.getLogger(DefinitionState.class.getName()); 56 57 private static final 58 LruCache<ClassKey,SoftReference <QuercusClass>> _classCache 59 = new LruCache<ClassKey,SoftReference <QuercusClass>>(4096); 60 61 private final Quercus _quercus; 62 63 private boolean _isStrict; 64 65 private HashMap <String , AbstractFunction> _funMap; 66 67 private HashMap <String , AbstractFunction> _lowerFunMap; 68 69 private HashMap <String , ClassDef> _classDefMap; 70 71 private HashMap <String , ClassDef> _lowerClassDefMap; 72 73 private boolean _isLazy; 74 75 private long _crc; 77 78 public DefinitionState(Quercus quercus) 79 { 80 _quercus = quercus; 81 82 _isStrict = quercus.isStrict(); 83 84 _funMap = new HashMap <String , AbstractFunction>(8192, 0.5F); 85 _classDefMap = new HashMap <String , ClassDef>(); 86 87 if (! _isStrict) { 88 _lowerFunMap = new HashMap <String , AbstractFunction>(8192, 0.5F); 89 90 _lowerClassDefMap = new HashMap <String , ClassDef>(); 91 } 92 } 93 94 private DefinitionState(DefinitionState oldState) 95 { 96 this(oldState._quercus); 97 98 _funMap.putAll(oldState._funMap); 99 100 if (_lowerFunMap != null) 101 _lowerFunMap.putAll(oldState._lowerFunMap); 102 103 _classDefMap.putAll(oldState._classDefMap); 104 105 if (_lowerClassDefMap != null) 106 _lowerClassDefMap.putAll(oldState._lowerClassDefMap); 107 108 _crc = oldState._crc; 109 } 110 111 private DefinitionState(DefinitionState oldState, boolean isLazy) 112 { 113 _isLazy = true; 114 115 _quercus = oldState._quercus; 116 _isStrict = oldState._isStrict; 117 118 _funMap = oldState._funMap; 119 _lowerFunMap = oldState._lowerFunMap; 120 121 _classDefMap = oldState._classDefMap; 122 _lowerClassDefMap = oldState._lowerClassDefMap; 123 124 _crc = oldState._crc; 125 } 126 127 130 public final boolean isStrict() 131 { 132 return _isStrict; 133 } 134 135 138 public Quercus getQuercus() 139 { 140 return _quercus; 141 } 142 143 146 public long getCrc() 147 { 148 return _crc; 149 } 150 151 154 public ArrayValue getDefinedFunctions() 155 { 156 ArrayValue result = new ArrayValueImpl(); 157 158 ArrayValue internal = _quercus.getDefinedFunctions(); 159 ArrayValue user = new ArrayValueImpl(); 160 161 result.put(new StringValueImpl("internal"), internal); 162 result.put(new StringValueImpl("user"), user); 163 164 for (String name : _funMap.keySet()) { 165 StringValue key = new StringValueImpl(name); 166 167 if (! internal.contains(key).isset()) 168 user.put(name); 169 } 170 171 return result; 172 } 173 174 180 public AbstractFunction findFunction(String name) 181 { 182 AbstractFunction fun = _funMap.get(name); 183 184 if (fun == null) { 185 } 186 else if (fun instanceof UnsetFunction) { 187 UnsetFunction unsetFun = (UnsetFunction) fun; 188 189 if (_crc == unsetFun.getCrc()) 190 return null; 191 } 192 else { 193 return fun; 194 } 195 196 if (_lowerFunMap != null) { 197 fun = _lowerFunMap.get(name.toLowerCase()); 198 199 if (fun != null) { 200 _funMap.put(name, fun); 201 202 return fun; 203 } 204 } 205 206 fun = findModuleFunction(name); 207 208 if (fun != null) { 209 _funMap.put(name, fun); 210 211 return fun; 212 } 213 else { 214 _funMap.put(name, new UnsetFunction(_crc)); 215 216 return null; 217 } 218 } 219 220 226 private AbstractFunction findModuleFunction(String name) 227 { 228 AbstractFunction fun = null; 229 230 fun = _quercus.findFunction(name); 231 if (fun != null) 232 return fun; 233 234 return fun; 235 } 236 237 240 public Value addFunction(String name, AbstractFunction fun) 241 { 242 AbstractFunction oldFun = findFunction(name); 243 244 if (oldFun != null) { 245 throw new QuercusException(L.l("can't redefine function {0}", name)); 246 } 247 248 copyOnWrite(); 249 _funMap.put(name, fun); 250 _crc = Crc64.generate(_crc, name); 251 252 if (_lowerFunMap != null) 253 _lowerFunMap.put(name.toLowerCase(), fun); 254 255 return BooleanValue.TRUE; 256 } 257 258 264 public Value addFunction(String name, String lowerName, AbstractFunction fun) 265 { 266 278 279 copyOnWrite(); 280 _funMap.put(name, fun); 281 _crc = Crc64.generate(_crc, name); 282 283 if (_lowerFunMap != null) 284 _lowerFunMap.put(lowerName, fun); 285 286 return BooleanValue.TRUE; 287 } 288 289 292 public void addClassDef(String name, ClassDef cl) 293 { 294 copyOnWrite(); 295 _classDefMap.put(name, cl); 296 _crc = Crc64.generate(_crc, name); 297 298 if (_lowerClassDefMap != null) 299 _lowerClassDefMap.put(name.toLowerCase(), cl); 300 } 301 302 305 public ClassDef findClassDef(String name) 306 { 307 ClassDef def = _classDefMap.get(name); 308 309 if (def != null) 310 return def; 311 312 if (_lowerClassDefMap != null) 313 def = _lowerClassDefMap.get(name.toLowerCase()); 314 315 return def; 316 } 317 318 323 public Value getDeclaredClasses() 324 { 325 ArrayList <String > names = new ArrayList <String >(); 326 327 333 334 for (String name : _classDefMap.keySet()) { 335 if (! names.contains(name)) 336 names.add(name); 337 } 338 339 for (String name : _quercus.getClassMap().keySet()) { 340 if (! names.contains(name)) 341 names.add(name); 342 } 343 344 Collections.sort(names); 345 346 ArrayValue array = new ArrayValueImpl(); 347 348 for (String name : names) { 349 array.put(new StringValueImpl(name)); 350 } 351 352 return array; 353 } 354 355 public DefinitionState copy() 356 { 357 return new DefinitionState(this); 358 } 359 360 public DefinitionState copyLazy() 361 { 362 return new DefinitionState(this, true); 363 } 364 365 private void copyOnWrite() 366 { 367 if (! _isLazy) 368 return; 369 370 _isLazy = false; 371 372 _funMap = new HashMap <String , AbstractFunction>(_funMap); 373 374 if (_lowerFunMap != null) { 375 _lowerFunMap = new HashMap <String , AbstractFunction>(_lowerFunMap); 376 } 377 378 _classDefMap = new HashMap <String , ClassDef>(_classDefMap); 379 380 if (_lowerClassDefMap != null) { 381 _lowerClassDefMap = new HashMap <String , ClassDef>(_lowerClassDefMap); 382 } 383 } 384 385 static class ClassKey { 386 private final WeakReference <ClassDef> _defRef; 387 private final WeakReference <QuercusClass> _parentRef; 388 389 ClassKey(ClassDef def, QuercusClass parent) 390 { 391 _defRef = new WeakReference <ClassDef>(def); 392 393 if (parent != null) 394 _parentRef = new WeakReference <QuercusClass>(parent); 395 else 396 _parentRef = null; 397 } 398 399 public int hashCode() 400 { 401 int hash = 37; 402 403 ClassDef def = _defRef.get(); 404 405 QuercusClass parent = null; 406 if (_parentRef != null) 407 parent = _parentRef.get(); 408 409 if (def != null) 410 hash = 65521 * hash + def.hashCode(); 411 412 if (parent != null) 413 hash = 65521 * hash + parent.hashCode(); 414 415 return hash; 416 } 417 418 public boolean equals(Object o) 419 { 420 ClassKey key = (ClassKey) o; 421 422 ClassDef aDef = _defRef.get(); 423 ClassDef bDef = key._defRef.get(); 424 425 if (aDef != bDef) 426 return false; 427 428 if (_parentRef == key._parentRef) 429 return true; 430 431 else if (_parentRef != null && key._parentRef != null) 432 return _parentRef.get() == key._parentRef.get(); 433 434 else 435 return false; 436 } 437 } 438 } 439 440 | Popular Tags |