001: /*
002: * Copyright 2005-2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.opensource.org/licenses/ecl1.php
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.kuali.core.util.cache;
017:
018: import java.util.Properties;
019:
020: import org.apache.log4j.Logger;
021: import org.apache.ojb.broker.Identity;
022: import org.apache.ojb.broker.PersistenceBroker;
023: import org.apache.ojb.broker.cache.ObjectCacheInternal;
024: import org.apache.ojb.broker.cache.ObjectCacheTwoLevelImpl;
025: import org.apache.ojb.broker.cache.RuntimeCacheException;
026: import org.kuali.rice.KNSServiceLocator;
027:
028: import com.opensymphony.oscache.base.Cache;
029: import com.opensymphony.oscache.base.NeedsRefreshException;
030: import com.opensymphony.oscache.general.GeneralCacheAdministrator;
031:
032: /*
033: * Copyright 2002-2004 The Apache Software Foundation
034: *
035: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
036: * You may obtain a copy of the License at
037: *
038: * http://www.apache.org/licenses/LICENSE-2.0
039: *
040: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
041: * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
042: * governing permissions and limitations under the License.
043: */
044:
045: /**
046: * ObjectCacheOSCacheImpl
047: *
048: * Original source http://db.apache.org/ojb/docu/guides/objectcache.html#oscache
049: *
050: * We use the extended caching interface {@link ObjectCacheInternal}to allow usage of this implementation in
051: * {@link ObjectCacheTwoLevelImpl}.
052: */
053: public class ObjectCacheOSCacheImpl implements ObjectCacheInternal {
054: private static final Logger LOG = Logger
055: .getLogger(ObjectCacheOSCacheImpl.class);
056: private static final int REFRESH_PERIOD = com.opensymphony.oscache.base.CacheEntry.INDEFINITE_EXPIRY;
057:
058: // using SpringServiceLocator to get the admin, since there's no obvious way to let Spring inject
059: // create/manage the actual cache instance that OJB will use
060: private final GeneralCacheAdministrator admin;
061:
062: /**
063: * Required default constructor.
064: */
065: public ObjectCacheOSCacheImpl() {
066: admin = KNSServiceLocator.getPersistenceCacheAdministrator();
067: }
068:
069: /**
070: * Required constructor.
071: *
072: * @param broker
073: * @param prop
074: */
075: public ObjectCacheOSCacheImpl(PersistenceBroker broker,
076: Properties prop) {
077: this ();
078: }
079:
080: /**
081: * @see org.apache.ojb.broker.cache.ObjectCache#cache(org.apache.ojb.broker.Identity, java.lang.Object)
082: */
083: public void cache(Identity oid, Object obj) {
084: Cache cache = admin.getCache();
085:
086: try {
087: /*
088: * Actually, OSCache sends notifications (Events) only on flush events. The putInCache method do not flush the cache, so
089: * no event is sent. The ObjectCacheOSCacheInternalImpl should force OSCache to flush the entry in order to generate an
090: * event. This guarantee that other nodes always in sync with the DB. Alternative a non-indefinite refresh-period could
091: * be used in conjunction with optimistic-locking for persistent objects.
092: */
093: remove(oid);
094: admin.putInCache(oid.toString(), obj);
095: } catch (Exception e) {
096: LOG.error("error caching object: " + oid, e);
097: }
098:
099: }
100:
101: /**
102: * @see org.apache.ojb.broker.cache.ObjectCacheInternal#doInternalCache(org.apache.ojb.broker.Identity, java.lang.Object, int)
103: */
104: public void doInternalCache(Identity oid, Object obj, int type) {
105: cache(oid, obj);
106: }
107:
108: /**
109: * @see org.apache.ojb.broker.cache.ObjectCacheInternal#cacheIfNew(org.apache.ojb.broker.Identity, java.lang.Object)
110: */
111: public boolean cacheIfNew(Identity oid, Object obj) {
112: boolean result = false;
113:
114: Cache cache = admin.getCache();
115: try {
116: cache.getFromCache(oid.toString());
117: } catch (NeedsRefreshException e) {
118: try {
119: cache.putInCache(oid.toString(), obj);
120: result = true;
121: } catch (Exception e1) {
122: cache.cancelUpdate(oid.toString());
123: LOG.error("error caching object: " + oid, e);
124: }
125: }
126:
127: return result;
128: }
129:
130: /**
131: * @see org.apache.ojb.broker.cache.ObjectCache#lookup(org.apache.ojb.broker.Identity)
132: */
133: public Object lookup(Identity oid) {
134: Object cachedObject = null;
135: Cache cache = admin.getCache();
136: try {
137: cachedObject = cache.getFromCache(oid.toString(),
138: REFRESH_PERIOD);
139: } catch (NeedsRefreshException e) {
140: cache.cancelUpdate(oid.toString());
141: } catch (Exception e) {
142: cache.cancelUpdate(oid.toString());
143: LOG.error("error retrieving object from cache: " + oid, e);
144: }
145:
146: return cachedObject;
147: }
148:
149: /**
150: * @see org.apache.ojb.broker.cache.ObjectCache#remove(org.apache.ojb.broker.Identity)
151: */
152: public void remove(Identity oid) {
153: try {
154: admin.flushEntry(oid.toString());
155: } catch (Exception e) {
156: throw new RuntimeCacheException(
157: "error removing object from cache: " + oid, e);
158: }
159: }
160:
161: /**
162: * @see org.apache.ojb.broker.cache.ObjectCache#clear()
163: */
164: public void clear() {
165: try {
166: admin.flushAll();
167: } catch (Exception e) {
168: throw new RuntimeCacheException("error clearing cache", e);
169: }
170: }
171: }
|