View Javadoc

1   /*
2    * Copyright (c) 1998, 2005 Gargoyle Software Inc. All rights reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, are permitted provided that the following conditions are met:
6    *
7    * 1. Redistributions of source code must retain the above copyright notice,
8    *    this list of conditions and the following disclaimer.
9    * 2. Redistributions in binary form must reproduce the above copyright notice,
10   *    this list of conditions and the following disclaimer in the documentation
11   *    and/or other materials provided with the distribution.
12   * 3. The end-user documentation included with the redistribution, if any, must
13   *    include the following acknowledgment:
14   *
15   *       "This product includes software developed by Gargoyle Software Inc.
16   *        (http://www.GargoyleSoftware.com/)."
17   *
18   *    Alternately, this acknowledgment may appear in the software itself, if
19   *    and wherever such third-party acknowledgments normally appear.
20   * 4. The name "Gargoyle Software" must not be used to endorse or promote
21   *    products derived from this software without prior written permission.
22   *    For written permission, please contact info@GargoyleSoftware.com.
23   * 5. Products derived from this software may not be called "GSBase", nor may
24   *    "GSBase" appear in their name, without prior written permission of
25   *    Gargoyle Software Inc.
26   *
27   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
28   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
29   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
30   * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
33   * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
36   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37   */
38  package com.gargoylesoftware.base.objectstore;
39  
40  import com.gargoylesoftware.base.resource.ManagedResource;
41  import com.gargoylesoftware.base.resource.ResourceFactory;
42  import com.gargoylesoftware.base.resource.ResourceManager;
43  import com.gargoylesoftware.base.util.DetailedNullPointerException;
44  import java.util.Iterator;
45  import java.util.Map;
46  
47  /***
48   *  This is a wrapper for the data layer in an application. Any code that
49   *  accesses a database or some other form of data should be in a subclass of
50   *  ObjectStore
51   *
52   * @version  $Revision: 1.5 $
53   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
54   */
55  public abstract class ObjectStore {
56  
57      private ResourceManager resourceManager_ = null;
58  
59  
60      /***
61       *  Create an instance
62       */
63      protected ObjectStore() {
64      }
65  
66  
67      /***
68       *  <p>Set the resource map. This defines what class is used when a specific
69       *  resource factory is requested.</p>
70       * 
71       *  <p>It is recommended to use {@link #setResourceManager(ResourceManager)} instead</p>
72       * @param  inputMap A map containing string/class pairs.
73       */
74      public final void setResourceFactoryMap( final Map inputMap ) {
75          assertNotNull("inputMap", inputMap);
76  
77          Map.Entry entry;
78          final ResourceManager newResourceManager = new ResourceManager( getClass().getName() );
79  
80          final Iterator iterator = inputMap.entrySet().iterator();
81          while( iterator.hasNext() ) {
82              entry = ( Map.Entry )iterator.next();
83              newResourceManager.addFactory( ( String )entry.getKey(), ( ResourceFactory )entry.getValue() );
84          }
85  
86          setResourceManager( newResourceManager );
87      }
88  
89  
90      /***
91       *  Set the resource manager
92       *
93       * @param  resourceManager The new resource manager
94       */
95      public final void setResourceManager( final ResourceManager resourceManager ) {
96          if( resourceManager_ != null ) {
97              resourceManager_.releaseAllResources();
98          }
99          resourceManager_ = resourceManager;
100     }
101 
102 
103     /***
104      *  Gets the resource manager
105      *
106      * @return  The resource manager or null if a resource manager has not been
107      *      set.
108      */
109     public final ResourceManager getResourceManager() {
110         return resourceManager_;
111     }
112 
113 
114     /***
115      *  Perform the actions specified by the key and return a value. The
116      *  subclasses will perform the actual work in overridden versions of
117      *  executeImpl()
118      *
119      * @param  command The object that tells the object store what to do
120      * @return  The results of the actions or null if there are no results
121      * @exception  ObjectStoreCommandNotSupportedException If the command
122      * is not supported by this store
123      * @exception  ObjectStoreException If an error occurs during processing
124      * of this command.
125      * @see  #executeImpl(ObjectStoreCommand)
126      */
127     public final synchronized Object execute(
128             final ObjectStoreCommand command )
129         throws
130             ObjectStoreCommandNotSupportedException,
131             ObjectStoreException {
132 
133         Object result;
134         try {
135             result = executeImpl( command );
136         }
137         catch( final Exception e ) {
138             result = handleException( e );
139         }
140         catch( final Error e ) {
141             result = handleError( e );
142         }
143         catch( final Throwable practicallyImpossibleButRequiredByTheCompiler ) {
144             practicallyImpossibleButRequiredByTheCompiler.printStackTrace();
145             result = null;
146         }
147         finally {
148             if( resourceManager_ != null ) {
149                 resourceManager_.releaseAllResources();
150             }
151         }
152 
153         return result;
154     }
155 
156 
157     /***
158      *  Handle an exception that occured during the processing of executeImpl().
159      *  Usually these exceptions will be rethrown after logging them to some
160      *  error log<p>
161      *
162      *  The default behaviour is to rethrow any ObjectStoreExceptions or
163      *  ObjectStoreCommandNotSupportedExceptions. All other exceptions are
164      *  wrapped in a new ObjectStoreException and then that wrapper is thown
165      *
166      * @param  exception the exception that had been thrown
167      * @return  The object to return from execute in those cases where an
168      *      exception is not thrown out of this method
169      * @exception  ObjectStoreException The exception to be thrown back out of
170      *      execute()
171      * @exception  ObjectStoreCommandNotSupportedException the exception to be
172      *      thrown back out of execute()
173      */
174     protected Object handleException( final Exception exception )
175         throws
176             ObjectStoreException,
177             ObjectStoreCommandNotSupportedException {
178 
179         if( exception instanceof ObjectStoreException ) {
180             throw ( ObjectStoreException )exception;
181         }
182         if( exception instanceof ObjectStoreCommandNotSupportedException ) {
183             throw ( ObjectStoreCommandNotSupportedException )exception;
184         }
185 
186         throw new ObjectStoreException( exception );
187     }
188 
189 
190     /***
191      *  Handle an exception that occured during the processing of executeImpl().
192      *  Usually these exceptions will be rethrown after logging them to some
193      *  error log<p>
194      *
195      *  The default behaviour is to rethrow the error
196      *
197      * @param  error The error that had been thrown
198      * @return  The object to return from execute in those cases where an
199      *      exception is not thrown out of this method
200      */
201     protected Object handleError( final Error error ) {
202         throw error;
203     }
204 
205 
206     /***
207      *  Return a resource from the specified factory
208      *
209      * @param  name The name of the factory
210      * @return  The specified resource
211      * @see  #setResourceFactoryMap(Map)
212      */
213     protected final Object getResource( final String name ) {
214         return getResourceManagerOrDie().getResource( name );
215     }
216 
217 
218     /***
219      *  Override this to provide the actual processing of the object store.
220      *
221      * @param  command The object that tells the object store what to do
222      * @return  The results of the actions or null if there are no results
223      * @exception  ObjectStoreCommandNotSupportedException If the specified
224      *      command is not understood by the object store
225      * @exception  Throwable If an error occurs
226      * @see  #execute(ObjectStoreCommand)
227      */
228     protected abstract Object executeImpl(
229             final ObjectStoreCommand command )
230         throws
231             Throwable,
232             ObjectStoreCommandNotSupportedException;
233 
234 
235     /***
236      *  Release the specified resource
237      *
238      * @param  object The resource to release
239      */
240     protected final void releaseResource( final ManagedResource object ) {
241         getResourceManagerOrDie().releaseResource( object );
242     }
243 
244 
245     /***
246      *  Return the resource manager. If a resource manager has not been
247      *  specified then throw an exception.
248      *
249      * @return  The resource manager
250      */
251     private ResourceManager getResourceManagerOrDie() {
252         if( resourceManager_ == null ) {
253             throw new IllegalStateException( "No ResourceManager has been specified" );
254         }
255         return resourceManager_;
256     }
257 
258 
259     /***
260      * Throw an exception if the specified object is null
261      * @param fieldName The name of the paremeter we are checking
262      * @param object The value of the parameter we are checking
263      */
264     protected final void assertNotNull( final String fieldName, final Object object ) {
265         if( object == null ) {
266             throw new DetailedNullPointerException(fieldName);
267         }
268     }
269 }
270