3b4b6ce2be8058ab495a4fe98daa911ba981ce69
[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.util.HashMap;
63 import java.util.Iterator;
64 import java.util.Map;
65 import java.util.MissingResourceException;
66
67 import javax.servlet.http.HttpServletRequest;
68
69 import mir.config.MirPropertiesConfiguration;
70 import mir.log.LoggerWrapper;
71
72 public class ObjectStore {
73
74   private final static ObjectStore INSTANCE = new ObjectStore();
75   private final static Map containerMap = new HashMap(); // StoreContainerType/StoreContainer
76   private static long storeHit = 0, storeMiss = 0;
77   private MirPropertiesConfiguration configuration;
78   private LoggerWrapper logger;
79
80   private ObjectStore() {
81     logger = new LoggerWrapper("Database.ObjectStore");
82     configuration = MirPropertiesConfiguration.instance();
83   }
84
85   public static ObjectStore getInstance() {
86     return INSTANCE;
87   }
88
89   /**
90    *  Method:       use
91    *  Description:  The ObjectStore tries to find the @see StoreIdentifier sid
92    *                and returns the stored Object.
93    *
94    *  @return       StorableObject is null when no StorableObject for the
95    *                StoreIdentifier sid is found.
96    */
97   public StorableObject use(StoreIdentifier sid) {
98     if (sid != null) {
99       StorableObject storeObject = null;
100       StoreContainer stoc = getStoreContainerForSid(sid);
101       if (stoc != null)
102         storeObject = stoc.use(sid);
103       else
104         logger.warn("container not found for: " + sid.toString());
105       if (storeObject != null) {
106         storeHit++;
107         return storeObject;
108       }
109     }
110     storeMiss++;
111     return null;
112
113   }
114
115   /**
116    *  Method:       add
117    *  Description:  A StoreIdentifier is added to the ObjectStore, if it
118    *                contains a reference to a @see StorableObject.
119    */
120   public void add(StoreIdentifier sid) {
121     if (sid != null && sid.hasReference()) {
122       // find the right StoreContainer for sid
123       StoreContainer stoc = getStoreContainerForSid(sid);
124       if (stoc == null) {
125         // we have to make new StoreContainer
126         StoreContainerType stocType = sid.getStoreContainerType();
127         stoc = new StoreContainer(stocType);
128         containerMap.put(stocType, stoc);
129       }
130       stoc.add(sid);
131     }
132   }
133
134   /**
135    *  Method:       invalidate(StorableObject sto)
136    *  Description:  ObjectStore is notified of change of a @see StorableObject
137    *                sto and invalidates all relevant cache entries.
138    */
139
140   public void invalidate(StoreIdentifier sid) {
141     // propagate invalidation to StoreContainer
142     if (sid != null) {
143       StoreContainer stoc = getStoreContainerForSid(sid);
144       stoc.invalidate(sid);
145     }
146   }
147
148   /**
149    * serves to invalidate a whole StoreContainer
150    */
151   public void invalidate(StoreContainerType stoc_type) {
152     if (stoc_type != null) {
153       StoreContainer stoc = getStoreContainerForStocType(stoc_type);
154       if (stoc != null)
155         stoc.invalidate();
156     }
157
158   }
159
160   // internal methods for StoreContainer managment
161
162   /**
163    *  Method:       getStoreContainerForSid
164    *  Description:  private method to find the right @see StoreContainer for
165    *                the @see StoreIdentifier sid.
166    *
167    *  @return       StoreContainer is null when no Container is found.
168    */
169   private StoreContainer getStoreContainerForSid(StoreIdentifier sid) {
170     // find apropriate container for a specific sid
171     if (sid != null) {
172       StoreContainerType stoc_type = sid.getStoreContainerType();
173       return getStoreContainerForStocType(stoc_type);
174     }
175     return null;
176   }
177
178   private StoreContainer getStoreContainerForStocType(StoreContainerType
179       stoc_type) {
180     if (stoc_type != null && containerMap.containsKey(stoc_type))
181       return (StoreContainer) containerMap.get(stoc_type);
182     return null;
183   }
184
185   private boolean has(StoreIdentifier sid) {
186     StoreContainer stoc = getStoreContainerForSid(sid);
187     return (stoc != null && stoc.has(sid)) ? true : false;
188   }
189
190   public String getConfProperty(String name) {
191     if (name != null) {
192       try {
193         return configuration.getString(name);
194       }
195       catch (MissingResourceException e) {
196         logger.error("getConfProperty: " + e.toString());
197       }
198     }
199     return null;
200   }
201
202   /**
203    *  Method:       toString()
204    *  Description:  Displays statistical information about the ObjectStore.
205        *                Further information is gathered from all @see StoreContainer
206    *
207    *  @return       String
208    */
209   public String toString() {
210     return toHtml(null);
211   }
212
213   public String toHtml(HttpServletRequest req) {
214     float hitRatio = 0;
215     long divisor = storeHit + storeMiss;
216     if (divisor > 0)
217       hitRatio = (float) storeHit / (float) divisor;
218     hitRatio *= 100;
219
220     StringBuffer sb = new StringBuffer("Mir-ObjectStore ");
221     sb.append( ( (req != null) ? html_version() : version())).append("\n");
222     sb.append("ObjectStore overall hits/misses/ratio: ").append(storeHit);
223     sb.append("/").append(storeMiss).append("/").append(hitRatio);
224     sb.append("%\nCurrently ").append(containerMap.size());
225     sb.append(" StoreContainer in use - listing information:\n");
226
227     // ask container for information
228     StoreContainer currentStoc;
229     for (Iterator it = containerMap.keySet().iterator(); it.hasNext(); ) {
230       currentStoc = (StoreContainer) containerMap.get(it.next());
231       sb.append(currentStoc.toHtml(req));
232     }
233
234     return sb.toString();
235   }
236
237   /**
238    *  Method:       html_version()
239        *  Description:  returns ObjectStore version as String for HTML representation
240    *
241    *  @return       String
242    */
243   private String html_version() {
244     return "<i>" + version() + "</i>";
245   }
246
247   /**
248    *  Method:       version()
249    *  Description:  returns ObjectStore version as String
250    *
251    *  @return       String
252    */
253   private String version() {
254     return "v_sstart3__1.0";
255   }
256
257 }