001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ejb3.mdb.inflow;
023:
024: import java.lang.reflect.InvocationHandler;
025: import java.lang.reflect.Method;
026: import java.util.Collection;
027: import java.util.HashMap;
028:
029: import javax.ejb.TransactionManagementType;
030: import javax.ejb.TransactionAttribute;
031: import javax.ejb.TransactionAttributeType;
032: import javax.management.ObjectName;
033: import javax.management.MBeanServer;
034: import javax.management.MalformedObjectNameException;
035: import javax.resource.spi.ActivationSpec;
036: import javax.resource.spi.UnavailableException;
037: import javax.resource.spi.endpoint.MessageEndpoint;
038: import javax.resource.spi.endpoint.MessageEndpointFactory;
039: import javax.transaction.xa.XAResource;
040:
041: import org.jboss.deployment.DeploymentException;
042: import org.jboss.ejb3.Container;
043: import org.jboss.ejb3.KernelAbstractionFactory;
044: import org.jboss.ejb3.tx.TxUtil;
045: import org.jboss.ejb3.mdb.MessagingContainer;
046: import org.jboss.mx.util.JMXExceptionDecoder;
047: import org.jboss.logging.Logger;
048:
049: import EDU.oswego.cs.dl.util.concurrent.SynchronizedInt;
050:
051: /**
052: * EJBProxyFactory for inflow message driven beans
053: *
054: * @version <tt>$Revision: 60233 $</tt>
055: * @author <a href="mailto:bdecoste@jboss.com">William DeCoste</a>
056: * @author <a href="mailto:bill@jboss.com">Bill Burke</a>
057: */
058: public class JBossMessageEndpointFactory implements
059: MessageEndpointFactory {
060: private static final Logger log = Logger
061: .getLogger(JBossMessageEndpointFactory.class);
062:
063: /** Whether trace is enabled */
064: protected boolean trace = log.isTraceEnabled();
065:
066: /** Our container */
067: protected MessagingContainer container;
068:
069: /** The activation properties */
070: protected HashMap properties = new HashMap();
071:
072: /** The messaging type class */
073: protected Class messagingTypeClass;
074:
075: /** The resource adapter name */
076: protected String resourceAdapterName;
077:
078: protected ObjectName resourceAdapterObjectName;
079:
080: /** The activation spec */
081: protected ActivationSpec activationSpec;
082:
083: /** The interfaces */
084: protected Class[] interfaces;
085:
086: /** The next proxy id */
087: protected SynchronizedInt nextProxyId = new SynchronizedInt(0);
088:
089: // Static --------------------------------------------------------
090:
091: /** The signature for createActivationSpec */
092: protected String[] createActivationSpecSig = new String[] {
093: Class.class.getName(), Collection.class.getName() };
094:
095: /** The signature for activate/deactivateEndpint */
096: protected String[] activationSig = new String[] {
097: MessageEndpointFactory.class.getName(),
098: ActivationSpec.class.getName() };
099:
100: // Constructors --------------------------------------------------
101:
102: public JBossMessageEndpointFactory() {
103: }
104:
105: // Public --------------------------------------------------------
106:
107: /**
108: * Get the message driven container
109: *
110: * @return the container
111: */
112: public MessagingContainer getContainer() {
113: return container;
114: }
115:
116: // MessageEndpointFactory implementation -------------------------
117:
118: public MessageEndpoint createEndpoint(XAResource resource)
119: throws UnavailableException {
120: trace = log.isTraceEnabled();
121:
122: if (trace)
123: log.trace("createEndpoint " + this + " xaResource="
124: + resource);
125:
126: MessageEndpoint endpoint = createProxy(resource);
127:
128: if (trace)
129: log.trace("Created endpoint " + endpoint + " from " + this );
130:
131: return endpoint;
132: }
133:
134: protected MessageEndpoint createProxy(XAResource resource) {
135: try {
136: Class proxyClass = java.lang.reflect.Proxy.getProxyClass(
137: container.getBeanClass().getClassLoader(),
138: interfaces);
139:
140: final Class[] constructorParams = { InvocationHandler.class };
141: java.lang.reflect.Constructor proxyConstructor = proxyClass
142: .getConstructor(constructorParams);
143:
144: MessageInflowLocalProxy proxy = new MessageInflowLocalProxy(
145: container);
146: proxy.setXaResource(resource);
147: proxy.setMessageEndpointFactory(this );
148:
149: Object[] args = { proxy };
150: MessageEndpoint endpoint = (MessageEndpoint) proxyConstructor
151: .newInstance(args);
152: return endpoint;
153:
154: } catch (Exception e) {
155: e.printStackTrace();
156: return null;
157: }
158: }
159:
160: public boolean isDeliveryTransacted(Method method)
161: throws NoSuchMethodException {
162: TransactionManagementType mtype = TxUtil
163: .getTransactionManagementType(container);
164: if (mtype == javax.ejb.TransactionManagementType.BEAN)
165: return false;
166:
167: TransactionAttribute attr = (TransactionAttribute) container
168: .resolveAnnotation(method, TransactionAttribute.class);
169: if (attr == null) {
170: attr = (TransactionAttribute) container
171: .resolveAnnotation(TransactionAttribute.class);
172: }
173: TransactionAttributeType type = TransactionAttributeType.REQUIRED;
174: if (attr != null)
175: type = attr.value();
176: return type == javax.ejb.TransactionAttributeType.REQUIRED;
177: }
178:
179: // ServiceMBeanSupport overrides ---------------------------------
180:
181: public void start() throws Exception {
182: // Resolve the message listener
183: resolveMessageListener();
184: resolveResourceAdapterName();
185: // Resolve the resource adapter
186: resolveResourceAdapter();
187: // Create the activation config
188: createActivationSpec();
189: // Set up proxy parameters
190: // Set the interfaces
191: interfaces = new Class[] { MessageEndpoint.class,
192: messagingTypeClass };
193: // Activate
194: activate();
195: }
196:
197: public void stop() throws Exception {
198: // Deactivate
199: deactivate();
200: }
201:
202: // ContainerService implementation -------------------------------
203:
204: /**
205: * Set the container for which this is an invoker to.
206: *
207: * @param container The container for which this is an invoker to.
208: */
209: public void setContainer(final Container container) {
210: this .container = (MessagingContainer) container;
211: }
212:
213: // Object overrides ----------------------------------------------
214:
215: /**
216: * Return a string representation of the current config state.
217: */
218: public String toString() {
219: StringBuffer buffer = new StringBuffer(100);
220: buffer.append(super .toString());
221: buffer.append("{ resourceAdapter=").append(resourceAdapterName);
222: buffer.append(", messagingType=").append(
223: container.getMessagingType());
224: buffer.append(", ejbName=").append(container.getEjbName());
225: buffer.append(", activationConfig=")
226: .append(properties.values());
227: buffer.append(", activationSpec=").append(activationSpec);
228: buffer.append("}");
229: return buffer.toString();
230: }
231:
232: // Protected -----------------------------------------------------
233:
234: /**
235: * Resolve message listener class
236: *
237: * @throws DeploymentException for any error
238: */
239: protected void resolveMessageListener() throws DeploymentException {
240: messagingTypeClass = container.getMessagingType();
241: }
242:
243: /**
244: * Resolve the resource adapter name
245: *
246: * @return the resource adapter name
247: * @throws DeploymentException for any error
248: */
249: protected void resolveResourceAdapterName()
250: throws DeploymentException {
251: resourceAdapterName = container.getResourceAdaptorName();
252: }
253:
254: protected void resolveResourceAdapter() {
255: try {
256: resourceAdapterObjectName = new ObjectName(
257: "jboss.jca:service=RARDeployment,name='"
258: + resourceAdapterName + "'");
259: // todo register with kernel and push dependencies to kernel
260: } catch (MalformedObjectNameException e) {
261: throw new RuntimeException(e);
262: }
263: }
264:
265: /**
266: * Create the activation spec
267: *
268: * @throws DeploymentException for any error
269: */
270: protected void createActivationSpec() throws DeploymentException {
271: properties = new HashMap(container
272: .getActivationConfigProperties());
273:
274: Object[] params = new Object[] { messagingTypeClass,
275: properties.values() };
276:
277: try {
278: activationSpec = (ActivationSpec) KernelAbstractionFactory
279: .getInstance().invoke(resourceAdapterObjectName,
280: "createActivationSpec", params,
281: createActivationSpecSig);
282: } catch (Throwable t) {
283: t = JMXExceptionDecoder.decode(t);
284: DeploymentException
285: .rethrowAsDeploymentException(
286: "Unable to create activation spec ra="
287: + resourceAdapterObjectName
288: + " messaging-type="
289: + messagingTypeClass.getName()
290: + " properties="
291: + container
292: .getActivationConfigProperties(),
293: t);
294: }
295: }
296:
297: /**
298: * Activate
299: *
300: * @throws DeploymentException for any error
301: */
302: protected void activate() throws DeploymentException {
303: Object[] params = new Object[] { this , activationSpec };
304: try {
305: KernelAbstractionFactory.getInstance().invoke(
306: resourceAdapterObjectName, "endpointActivation",
307: params, activationSig);
308: } catch (Throwable t) {
309: t = JMXExceptionDecoder.decode(t);
310: DeploymentException.rethrowAsDeploymentException(
311: "Endpoint activation failed ra="
312: + resourceAdapterObjectName
313: + " activationSpec=" + activationSpec, t);
314: }
315: }
316:
317: /**
318: * Deactivate
319: */
320: protected void deactivate() {
321: Object[] params = new Object[] { this , activationSpec };
322: try {
323: KernelAbstractionFactory.getInstance().invoke(
324: resourceAdapterObjectName, "endpointDeactivation",
325: params, activationSig);
326: } catch (Throwable t) {
327: t = JMXExceptionDecoder.decode(t);
328: log.warn("Endpoint activation failed ra="
329: + resourceAdapterObjectName + " activationSpec="
330: + activationSpec, t);
331: }
332: }
333: }
|