001: /*
002: * $Id: MuleResourceAdapter.java 11373 2008-03-15 05:03:10Z dfeist $
003: * --------------------------------------------------------------------------------------
004: * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
005: *
006: * The software in this package is published under the terms of the CPAL v1.0
007: * license, a copy of which has been included with this distribution in the
008: * LICENSE.txt file.
009: */
010:
011: package org.mule.module.jca;
012:
013: import org.mule.RegistryContext;
014: import org.mule.api.MuleContext;
015: import org.mule.api.MuleException;
016: import org.mule.api.config.ConfigurationBuilder;
017: import org.mule.api.context.MuleContextBuilder;
018: import org.mule.api.endpoint.EndpointBuilder;
019: import org.mule.api.endpoint.InboundEndpoint;
020: import org.mule.api.model.Model;
021: import org.mule.api.service.Service;
022: import org.mule.config.DefaultMuleConfiguration;
023: import org.mule.context.DefaultMuleContextBuilder;
024: import org.mule.context.DefaultMuleContextFactory;
025: import org.mule.endpoint.EndpointURIEndpointBuilder;
026: import org.mule.endpoint.URIBuilder;
027: import org.mule.util.ClassUtils;
028:
029: import java.io.IOException;
030: import java.io.ObjectInputStream;
031: import java.io.Serializable;
032: import java.util.HashMap;
033: import java.util.Map;
034:
035: import javax.resource.NotSupportedException;
036: import javax.resource.ResourceException;
037: import javax.resource.spi.ActivationSpec;
038: import javax.resource.spi.BootstrapContext;
039: import javax.resource.spi.ResourceAdapter;
040: import javax.resource.spi.ResourceAdapterInternalException;
041: import javax.resource.spi.endpoint.MessageEndpointFactory;
042: import javax.transaction.xa.XAResource;
043:
044: import org.apache.commons.logging.Log;
045: import org.apache.commons.logging.LogFactory;
046:
047: /**
048: * <code>MuleResourceAdapter</code> TODO
049: */
050: public class MuleResourceAdapter implements ResourceAdapter,
051: Serializable {
052: /**
053: * Serial version
054: */
055: private static final long serialVersionUID = 5727648958127416509L;
056:
057: /**
058: * logger used by this class
059: */
060: protected transient Log logger = LogFactory.getLog(this .getClass());
061:
062: protected transient MuleContext muleContext;
063:
064: protected transient BootstrapContext bootstrapContext;
065: protected MuleConnectionRequestInfo info = new MuleConnectionRequestInfo();
066: protected final Map endpoints = new HashMap();
067: protected String defaultJcaModelName;
068:
069: public MuleResourceAdapter() {
070: RegistryContext.getOrCreateRegistry();
071: }
072:
073: private void readObject(ObjectInputStream ois)
074: throws ClassNotFoundException, IOException {
075: ois.defaultReadObject();
076: this .logger = LogFactory.getLog(this .getClass());
077: }
078:
079: /**
080: * @see javax.resource.spi.ResourceAdapter#start(javax.resource.spi.BootstrapContext)
081: */
082: public void start(BootstrapContext bootstrapContext)
083: throws ResourceAdapterInternalException {
084: this .bootstrapContext = bootstrapContext;
085:
086: if (info.getConfigurations() != null) {
087: ConfigurationBuilder configBuilder = null;
088: try {
089: configBuilder = (ConfigurationBuilder) ClassUtils
090: .instanciateClass(
091: info.getConfigurationBuilder(),
092: new Object[] { info.getConfigurations() });
093: } catch (Exception e) {
094: throw new ResourceAdapterInternalException(
095: "Failed to instanciate configurationBuilder class: "
096: + info.getConfigurationBuilder(), e);
097: }
098:
099: try {
100: logger.info("Initializing Mule...");
101:
102: MuleContextBuilder contextBuilder = new DefaultMuleContextBuilder();
103: DefaultMuleConfiguration config = new DefaultMuleConfiguration();
104: config.setSystemModelType(JcaModel.JCA_MODEL_TYPE);
105: contextBuilder.setMuleConfiguration(config);
106: muleContext = new DefaultMuleContextFactory()
107: .createMuleContext(configBuilder,
108: contextBuilder);
109: } catch (MuleException e) {
110: logger.error(e);
111: throw new ResourceAdapterInternalException(
112: "Failed to load configurations: "
113: + info.getConfigurations(), e);
114: }
115: try {
116: logger.info("Starting Mule...");
117: muleContext.start();
118: } catch (MuleException e) {
119: logger.error(e);
120: throw new ResourceAdapterInternalException(
121: "Failed to start management context", e);
122: }
123: }
124: }
125:
126: /**
127: * @see javax.resource.spi.ResourceAdapter#stop()
128: */
129: public void stop() {
130: logger.info("Stopping Mule...");
131: muleContext.dispose();
132: muleContext = null;
133: bootstrapContext = null;
134: }
135:
136: /**
137: * @return the bootstrap context for this adapter
138: */
139: public BootstrapContext getBootstrapContext() {
140: return bootstrapContext;
141: }
142:
143: /**
144: * @see javax.resource.spi.ResourceAdapter#endpointActivation(javax.resource.spi.endpoint.MessageEndpointFactory,
145: * javax.resource.spi.ActivationSpec)
146: */
147: public void endpointActivation(
148: MessageEndpointFactory endpointFactory,
149: ActivationSpec activationSpec) throws ResourceException {
150: if (activationSpec.getResourceAdapter() != this ) {
151: throw new ResourceException(
152: "ActivationSpec not initialized with this ResourceAdapter instance");
153: }
154:
155: if (activationSpec.getClass().equals(MuleActivationSpec.class)) {
156: MuleActivationSpec muleActivationSpec = (MuleActivationSpec) activationSpec;
157: try {
158: // Resolve modelName
159: String modelName = resolveModelName(muleActivationSpec);
160:
161: // Lookup/create JCA Model
162: JcaModel model = getJcaModel(modelName);
163:
164: // Create Endpoint
165: InboundEndpoint endpoint = createMessageInflowEndpoint(muleActivationSpec);
166:
167: // Create Service
168: Service service = createJcaService(endpointFactory,
169: model, endpoint);
170:
171: // Keep reference to JcaService descriptor for endpointDeactivation
172: MuleEndpointKey key = new MuleEndpointKey(
173: endpointFactory, muleActivationSpec);
174: endpoints.put(key, service);
175: } catch (Exception e) {
176: logger.error(e.getMessage(), e);
177: }
178: } else {
179: throw new NotSupportedException(
180: "That type of ActicationSpec not supported: "
181: + activationSpec.getClass());
182: }
183:
184: }
185:
186: /**
187: * @see javax.resource.spi.ResourceAdapter#endpointDeactivation(javax.resource.spi.endpoint.MessageEndpointFactory,
188: * javax.resource.spi.ActivationSpec)
189: */
190: public void endpointDeactivation(
191: MessageEndpointFactory endpointFactory,
192: ActivationSpec activationSpec) {
193:
194: if (activationSpec.getClass().equals(MuleActivationSpec.class)) {
195: MuleActivationSpec muleActivationSpec = (MuleActivationSpec) activationSpec;
196: MuleEndpointKey key = new MuleEndpointKey(endpointFactory,
197: (MuleActivationSpec) activationSpec);
198: Service service = (Service) endpoints.remove(key);
199: if (service == null) {
200: logger.warn("No endpoint was registered with key: "
201: + key);
202: return;
203: }
204:
205: // Resolve modelName
206: String modelName = null;
207: try {
208: modelName = resolveModelName(muleActivationSpec);
209: } catch (ResourceException e) {
210: logger.error(e.getMessage(), e);
211: }
212:
213: try {
214: muleContext.getRegistry().unregisterService(
215: service.getName());
216: } catch (MuleException e) {
217: logger.error(e.getMessage(), e);
218: }
219: }
220: }
221:
222: protected String resolveModelName(MuleActivationSpec activationSpec)
223: throws ResourceException {
224: // JCA specification mentions activationSpec properties inheriting
225: // resourceAdaptor properties, but this doesn't seem to work, at
226: // least with JBOSS, so do it manually.
227: String modelName = activationSpec.getModelName();
228: if (modelName == null) {
229: modelName = defaultJcaModelName;
230: }
231: if (modelName == null) {
232: throw new ResourceException(
233: "The 'modelName' property has not been configured for either the MuleResourceAdaptor or MuleActicationSpec.");
234: }
235: return modelName;
236: }
237:
238: protected JcaModel getJcaModel(String modelName)
239: throws MuleException, ResourceException {
240: Model model = muleContext.getRegistry().lookupModel(modelName);
241: if (model != null) {
242: if (model instanceof JcaModel) {
243: return (JcaModel) model;
244: } else {
245: throw new ResourceException("Model:-" + modelName
246: + " is not compatible with JCA type");
247: }
248: } else {
249: JcaModel jcaModel = new JcaModel();
250: jcaModel.setName(modelName);
251: muleContext.getRegistry().registerModel(jcaModel);
252: return jcaModel;
253: }
254: }
255:
256: protected Service createJcaService(
257: MessageEndpointFactory endpointFactory, JcaModel model,
258: InboundEndpoint endpoint) throws MuleException {
259: String name = "JcaService#" + endpointFactory.hashCode();
260: Service service = new JcaService();
261: service.setName(name);
262: service.getInboundRouter().addEndpoint(endpoint);
263:
264: // Set endpointFactory rather than endpoint here, so we can obtain a
265: // new endpoint instance from factory for each incoming message in
266: // JcaComponet as reccomended by JCA specification
267: service.setComponent(new JcaComponent(endpointFactory, model
268: .getEntryPointResolverSet(), service,
269: new DelegateWorkManager(bootstrapContext
270: .getWorkManager())));
271: service.setModel(model);
272: muleContext.getRegistry().registerService(service);
273: return service;
274: }
275:
276: protected InboundEndpoint createMessageInflowEndpoint(
277: MuleActivationSpec muleActivationSpec) throws MuleException {
278: EndpointBuilder endpointBuilder = new EndpointURIEndpointBuilder(
279: new URIBuilder(muleActivationSpec.getEndpoint()),
280: muleContext);
281:
282: // Use asynchronous endpoint as we need to dispatch to service
283: // rather than send.
284: endpointBuilder.setSynchronous(false);
285:
286: return muleContext.getRegistry().lookupEndpointFactory()
287: .getInboundEndpoint(endpointBuilder);
288: }
289:
290: /**
291: * We only connect to one resource manager per ResourceAdapter instance, so any ActivationSpec will return
292: * the same XAResource.
293: *
294: * @see javax.resource.spi.ResourceAdapter#getXAResources(javax.resource.spi.ActivationSpec[])
295: */
296: public XAResource[] getXAResources(ActivationSpec[] activationSpecs)
297: throws ResourceException {
298: return new XAResource[] {};
299: }
300:
301: /**
302: * @return
303: */
304: public String getPassword() {
305: return info.getPassword();
306: }
307:
308: /**
309: * @return
310: */
311: public String getConfigurations() {
312: return info.getConfigurations();
313: }
314:
315: /**
316: * @return
317: */
318: public String getUserName() {
319: return info.getUserName();
320: }
321:
322: /**
323: * @param password
324: */
325: public void setPassword(String password) {
326: info.setPassword(password);
327: }
328:
329: /**
330: * @param configurations
331: */
332: public void setConfigurations(String configurations) {
333: info.setConfigurations(configurations);
334: }
335:
336: /**
337: * @param userid
338: */
339: public void setUserName(String userid) {
340: info.setUserName(userid);
341: }
342:
343: public String getConfigurationBuilder() {
344: return info.getConfigurationBuilder();
345: }
346:
347: public void setConfigurationBuilder(String configbuilder) {
348: info.setConfigurationBuilder(configbuilder);
349: }
350:
351: /**
352: * @return Returns the info.
353: */
354: public MuleConnectionRequestInfo getInfo() {
355: return info;
356: }
357:
358: public boolean equals(Object o) {
359: if (this == o) {
360: return true;
361: }
362: if (!(o instanceof MuleResourceAdapter)) {
363: return false;
364: }
365:
366: final MuleResourceAdapter muleResourceAdapter = (MuleResourceAdapter) o;
367:
368: if (info != null ? !info.equals(muleResourceAdapter.info)
369: : muleResourceAdapter.info != null) {
370: return false;
371: }
372:
373: return true;
374: }
375:
376: public int hashCode() {
377: return (info != null ? info.hashCode() : 0);
378: }
379:
380: public String getModelName() {
381: return defaultJcaModelName;
382: }
383:
384: public void setModelName(String modelName) {
385: this.defaultJcaModelName = modelName;
386: }
387:
388: }
|