KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > sape > carbon > services > ejb > remote > RemoteHomeFactoryImpl


1 /*
2  * The contents of this file are subject to the Sapient Public License
3  * Version 1.0 (the "License"); you may not use this file except in compliance
4  * with the License. You may obtain a copy of the License at
5  * http://carbon.sf.net/License.html.
6  *
7  * Software distributed under the License is distributed on an "AS IS" basis,
8  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
9  * the specific language governing rights and limitations under the License.
10  *
11  * The Original Code is The Carbon Component Framework.
12  *
13  * The Initial Developer of the Original Code is Sapient Corporation
14  *
15  * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
16  */

17
18 package org.sape.carbon.services.ejb.remote;
19
20
21 import java.util.HashMap JavaDoc;
22 import java.util.Map JavaDoc;
23
24 import javax.ejb.EJBHome JavaDoc;
25 import javax.naming.Context JavaDoc;
26 import javax.naming.NamingException JavaDoc;
27 import javax.rmi.PortableRemoteObject JavaDoc;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31
32 import org.sape.carbon.core.component.ComponentConfiguration;
33 import org.sape.carbon.core.component.lifecycle.Configurable;
34 import org.sape.carbon.core.config.InvalidConfigurationException;
35
36 import org.sape.carbon.services.ejb.EnterpriseBeanConfiguration;
37 import org.sape.carbon.services.ejb.HomeFactoryClassCastException;
38 import org.sape.carbon.services.ejb.HomeFactoryClassNotFoundException;
39 import org.sape.carbon.services.ejb.HomeFactoryException;
40 import org.sape.carbon.services.ejb.HomeFactoryNamingException;
41
42 /**
43  * <p>The functional implementation of the Remote Home Factory functional interface.<br>
44  *
45  * The following list summarizes the key entites involved in using this servive
46  * <ul>
47  * <li>Configuration Interface {@link org.sape.carbon.services.ejb.remote.RemoteHomeFactoryConfiguration}
48  * <li>Functional Interface {@link org.sape.carbon.services.ejb.remote.RemoteHomeFactory}
49  * </ul>
50  * </p>
51  *
52  * @see org.sape.carbon.services.ejb.remote.RemoteHomeFactory
53  * @see org.sape.carbon.services.ejb.remote.RemoteHomeFactoryConfiguration
54  * @see org.sape.carbon.services.ejb.EnterpriseBeanConfiguration
55  * @see org.sape.carbon.services.ejb.HomeFactoryConfiguration
56  * @since carbon 1.0
57  * @author Erik M Gottesman, June 2002
58  * @version $Revision: 1.17 $($Author: dvoet $ / $Date: 2003/11/05 17:45:16 $)
59  * @stereotype implementationClass
60  */

