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.util.DetailedIllegalArgumentException;
41  import java.lang.reflect.InvocationTargetException;
42  import java.lang.reflect.Method;
43  import java.util.HashMap;
44  import java.util.Map;
45  
46  /***
47   * An object store that allows configuration by reflection.  Commands are mapped to
48   * method names such that when a specified command is received, it will be dispatched
49   * via reflection to the specified method.
50   *
51   * @version  $Revision: 1.4 $
52   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
53   */
54  public abstract class ReflectedObjectStore extends ObjectStore {
55  
56      private final Map commandMap_ = new HashMap( 89 );
57  
58  
59      /***
60       *  Create an instance
61       */
62      public ReflectedObjectStore() {
63      }
64  
65  
66      /***
67       * Execute the specified command
68       *
69       * @param  command The command to execute
70       * @return An object
71       * @exception  Throwable If an error occurs
72       */
73      protected final Object executeImpl( final ObjectStoreCommand command )
74          throws Throwable {
75  
76          final Method method = (Method)commandMap_.get( command.getClass() );
77          if( method == null ) {
78              throw new ObjectStoreCommandNotSupportedException( command );
79          }
80  
81          try {
82              return method.invoke( this, new Object[]{command} );
83          }
84          catch( final InvocationTargetException e ) {
85              throw e.getTargetException();
86          }
87      }
88  
89  
90      /***
91       * Register a command and the method that will be invoked when that command is
92       * passed into execute()
93       *
94       * @param  commandClass The class of the command
95       * @param  methodName The name of the method that will be executed
96       */
97      public void registerCommand( final Class commandClass, final String methodName ) {
98          assertNotNull( "commandClass", commandClass );
99          assertNotNull( "methodName", methodName );
100 
101         if( ObjectStoreCommand.class.isAssignableFrom( commandClass ) == false ) {
102             throw new DetailedIllegalArgumentException(
103                 "commandClass", commandClass, "Must be an instance of ObjectStoreCommand" );
104         }
105 
106         final Method method;
107         try {
108             method = getClass().getDeclaredMethod( methodName, new Class[]{commandClass} );
109         }
110         catch( final NoSuchMethodException e ) {
111             throw new DetailedIllegalArgumentException(
112                 "methodName", methodName, "No method found on class " + commandClass.getName() );
113         }
114 
115         attemptToSuppressAccessControl( method );
116 
117         commandMap_.put( commandClass, method );
118     }
119 
120 
121     private void attemptToSuppressAccessControl( final Method method ) {
122         try {
123             method.setAccessible( true );
124         }
125         catch( final SecurityException e ) {
126             // Nothing we can do if this fails
127         }
128     }
129 }
130