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