f84206df04b8e93bc0562bd51d401bc3345ba49a
[mir.git] / source / mir / storage / store / ObjectStore.java
1 /*
2  * Copyright (C) 2001, 2002 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with  any library licensed under the Apache Software License, 
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library 
23  * (or with modified versions of the above that use the same license as the above), 
24  * and distribute linked combinations including the two.  You must obey the 
25  * GNU General Public License in all respects for all of the code used other than 
26  * the above mentioned libraries.  If you modify this file, you may extend this 
27  * exception to your version of the file, but you are not obligated to do so.  
28  * If you do not wish to do so, delete this exception statement from your version.
29  */
30 package mir.storage.store;
31
32 /**
33  * Title:         ObjectStore for StorableObjects
34  * Description:   ObjectStore holds a Map of @see StoreContainer for all possible
35  *                @see StoreIdentifier.
36  *
37  *                @see StorageIdentifier - identitfies one object in the ObjectStore
38  *                      i.e. in its apropriate bucket. It holds a unique identifier
39  *                      of a StorableObject and a reference on the StorableObject.
40  *
41  *                @see StoreContainer - "Buckets" to store different types of Objects
42  *                      in one Container. These buckets are cofigurable via
43  *                      config.properties.
44  *
45  *                @see StoreContainerType - is a signature for all StoreContainer
46  *                      and StoreIdentifier.
47  *
48  *                @see StorableObjects - Interface Object have to implement to
49  *                      be handled by the ObjectStore
50  *
51  *                @see ServletStoreInfo - Maintenance Servlet for ObjectStore.
52  *                      Displays information about current content of the
53  *                      ObjectStore.
54  *
55  *
56  * Copyright:     Copyright (c) 2002
57  * Company:       indy
58  * @author        rk
59  * @version 1.0
60  */
61
62 import java.io.BufferedInputStream;
63 import java.io.FileInputStream;
64 import java.util.HashMap;
65 import java.util.Iterator;
66 import java.util.Map;
67 import java.util.MissingResourceException;
68 import java.util.Properties;
69
70 import javax.servlet.http.HttpServletRequest;
71
72 import mir.config.MirPropertiesConfiguration;
73 import mir.log.LoggerWrapper;
74
75 public class ObjectStore {
76
77   private final static ObjectStore INSTANCE = new ObjectStore();
78   private final static Map containerMap = new HashMap(); // StoreContainerType/StoreContainer
79   private static long storeHit = 0, storeMiss = 0;
80   private Properties ostoreConf;
81   private LoggerWrapper logger;
82
83   private ObjectStore() {
84     String confName = null;
85
86     logger = new LoggerWrapper("Database.ObjectStore");
87     Properties conf = new Properties();
88
89     try {
90       confName =
91           MirPropertiesConfiguration.instance().getString("Home") +
92           "etc/objectstore.properties";
93       conf.load(new BufferedInputStream(new FileInputStream(confName)));
94     }
95     catch (java.io.FileNotFoundException fnfe) {
96       logger.error("could not read config file. not found: " + confName);
97     }
98     catch (Throwable t) {
99       logger.error("could not get config: " + t.getMessage());
100     }
101     ostoreConf = conf;
102   }
103
104   public static ObjectStore getInstance() {
105     return INSTANCE;
106   }
107
108   /**
109    *  Method:       use
110    *  Description:  The ObjectStore tries to find the @see StoreIdentifier sid
111    *                and returns the stored Object.
112    *
113    *  @return       StorableObject is null when no StorableObject for the
114    *                StoreIdentifier sid is found.
115    */
116   public StorableObject use(StoreIdentifier sid) {
117     if (sid != null) {
118       StorableObject storeObject = null;
119       StoreContainer stoc = getStoreContainerForSid(sid);
120       if (stoc != null)
121         storeObject = stoc.use(sid);
122       else
123         logger.warn("container not found for: " + sid.toString());
124       if (storeObject != null) {
125         storeHit++;
126         return storeObject;
127       }
128     }
129     storeMiss++;
130     return null;
131
132   }
133
134   /**
135    *  Method:       add
136    *  Description:  A StoreIdentifier is added to the ObjectStore, if it
137    *                contains a reference to a @see StorableObject.
138    */
139   public void add(StoreIdentifier sid) {
140     if (sid != null && sid.hasReference()) {
141       // find the right StoreContainer for sid
142       StoreContainer stoc = getStoreContainerForSid(sid);
143       if (stoc == null) {
144         // we have to make new StoreContainer
145         StoreContainerType stocType = sid.getStoreContainerType();
146         stoc = new StoreContainer(stocType);
147         containerMap.put(stocType, stoc);
148       }
149       stoc.add(sid);
150     }
151   }
152
153   /**
154    *  Method:       invalidate(StorableObject sto)
155    *  Description:  ObjectStore is notified of change of a @see StorableObject
156    *                sto and invalidates all relevant cache entries.
157    */
158
159   public void invalidate(StoreIdentifier sid) {
160     // propagate invalidation to StoreContainer
161     if (sid != null) {
162       StoreContainer stoc = getStoreContainerForSid(sid);
163       stoc.invalidate(sid);
164     }
165   }
166
167   /**
168    *  Method:       invalidate(StoreContainerType)
169    *  Description:  serves to invalidate a whole StoreContainer
170    *
171    *  @return
172    */
173   public void invalidate(StoreContainerType stoc_type) {
174     if (stoc_type != null) {
175       /** @todo invalidates too much:
176        *  improvement: if instanceof StoreContainerEntity && EntityList
177        *  then invalidate only StoreIdentifier matching the right table
178        */
179       StoreContainer stoc = getStoreContainerForStocType(stoc_type);
180       if (stoc != null)
181         stoc.invalidate();
182     }
183
184   }
185
186   // internal methods for StoreContainer managment
187
188   /**
189    *  Method:       getStoreContainerForSid
190    *  Description:  private method to find the right @see StoreContainer for
191    *                the @see StoreIdentifier sid.
192    *
193    *  @return       StoreContainer is null when no Container is found.
194    */
195   private StoreContainer getStoreContainerForSid(StoreIdentifier sid) {
196     // find apropriate container for a specific sid
197     if (sid != null) {
198       StoreContainerType stoc_type = sid.getStoreContainerType();
199       return getStoreContainerForStocType(stoc_type);
200     }
201     return null;
202   }
203
204   private StoreContainer getStoreContainerForStocType(StoreContainerType
205       stoc_type) {
206     if (stoc_type != null && containerMap.containsKey(stoc_type))
207       return (StoreContainer) containerMap.get(stoc_type);
208     return null;
209   }
210
211   private boolean has(StoreIdentifier sid) {
212     StoreContainer stoc = getStoreContainerForSid(sid);
213     return (stoc != null && stoc.has(sid)) ? true : false;
214   }
215
216   public String getConfProperty(String name) {
217     if (name != null) {
218       String returnValue = "";
219       try {
220         return ostoreConf.getProperty(name);
221       }
222       catch (MissingResourceException e) {
223         logger.error("getConfProperty: " + e.toString());
224       }
225     }
226     return null;
227   }
228
229   /**
230    *  Method:       toString()
231    *  Description:  Displays statistical information about the ObjectStore.
232        *                Further information is gathered from all @see StoreContainer
233    *
234    *  @return       String
235    */
236   public String toString() {
237     return toHtml(null);
238   }
239
240   public String toHtml(HttpServletRequest req) {
241     float hitRatio = 0;
242     long divisor = storeHit + storeMiss;
243     if (divisor > 0)
244       hitRatio = (float) storeHit / (float) divisor;
245     hitRatio *= 100;
246
247     StringBuffer sb = new StringBuffer("Mir-ObjectStore ");
248     sb.append( ( (req != null) ? html_version() : version())).append("\n");
249     sb.append("ObjectStore overall hits/misses/ratio: ").append(storeHit);
250     sb.append("/").append(storeMiss).append("/").append(hitRatio);
251     sb.append("%\nCurrently ").append(containerMap.size());
252     sb.append(" StoreContainer in use - listing information:\n");
253
254     // ask container for information
255     StoreContainer currentStoc;
256     for (Iterator it = containerMap.keySet().iterator(); it.hasNext(); ) {
257       currentStoc = (StoreContainer) containerMap.get(it.next());
258       sb.append(currentStoc.toHtml(req));
259     }
260
261     return sb.toString();
262   }
263
264   /**
265    *  Method:       html_version()
266        *  Description:  returns ObjectStore version as String for HTML representation
267    *
268    *  @return       String
269    */
270   private String html_version() {
271     return "<i>" + version() + "</i>";
272   }
273
274   /**
275    *  Method:       version()
276    *  Description:  returns ObjectStore version as String
277    *
278    *  @return       String
279    */
280   private String version() {
281     return "v_sstart3__1.0";
282   }
283
284 }