KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openharmonise > rm > factory > GeneralCache


1 /*
2  * The contents of this file are subject to the
3  * Mozilla Public License Version 1.1 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
6  *
7  * Software distributed under the License is distributed on an "AS IS"
8  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
9  * See the License for the specific language governing rights and
10  * limitations under the License.
11  *
12  * The Initial Developer of the Original Code is Simulacra Media Ltd.
13  * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
14  *
15  * All Rights Reserved.
16  *
17  * Contributor(s):
18  */

19 package org.openharmonise.rm.factory;
20
21 import java.lang.reflect.*;
22 import java.sql.*;
23 import java.util.*;
24 import java.util.logging.*;
25
26 import org.openharmonise.commons.cache.*;
27 import org.openharmonise.commons.dsi.*;
28 import org.openharmonise.commons.dsi.dml.SelectStatement;
29 import org.openharmonise.rm.DataAccessException;
30 import org.openharmonise.rm.config.*;
31 import org.openharmonise.rm.dsi.DataStoreObject;
32 import org.openharmonise.rm.resources.*;
33 import org.openharmonise.rm.resources.lifecycle.*;
34
35
36
37 /**
38  * Extends <code>AbstractCache</code> to cache instances of the core classes
39  * in Harmonise.
40  *
41  * @author Michael Bell
42  * @version $Revision: 1.3 $
43  *
44  */

