001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2008
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.shared;
034:
035: import com.flexive.shared.exceptions.FxLookupException;
036: import com.flexive.shared.interfaces.*;
037: import org.apache.commons.logging.Log;
038: import org.apache.commons.logging.LogFactory;
039:
040: import javax.naming.InitialContext;
041: import javax.naming.NamingException;
042: import javax.naming.NameClassPair;
043: import javax.naming.NamingEnumeration;
044: import javax.transaction.TransactionManager;
045: import javax.ejb.SessionContext;
046: import java.util.Hashtable;
047: import java.util.concurrent.ConcurrentHashMap;
048: import java.util.concurrent.ConcurrentMap;
049:
050: /**
051: * Utility class for EJB lookups.
052: *
053: * @author Daniel Lichtenberger (daniel.lichtenberger@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
054: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
055: */
056: public class EJBLookup {
057: private static transient Log LOG = LogFactory
058: .getLog(EJBLookup.class);
059: public static String APPNAME = "flexive";
060:
061: private enum STRATEGY {
062: APP_SIMPLENAME_LOCAL, JAVA_COMP_ENV, APP_SIMPLENAME_REMOTE, COMPLEXNAME, SIMPLENAME_LOCAL, SIMPLENAME_REMOTE, UNKNOWN
063: }
064:
065: private static STRATEGY used_strategy = null;
066: private static final ConcurrentMap<String, Object> ejbCache = new ConcurrentHashMap<String, Object>(
067: 100);
068:
069: /**
070: * Protected default constructor to avoid instantiation.
071: */
072: protected EJBLookup() {
073: }
074:
075: /**
076: * Lookup of the AccountEngine EJB.
077: *
078: * @return a reference to the AccountEngine EJB
079: */
080: public static AccountEngine getAccountEngine() {
081: return getEngine(AccountEngine.class);
082: }
083:
084: /**
085: * Lookup of the SqlSearch EJB.
086: *
087: * @return a reference to the SqlSearch EJB
088: */
089: public static SearchEngine getSearchEngine() {
090: return getEngine(SearchEngine.class);
091: }
092:
093: /**
094: * Lookup of the Briefcase EJB.
095: *
096: * @return a reference to the Briefcase EJB
097: */
098: public static BriefcaseEngine getBriefcaseEngine() {
099: return getEngine(BriefcaseEngine.class);
100: }
101:
102: /**
103: * Lookup of the Template EJB.
104: *
105: * @return a reference to the Briefcase EJB
106: */
107: public static TemplateEngine getTemplateEngine() {
108: return getEngine(TemplateEngine.class);
109: }
110:
111: /**
112: * Lookup of the GroupEngine EJB.
113: *
114: * @return a reference to the GroupEngine EJB
115: */
116: public static UserGroupEngine getUserGroupEngine() {
117: return getEngine(UserGroupEngine.class);
118: }
119:
120: /**
121: * Lookup of the MandatorEngine EJB.
122: *
123: * @return a reference to the MandatorEngine EJB
124: */
125: public static MandatorEngine getMandatorEngine() {
126: return getEngine(MandatorEngine.class);
127: }
128:
129: /**
130: * Lookup of the ACLEngine EJB.
131: *
132: * @return a reference to the ACLEngine EJB
133: */
134: public static ACLEngine getACLEngine() {
135: return getEngine(ACLEngine.class);
136: }
137:
138: /**
139: * Lookup of the Language EJB.
140: *
141: * @return a reference to the Language EJB
142: */
143: public static LanguageEngine getLanguageEngine() {
144: return getEngine(LanguageEngine.class);
145: }
146:
147: /**
148: * Lookup of the UserConfigurationEngine EJB.
149: *
150: * @return a reference to the UserConfigurationEngine EJB
151: */
152: public static UserConfigurationEngine getUserConfigurationEngine() {
153: return getEngine(UserConfigurationEngine.class);
154: }
155:
156: /**
157: * Lookup of the DivisionConfigurationEngine EJB.
158: *
159: * @return a reference to the DivisionConfigurationEngine EJB
160: */
161: public static DivisionConfigurationEngine getDivisionConfigurationEngine() {
162: return getEngine(DivisionConfigurationEngine.class);
163: }
164:
165: /**
166: * Lookup of the GlobalConfigurationBean EJB.
167: *
168: * @return a reference to the GlobalConfigurationBean EJB.
169: */
170: public static GlobalConfigurationEngine getGlobalConfigurationEngine() {
171: return getEngine(GlobalConfigurationEngine.class);
172: }
173:
174: /**
175: * Lookup of the FxConfiguration EJB.
176: *
177: * @return a reference to the FxConfiguration EJB.
178: */
179: public static ConfigurationEngine getConfigurationEngine() {
180: return getEngine(ConfigurationEngine.class);
181: }
182:
183: /**
184: * Lookup of the AssignmentEngine EJB.
185: *
186: * @return a reference to the AssignmentEngine EJB.
187: */
188: public static AssignmentEngine getAssignmentEngine() {
189: return getEngine(AssignmentEngine.class);
190: }
191:
192: /**
193: * Lookup of the TypeEngine EJB.
194: *
195: * @return a reference to the TypeEngine EJB.
196: */
197: public static TypeEngine getTypeEngine() {
198: return getEngine(TypeEngine.class);
199: }
200:
201: /**
202: * Lookup of the SelectListEngine EJB.
203: *
204: * @return a reference to the SelectListEngine EJB
205: */
206: public static SelectListEngine getSelectListEngine() {
207: return getEngine(SelectListEngine.class);
208: }
209:
210: /**
211: * Lookup of the WorkflowEngine EJB.
212: *
213: * @return a reference to the WorkflowEngine EJB.
214: */
215: public static WorkflowEngine getWorkflowEngine() {
216: return getEngine(WorkflowEngine.class);
217: }
218:
219: /**
220: * Lookup of the StepEngine EJB.
221: *
222: * @return a reference to the StepEngine EJB.
223: */
224: public static StepEngine getWorkflowStepEngine() {
225: return getEngine(StepEngine.class);
226: }
227:
228: /**
229: * Lookup of the RouteEngine EJB.
230: *
231: * @return a reference to the RouteEngine EJB.
232: */
233: public static RouteEngine getWorkflowRouteEngine() {
234: return getEngine(RouteEngine.class);
235: }
236:
237: /**
238: * Lookup of the StepDefinitionEngine EJB.
239: *
240: * @return a reference to the StepDefinitionEngine EJB.
241: */
242: public static StepDefinitionEngine getWorkflowStepDefinitionEngine() {
243: return getEngine(StepDefinitionEngine.class);
244: }
245:
246: /**
247: * Lookup of the ContentEngine EJB.
248: *
249: * @return a reference to the ContentEngine EJB.
250: */
251: public static ContentEngine getContentEngine() {
252: return getEngine(ContentEngine.class);
253: }
254:
255: /**
256: * Lookup of the StatelessTest EJB.
257: *
258: * @return a reference to the StatelessTest EJB.
259: */
260: public static StatelessTest getStatelessTestInterface() {
261: return getEngine(StatelessTest.class);
262: }
263:
264: /**
265: * Lookup of the SequencerEngine EJB.
266: *
267: * @return a reference to the SequencerEngine EJB.
268: */
269: public static SequencerEngine getSequencerEngine() {
270: return getEngine(SequencerEngine.class);
271: }
272:
273: /**
274: * Lookup of the ScriptingEngine EJB
275: *
276: * @return a reference to the ScriptingEngine EJB
277: */
278: public static ScriptingEngine getScriptingEngine() {
279: return getEngine(ScriptingEngine.class);
280: }
281:
282: /**
283: * Lookup of the FxTimerService EJB
284: *
285: * @return a reference to the FxTimerService EJB
286: */
287: public static FxTimerService getTimerService() {
288: return getEngine(FxTimerService.class);
289: }
290:
291: /**
292: * Lookup of the FxTree EJB
293: *
294: * @return a reference to the FxTree EJB
295: */
296: public static TreeEngine getTreeEngine() {
297: return getEngine(TreeEngine.class);
298: }
299:
300: /**
301: * Lookup of the ResultPreferencesEngine EJB.
302: *
303: * @return a reference to the ResultPreferencesEngine EJB.
304: */
305: public static ResultPreferencesEngine getResultPreferencesEngine() {
306: return getEngine(ResultPreferencesEngine.class);
307: }
308:
309: /**
310: * Get a reference of the transaction manager
311: *
312: * @return TransactionManager
313: */
314: public static TransactionManager getTransactionManager() {
315: try {
316: InitialContext ctx = new InitialContext();
317: try {
318: return (TransactionManager) ctx
319: .lookup("java:TransactionManager");
320: } catch (NamingException e) {
321: try {
322: return (TransactionManager) ctx
323: .lookup("java:comp/TransactionManager");
324: } catch (NamingException e2) {
325: return (TransactionManager) ctx
326: .lookup("java:appserver/TransactionManager");
327: }
328: }
329: } catch (Exception e) {
330: throw new FxLookupException(
331: "Failed to lookup transaction manager: "
332: + e.getMessage(), e).asRuntimeException();
333: }
334: }
335:
336: /**
337: * Get a reference of the current EJB session context.
338: *
339: * @return the EJB session context
340: */
341: public static SessionContext getSessionContext() {
342: try {
343: final InitialContext ctx = new InitialContext();
344: return (SessionContext) ctx.lookup("java:comp/EJBContext");
345: } catch (NamingException e) {
346: throw new FxLookupException(
347: "Failed to lookup session context: "
348: + e.getMessage(), e).asRuntimeException();
349: }
350: }
351:
352: /**
353: * Lookup the EJB found under the given Class's name. Uses default flexive naming scheme.
354: *
355: * @param type EJB interface class instance
356: * @param appName EJB application name
357: * @param environment optional environment for creating the initial context
358: * @param <T> EJB interface type
359: * @return a reference to the given EJB
360: */
361: protected static <T> T getInterface(Class<T> type, String appName,
362: Hashtable environment) {
363: // Try to obtain interface from the lookup cache
364: Object ointerface = ejbCache.get(type.getName());
365: if (ointerface != null) {
366: return type.cast(ointerface);
367: }
368:
369: // Cache miss: obtain interface and store it in the cache
370: synchronized (EJBLookup.class) {
371: String name = "<unknown>";
372: try {
373: if (environment == null)
374: environment = new Hashtable();
375: InitialContext ctx = new InitialContext(environment);
376: if (used_strategy == null) {
377: appName = discoverStrategy(appName, ctx, type);
378: if (used_strategy != null) {
379: LOG.info("Working lookup strategy: "
380: + used_strategy);
381: } else {
382: LOG
383: .error("No working lookup strategy found! Possibly because of pending redeployment.");
384: }
385: }
386: name = buildName(appName, type);
387: ointerface = ctx.lookup(name);
388: ejbCache.putIfAbsent(type.getName(), ointerface);
389:
390: return type.cast(ointerface);
391: } catch (Exception exc) {
392: throw new FxLookupException(LOG, exc,
393: "ex.ejb.lookup.failure", type, exc)
394: .asRuntimeException();
395: }
396: }
397: }
398:
399: /**
400: * Discover which lookup strategy works for the given class
401: *
402: * @param appName EJB application name
403: * @param ctx InitialContext
404: * @param type the class
405: * @return appName (may have changed)
406: */
407: private static <T> String discoverStrategy(String appName,
408: InitialContext ctx, Class<T> type) {
409: for (STRATEGY strat : STRATEGY.values()) {
410: if (strat == STRATEGY.UNKNOWN)
411: continue;
412: used_strategy = strat;
413: try {
414: ctx.lookup(buildName(appName, type));
415: return appName;
416: } catch (Exception e) {
417: //ignore and try next
418: }
419: }
420: //houston, we have a problem - try locale and remote with appname again iterating through all "root" ctx bindings
421: //this can happen if the ear is not named flexive.ear
422: try {
423: NamingEnumeration<NameClassPair> ncpe = ctx.list("");
424: while (ncpe.hasMore()) {
425: NameClassPair ncp = ncpe.next();
426: if (ncp.getClassName().endsWith("NamingContext")) {
427: appName = ncp.getName();
428: try {
429: used_strategy = STRATEGY.APP_SIMPLENAME_LOCAL;
430: ctx.lookup(buildName(ncp.getName(), type));
431: APPNAME = ncp.getName();
432: LOG.info("Using application name [" + appName
433: + "] for lookups!");
434: return APPNAME;
435: } catch (Exception e) {
436: //ignore and try remote
437: }
438: try {
439: used_strategy = STRATEGY.APP_SIMPLENAME_REMOTE;
440: ctx.lookup(buildName(ncp.getName(), type));
441: APPNAME = ncp.getName();
442: LOG.info("Using application name [" + appName
443: + "] for lookups!");
444: return APPNAME;
445: } catch (Exception e) {
446: //ignore and try remote
447: }
448: }
449: }
450:
451: } catch (Exception e) {
452: LOG.warn(e);
453: }
454: used_strategy = null;
455: return appName;
456: }
457:
458: /**
459: * Build the correct JNDI name to request for lookups depending on the discovered lookup strategy
460: *
461: * @param appName EJB application name
462: * @param type the class to lookup
463: * @return JNDI name
464: */
465: private static <T> String buildName(String appName, Class<T> type) {
466: switch (used_strategy) {
467: case APP_SIMPLENAME_LOCAL:
468: return appName + "/" + type.getSimpleName() + "/local";
469: case APP_SIMPLENAME_REMOTE:
470: return appName + "/" + type.getSimpleName() + "/remote";
471: case COMPLEXNAME:
472: return type.getCanonicalName();
473: case SIMPLENAME_LOCAL:
474: return type.getSimpleName() + "/local";
475: case SIMPLENAME_REMOTE:
476: return type.getSimpleName() + "/remote";
477: case JAVA_COMP_ENV:
478: return "java:comp/env/" + type.getSimpleName();
479: default:
480: throw new FxLookupException(
481: "Unsupported/unknown lookup strategy "
482: + used_strategy + "!").asRuntimeException();
483: }
484: }
485:
486: /**
487: * Lookup the EJB found under the given Class's name. Uses default flexive naming scheme.
488: *
489: * @param appName EJB application name
490: * @param type EJB interface class instance
491: * @param <T> EJB interface type
492: * @return a reference to the given EJB
493: */
494: public static <T> T getEngine(String appName, Class<T> type) {
495: return getInterface(type, appName, null);
496: }
497:
498: /**
499: * Lookup the EJB found under the given Class's name. Uses default flexive naming scheme.
500: *
501: * @param type EJB interface class instance
502: * @param <T> EJB interface type
503: * @return a reference to the given EJB
504: */
505: public static <T> T getEngine(Class<T> type) {
506: return getInterface(type, APPNAME, null);
507: }
508: }
|