/home/mario/oci/jnb/dataaccess/source/src/java/com/ociweb/service/ServiceLocatorImpl.java

1    /** 
2     * This software program, Simple Data Access Layer (SDAL), is copyrighted by Object 
3     * Computing inc of St. Louis MO USA. It is provided under the open-source model 
4     * and is free of license fees. You are free to modify this code for your own use 
5     * but you may not claim copyright. 
6     * 
7     * Since SDAL is open source and free of licensing fees, you are free to use, 
8     * modify, and distribute the source code, as long as you include this copyright 
9     * statement. 
10    * 
11    * In particular, you can use SDAL to build proprietary software and are under no 
12    * obligation to redistribute any of your source code that is built using SDAL. 
13    * Note, however, that you may not do anything to the SDAL code, such as 
14    * copyrighting it yourself or claiming authorship of the SDAL code, that will 
15    * prevent SDAL from being distributed freely using an open source development 
16    * model. 
17    * 
18    * Warranty 
19    * LICENSED PRODUCT, SDAL, IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 
20    * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE, 
21    * NONINFRINGEMENT, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 
22    * 
23    * Support 
24    * LICENSED PRODUCT, SDAL, IS PROVIDED WITH NO SUPPORT AND WITHOUT ANY OBLIGATION ON THE 
25    * PART OF OCI OR ANY OF ITS SUBSIDIARIES OR AFFILIATES TO ASSIST IN ITS USE, 
26    * CORRECTION, MODIFICATION OR ENHANCEMENT. 
27    * 
28    * Support may be available from OCI to users who have agreed to a support 
29    * contract. 
30    * 
31    * Liability 
32    * OCI OR ANY OF ITS SUBSIDIARIES OR AFFILIATES SHALL HAVE NO LIABILITY WITH 
33    * RESPECT TO THE INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY 
34    * LICENSED PRODUCT OR ANY PART THEREOF. 
35    * 
36    * IN NO EVENT WILL OCI OR ANY OF ITS SUBSIDIARIES OR AFFILIATES BE LIABLE FOR ANY 
37    * LOST REVENUE OR PROFITS OR OTHER SPECIAL, INDIRECT AND CONSEQUENTIAL DAMAGES, 
38    * EVEN IF OCI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
39    * 
40    * Copyright OCI. St. Louis MO USA, 2004 
41    * 
42    */ 
43   package com.ociweb.service; 
44    
45   import com.ociweb.service.ServiceLocator; 
46   import com.ociweb.service.ServiceLocatorException; 
47   import com.ociweb.service.*; 
48    
49   import java.lang.reflect.InvocationHandler; 
50   import java.lang.reflect.Method; 
51   import java.lang.reflect.Proxy; 
52   import java.util.*; 
53    
54   import net.sf.hibernate.Session; 
55   import net.sf.hibernate.HibernateException; 
56   import org.apache.log4j.Logger; 
57   import org.apache.log4j.LogManager; 
58    
59   class ServiceLocatorImpl implements ServiceLocator { 
60       private static final Map COMMANDS = new Hashtable(); 
61       private static final Command FIND_WITH_NAMED_QUERY_COMMAND = new FindWithNamedQueryCommand(); 
62       private List validatedClasses = new Vector(); 
63    
64       public ServiceLocatorImpl() { 
65           COMMANDS.put("add", new AddCommand()); 
66           COMMANDS.put("update", new UpdateCommand()); 
67           COMMANDS.put("remove", new RemoveCommand()); 
68           COMMANDS.put("findByPrimaryKey", new FindByPrimaryKeyCommand()); 
69           COMMANDS.put("findAll", new FindAllCommand()); 
70       } 
71    
72       public Object getDomainObjectManager(Class managerClass) throws ServiceLocatorException { 
73           validate(managerClass); 
74           return Proxy.newProxyInstance(managerClass.getClassLoader(), new Class[]{managerClass}, 
75                                         new ManagerDelegate()); 
76       } 
77    
78       private void validate(Class managerClass) throws ServiceLocatorException { 
79           if (!validatedClasses.contains(managerClass)) { 
80               validateIsInterface(managerClass); 
81               validateHasCRUDlikeAPI(managerClass); 
82               validatedClasses.add(managerClass); 
83           } 
84       } 
85    
86       private void validateIsInterface(Class managerClass) throws ServiceLocatorException { 
87           if (!managerClass.isInterface()) { 
88               throw exceptionFactory(managerClass, " is not an Interface"); 
89           } 
90       } 
91    
92       private void validateHasCRUDlikeAPI(Class managerClass) throws ServiceLocatorException { 
93           Method[] methods = managerClass.getMethods(); 
94           List mgrMethods = new ArrayList(methods.length); 
95           for (int i = 0; i < methods.length; i++) { 
96               Method method = methods[i]; 
97               mgrMethods.add(method.getName()); 
98           } 
99           if (!mgrMethods.containsAll(COMMANDS.keySet())) { 
100              throw exceptionFactory(managerClass, 
101                                     " must contain all of the following methods: 'add', 'update', 'remove', " + 
102                                     "'findByPrimaryKey', 'findAll'"); 
103          } 
104      } 
105   
106      private ServiceLocatorException exceptionFactory(Class managerClass, String message) { 
107          return new ServiceLocatorException("The supplied Class object (" + managerClass.getName() + ") " + message); 
108      } 
109   
110      private static class ManagerDelegate implements InvocationHandler { 
111          private Logger log = LogManager.getLogger(getClass()); 
112   
113          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
114              Command command = resolveCommand(method); 
115              if (command == null) { 
116                  throw new UnsupportedOperationException(); 
117              } 
118              try { 
119                  return command.execute(method, args, getSession()); 
120              } catch (Exception e) { 
121                  invalidateSession(); 
122                  throw e; 
123              } 
124          } 
125   
126          private Command resolveCommand(Method method) { 
127              Command result = (Command) COMMANDS.get(method.getName()); 
128              if (result == null && method.getName().startsWith("find")) { 
129                  //If it is not one of the default commands but it begins with 'find', assume it is a finder for 
130                  //named queries 
131                  result = FIND_WITH_NAMED_QUERY_COMMAND; 
132              } 
133              return result; 
134          } 
135   
136          private Session getSession() throws SessionException { 
137              Session session = ThreadSessionHolder.get(); 
138   
139              if (!session.isConnected()) { 
140                  try { 
141                      session.reconnect(); 
142                  } catch (HibernateException he) { 
143                      throw new SessionException("Could not reconnect the session", he); 
144                  } 
145              } 
146              return session; 
147          } 
148   
149          private void invalidateSession() { 
150              try { 
151                  ThreadSessionHolder.get().close(); 
152              } catch (HibernateException e) { 
153                  log.error("Unable to close the session"); 
154              } 
155              ThreadSessionHolder.set(null); 
156          } 
157      } 
158  } 
159