45 public final class GeneralCache
46     extends AbstractCache
47     implements EditEventListener {
48
49     /**
50      * The name of class cached by this object
51      */

52     private String JavaDoc m_sClassname = null;
53     
54     /**
55      * The data store interface
56      */

57     protected AbstractDataStoreInterface m_dsi = null;
58     
59     /**
60      * A <code>Map</code> mapping between paths and object cache keys
61      */

62     protected Map m_path_cache;
63     
64     /**
65      * An instance of the class cached by this cache
66      */

67     private AbstractObject m_xobj_instance;
68
69     /**
70      * Constant suffix used to build the cache size config parameter name.
71      * The pattern will build paramter names as follows - 'class name' + "_cache_size"
72      */

73     private static final String JavaDoc PNAME_CACHESIZE = "_cache_size";
74
75     /**
76      * Logger for this class
77      */

78     private static final Logger m_logger = Logger.getLogger(GeneralCache.class.getName());
79     
80     /**
81      * Creates cache with default parameters with the given data store
82      * interface and named after the class name.
83      *
84      * @param dbinterf the data store interface
85      * @param sClassname the name of class which is cached in this cache
86      * @throws CacheException if the class name is not valid
87      */

88     public GeneralCache(AbstractDataStoreInterface dbinterf, String JavaDoc sClassname)
89         throws CacheException {
90         super(sClassname);
91
92         String JavaDoc sObjectName = sClassname;
93
94         if (sClassname.indexOf('.') > 0) {
95             sObjectName = sClassname.substring(sClassname.lastIndexOf('.') + 1);
96         }
97
98         String JavaDoc pname_cache_size = sObjectName + PNAME_CACHESIZE;
99
100         int max_cache_size = 0;
101         int cachepage_size = 0;
102
103         try {
104             max_cache_size =
105                 ConfigSettings.getIntProperty(
106                     pname_cache_size,
107                     "" + DEFAULT_CACHESIZE);
108
109             setCacheMaxSize(max_cache_size);
110
111         } catch (ConfigException e) {
112             // dont care about errors here, just use the defaults
113
m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
114         }
115
116         m_path_cache =
117             Collections.synchronizedMap(new HashMap(super.DEFAULT_CACHESIZE));
118         m_dsi = dbinterf;
119         m_sClassname = sClassname;
120
121         try {
122             Class JavaDoc cls = Class.forName(m_sClassname);
123             m_xobj_instance = (AbstractObject) cls.newInstance();
124         } catch (InstantiationException JavaDoc ins_e) {
125             throw new CacheException(
126                 "Cannot instantiate command class " + m_sClassname);
127         } catch (ClassNotFoundException JavaDoc clss_e) {
128             throw new CacheException(
129                 m_sClassname + " is not a valid harmonise object");
130         } catch (IllegalAccessException JavaDoc ia_e) {
131             throw new CacheException(
132                 "Can't call newInstance() on " + m_sClassname);
133         }
134
135     }
136
137     /* (non-Javadoc)
138      * @see org.openharmonise.commons.cache.AbstractCache#getCacheName()
139      */

140     public String JavaDoc getCacheName() {
141         return (this.m_sClassname);
142     }
143
144     /**
145      * Returns an object from the cache which matches the given path.
146      *
147      * @param sPath the path of object to return
148      * @return an object from the cache which matches the given path.
149      * @throws CacheException if there is an error instantiating the
150      * requested object
151      */

152     public Object JavaDoc getObjectFromPath(String JavaDoc sPath) throws CacheException {
153         String JavaDoc sIdKey = null;
154
155         if (m_path_cache.containsKey(sPath)) {
156             sIdKey = (String JavaDoc) m_path_cache.get(sPath);
157         } else {
158             
159             if(sPath.equals("/root") || sPath.lastIndexOf("/") == 0) {
160                 sIdKey = this.getIdKeyFromPath(sPath);
161             }
162
163             if ((sIdKey == null)
164                 || (sIdKey.length() == 0)
165                 || (sIdKey.equals("-1") == true)) {
166                 int nIndex = sPath.lastIndexOf("/");
167
168                 if (m_logger.isLoggable(Level.FINE)) {
169                     m_logger.logp(Level.FINE, this.getClass().getName(), "getObjectFromPath", "Looking for path - " + sPath);
170                 }
171
172                 String JavaDoc sGroupName = sPath.substring(0, nIndex);
173                 
174
175                 String JavaDoc sGroupClassName = null;
176
177                 AbstractChildObject child = null;
178
179                 try {
180
181                     child =
182                         (AbstractChildObject) Class
183                             .forName(this.m_sClassname)
184                             .newInstance();
185                 } catch (InstantiationException JavaDoc ins_e) {
186                     throw new CacheException(
187                         "Cannot instantiate command class " + m_sClassname);
188                 } catch (ClassNotFoundException JavaDoc clss_e) {
189                     throw new CacheException(
190                         m_sClassname + " is not a valid harmonise object");
191                 } catch (IllegalAccessException JavaDoc ia_e) {
192                     throw new CacheException(
193                         "Can't call newInstance() on " + m_sClassname);
194                 }
195
196                 sGroupClassName = child.getParentObjectClassName();
197
198                 AbstractParentObject grpObj =
199                     (AbstractParentObject) CacheHandler.getInstance(
200                         this.m_dsi).getObjectFromPath(
201                         sGroupClassName,
202                         sGroupName);
203
204                 if (grpObj != null) {
205                     Vector descendants = new Vector();
206
207                     try {
208
209                         Class JavaDoc objClass = Class.forName(this.m_sClassname);
210
211                         //if the grpObj is an instance of this class type then
212
//this will be a AbstractParentObject and so is a branch node
213
if (objClass.isInstance(grpObj) == true) {
214                             descendants.addAll(
215                                 grpObj.getChildrenByType(
216                                     AbstractParentObject.BRANCH_NODES));
217                         } else {
218                             descendants.addAll(
219                                 grpObj.getChildrenByType(
220                                     AbstractParentObject.LEAF_NODES));
221                         }
222                     } catch (ClassNotFoundException JavaDoc clss_e) {
223                         throw new CacheException(
224                             m_sClassname + " is not a valid harmonise object");
225                     } catch (DataAccessException da_e) {
226                         throw new CacheException(
227                             "Problem occured accessing children",da_e);
228                     }
229
230                     boolean bFound = false;
231                     int i = 0;
232
233                     while ((i < descendants.size()) && (bFound == false)) {
234                         child = (AbstractChildObject) descendants.elementAt(i);
235
236                         int nWildCardIndex = sPath.indexOf("*");
237
238                         try {
239
240                             if (nWildCardIndex > 0) {
241                                 if (child
242                                     .getName()
243                                     .startsWith(
244                                         sPath.substring(
245                                             (nIndex + 1),
246                                             nWildCardIndex))) {
247                                     sIdKey = String.valueOf(child.getId());
248                                     bFound = true;
249                                 }
250                             } else {
251                                 if (child
252                                     .getName()
253                                     .equals(sPath.substring(nIndex + 1))) {
254                                     sIdKey = String.valueOf(child.getId());
255                                     bFound = true;
256                                 }
257                             }
258                         } catch (DataAccessException da_e) {
259                             throw new CacheException(
260                                 "Problem occurred finding name of child object",da_e);
261                         }
262
263                         i++;
264                     }
265                 }
266             }
267
268             if ((sIdKey != null) && (sIdKey.length() > 0)) {
269                 m_path_cache.put(sPath, sIdKey);
270             }
271         }
272
273         if (m_logger.isLoggable(Level.FINER)) {
274             m_logger.logp(Level.FINER, this.getClass().getName(), "getObjectFromPath","Found key - " + sIdKey);
275         }
276
277         if (sIdKey != null) {
278             return getObject(sIdKey);
279         } else {
280             return null;
281         }
282     }
283
284     /**
285      * Create a new instance of the specified class name.
286      *
287      * @param dbintrf the data store interface to be used in constructing new instance
288      * @param sClassName the name of class to be instantiated
289      * @return a new instance of the specified class name
290      * @throws CacheException if an error occurs instantiating the new object
291      */

292     public static Object JavaDoc createObject(
293         AbstractDataStoreInterface dbintrf,
294         String JavaDoc sClassName)
295         throws CacheException {
296         return createObject(dbintrf, sClassName, -1);
297     }
298
299     /**
300      * Creates an instance of the specified class name with the specified id.
301      *
302      * @param dbintrf the data store interface to be used in constructing
303      * new instance
304      * @param sClassName the name of class to be instantiated
305      * @param nId the id of instance to be created
306      * @return an instance of the specified class name with the specified id
307      * @throws CacheException if an error occurs instantiating the new object
308      */

309     public static Object JavaDoc createObject(
310         AbstractDataStoreInterface dbintrf,
311         String JavaDoc sClassName,
312         int nId)
313         throws CacheException {
314         Object JavaDoc obj = null;
315
316         try {
317             Class JavaDoc[] initArgsClass = null;
318             Object JavaDoc[] initArgs = null;
319
320             if (nId > 0) {
321                 initArgsClass =
322                     new Class JavaDoc[] { AbstractDataStoreInterface.class, int.class };
323
324                 Integer JavaDoc intId = new Integer JavaDoc(nId);
325                 initArgs = new Object JavaDoc[] { dbintrf, intId };
326             } else {
327                 initArgsClass =
328                     new Class JavaDoc[] { AbstractDataStoreInterface.class };
329                 initArgs = new Object JavaDoc[] { dbintrf };
330             }
331
332             Class JavaDoc grpObjDefinition = Class.forName(sClassName);
333             Constructor initArgsConstructor =
334                 grpObjDefinition.getConstructor(initArgsClass);
335             obj = (Object JavaDoc) initArgsConstructor.newInstance(initArgs);
336         } catch (InstantiationException JavaDoc ins_e) {
337             throw new CacheException(
338                 "Cannot instantiate command class " + sClassName);
339         } catch (ClassNotFoundException JavaDoc clss_e) {
340             throw new CacheException(sClassName + " is not a valid harmonise object");
341         } catch (IllegalAccessException JavaDoc ia_e) {
342             throw new CacheException(
343                 "Can't call newInstance() on " + sClassName);
344         } catch (NoSuchMethodException JavaDoc nsm_e) {
345             throw new CacheException(
346                 "Error on method call:" + nsm_e.getLocalizedMessage());
347         } catch (InvocationTargetException inv_e) {
348             throw new CacheException(
349                 "Error on method call:" + inv_e.getLocalizedMessage());
350         }
351
352         return obj;
353     }
354
355     /**
356      * Creates an instance of the specified class name with the specified name.
357      *
358      * @param dbintrf the data store interface to be used in constructing
359      * new instance
360      * @param sClassName the name of class to be instantiated
361      * @param sName the name of instance to be created
362      * @return an instance of the specified class name with the specified name
363      * @throws CacheException if an error occurs instantiating the new object
364      */

365     public static Object JavaDoc createObject(
366         AbstractDataStoreInterface dbintrf,
367         String JavaDoc sClassName,
368         String JavaDoc sName)
369         throws CacheException {
370         Object JavaDoc obj = null;
371
372         try {
373             Class JavaDoc[] initArgsClass = null;
374             Object JavaDoc[] initArgs = null;
375
376             if ((sName != null) && (sName.length() > 0)) {
377                 initArgsClass =
378                     new Class JavaDoc[] {
379                         AbstractDataStoreInterface.class,
380                         String JavaDoc.class };
381                 initArgs = new Object JavaDoc[] { dbintrf, sName };
382             } else {
383                 initArgsClass =
384                     new Class JavaDoc[] { AbstractDataStoreInterface.class };
385                 initArgs = new Object JavaDoc[] { dbintrf };
386             }
387
388             Class JavaDoc grpObjDefinition = Class.forName(sClassName);
389             Constructor initArgsConstructor =
390                 grpObjDefinition.getConstructor(initArgsClass);
391             obj = (Object JavaDoc) initArgsConstructor.newInstance(initArgs);
392         } catch (InstantiationException JavaDoc ins_e) {
393             throw new CacheException(
394                 "Cannot instantiate command class " + sClassName);
395         } catch (ClassNotFoundException JavaDoc clss_e) {
396             throw new CacheException(sClassName + " is not a valid harmonise object");
397         } catch (IllegalAccessException JavaDoc ia_e) {
398             throw new CacheException(
399                 "Can't call newInstance() on " + sClassName);
400         } catch (NoSuchMethodException JavaDoc nsm_e) {
401             throw new CacheException(
402                 "Error on method call:" + nsm_e.getLocalizedMessage());
403         } catch (InvocationTargetException inv_e) {
404             throw new CacheException(
405                 "Error on method call:" + inv_e.getLocalizedMessage());
406         }
407
408         return obj;
409     }
410
411     /* (non-Javadoc)
412      * @see org.openharmonise.commons.cache.AbstractCache#changeObject(java.lang.Object, java.lang.String, java.lang.Object)
413      */

414     public void changeObject(
415         Object JavaDoc cache_key,
416         String JavaDoc sChangeCode,
417         Object JavaDoc newObject) {
418         try {
419             if (sChangeCode.equalsIgnoreCase(CHANGE_DELETE)) {
420                 if (newObject instanceof AbstractChildObject) {
421                     AbstractChildObject child = (AbstractChildObject) newObject;
422                     m_path_cache.remove(child.getFullPath());
423                 }
424             }
425         } catch (Exception JavaDoc e) {
426             m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
427         }
428
429         super.changeObject(cache_key, sChangeCode, newObject);
430     }
431
432     /* (non-Javadoc)
433      * @see org.openharmonise.commons.cache.AbstractCache#clearCache()
434      */

435     public void clearCache() {
436         m_path_cache.clear();
437         super.clearCache();
438     }
439
440     /* (non-Javadoc)
441      * @see org.openharmonise.rm.resources.lifecycle.EditEventListener#workflowObjectSaved(org.openharmonise.rm.resources.lifecycle.EditEvent)
442      */

443     public void workflowObjectSaved(EditEvent event) {
444         AbstractObject obj = (AbstractObject) event.getResult();
445         addToCache(String.valueOf(obj.getId()), obj);
446
447     }
448
449     /* (non-Javadoc)
450      * @see org.openharmonise.rm.resources.lifecycle.EditEventListener#workflowObjectStatusChanged(org.openharmonise.rm.resources.lifecycle.EditEvent)
451      */

452     public void workflowObjectStatusChanged(EditEvent event) {
453         AbstractObject obj = (AbstractObject) event.getSource();
454
455         removeObjectFromCache(String.valueOf(obj.getId()));
456
457         AbstractObject result = (AbstractObject) event.getResult();
458         
459         addToCache(String.valueOf(result.getId()), result);
460
461     }
462
463     /* (non-Javadoc)
464      * @see org.openharmonise.rm.resources.lifecycle.EditEventListener#workflowObjectArchived(org.openharmonise.rm.resources.lifecycle.EditEvent)
465      */

466     public void workflowObjectArchived(EditEvent event) {
467
468         AbstractObject obj = (AbstractObject) event.getSource();
469
470         removeObjectFromCache(String.valueOf(obj.getId()));
471     }
472
473     /* (non-Javadoc)
474      * @see org.openharmonise.rm.resources.lifecycle.EditEventListener#workflowObjectReactivated(org.openharmonise.rm.resources.lifecycle.EditEvent)
475      */

476     public void workflowObjectReactivated(EditEvent event) {
477         AbstractObject obj = (AbstractObject) event.getResult();
478         addToCache(String.valueOf(obj.getId()), obj);
479
480     }
481
482     /* (non-Javadoc)
483      * @see org.openharmonise.rm.resources.lifecycle.EditEventListener#workflowObjectLocked(org.openharmonise.rm.resources.lifecycle.EditEvent)
484      */

485     public void workflowObjectLocked(EditEvent event) {
486         //do nothing
487

488     }
489
490     /* (non-Javadoc)
491      * @see org.openharmonise.rm.resources.lifecycle.EditEventListener#workflowObjectUnlocked(org.openharmonise.rm.resources.lifecycle.EditEvent)
492      */

493     public void workflowObjectUnlocked(EditEvent event) {
494         // do nothing
495

496     }
497
498     /**
499      * Returns an id for an object of the specified path.
500      *
501      * @param dbintrf the data store interface
502      * @param dsObj <code>DataStoreObject</code> which provides access to the relavent
503      * <code>ColumnRef</code> objects used in any DB queries
504      * @param sFullPath the path of the object
505      * @return an id for an object of the specified path
506      * @throws CacheException if an error occurs building the query from the
507      * parameters given
508      */

509     public static int getIdKeyFromPath(
510         AbstractDataStoreInterface dbintrf,
511         DataStoreObject dsObj,
512         String JavaDoc sFullPath)
513         throws CacheException {
514         int nKeyId = -1;
515         ResultSet rs = null;
516
517         try {
518             SelectStatement select = new SelectStatement();
519
520             int nIndex = sFullPath.lastIndexOf('/');
521             String JavaDoc sName = null;
522             String JavaDoc sPath = null;
523
524             if (nIndex >= 0) {
525                 sName = sFullPath.substring(nIndex + 1, sFullPath.length());
526
527                 if (nIndex > 0) {
528                     sPath = sFullPath.substring(0, nIndex);
529                 }
530             } else {
531                 sName = sFullPath;
532             }
533
534             //System.out.println("path - " + sPath + ", name - " + sName);
535
select.addSelectColumn(
536                 dsObj.getInstanceColumnRef(AbstractObject.ATTRIB_ID, false));
537
538             ColumnRef status_col =
539                 dsObj.getInstanceColumnRef(
540                     AbstractEditableObject.TAG_STATUS,
541                     false);
542             select.addSelectColumn(status_col);
543
544             ColumnRef nameCol =
545                 dsObj.getInstanceColumnRef(AbstractObject.TAG_NAME, false);
546             select.addSelectColumn(nameCol);
547
548             if ((sPath != null) && (sPath.length() > 0)) {
549                 ColumnRef pathCol =
550                     dsObj.getInstanceColumnRef(
551                         AbstractChildObject.TAG_PATH,
552                         false);
553                 select.addSelectColumn(pathCol);
554
555                 select.addWhereCondition(pathCol, "=", sPath);
556             }
557
558             select.addWhereCondition(nameCol, "=", sName);
559
560             select.addOrderBy(status_col,SelectStatement.ORDER_ASCENDING);
561
562             rs = dbintrf.execute(select);
563
564             if (rs.next()) {
565                 boolean bMatch = true;
566
567                 //perform match to catch case where DB isn't case sensitive
568
if (rs.getString(3).equals(sName) == false) {
569                     if ((sPath != null)
570                         && (sPath.length() > 0)
571                         && (rs.getString(4).equals(sPath) == false)) {
572                         bMatch = false;
573                     } else {
574                         bMatch = false;
575                     }
576                 }
577
578                 if (bMatch == true) {
579                     nKeyId = rs.getInt(1);
580                 }
581             }
582         } catch (DataStoreException ds_e) {
583             throw new CacheException(
584                 "Problem occured constructing query",ds_e);
585         } catch (SQLException sql_e) {
586             throw new CacheException(
587                 "Problem occured processing query",sql_e);
588         } finally {
589             if (rs != null) {
590                 try {
591
592                     rs.close();
593                 } catch (SQLException sql_e) {
594                     throw new CacheException(
595                         "Problem closing result set",sql_e);
596                 }
597             }
598         }
599
600         return nKeyId;
601     }
602
603     /* (non-Javadoc)
604      * @see org.openharmonise.commons.cache.AbstractCache#removeObjectFromCache(java.lang.Object)
605      */

606     public void removeObjectFromCache(Object JavaDoc cache_key) {
607         if (m_path_cache.containsValue(cache_key) == true) {
608             Iterator iter = m_path_cache.keySet().iterator();
609
610             String JavaDoc removeKey = null;
611             boolean bFound = false;
612
613             while (iter.hasNext() && (bFound == false)) {
614                 String JavaDoc tempKey = (String JavaDoc) iter.next();
615
616                 if (m_path_cache.get(tempKey).equals(cache_key) == true) {
617                     bFound = true;
618                     removeKey = tempKey;
619                 }
620             }
621
622             if ((bFound == true) && (removeKey != null)) {
623                 m_path_cache.remove(removeKey);
624             }
625         }
626
627         super.removeObjectFromCache(cache_key);
628     }
629
630     /* (non-Javadoc)
631      * @see org.openharmonise.commons.cache.AbstractCache#getCacheableObject(java.lang.Object)
632      */

633     protected Object JavaDoc getCacheableObject(Object JavaDoc object_id)
634         throws CacheException {
635         if (object_id == null) {
636             throw new IllegalArgumentException JavaDoc(
637                 m_sClassname
638                     + " id must be passed "
639                     + " to GetCacheableObject object_id:"
640                     + object_id);
641         }
642
643         Object JavaDoc object = null;
644
645         try {
646             int id = Integer.parseInt((String JavaDoc) object_id);
647             object =
648                 createObject(
649                     this.m_dsi,
650                     m_sClassname,
651                     Integer.parseInt((String JavaDoc) object_id));
652         } catch (NumberFormatException JavaDoc e) {
653             object = createObject(this.m_dsi, m_sClassname, (String JavaDoc) object_id);
654         }
655
656         if (object == null) {
657             throw new RuntimeException JavaDoc(
658                 "Could not get "
659                     + m_sClassname
660                     + " for "
661                     + m_sClassname
662                     + ":"
663                     + object_id);
664         }
665
666         if (object instanceof Editable) {
667             ((Editable) object).addEditEventListener(this);
668         }
669
670         return object;
671     }
672
673     /**
674      * Display path cache data in standard out.
675      *
676      */

677     private void printPathCache() {
678         Iterator iter = this.m_path_cache.values().iterator();
679
680         while (iter.hasNext()) {
681             System.out.println((String JavaDoc) iter.next());
682         }
683     }
684
685     /**
686      * Returns an id for an object of the given path.
687      *
688      * @param sFullPath the path of object
689      * @return an id for an object of the given path
690      * @throws CacheException if an error occurs
691      */

692     private String JavaDoc getIdKeyFromPath(String JavaDoc sFullPath) throws CacheException {
693         String JavaDoc sKeyId = null;
694
695         sKeyId =
696             String.valueOf(
697                 getIdKeyFromPath(
698                     m_dsi,
699                     (DataStoreObject) m_xobj_instance,
700                     sFullPath));
701
702         return sKeyId;
703     }
704
705     /* (non-Javadoc)
706      * @see org.openharmonise.commons.cache.AbstractCache#getObject(java.lang.Object)
707      */

708     public Object JavaDoc getObject(Object JavaDoc key) throws CacheException {
709         AbstractEditableObject child = (AbstractEditableObject) super.getObject(key);
710         
711         if(child != null) {
712             child.addEditEventListener(this);
713         }
714         
715         return child;
716     }
717
718 }
Popular Tags