61 public class RemoteHomeFactoryImpl implements Configurable, RemoteHomeFactory {
62
63     /**
64      * Provides a handle to Apache-commons logger
65      */

66     private Log log = LogFactory.getLog(this.getClass());
67
68     /**
69      * Used for performing comparisons/null-checks on configuration data
70      */

71     private static final String JavaDoc EMPTY_STRING = "";
72
73     private RemoteHomeFactoryConfiguration configuration;
74
75     /**
76      * A private <code>Map</code> object used to store the lookup details of
77      * EJBs associated with this home factory component
78      */

79     private Map JavaDoc ejbMap;
80
81
82     /**
83      * A private <code>Map</code> object used for caching the home interfaces of
84      * EJBs associated with this home factory component
85      */

86     private Map JavaDoc homeCache = new HashMap JavaDoc();
87
88
89     /**
90      * @see RemoteHomeFactory
91      */

92     public EJBHome JavaDoc lookup(String JavaDoc logicalName) throws HomeFactoryException {
93
94         Context JavaDoc context = null;
95
96         try {
97             context = this.configuration.getInitialContextFactory().getContext();
98                 
99             return lookup(logicalName, context);
100             
101         } catch (NamingException JavaDoc ne) {
102             throw new HomeFactoryNamingException(this.getClass(),
103                 "javax.naming.NamingException occurred for EJB name = "
104                 + "'"
105                 + logicalName
106                 + "'", ne);
107                 
108         } finally {
109             if (context != null) {
110                 try {
111                     context.close();
112                 } catch (NamingException JavaDoc ne) {
113                     log.debug("Caught naming exception closing context: " + ne);
114                 }
115             }
116         }
117
118         
119     }
120
121
122     /**
123      * @see RemoteHomeFactory
124      */

125     public EJBHome JavaDoc lookup(String JavaDoc logicalName,
126         String JavaDoc principal,
127         String JavaDoc credentials)
128         throws HomeFactoryException {
129
130         Context JavaDoc context = null;
131
132         try {
133             Map JavaDoc securityInfo = new HashMap JavaDoc();
134             securityInfo.put(Context.SECURITY_PRINCIPAL, principal);
135             securityInfo.put(Context.SECURITY_CREDENTIALS, credentials);
136             context = this.configuration.getInitialContextFactory().
137                 getContext(securityInfo);
138
139             return lookup(logicalName, context);
140
141         } catch (NamingException JavaDoc ne) {
142             throw new HomeFactoryNamingException(this.getClass(),
143                 "javax.naming.NamingException occurred for EJB name = "
144                 + "'"
145                 + logicalName
146                 + "'", ne);
147
148         } finally {
149             if (context != null) {
150                 try {
151                     context.close();
152                 } catch (NamingException JavaDoc ne) {
153                     log.debug("Caught naming exception closing context: " + ne);
154                 }
155             }
156         }
157     }
158
159
160     /**
161      * @see RemoteHomeFactory
162      */

163     public EJBHome JavaDoc lookup(String JavaDoc logicalName, Context JavaDoc context)
164         throws HomeFactoryException {
165
166         if (log.isTraceEnabled()) {
167             log.trace("Performing lookup for EJB with logical name: "
168                 + logicalName);
169         }
170
171         // Define local variables
172
EJBHome JavaDoc ejbHome = null;
173
174         EnterpriseBeanConfiguration ejbDetails =
175             (EnterpriseBeanConfiguration) this.ejbMap.get(logicalName);
176
177         if (ejbDetails == null) {
178             throw new HomeFactoryNamingException(this.getClass(),
179                 "Unable to retrieve configuration details for EJB name = '"
180                 + logicalName
181                 + "'");
182         }
183
184         if (ejbDetails.isCacheable()) {
185
186             if (log.isTraceEnabled()) {
187                 log.trace("Checking home cache for EJB: "
188                     + logicalName);
189             }
190
191             /*
192              * Assumption: a compound key has not been implemented for caching
193              * a home interface in multiple security contexts
194              */

195             ejbHome = (EJBHome JavaDoc) homeCache.get(logicalName);
196         }
197
198         if (ejbHome == null) {
199
200             // Get the JNDI Initial Context and lookup the JNDI bean name.
201
Object JavaDoc homeObject = null;
202
203             try {
204                 homeObject = context.lookup(logicalName);
205             } catch (NamingException JavaDoc ne) {
206                 throw new HomeFactoryNamingException(this.getClass(),
207                     "javax.naming.NamingException occurred for EJB name = '"
208                     + logicalName
209                     + "'", ne);
210             }
211
212             // Find home, first check if it uses RMI-IIOP or RMI-JRMP
213
if (this.configuration.isRmiIiop()) {
214
215                 /*
216                  * For RMI-IIOP, convert the remote reference from the more
217                  * general type, Object, to the more specific type (as specified
218                  * via the Config service).
219                  */

220
221                 Class JavaDoc homeClass;
222
223                 String JavaDoc homeInterfaceClassName = ejbDetails.getHomeInterface();
224
225                 try {
226                     // Get the name of the class that defines the home interface
227

228                     // Get the home interface class
229
homeClass = Class.forName(homeInterfaceClassName);
230
231                     // Narrow the EJB home reference accordingly
232
ejbHome = (EJBHome JavaDoc) PortableRemoteObject.narrow(
233                         homeObject, homeClass);
234                 } catch (ClassNotFoundException JavaDoc cnfe) {
235                     throw new HomeFactoryClassNotFoundException(this.getClass(),
236                         "Unable to obtain class: for name = '"
237                         + homeInterfaceClassName
238                         + "'", cnfe);
239                 } catch (ClassCastException JavaDoc cce) {
240                     throw new HomeFactoryClassCastException(this.getClass(),
241                         "java.lang.ClassCastException "
242                         + "occurred while attempting to narrow the EJB home "
243                         + "reference - logical name = '"
244                         + logicalName
245                         + "'", cce);
246                 }
247
248             } else {
249
250                 // For Java RMI, simply downcast the home object to EJBHome
251
try {
252                     ejbHome = (EJBHome JavaDoc) homeObject;
253                 } catch (ClassCastException JavaDoc cce) {
254                     throw new HomeFactoryClassCastException(this.getClass(),
255                         "java.lang.ClassCastException "
256                         + " occurred while attempting to downcast the EJB home "
257                         + "reference - logical name = '"
258                         + logicalName
259                         + "'", cce);
260                 }
261             }
262
263             /*
264              * If the EJB is declared as cacheable, store a reference to its
265              * home interface in order to expedite future lookups
266              */

267             if (ejbDetails.isCacheable()) {
268
269                 if (log.isTraceEnabled()) {
270                     log.trace("Adding EJB: "
271                         + logicalName
272                         + " to the home interface cache");
273                 }
274
275                 cacheHome(logicalName, ejbHome);
276             }
277         }
278
279         // Return the EJBHome object to the caller
280
return ejbHome;
281     }
282
283
284     /**
285      * Configures the component. This is preceded and followed by the suspend
286      * and resume operations if they are available on the component.
287      * @param configuration A HomeFactoryConfiguration instance
288      */

289     public void configure(ComponentConfiguration configuration) {
290
291         try {
292             this.configuration = (RemoteHomeFactoryConfiguration) configuration;
293         } catch (ClassCastException JavaDoc cce) {
294             throw new InvalidConfigurationException(
295                 this.getClass(),
296                 configuration.getConfigurationName(),
297                 "ConfigurationInterface",
298                 "Configuration interface must be of type " +
299                     RemoteHomeFactoryConfiguration.class.getName());
300         }
301
302         EnterpriseBeanConfiguration ejbs[];
303
304         ejbs = (EnterpriseBeanConfiguration[])
305             this.configuration.getEnterpriseBean();
306
307         this.ejbMap = new HashMap JavaDoc(ejbs.length);
308
309         /*
310          * Build the internal data structures that will be used to hold
311          * EJB configuration details and (optionally) cached home interfaces
312          */

313         for (int i = 0; i < ejbs.length; i++) {
314
315             /*
316              * Perform a check to ensure that the home interface is specified
317              * in configuration if RMI-IIOP is to be used
318              */

319             if (this.configuration.isRmiIiop() == true
320                 && (ejbs[i].getHomeInterface().equals(EMPTY_STRING)
321                 || ejbs[i].getHomeInterface() == null)) {
322
323                 throw new InvalidConfigurationException(this.getClass(),
324                     configuration.getConfigurationName(),
325                     "Home interface for EJB "
326                     + ejbs[i]
327                     + "must be specified if RMI-IIOP is enabled");
328             }
329
330             this.ejbMap.put(ejbs[i].getLogicalName(), ejbs[i]);
331         }
332     }
333
334
335     /**
336      * @see RemoteHomeFactory
337      */

338     public EnterpriseBeanConfiguration getEJBDetails(String JavaDoc logicalName) {
339         return (EnterpriseBeanConfiguration)
340             this.ejbMap.get(logicalName);
341     }
342
343
344     /**
345      * <p>Associates the home interface object of a locally deployed EJB
346      * with a logical name (usually its JNDI name), and caches it to
347      * decrease the cost of subsequent JNDI lookups</p>
348      * @param logicalName a String representation of the EJB's logical name
349      * in JNDI
350      * @param ejbHome the home interface object of a remotely deployed EJB
351      */

352     protected void cacheHome(String JavaDoc logicalName, EJBHome JavaDoc ejbHome) {
353                 this.homeCache.put(logicalName, ejbHome);
354     }
355 }
356
Popular Tags