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.message;
031:
032: import com.caucho.config.*;
033: import com.caucho.ejb.AbstractContext;
034: import com.caucho.ejb.AbstractServer;
035: import com.caucho.ejb.manager.EjbContainer;
036: import com.caucho.ejb.xa.*;
037: import com.caucho.jca.*;
038: import com.caucho.util.L10N;
039: import com.caucho.webbeans.component.*;
040: import com.caucho.webbeans.manager.*;
041:
042: import javax.ejb.MessageDrivenContext;
043: import javax.jms.*;
044: import javax.naming.*;
045: import javax.resource.spi.*;
046: import javax.resource.spi.endpoint.*;
047: import javax.transaction.*;
048: import javax.transaction.xa.*;
049: import javax.webbeans.*;
050: import java.lang.reflect.*;
051: import java.util.logging.Level;
052: import java.util.logging.Logger;
053:
054: /**
055: * JCA activation-spec server container for a message bean.
056: */
057: public class MessageServer extends AbstractServer implements
058: MessageEndpointFactory {
059: private static final L10N L = new L10N(MessageServer.class);
060: protected static final Logger log = Logger
061: .getLogger(MessageServer.class.getName());
062:
063: private ResourceAdapter _ra;
064: private ActivationSpec _activationSpec;
065:
066: private MessageDrivenContext _context;
067:
068: private Method _ejbCreate;
069:
070: public MessageServer(EjbContainer ejbContainer) {
071: super (ejbContainer);
072:
073: WebBeansContainer webBeans = WebBeansContainer.create();
074: UserTransaction ut = webBeans.getObject(UserTransaction.class);
075:
076: // ejb/0fbl
077: _context = new MessageDrivenContextImpl(this , ut);
078: }
079:
080: protected String getType() {
081: return "message:";
082: }
083:
084: /**
085: * Sets the activation spec
086: */
087: public void setActivationSpec(ActivationSpec activationSpec) {
088: _activationSpec = activationSpec;
089: }
090:
091: /**
092: * Sets the resource adapter
093: */
094: public void setResourceAdapter(ResourceAdapter ra) {
095: _ra = ra;
096: }
097:
098: /**
099: * Initialize the server
100: */
101: @Override
102: public void init() throws Exception {
103: Thread thread = Thread.currentThread();
104: ClassLoader oldLoader = thread.getContextClassLoader();
105:
106: try {
107: thread.setContextClassLoader(_loader);
108:
109: super .init();
110:
111: if (_activationSpec == null)
112: throw error(L
113: .l(
114: "ActivationSpec is missing from message-driven bean '{0}'.",
115: getEJBName()));
116:
117: if (_ra == null)
118: throw error(L
119: .l(
120: "ResourceAdapter is missing from message-driven bean '{0}'.",
121: getEJBName()));
122:
123: try {
124: Class beanClass = getBeanSkelClass();
125:
126: _ejbCreate = beanClass.getMethod("ejbCreate",
127: new Class[0]);
128: } catch (Exception e) {
129: log.log(Level.FINEST, e.toString(), e);
130: }
131: } finally {
132: thread.setContextClassLoader(oldLoader);
133: }
134: }
135:
136: @Override
137: protected void bindContext() {
138: WebBeansContainer webBeans = WebBeansContainer.create();
139:
140: webBeans.addSingleton(_context);
141: }
142:
143: /**
144: * Starts the server.
145: */
146: @Override
147: public boolean start() throws Exception {
148: if (!super .start())
149: return false;
150:
151: _ra.endpointActivation(this , _activationSpec);
152:
153: return true;
154: }
155:
156: /**
157: * Returns the message driven context
158: */
159: public MessageDrivenContext getMessageContext() {
160: return _context;
161: }
162:
163: void generate() throws Exception {
164: }
165:
166: @Override
167: public AbstractContext getContext(Object obj, boolean foo) {
168: throw new UnsupportedOperationException();
169: }
170:
171: /**
172: * Creates an endpoint with the associated XA resource.
173: */
174: public MessageEndpoint createEndpoint(XAResource xaResource)
175: throws UnavailableException {
176: try {
177: Object listener = createMessageListener();
178:
179: ((CauchoMessageEndpoint) listener)
180: .__caucho_setXAResource(xaResource);
181:
182: return (MessageEndpoint) listener;
183: } catch (RuntimeException e) {
184: throw e;
185: } catch (InvocationTargetException e) {
186: if (e.getCause() instanceof RuntimeException)
187: throw (RuntimeException) e.getCause();
188: if (e.getCause() != null)
189: throw new UnavailableException(e.getCause());
190: else
191: throw new UnavailableException(e);
192: } catch (Exception e) {
193: throw new RuntimeException(e);
194: }
195: }
196:
197: /**
198: * Returns true to find out whether message deliveries to the
199: * message endpoint will be transacted. This is only a hint.
200: */
201: public boolean isDeliveryTransacted(Method method)
202: throws NoSuchMethodException {
203: return false;
204: }
205:
206: private Object createMessageListener() throws Exception {
207: Thread thread = Thread.currentThread();
208: ClassLoader oldLoader = thread.getContextClassLoader();
209:
210: try {
211: thread.setContextClassLoader(getClassLoader());
212:
213: Class beanClass = getBeanSkelClass();
214:
215: Constructor ctor = beanClass
216: .getConstructor(new Class[] { MessageServer.class });
217:
218: Object listener = ctor.newInstance(this );
219:
220: initInstance(listener, new ConfigContext());
221:
222: if (_ejbCreate != null)
223: _ejbCreate.invoke(listener);
224:
225: return listener;
226: } finally {
227: thread.setContextClassLoader(oldLoader);
228: }
229: }
230:
231: /**
232: * Cleans up the entity server nicely.
233: */
234: @Override
235: public void destroy() {
236: _ra.endpointDeactivation(this , _activationSpec);
237: }
238:
239: @Override
240: public Object getRemoteObject(Class api, String protocol) {
241: return null;
242: }
243:
244: @Override
245: public Object getLocalObject(Class api) {
246: return null;
247: }
248:
249: @Override
250: public Object getLocalProxy(Class api) {
251: return null;
252: }
253: }
|