KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > inversoft > verge > repository > Repository


1 /*
2  * Copyright (c) 2003, Inversoft
3  *
4  * This software is distribuable under the GNU Lesser General Public License.
5  * For more information visit gnu.org.
6  */

7 package com.inversoft.verge.repository;
8
9
10 import java.util.Enumeration JavaDoc;
11 import java.util.Properties JavaDoc;
12
13 import javax.servlet.ServletContext JavaDoc;
14 import javax.servlet.ServletRequest JavaDoc;
15 import javax.servlet.http.HttpServletRequest JavaDoc;
16 import javax.servlet.http.HttpSession JavaDoc;
17
18 import org.apache.log4j.Logger;
19
20 import com.inversoft.beans.BeanException;
21 import com.inversoft.beans.JavaBean;
22 import com.inversoft.util.typeconverter.TypeConversionException;
23 import com.inversoft.verge.repository.config.Config;
24 import com.inversoft.verge.repository.config.RepositoryConfigRegistry;
25 import com.inversoft.verge.util.ScopeConstants;
26
27
28 /**
29  * This class is a facade that sits on top of the http request,
30  * http session and servlet context (or servlet container) and
31  * acts like a repository. This allows classes to look up objects
32  * defined in configuration file by id. All objects in the repository
33  * have unique ids, Therefore, a request scoped object and a
34  * seesion scope object can NOT have the same id.
35  *
36  * @author Brian Pontarelli
37  */

