1 package org.apache.ojb.broker.cache; 2 3 17 18 import java.util.ArrayList ; 19 import java.util.HashMap ; 20 import java.util.Iterator ; 21 import java.util.List ; 22 import java.util.Map ; 23 import java.util.Properties ; 24 import java.util.StringTokenizer ; 25 26 import org.apache.commons.lang.SystemUtils; 27 import org.apache.commons.lang.builder.ToStringBuilder; 28 import org.apache.commons.lang.builder.ToStringStyle; 29 import org.apache.ojb.broker.Identity; 30 import org.apache.ojb.broker.OJBRuntimeException; 31 import org.apache.ojb.broker.PersistenceBroker; 32 import org.apache.ojb.broker.metadata.ObjectCacheDescriptor; 33 import org.apache.ojb.broker.util.ClassHelper; 34 import org.apache.ojb.broker.util.configuration.impl.OjbConfigurator; 35 import org.apache.ojb.broker.util.logging.Logger; 36 import org.apache.ojb.broker.util.logging.LoggerFactory; 37 38 57 class CacheDistributor implements ObjectCacheInternal 58 { 59 private static Logger log = LoggerFactory.getLogger(CacheDistributor.class); 60 private static final String DESCRIPTOR_BASED_CACHES = "descriptorBasedCaches"; 61 public static final String CACHE_EXCLUDES_STRING = "cacheExcludes"; 62 private static final String DELIMITER_FOR_EXCLUDE = ","; 63 private static final ObjectCacheInternal DUMMY_CACHE = 64 new ObjectCacheInternalWrapper(new ObjectCacheEmptyImpl(null, null)); 65 66 69 private Map caches = new HashMap (); 70 private List excludedPackages; 71 72 private final PersistenceBroker broker; 73 79 private boolean descriptorBasedCaches; 80 81 84 public CacheDistributor(final PersistenceBroker broker) 85 { 86 this.broker = broker; 87 this.descriptorBasedCaches = OjbConfigurator.getInstance().getConfigurationFor(null) 88 .getBoolean(DESCRIPTOR_BASED_CACHES, false); 89 String exclude = broker.serviceConnectionManager().getConnectionDescriptor().getAttribute(CACHE_EXCLUDES_STRING); 90 if(exclude != null) 91 { 92 exclude = exclude.trim(); 93 if(exclude.length() > 0) 94 { 95 excludedPackages = createExcludedPackagesList(exclude); 96 log.info("Packages to exclude from caching: " + excludedPackages); 97 } 98 } 99 } 100 101 public void cache(Identity oid, Object obj) 102 { 103 getCache(oid.getObjectsTopLevelClass()).cache(oid, obj); 104 } 105 106 109 public boolean cacheIfNew(Identity oid, Object obj) 110 { 111 return getCache(oid.getObjectsTopLevelClass()).cacheIfNew(oid, obj); 112 } 113 114 public Object lookup(Identity oid) 115 { 116 return getCache(oid.getObjectsTopLevelClass()).lookup(oid); 117 } 118 119 public void remove(Identity oid) 120 { 121 getCache(oid.getObjectsTopLevelClass()).remove(oid); 122 } 123 124 public void clear() 125 { 126 synchronized(caches) 127 { 128 Iterator it = caches.values().iterator(); 129 ObjectCache oc = null; 130 while(it.hasNext()) 131 { 132 oc = (ObjectCache) it.next(); 133 try 134 { 135 oc.clear(); 136 } 137 catch(Exception e) 138 { 139 log.error("Error while call method 'clear()' on '" + oc + "'", e); 140 } 141 } 142 } 143 } 144 145 public void doInternalCache(Identity oid, Object obj, int type) 146 { 147 getCache(oid.getObjectsTopLevelClass()).doInternalCache(oid, obj, type); 148 } 149 150 public ObjectCacheInternal getCache(Class targetClass) 151 { 152 157 boolean useConnectionLevelCache = false; 158 ObjectCacheInternal retval = null; 159 163 ObjectCacheDescriptor ocd = searchInClassDescriptor(targetClass); 164 if(ocd == null) 165 { 166 ocd = searchInJdbcConnectionDescriptor(); 167 useConnectionLevelCache = true; 168 } 169 if(ocd == null) 170 { 171 throw new OJBRuntimeException("No object cache descriptor found for " + targetClass + ", using PBKey " + broker.getPBKey() 172 + ". Please set a cache descriptor in jdbc-connection-descriptor or in class-descriptor"); 173 } 174 else 175 { 176 if(!useConnectionLevelCache) 178 { 179 if(!descriptorBasedCaches) 180 { 181 synchronized(caches) 182 { 183 retval = lookupCache(targetClass); 184 185 if(retval == null) 186 { 187 if(log.isEnabledFor(Logger.INFO)) 188 { 189 String eol = SystemUtils.LINE_SEPARATOR; 190 log.info(eol + "<====" + eol + "Setup new object cache instance on CLASS LEVEL for" + eol 191 + "PersistenceBroker: " + broker + eol 192 + "descriptorBasedCache: " + descriptorBasedCaches + eol 193 + "Class: " + targetClass + eol 194 + "ObjectCache: " + ocd + eol + "====>"); 195 } 196 retval = prepareAndAddCache(targetClass, ocd); 197 } 198 } 199 } 200 else 201 { 202 synchronized(caches) 203 { 204 retval = lookupCache(ocd); 205 206 if(retval == null) 207 { 208 if(log.isEnabledFor(Logger.INFO)) 209 { 210 String eol = SystemUtils.LINE_SEPARATOR; 211 log.info(eol + "<====" + eol + "Setup new object cache instance on CLASS LEVEL for" + eol 212 + "PersistenceBroker: " + broker + eol 213 + "descriptorBasedCache: " + descriptorBasedCaches + eol 214 + "class: " + targetClass + eol 215 + "ObjectCache: " + ocd + eol + "====>"); 216 } 217 retval = prepareAndAddCache(ocd, ocd); 218 } 219 } 220 } 221 } 222 else 224 { 225 if(isExcluded(targetClass)) 226 { 227 if(log.isDebugEnabled()) log.debug("Class '" + targetClass.getName() + "' is excluded from being cached"); 228 retval = DUMMY_CACHE; 229 } 230 else 231 { 232 String jcdAlias = broker.serviceConnectionManager().getConnectionDescriptor().getJcdAlias(); 233 synchronized(caches) 234 { 235 retval = lookupCache(jcdAlias); 236 237 if(retval == null) 238 { 239 if(log.isEnabledFor(Logger.INFO)) 240 { 241 String eol = SystemUtils.LINE_SEPARATOR; 242 log.info(eol + "<====" + eol + "Setup new object cache instance on CONNECTION LEVEL for" + eol 243 + "PersistenceBroker: " + broker + eol 244 + "descriptorBasedCache: " + descriptorBasedCaches + eol 245 + "Connection jcdAlias: " + jcdAlias + eol 246 + "Calling class: " + targetClass 247 + "ObjectCache: " + ocd + eol + "====>"); 248 } 249 retval = prepareAndAddCache(jcdAlias, ocd); 250 } 251 } 252 } 253 } 254 } 255 return retval; 256 } 257 258 private ObjectCacheInternal prepareAndAddCache(Object key, ObjectCacheDescriptor ocd) 259 { 260 ObjectCacheInternal cache; 261 if((cache = lookupCache(key)) != null) 264 { 265 log.info("Key '" + key + "' was already in use no need to create the ObjectCache instance again"); 266 } 267 else 268 { 269 if(log.isDebugEnabled()) log.debug("Create new ObjectCache implementation for " + key); 270 try 271 { 272 ObjectCache temp = (ObjectCache) ClassHelper.newInstance(ocd.getObjectCache(), 273 new Class []{PersistenceBroker.class, Properties .class}, 274 new Object []{broker, ocd.getConfigurationProperties()}); 275 if(temp instanceof ObjectCacheInternal) 276 { 277 cache = (ObjectCacheInternal) temp; 278 } 279 else 280 { 281 log.info("Specified cache " + ocd.getObjectCache() + " does not implement " 282 + ObjectCacheInternal.class + " and will be wrapped by a helper class"); 283 cache = new ObjectCacheInternalWrapper(temp); 284 } 285 } 286 catch(Exception e) 287 { 288 log.error("Can not create ObjectCache instance using class " + ocd.getObjectCache(), e); 289 throw new OJBRuntimeException(e); 290 } 291 caches.put(key, cache); 292 } 293 return cache; 294 } 295 296 private ObjectCacheInternal lookupCache(Object key) 297 { 298 return (ObjectCacheInternal) caches.get(key); 299 } 300 301 private List createExcludedPackagesList(String theList) 302 { 303 StringTokenizer tok = new StringTokenizer (theList, DELIMITER_FOR_EXCLUDE); 304 String token = null; 305 ArrayList result = new ArrayList (); 306 while(tok.hasMoreTokens()) 307 { 308 token = tok.nextToken().trim(); 309 if(token.length() > 0) result.add(token); 310 } 311 return result; 312 } 313 314 private boolean isExcluded(Class targetClass) 315 { 316 if(excludedPackages != null) 317 { 318 String name = targetClass.getName(); 319 for(int i = 0; i < excludedPackages.size(); i++) 320 { 321 String exclude = (String ) excludedPackages.get(i); 322 if(name.startsWith(exclude)) 323 { 324 return true; 325 } 326 } 327 } 328 return false; 329 } 330 331 339 protected ObjectCacheDescriptor searchInClassDescriptor(Class targetClass) 340 { 341 return targetClass != null ? broker.getClassDescriptor(targetClass).getObjectCacheDescriptor() : null; 342 } 343 344 351 protected ObjectCacheDescriptor searchInJdbcConnectionDescriptor() 352 { 353 return broker.serviceConnectionManager().getConnectionDescriptor().getObjectCacheDescriptor(); 354 } 355 356 public String toString() 357 { 358 ToStringBuilder buf = new ToStringBuilder(this, ToStringStyle.DEFAULT_STYLE); 359 return buf.append("Associated PB", broker) 360 .append("Mapped caches", caches).toString(); 361 } 362 363 370 static final class ObjectCacheInternalWrapper implements ObjectCacheInternal 371 { 372 ObjectCache cache = null; 373 374 public ObjectCacheInternalWrapper(ObjectCache cache) 375 { 376 this.cache = cache; 377 } 378 379 public void doInternalCache(Identity oid, Object obj, int type) 380 { 381 cache(oid, obj); 382 } 383 384 public void doInternalClear() 385 { 386 } 388 389 public boolean contains(Identity oid) 390 { 391 return cache.lookup(oid) != null; 392 } 393 394 public void cache(Identity oid, Object obj) 395 { 396 cache.cache(oid, obj); 397 } 398 399 public boolean cacheIfNew(Identity oid, Object obj) 400 { 401 cache.cache(oid, obj); 402 return true; 403 } 404 405 public Object lookup(Identity oid) 406 { 407 return cache.lookup(oid); 408 } 409 410 public void remove(Identity oid) 411 { 412 cache.remove(oid); 413 } 414 415 public void clear() 416 { 417 cache.clear(); 418 } 419 } 420 421 } 422 | Popular Tags |