001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.ejb;
031:
032: import com.caucho.config.*;
033: import com.caucho.config.program.ConfigProgram;
034: import com.caucho.config.j2ee.InjectIntrospector;
035: import com.caucho.config.program.ConfigProgram;
036: import com.caucho.ejb.cfg.*;
037: import com.caucho.ejb.manager.EjbContainer;
038: import com.caucho.ejb.protocol.AbstractHandle;
039: import com.caucho.ejb.protocol.EjbProtocolManager;
040: import com.caucho.ejb.protocol.HandleEncoder;
041: import com.caucho.ejb.session.AbstractSessionContext;
042: import com.caucho.ejb.session.SessionServer;
043: import com.caucho.ejb.session.StatelessServer;
044: import com.caucho.ejb.timer.EjbTimerService;
045: import com.caucho.ejb.xa.EjbTransactionManager;
046: import com.caucho.ejb.xa.TransactionContext;
047: import com.caucho.lifecycle.Lifecycle;
048: import com.caucho.loader.DynamicClassLoader;
049: import com.caucho.loader.EnvironmentBean;
050: import com.caucho.loader.EnvironmentClassLoader;
051: import com.caucho.util.L10N;
052: import com.caucho.util.Log;
053: import com.caucho.webbeans.context.*;
054: import com.caucho.webbeans.component.*;
055:
056: import javax.ejb.*;
057: import javax.naming.Context;
058: import javax.naming.InitialContext;
059: import javax.naming.NamingException;
060: import javax.sql.DataSource;
061: import javax.transaction.UserTransaction;
062: import java.util.ArrayList;
063: import java.util.HashMap;
064: import java.util.logging.Logger;
065:
066: /**
067: * Base server for a single home/object bean pair.
068: */
069: abstract public class AbstractServer implements EnvironmentBean {
070: private final static Logger log = Log.open(AbstractServer.class);
071: private static final L10N L = new L10N(AbstractServer.class);
072:
073: protected final EjbContainer _ejbContainer;
074:
075: protected String _filename;
076: protected int _line;
077: protected String _location;
078:
079: protected String _id;
080: protected String _ejbName;
081: protected String _moduleName;
082: protected String _handleServerId;
083:
084: // name for IIOP, Hessian, JNDI
085: protected String _mappedName;
086:
087: private Context _jndiEnv;
088:
089: private ConfigProgram _serverProgram;
090:
091: protected HashMap<String, HandleEncoder> _protocolEncoderMap;
092: protected HandleEncoder _handleEncoder;
093:
094: protected DataSource _dataSource;
095:
096: protected EnvironmentClassLoader _loader;
097:
098: // The original bean implementation class
099: protected Class _ejbClass;
100:
101: // The class for the extended bean
102: protected Class _contextImplClass;
103:
104: protected Class _local21;
105: protected Class _remote21;
106:
107: protected Class _remoteHomeClass;
108: protected Class _remoteObjectClass;
109: protected ArrayList<Class> _remoteApiList = new ArrayList<Class>();
110: protected Class _primaryKeyClass;
111: protected Class _localHomeClass;
112: protected ArrayList<Class> _localApiList = new ArrayList<Class>();
113:
114: protected Class _remoteStubClass;
115: protected Class _homeStubClass;
116:
117: protected HomeHandle _homeHandle;
118: protected EJBHome _remoteHome;
119: protected EJBHome _remoteHomeView;
120: protected EJBLocalHome _localHome;
121: protected EJBMetaDataImpl _metaData;
122:
123: protected Class _serviceEndpointClass;
124:
125: protected long _transactionTimeout;
126:
127: protected ComponentImpl _component;
128:
129: private TimerService _timerService;
130:
131: protected ConfigProgram _initProgram;
132: protected ConfigProgram[] _initInject;
133:
134: private AroundInvokeConfig _aroundInvokeConfig;
135:
136: private PreDestroyConfig _preDestroyConfig;
137: private PostConstructConfig _postConstructConfig;
138:
139: private boolean _isContainerTransaction = true;
140:
141: private final Lifecycle _lifecycle = new Lifecycle();;
142:
143: /**
144: * Creates a new server container
145: *
146: * @param manager the owning server container
147: */
148: public AbstractServer(EjbContainer container) {
149: _ejbContainer = container;
150:
151: _loader = new EnvironmentClassLoader(container.getClassLoader());
152: }
153:
154: /**
155: * Returns the id, module-path#ejb-name.
156: */
157: public String getId() {
158: return _id;
159: }
160:
161: /**
162: * Sets the id, module-path#ejb-name.
163: */
164: public void setId(String id) {
165: _id = id;
166:
167: int p = id.lastIndexOf('/');
168: if (p > 0)
169: _loader.setId(getType() + id.substring(p + 1));
170: else
171: _loader.setId(getType() + id);
172: }
173:
174: public void setConfigLocation(String filename, int line) {
175: _filename = filename;
176: _line = line;
177: }
178:
179: public void setLocation(String location) {
180: _location = location;
181: }
182:
183: protected String getType() {
184: return "ejb:";
185: }
186:
187: public void setAroundInvoke(AroundInvokeConfig aroundInvoke) {
188: _aroundInvokeConfig = aroundInvoke;
189: }
190:
191: /**
192: * Sets the ejb name.
193: */
194: public void setEJBName(String ejbName) {
195: _ejbName = ejbName;
196: }
197:
198: /**
199: * Returns the ejb's name
200: */
201: public String getEJBName() {
202: return _ejbName;
203: }
204:
205: /**
206: * Set's the module that defined this ejb.
207: */
208: public void setModuleName(String moduleName) {
209: _moduleName = moduleName;
210: }
211:
212: /**
213: * Returns's the module that defined this ejb.
214: */
215: public String getModuleName() {
216: return _moduleName;
217: }
218:
219: /**
220: * Sets the mapped name, default is to use the EJBName. This is the name for
221: * both JNDI and the protocols such as IIOP and Hessian.
222: */
223: public void setMappedName(String mappedName) {
224: if (mappedName == null) {
225: _mappedName = null;
226: return;
227: }
228:
229: while (mappedName.startsWith("/"))
230: mappedName = mappedName.substring(1);
231:
232: while (mappedName.endsWith("/"))
233: mappedName = mappedName.substring(0,
234: mappedName.length() - 1);
235:
236: _mappedName = mappedName;
237: }
238:
239: /**
240: * Returns the mapped name.
241: */
242: public String getMappedName() {
243: return _mappedName == null ? getEJBName() : _mappedName;
244: }
245:
246: /**
247: * The name to use for remoting protocols, such as IIOP and Hessian.
248: */
249: public String getProtocolId() {
250: return "/" + getMappedName();
251: }
252:
253: /**
254: * The name to use for remoting protocols, such as IIOP and Hessian.
255: */
256: public String getProtocolId(Class cl) {
257: if (cl == null)
258: return getProtocolId();
259:
260: // XXX TCK: ejb30/bb/session/stateless/callback/defaultinterceptor/descriptor/defaultInterceptorsForCallbackBean1
261: if (cl.getName().startsWith("java."))
262: return getProtocolId();
263:
264: // Adds the suffix "#com_sun_ts_tests_ejb30_common_sessioncontext_Three1IF";
265: String url = getProtocolId() + "#"
266: + cl.getName().replace(".", "_");
267:
268: return url;
269: }
270:
271: /**
272: * Sets the ejb class
273: */
274: public void setEjbClass(Class cl) {
275: _ejbClass = cl;
276: }
277:
278: /**
279: * Sets the ejb class
280: */
281: protected Class getEjbClass() {
282: return _ejbClass;
283: }
284:
285: /**
286: * Sets the context implementation class.
287: */
288: public void setContextImplClass(Class cl) {
289: _contextImplClass = cl;
290: }
291:
292: /**
293: * Sets the remote home class.
294: */
295: public void setRemoteHomeClass(Class cl) {
296: _remoteHomeClass = cl;
297: }
298:
299: /**
300: * Gets the remote home class.
301: */
302: public Class getRemoteHomeClass() {
303: return _remoteHomeClass;
304: }
305:
306: /**
307: * Gets the 2.1 remote interface.
308: */
309: public Class getRemote21() {
310: return _remote21;
311: }
312:
313: /**
314: * Sets the remote object list.
315: */
316: public void setRemoteApiList(ArrayList<Class> list) {
317: _remoteApiList = new ArrayList<Class>(list);
318:
319: if (_remoteApiList.size() > 0)
320: _remoteObjectClass = _remoteApiList.get(0);
321: }
322:
323: /**
324: * Returns the remote object list.
325: */
326: public ArrayList<Class> getRemoteApiList() {
327: return _remoteApiList;
328: }
329:
330: /**
331: * Returns true if there is any remote object.
332: */
333: public boolean hasRemoteObject() {
334: if (_remoteApiList == null)
335: return false;
336:
337: if (_remoteApiList.size() == 0)
338: return false;
339:
340: return true;
341: }
342:
343: /**
344: * Sets the remote object class.
345: */
346: public void setRemoteObjectClass(Class cl) {
347: _remoteObjectClass = cl;
348:
349: if (_remoteApiList == null) {
350: _remoteApiList = new ArrayList<Class>();
351: _remoteApiList.add(cl);
352: }
353: }
354:
355: /**
356: * Gets the remote object class.
357: */
358: public Class getRemoteObjectClass() {
359: return _remoteObjectClass;
360: }
361:
362: /**
363: * Sets the local home class.
364: */
365: public void setLocalHomeClass(Class cl) {
366: _localHomeClass = cl;
367: }
368:
369: /**
370: * Gets the local home class.
371: */
372: public Class getLocalHomeClass() {
373: return _localHomeClass;
374: }
375:
376: /**
377: * Sets the service endpoint.
378: */
379: public void setServiceEndpoint(Class cl) {
380: _serviceEndpointClass = cl;
381: }
382:
383: /**
384: * Gets the service endpoint
385: */
386: public Class getServiceEndpoint() {
387: return _serviceEndpointClass;
388: }
389:
390: /**
391: * Sets the local api class list
392: */
393: public void setLocalApiList(ArrayList<Class> list) {
394: _localApiList = new ArrayList<Class>(list);
395: }
396:
397: /**
398: * Sets the remote object class.
399: */
400: public ArrayList<Class> getLocalApiList() {
401: return _localApiList;
402: }
403:
404: public HandleEncoder getHandleEncoder(String protocol) {
405: HandleEncoder encoder;
406:
407: if (_protocolEncoderMap != null) {
408: encoder = _protocolEncoderMap.get(protocol);
409:
410: if (encoder != null)
411: return encoder;
412: }
413:
414: try {
415: Class keyClass = getPrimaryKeyClass();
416:
417: encoder = _ejbContainer.getProtocolManager()
418: .createHandleEncoder(this , keyClass, protocol);
419: } catch (Exception e) {
420: throw EJBExceptionWrapper.createRuntime(e);
421: }
422:
423: if (_protocolEncoderMap == null)
424: _protocolEncoderMap = new HashMap<String, HandleEncoder>(8);
425:
426: _protocolEncoderMap.put(protocol, encoder);
427:
428: return encoder;
429: }
430:
431: /**
432: * Returns the encoded id.
433: */
434: public String encodeId(Object primaryKey) {
435: return String.valueOf(primaryKey);
436: }
437:
438: public HandleEncoder addHandleEncoder(String protocol,
439: String serverId) {
440: HandleEncoder encoder;
441:
442: if (_protocolEncoderMap != null) {
443: encoder = _protocolEncoderMap.get(protocol);
444:
445: if (encoder != null)
446: return encoder;
447: }
448:
449: try {
450: Class keyClass = getPrimaryKeyClass();
451:
452: encoder = new HandleEncoder(this , serverId + _ejbName);
453: } catch (Exception e) {
454: throw EJBExceptionWrapper.createRuntime(e);
455: }
456:
457: if (_protocolEncoderMap == null)
458: _protocolEncoderMap = new HashMap<String, HandleEncoder>(8);
459:
460: _protocolEncoderMap.put(protocol, encoder);
461:
462: return encoder;
463: }
464:
465: public HandleEncoder getHandleEncoder() {
466: return getHandleEncoder(EjbProtocolManager.getThreadProtocol());
467: }
468:
469: public void setHandleEncoder(HandleEncoder encoder) {
470: if (_homeHandle != null)
471: _homeHandle = null;
472:
473: _handleEncoder = encoder;
474: }
475:
476: public String getHandleServerId() {
477: if (_handleServerId == null)
478: _handleServerId = getHandleEncoder().getServerId();
479:
480: return _handleServerId;
481: }
482:
483: /**
484: * Looks up the JNDI object.
485: */
486: public Object lookup(String jndiName) {
487: try {
488: if (_jndiEnv == null)
489: _jndiEnv = (Context) new InitialContext()
490: .lookup("java:comp/env");
491:
492: // XXX: not tested
493: return _jndiEnv.lookup(jndiName);
494: } catch (NamingException e) {
495: throw new IllegalArgumentException(e);
496: }
497: }
498:
499: public UserTransaction getUserTransaction() {
500: return _ejbContainer.getTransactionManager()
501: .getUserTransaction();
502: }
503:
504: /**
505: * Returns the owning container.
506: */
507: public EjbContainer getEjbContainer() {
508: return _ejbContainer;
509: }
510:
511: /**
512: * Sets the server program.
513: */
514: public void setServerProgram(ConfigProgram serverProgram) {
515: _serverProgram = serverProgram;
516: }
517:
518: /**
519: * Sets the server program.
520: */
521: public ConfigProgram getServerProgram() {
522: return _serverProgram;
523: }
524:
525: /**
526: * Sets the transaction timeout.
527: */
528: public void setTransactionTimeout(long timeout) {
529: _transactionTimeout = timeout;
530: }
531:
532: /**
533: * Gets the transaction timeout.
534: */
535: public long getTransactionTimeout() {
536: return _transactionTimeout;
537: }
538:
539: /**
540: * Returns the timer service.
541: */
542: public TimerService getTimerService() {
543: // ejb/0fj0
544: if (_timerService == null) {
545: _timerService = EjbTimerService.getLocal(_ejbContainer
546: .getClassLoader(), getContext());
547: }
548:
549: return _timerService;
550: }
551:
552: /**
553: * Invalidates caches.
554: */
555: public void invalidateCache() {
556: }
557:
558: /**
559: * Remove an object.
560: */
561: public Object remove(AbstractHandle handle) {
562: throw new UnsupportedOperationException();
563: }
564:
565: /**
566: * Remove an object.
567: */
568: public void remove(Object primaryKey) {
569: throw new UnsupportedOperationException();
570: }
571:
572: /**
573: * Gets the class loader
574: */
575: public DynamicClassLoader getClassLoader() {
576: return _loader;
577: }
578:
579: /**
580: * Gets the generated skeleton class
581: */
582: public Class getBeanSkelClass() {
583: return _contextImplClass;
584: }
585:
586: public Class getRemoteStubClass() {
587: return _remoteStubClass;
588: }
589:
590: public Class getHomeStubClass() {
591: return _homeStubClass;
592: }
593:
594: /**
595: * Returns the meta data
596: */
597: public EJBMetaData getEJBMetaData() {
598: if (_metaData == null) {
599: try {
600: EJBHome home = getEJBHome();
601:
602: _metaData = new EJBMetaDataImpl(getEJBHome(),
603: getRemoteHomeClass(), getRemoteObjectClass(),
604: getPrimaryKeyClass());
605: } catch (RuntimeException e) {
606: throw e;
607: } catch (Exception e) {
608: throw new EJBException(e);
609: }
610:
611: if (this instanceof StatelessServer) {
612: _metaData.setSession(true);
613: _metaData.setStatelessSession(true);
614: } else if (this instanceof SessionServer) {
615: _metaData.setSession(true);
616: }
617: }
618:
619: return _metaData;
620: }
621:
622: /**
623: * Returns the home handle for the container
624: */
625: public HomeHandle getHomeHandle() {
626: if (_homeHandle == null)
627: _homeHandle = getHandleEncoder().createHomeHandle();
628:
629: return _homeHandle;
630: }
631:
632: void setEJBHome(EJBHome remoteHome) {
633: _remoteHome = remoteHome;
634: }
635:
636: /**
637: * Returns the EJBHome stub for the container
638: */
639: public EJBHome getEJBHome() {
640: if (_remoteHome != null)
641: return _remoteHome;
642: else {
643: EJBHome home = (EJBHome) getRemoteObject(
644: getRemoteHomeClass(), null);
645:
646: return home;
647: }
648: }
649:
650: /**
651: * Returns the EJBHome stub for the container
652: */
653: EJBHome getClientHome() {
654: return getEJBHome();
655: }
656:
657: /**
658: * Returns the session context.
659: */
660: public AbstractSessionContext getSessionContext() {
661: return null;
662: }
663:
664: /**
665: * Returns the EJBLocalHome stub for the container
666: */
667: public EJBLocalHome getEJBLocalHome() {
668: return _localHome;
669: }
670:
671: /**
672: * Returns the remote skeleton for the given API
673: *
674: * @param api the bean's api to return a value for
675: * @param protocol the remote protocol
676: */
677: abstract public Object getRemoteObject(Class api, String protocol);
678:
679: /**
680: * Returns the a new local stub for the given API
681: *
682: * @param api the bean's api to return a value for
683: */
684: abstract public Object getLocalObject(Class api);
685:
686: /**
687: * Returns the local jndi proxy for the given API
688: *
689: * @param api the bean's api to return a value for
690: */
691: abstract public Object getLocalProxy(Class api);
692:
693: /**
694: * Returns the object key from a handle.
695: */
696: public Class getPrimaryKeyClass() {
697: return _primaryKeyClass;
698: }
699:
700: public EJBObject getEJBObject(Object key) throws FinderException {
701: return getContext(key).getEJBObject();
702: }
703:
704: /**
705: * Returns the remote object.
706: */
707: public Object getRemoteObject(Object key) throws FinderException {
708: // XXX TCK: ejb30/.../remove
709: return getContext(key).createRemoteView();
710: }
711:
712: public AbstractContext getContext() {
713: return null;
714: }
715:
716: public AbstractContext getContext(Object key)
717: throws FinderException {
718: return getContext(key, true);
719: }
720:
721: public AbstractContext getContext(long key) throws FinderException {
722: return getContext(new Long(key));
723: }
724:
725: /**
726: * Returns the context with the given key
727: */
728: abstract public AbstractContext getContext(Object key,
729: boolean forceLoad) throws FinderException;
730:
731: /**
732: * Returns the currrent transaction context.
733: *
734: * @return the transaction context for the request
735: */
736: public EjbTransactionManager getTransactionManager() {
737: return _ejbContainer.getTransactionManager();
738: }
739:
740: /**
741: * Returns the currrent transaction context.
742: *
743: * @return the transaction context for the request
744: */
745: public TransactionContext getTransaction() {
746: return _ejbContainer.getTransactionManager()
747: .getTransactionContext();
748: }
749:
750: /**
751: * Sets the init program.
752: */
753: public void setInitProgram(ConfigProgram init) {
754: _initProgram = init;
755: }
756:
757: /**
758: * Gets the init program.
759: */
760: public ConfigProgram getInitProgram() {
761: return _initProgram;
762: }
763:
764: /**
765: * Initialize an instance
766: */
767: public void initInstance(Object instance) {
768: initInstance(instance, new ConfigContext());
769: }
770:
771: /**
772: * Initialize an instance
773: */
774: public void initInstance(Object instance, ConfigContext env) {
775: /*
776: if (scope != null)
777: scope.put(_component, scope);
778: */
779:
780: if (_initInject != null) {
781: Thread thread = Thread.currentThread();
782: ClassLoader oldLoader = thread.getContextClassLoader();
783:
784: try {
785: thread.setContextClassLoader(_loader);
786:
787: if (env == null)
788: env = new ConfigContext();
789:
790: for (ConfigProgram inject : _initInject)
791: inject.inject(instance, env);
792: } finally {
793: thread.setContextClassLoader(oldLoader);
794: }
795: }
796: }
797:
798: public void init() throws Exception {
799: _loader.init();
800: // _loader.setId("EnvironmentLoader[ejb:" + getId() + "]");
801: }
802:
803: public boolean start() throws Exception {
804: if (!_lifecycle.toActive())
805: return false;
806:
807: Thread thread = Thread.currentThread();
808: ClassLoader oldLoader = thread.getContextClassLoader();
809:
810: try {
811: thread.setContextClassLoader(_loader);
812:
813: _loader.start();
814:
815: bindContext();
816:
817: if (_serverProgram != null)
818: _serverProgram.configure(this );
819:
820: bindInjection();
821:
822: log.config(this + " active");
823: } finally {
824: thread.setContextClassLoader(oldLoader);
825: }
826:
827: return true;
828: }
829:
830: protected void bindContext() {
831:
832: }
833:
834: protected void bindInjection() {
835: // Injection binding occurs in the start phase
836:
837: ArrayList<ConfigProgram> injectList = new ArrayList<ConfigProgram>();
838: InjectIntrospector.introspectInject(injectList, getEjbClass());
839: // XXX: add inject from xml here
840:
841: if (_initProgram != null)
842: injectList.add(_initProgram);
843:
844: InjectIntrospector.introspectInit(injectList, getEjbClass());
845: // XXX: add init from xml here
846:
847: ConfigProgram[] injectArray = new ConfigProgram[injectList
848: .size()];
849: injectList.toArray(injectArray);
850:
851: if (injectArray.length > 0)
852: _initInject = injectArray;
853: }
854:
855: /**
856: * Returns true if container transaction is used.
857: */
858: public boolean isContainerTransaction() {
859: return _isContainerTransaction;
860: }
861:
862: /**
863: * Sets true if container transaction is used.
864: */
865: public void setContainerTransaction(boolean isContainerTransaction) {
866: _isContainerTransaction = isContainerTransaction;
867: }
868:
869: /**
870: * Returns true is there is a local home or local client object for the bean.
871: */
872: public boolean isLocal() {
873: return (_localHome != null || _localApiList != null
874: && _localApiList.size() > 0);
875: }
876:
877: /**
878: * Returns true is there is a remote home or remote client object
879: * for the bean.
880: */
881: public boolean isRemote() {
882: return _remoteHome != null || _remoteHomeView != null;
883: }
884:
885: /**
886: * Returns true if the server is dead.
887: */
888: public boolean isDead() {
889: return !_lifecycle.isActive();
890: }
891:
892: /**
893: * Cleans up the server on shutdown
894: */
895: public void destroy() {
896: _lifecycle.toDestroy();
897: }
898:
899: public PostConstructConfig getPostConstruct() {
900: return _postConstructConfig;
901: }
902:
903: public PreDestroyConfig getPreDestroy() {
904: return _preDestroyConfig;
905: }
906:
907: public void setPostConstruct(PostConstructConfig postConstruct) {
908: _postConstructConfig = postConstruct;
909: }
910:
911: public void setPreDestroy(PreDestroyConfig preDestroy) {
912: _preDestroyConfig = preDestroy;
913: }
914:
915: /**
916: * Client information for connecting to the server.
917: */
918: public void addClientRemoteConfig(StringBuilder sb) {
919: if (_remoteApiList != null && _remoteApiList.size() > 0) {
920: sb.append("<ejb-ref>\n");
921: sb.append("<ejb-ref-name>" + getEJBName()
922: + "</ejb-ref-name>\n");
923:
924: if (_remoteHomeClass != null)
925: sb.append("<home>" + _remoteHomeClass.getName()
926: + "</home>\n");
927:
928: sb.append("<remote>" + _remoteApiList.get(0).getName()
929: + "</remote>\n");
930: sb.append("</ejb-ref>\n");
931: }
932: }
933:
934: public ConfigException error(String msg) {
935: if (_filename != null)
936: throw new LineConfigException(_filename, _line, msg);
937: else
938: throw new ConfigException(msg);
939: }
940:
941: public String toString() {
942: if (getMappedName() != null)
943: return getClass().getSimpleName() + "[" + getEJBName()
944: + "," + getMappedName() + "]";
945: else
946: return getClass().getSimpleName() + "[" + getEJBName()
947: + "]";
948: }
949: }
|