38 public class Repository {
39
40     /**
41      * The logger category for this class
42      */

43     private static final Logger logger = Logger.getLogger(Repository.class);
44
45     /**
46      * Constructs a new repository and sets the context that the repository
47      * will live in (ie the container). This is private because this class is a
48      * singleton
49      */

50     private Repository() {
51     }
52
53
54     //--------------------------------------------------------------------------
55
//-------------------------- Singleton methods -----------------------------
56
//--------------------------------------------------------------------------
57

58     private static Repository instance = new Repository();
59
60     /**
61      * Gets the one and only instance, throws RepositoryException if the
62      * repository has not be initialized yet
63      */

64     public static Repository getInstance() {
65         return instance;
66     }
67
68
69     //--------------------------------------------------------------------------
70
//--------------------------- Public methods -------------------------------
71
//--------------------------------------------------------------------------
72

73
74     /**
75      * Retrieves the item with the given id from the repository. If the item
76      * does not exist, it is created, stored and then returned.
77      *
78      * @param request The request to use when retrieving request scoped and
79      * session scoped items
80      * @param id The repository id of the item to retrieve
81      * @return The item and never null
82      * @throws RepositoryException If the item was never defined in the
83      * configuration file
84      * @throws NullPointerException If request or id are null
85      */

86     public Object JavaDoc lookupItem(HttpServletRequest JavaDoc request, String JavaDoc id) {
87         return lookupItem(request, id, true);
88     }
89
90     /**
91      * Retrieves the item with the given id from the repository. If the item
92      * does not exist, it is created, stored and then returned. However, if the
93      * item is request scoped and has not been created, the boolean parameter
94      * createRequest determines whether or not the item is created or not. If
95      * the item has not been created and this boolean is false, then null is
96      * returned.
97      *
98      * @param request The request to use when retrieving request scoped and
99      * session scoped items
100      * @param id The repository id of the item to retrieve
101      * @param createRequest Determines if the request scoped item should be
102      * created and added to the request if it doesn't already exist.
103      * This is useful when retrieving data from a request scoped item
104      * an would like to neglect whether or not it exists
105      * @return The item and only null if the item is request scoped and does
106      * not exist in the request and the createRequest parameter is false
107      * @throws RepositoryException If the item was never defined in the
108      * configuration file
109      * @throws NullPointerException If request or id are null
110      */

111     public Object JavaDoc lookupItem(HttpServletRequest JavaDoc request, String JavaDoc id,
112             boolean createRequest) {
113
114         Config config = RepositoryConfigRegistry.getInstance(request).lookup(id);
115         if (config == null) {
116             throw new RepositoryException("Item with id of: " + id +
117                 " was not defined in the config file");
118         }
119
120         return lookupItem(request, config, createRequest);
121     }
122
123     /**
124      * Retrieves the item for the given config object from the repository. If the
125      * item does not exist, it is created, stored and then returned.
126      *
127      * @param request The request to use when retrieving request scoped and
128      * session scoped items
129      * @param config The config of the item to retrieve
130      * @return The item and never null
131      * @throws RepositoryException If the item was never defined in the
132      * configuration file
133      * @throws NullPointerException If request or config are null
134      */

135     public Object JavaDoc lookupItem(HttpServletRequest JavaDoc request, Config config) {
136         return lookupItem(request, config, true);
137     }
138
139     /**
140      * Retrieves the item from the repository with the given config. If the item
141      * does not exist, it is created, stored and returned. However, if the
142      * item is request scoped and has not been created, the boolean parameter
143      * createRequest determines whether or not the item is created or not. If
144      * the item has not been created and this boolean is false, then null is
145      * returned.
146      *
147      * @param request The request to use when retrieving request scoped and
148      * session scoped items
149      * @param config The config of the item to retrieve
150      * @param createRequest Determines if a request scoped item should be
151      * created and added to the request if it doesn't already exist.
152      * This is useful when retrieving data from a request scoped item
153      * and would like to neglect whether or not it exists
154      * @return The item and only null if the item is request scoped and does
155      * not exist in the request and the createRequest parameter is false
156      * @throws RepositoryException If the object was never defined in the
157      * configuration file
158      * @throws NullPointerException If request or config are null
159      */

160     public Object JavaDoc lookupItem(HttpServletRequest JavaDoc request, Config config,
161             boolean createRequest) {
162
163         if (logger.isDebugEnabled()) {
164             logger.debug("Looking up item with an ID of: " + config.getID());
165             logger.debug("Looking up item with an scope of: " + config.getScopeStr());
166         }
167
168         int scope = config.getScope();
169         boolean requestScope = false;
170         boolean sessionScope = false;
171         boolean applicationScope = false;
172
173         // Determine the scope
174
switch (scope) {
175         case ScopeConstants.REQUEST_INT:
176             requestScope = true;
177             logger.debug("Item is request scoped");
178             break;
179         case ScopeConstants.SESSION_INT:
180             sessionScope = true;
181             logger.debug("Item is session scoped");
182             break;
183         case ScopeConstants.APPLICATION_INT:
184             applicationScope = true;
185             logger.debug("Item is application scoped");
186             break;
187         default:
188             logger.error("Item config contains an invalid scope");
189             throw new RepositoryException("Item config contains an invalid scope");
190         }
191
192         if (applicationScope) {
193             return lookupItemSync(request, config);
194         }
195
196         // Look up the item
197
Object JavaDoc item = null;
198         String JavaDoc id = config.getID();
199         HttpSession JavaDoc session = request.getSession();
200         if (requestScope) {
201             item = request.getAttribute(id);
202         } else if (sessionScope) {
203             item = session.getAttribute(id);
204         } else {
205             assert (false) : "Should never get into this block. Application " +
206                 "look ups should be synchronized";
207         }
208
209         if (item == null) {
210
211             logger.debug("Creating item");
212
213             // Check the createRequest condition
214
if (!createRequest && requestScope) {
215                 return null;
216             }
217
218             try {
219                 Class JavaDoc klass = config.getBeanClass();
220                 item = klass.newInstance();
221                 logger.debug("Instantiating item");
222             } catch (Exception JavaDoc e) {
223                 logger.error("Error instantiating item", e);
224                 throw new RepositoryException("Error instantiating item", e);
225             }
226
227             // Store the item in the correct object
228
logger.debug("Storing item");
229             if (requestScope) {
230                 request.setAttribute(id, item);
231             } else if (sessionScope) {
232                 session.setAttribute(id, item);
233             } else {
234                 throw new AssertionError JavaDoc("Should never get into this block. " +
235                     "Application look ups should be synchronized");
236             }
237
238             // Setup initial values and references if there are any
239
populateProperties(request, config, item);
240             populateReferences(request, config, item);
241
242             logger.debug("Finished creating item");
243         }
244
245         logger.debug("Finished looking up item");
246
247         return item;
248     }
249
250     /**
251      * Synchronizingly retrieves the application scoped item from the repository
252      * with the given config. If the item does not exist, it is created, stored
253      * and returned.
254      *
255      * @param request The request to use when retrieving request scoped and
256      * session scoped items
257      * @param config The config of the item to retrieve
258      * @return The item and never null
259      * @throws RepositoryException If the object was never defined in the
260      * configuration file
261      * @throws NullPointerException If request or config are null
262      */

263     Object JavaDoc lookupItemSync(HttpServletRequest JavaDoc request, Config config) {
264         logger.debug("Looking up item");
265
266         // Look up the item
267
Object JavaDoc item = null;
268         String JavaDoc id = config.getID();
269         ServletContext JavaDoc context = request.getSession().getServletContext();
270
271         // Although not perfect, this will reduce the possibility that two
272
// people using a Thread unsafe ServletContext will not collide. This
273
// is only true if they use the repository
274
synchronized (context) {
275             item = context.getAttribute(id);
276
277             if (item == null) {
278
279                 logger.debug("Creating item");
280
281                 try {
282                     Class JavaDoc klass = config.getBeanClass();
283                     item = klass.newInstance();
284                     logger.debug("Instantiating item");
285                 } catch (Exception JavaDoc e) {
286                     logger.error("Error instantiating item", e);
287                     throw new RepositoryException("Error instantiating item", e);
288                 }
289
290                 context.setAttribute(id, item);
291
292                 // Setup initial values and references if there are any
293
populateProperties(request, config, item);
294                 populateReferences(request, config, item);
295
296                 logger.debug("Finished creating item");
297             }
298         }
299
300         logger.debug("Finished looking up item");
301
302         return item;
303     }
304
305     /**
306      * Populates an item with the property values setup in its Config object.
307      * This method is really dumb, it does no checks just starts trying to
308      * set properties (if there are any)
309      *
310      * @param request The request used to lookup request and session scoped
311      * items
312      * @param config The Config from which the properties names and values
313      * will be retrieved
314      * @param item The item to set the properties on
315      * @throws RepositoryException If any of the properties in the config
316      * are not valid JavaBean properties of the item object
317      */

318     void populateProperties(HttpServletRequest JavaDoc request, Config config,
319             Object JavaDoc item) throws RepositoryException {
320         logger.debug("Populating item properties");
321
322         Properties JavaDoc props = config.getProperties();
323         JavaBean javaBean = config.getJavaBean();
324         Enumeration JavaDoc names;
325         String JavaDoc name;
326         String JavaDoc value;
327
328         // Debug the number of properties
329
if (logger.isDebugEnabled()) {
330             logger.debug("Item has " + props.size() + " properties");
331         }
332
333         if (props.size() > 0) {
334
335             // Loop through all the properties and set them using the JavaBean
336
names = props.propertyNames();
337             while (names.hasMoreElements()) {
338                 name = (String JavaDoc) names.nextElement();
339                 value = props.getProperty(name);
340
341                 try {
342                     if (logger.isDebugEnabled()) {
343                         logger.debug("Setting property named: " + name + " with value: "
344                             + value + " for item with id of: " + config.getID());
345                     }
346                     // set the value into the item
347
javaBean.setPropertyValue(name, item, value, /*convert=*/true);
348                 } catch (BeanException be) {
349                     throw new RepositoryException(be);
350                 } catch (TypeConversionException tce) {
351                     throw new RepositoryException(tce);
352                 }
353             }
354         }
355
356         logger.debug("Finished populating item properties");
357     }
358
359     /**
360      * Populates an item with any references setup in the Config object. These
361      * are references to other items in the repository.
362      *
363      * @param request The request used to lookup request and session scoped
364      * items being referenced
365      * @param config The Config from which the references are retrieved
366      * @param item The item to set the properties on
367      * @throws RepositoryException If any of the properties in the Config
368      * are not valid JavaBean properties of the item or they reference
369      * other items that do not exists or could not be created
370      */

371     void populateReferences(HttpServletRequest JavaDoc request, Config config,
372             Object JavaDoc item) throws RepositoryException {
373         JavaBean javaBean = config.getJavaBean();
374         Properties JavaDoc refs = config.getReferences();
375         Enumeration JavaDoc names;
376         Object JavaDoc reference;
377         String JavaDoc name, value;
378
379         if (refs != null && refs.size() > 0) {
380
381             names = refs.propertyNames();
382
383             while (names.hasMoreElements()) {
384                 name = (String JavaDoc) names.nextElement();
385                 value = refs.getProperty(name);
386
387                 try {
388                     if (logger.isDebugEnabled()) {
389                         logger.debug("Setting reference property: " + name +
390                             " with value: " + value + " for item with id of: " +
391                             config.getID());
392                     }
393
394                     // Look up the reference from the repository
395
reference = lookupItem(request, value);
396                     logger.debug("Found reference object");
397
398                     // set the reference into the item (notice the 3rd parameter)
399
javaBean.setPropertyValue(name, item, reference, /*convert=*/false);
400                 } catch (BeanException be) {
401                     throw new RepositoryException(be);
402                 } catch (RepositoryException re) {
403                     throw new RepositoryException("Error resolving reference named: "
404                         + value, re);
405                 } catch (TypeConversionException tce) {
406                     throw new RepositoryException(tce);
407                 }
408             }
409         }
410     }
411
412     /**
413      * Returns true if an item with the given id was defined it the configuration
414      * for the repository.
415      *
416      * @param id The items repository id
417      * @return True if it was configured, false otherwise
418      */

419     public boolean isValidItem(ServletRequest JavaDoc request, String JavaDoc id) {
420         return (RepositoryConfigRegistry.getInstance(request).lookup(id) != null);
421     }
422
423     /**
424      * Returns true if the item with the given repository id has been created and
425      * stored in the repository.
426      *
427      * @param request The request to use when looking for request scoped and
428      * session scoped items
429      * @param id The repository id of the item
430      * @return True or false, see comment
431      */

432     public boolean isItemLoaded(HttpServletRequest JavaDoc request, String JavaDoc id) {
433
434         Config config = RepositoryConfigRegistry.getInstance(request).lookup(id);
435         if (config == null) {
436             return false;
437         }
438
439         // Determine the scope
440
int scope = config.getScope();
441         switch (scope) {
442         case ScopeConstants.REQUEST_INT:
443             logger.debug("Item is request scoped");
444             return (request.getAttribute(id) != null);
445         case ScopeConstants.SESSION_INT:
446             logger.debug("Item is session scoped");
447             return (request.getSession().getAttribute(id) != null);
448         case ScopeConstants.APPLICATION_INT:
449             return isItemLoadedSync(request, id);
450         }
451
452         logger.error("Item config contains an invalid scope");
453         throw new RepositoryException("Item config contains an invalid scope");
454     }
455
456     /**
457      * Returns true if the item with the given repository id has been created and
458      * stored in the repository.
459      *
460      * @param request The request to use when looking for request scoped and
461      * session scoped items
462      * @param id The repository id of the item
463      * @return True or false, see comment
464      */

465     boolean isItemLoadedSync(HttpServletRequest JavaDoc request, String JavaDoc id) {
466
467         logger.debug("Item is application scoped");
468         ServletContext JavaDoc context = request.getSession().getServletContext();
469         synchronized (context) {
470             return (context.getAttribute(id) != null);
471         }
472     }
473
474
475     /**
476      * Returns the configuration object for the item with the given repository id
477      *
478      * @param id The repository id of the item to get the configuration for
479      * @return The Config object for the item or null if the item was not defined
480      */

481     public Config lookupConfig(HttpServletRequest JavaDoc request, String JavaDoc id) {
482         return RepositoryConfigRegistry.getInstance(request).lookup(id);
483     }
484 }
485
Popular Tags