001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.geronimo.connector.deployment;
018
019 import java.beans.Introspector;
020 import java.beans.PropertyEditor;
021 import java.io.File;
022 import java.io.IOException;
023 import java.lang.reflect.Method;
024 import java.net.URI;
025 import java.net.URL;
026 import java.util.ArrayList;
027 import java.util.Collection;
028 import java.util.Date;
029 import java.util.Enumeration;
030 import java.util.HashMap;
031 import java.util.HashSet;
032 import java.util.LinkedHashMap;
033 import java.util.List;
034 import java.util.Map;
035 import java.util.Set;
036 import java.util.TreeMap;
037 import java.util.Collections;
038 import java.util.jar.JarFile;
039 import java.util.zip.ZipEntry;
040
041 import javax.xml.namespace.QName;
042
043 import org.apache.commons.logging.Log;
044 import org.apache.commons.logging.LogFactory;
045 import org.apache.geronimo.common.DeploymentException;
046 import org.apache.geronimo.common.propertyeditor.PropertyEditors;
047 import org.apache.geronimo.connector.ActivationSpecWrapperGBean;
048 import org.apache.geronimo.connector.AdminObjectWrapper;
049 import org.apache.geronimo.connector.AdminObjectWrapperGBean;
050 import org.apache.geronimo.connector.JCAResourceImplGBean;
051 import org.apache.geronimo.connector.ResourceAdapterImplGBean;
052 import org.apache.geronimo.connector.ResourceAdapterModuleImplGBean;
053 import org.apache.geronimo.connector.ResourceAdapterWrapperGBean;
054 import org.apache.geronimo.connector.outbound.JCAConnectionFactoryImplGBean;
055 import org.apache.geronimo.connector.outbound.ManagedConnectionFactoryWrapper;
056 import org.apache.geronimo.connector.outbound.ManagedConnectionFactoryWrapperGBean;
057 import org.apache.geronimo.connector.outbound.connectionmanagerconfig.LocalTransactions;
058 import org.apache.geronimo.connector.outbound.connectionmanagerconfig.NoPool;
059 import org.apache.geronimo.connector.outbound.connectionmanagerconfig.NoTransactions;
060 import org.apache.geronimo.connector.outbound.connectionmanagerconfig.PartitionedPool;
061 import org.apache.geronimo.connector.outbound.connectionmanagerconfig.PoolingSupport;
062 import org.apache.geronimo.connector.outbound.connectionmanagerconfig.SinglePool;
063 import org.apache.geronimo.connector.outbound.connectionmanagerconfig.TransactionLog;
064 import org.apache.geronimo.connector.outbound.connectionmanagerconfig.TransactionSupport;
065 import org.apache.geronimo.connector.outbound.connectionmanagerconfig.XATransactions;
066 import org.apache.geronimo.deployment.ModuleIDBuilder;
067 import org.apache.geronimo.deployment.NamespaceDrivenBuilder;
068 import org.apache.geronimo.deployment.NamespaceDrivenBuilderCollection;
069 import org.apache.geronimo.deployment.service.EnvironmentBuilder;
070 import org.apache.geronimo.deployment.service.GBeanBuilder;
071 import org.apache.geronimo.deployment.util.DeploymentUtil;
072 import org.apache.geronimo.deployment.xbeans.EnvironmentType;
073 import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
074 import org.apache.geronimo.gbean.AbstractName;
075 import org.apache.geronimo.gbean.AbstractNameQuery;
076 import org.apache.geronimo.gbean.DynamicGAttributeInfo;
077 import org.apache.geronimo.gbean.GAttributeInfo;
078 import org.apache.geronimo.gbean.GBeanData;
079 import org.apache.geronimo.gbean.GBeanInfo;
080 import org.apache.geronimo.gbean.GBeanInfoBuilder;
081 import org.apache.geronimo.gbean.InvalidConfigurationException;
082 import org.apache.geronimo.gbean.GBeanLifecycle;
083 import org.apache.geronimo.j2ee.deployment.ActivationSpecInfoLocator;
084 import org.apache.geronimo.j2ee.deployment.ConnectorModule;
085 import org.apache.geronimo.j2ee.deployment.EARContext;
086 import org.apache.geronimo.j2ee.deployment.Module;
087 import org.apache.geronimo.j2ee.deployment.ModuleBuilder;
088 import org.apache.geronimo.j2ee.deployment.annotation.AnnotatedApp;
089 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
090 import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
091 import org.apache.geronimo.kernel.GBeanNotFoundException;
092 import org.apache.geronimo.kernel.Naming;
093 import org.apache.geronimo.kernel.config.Configuration;
094 import org.apache.geronimo.kernel.config.ConfigurationStore;
095 import org.apache.geronimo.kernel.repository.Environment;
096 import org.apache.geronimo.management.JCAConnectionFactory;
097 import org.apache.geronimo.management.geronimo.JCAAdminObject;
098 import org.apache.geronimo.management.geronimo.JCAResourceAdapter;
099 import org.apache.geronimo.management.geronimo.ResourceAdapterModule;
100 import org.apache.geronimo.naming.deployment.ENCConfigBuilder;
101 import org.apache.geronimo.schema.SchemaConversionUtils;
102 import org.apache.geronimo.xbeans.geronimo.GerAdminobjectInstanceType;
103 import org.apache.geronimo.xbeans.geronimo.GerAdminobjectType;
104 import org.apache.geronimo.xbeans.geronimo.GerConfigPropertySettingType;
105 import org.apache.geronimo.xbeans.geronimo.GerConnectionDefinitionType;
106 import org.apache.geronimo.xbeans.geronimo.GerConnectiondefinitionInstanceType;
107 import org.apache.geronimo.xbeans.geronimo.GerConnectionmanagerType;
108 import org.apache.geronimo.xbeans.geronimo.GerConnectorDocument;
109 import org.apache.geronimo.xbeans.geronimo.GerConnectorType;
110 import org.apache.geronimo.xbeans.geronimo.GerPartitionedpoolType;
111 import org.apache.geronimo.xbeans.geronimo.GerResourceadapterInstanceType;
112 import org.apache.geronimo.xbeans.geronimo.GerResourceadapterType;
113 import org.apache.geronimo.xbeans.geronimo.GerSinglepoolType;
114 import org.apache.geronimo.xbeans.j2ee.ActivationspecType;
115 import org.apache.geronimo.xbeans.j2ee.AdminobjectType;
116 import org.apache.geronimo.xbeans.j2ee.ConfigPropertyType;
117 import org.apache.geronimo.xbeans.j2ee.ConnectionDefinitionType;
118 import org.apache.geronimo.xbeans.j2ee.ConnectorDocument;
119 import org.apache.geronimo.xbeans.j2ee.ConnectorType;
120 import org.apache.geronimo.xbeans.j2ee.MessagelistenerType;
121 import org.apache.geronimo.xbeans.j2ee.ResourceadapterType;
122 import org.apache.xmlbeans.XmlCursor;
123 import org.apache.xmlbeans.XmlDocumentProperties;
124 import org.apache.xmlbeans.XmlException;
125 import org.apache.xmlbeans.XmlObject;
126
127 /**
128 * @version $Rev:385659 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
129 */
130 public class ConnectorModuleBuilder implements ModuleBuilder, ActivationSpecInfoLocator, GBeanLifecycle {
131 private final static Log log = LogFactory.getLog(ConnectorModuleBuilder.class);
132
133 private static final QName RESOURCE_ADAPTER_VERSION = new QName(SchemaConversionUtils.J2EE_NAMESPACE, "resourceadapter-version");
134 private static QName CONNECTOR_QNAME = GerConnectorDocument.type.getDocumentElementName();
135 static final String GERCONNECTOR_NAMESPACE = CONNECTOR_QNAME.getNamespaceURI();
136 private static final Map<String, String> NAMESPACE_UPDATES = new HashMap<String, String>();
137 static {
138 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/connector", "http://geronimo.apache.org/xml/ns/j2ee/connector-1.2");
139 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/connector-1.1", "http://geronimo.apache.org/xml/ns/j2ee/connector-1.2");
140 }
141
142 private static final Map<String, Class> TYPE_LOOKUP = new HashMap<String, Class>();
143 static {
144 TYPE_LOOKUP.put("byte", Byte.class);
145 TYPE_LOOKUP.put(Byte.class.getName(), Byte.class);
146 TYPE_LOOKUP.put("int", Integer.class);
147 TYPE_LOOKUP.put(Integer.class.getName(), Integer.class);
148 TYPE_LOOKUP.put("short", Short.class);
149 TYPE_LOOKUP.put(Short.class.getName(), Short.class);
150 TYPE_LOOKUP.put("long", Long.class);
151 TYPE_LOOKUP.put(Long.class.getName(), Long.class);
152 TYPE_LOOKUP.put("float", Float.class);
153 TYPE_LOOKUP.put(Float.class.getName(), Float.class);
154 TYPE_LOOKUP.put("double", Double.class);
155 TYPE_LOOKUP.put(Double.class.getName(), Double.class);
156 TYPE_LOOKUP.put("boolean", Boolean.class);
157 TYPE_LOOKUP.put(Boolean.class.getName(), Boolean.class);
158 TYPE_LOOKUP.put("char", Character.class);
159 TYPE_LOOKUP.put(Character.class.getName(), Character.class);
160 TYPE_LOOKUP.put(String.class.getName(), String.class);
161 }
162
163 private final int defaultMaxSize;
164 private final int defaultMinSize;
165 private final int defaultBlockingTimeoutMilliseconds;
166 private final int defaultIdleTimeoutMinutes;
167 private final boolean defaultXATransactionCaching;
168 private final boolean defaultXAThreadCaching;
169 private final Environment defaultEnvironment;
170 private final NamespaceDrivenBuilderCollection serviceBuilders;
171 private final String defaultWorkManagerName;
172
173 public ConnectorModuleBuilder(Environment defaultEnvironment,
174 int defaultMaxSize,
175 int defaultMinSize,
176 int defaultBlockingTimeoutMilliseconds,
177 int defaultIdleTimeoutMinutes,
178 boolean defaultXATransactionCaching,
179 boolean defaultXAThreadCaching,
180 String defaultWorkManagerName,
181 Collection serviceBuilders) {
182 this.defaultEnvironment = defaultEnvironment;
183
184 this.defaultMaxSize = defaultMaxSize;
185 this.defaultMinSize = defaultMinSize;
186 this.defaultBlockingTimeoutMilliseconds = defaultBlockingTimeoutMilliseconds;
187 this.defaultIdleTimeoutMinutes = defaultIdleTimeoutMinutes;
188 this.defaultXATransactionCaching = defaultXATransactionCaching;
189 this.defaultXAThreadCaching = defaultXAThreadCaching;
190 this.defaultWorkManagerName = defaultWorkManagerName;
191 this.serviceBuilders = new NamespaceDrivenBuilderCollection(serviceBuilders, GBeanBuilder.SERVICE_QNAME);
192 }
193
194 public void doStart() throws Exception {
195 XmlBeansUtil.registerNamespaceUpdates(NAMESPACE_UPDATES);
196 }
197
198 public void doStop() {
199 XmlBeansUtil.unregisterNamespaceUpdates(NAMESPACE_UPDATES);
200 }
201
202 public void doFail() {
203 doStop();
204 }
205
206 public Module createModule(File plan, JarFile moduleFile, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
207 return createModule(plan, moduleFile, "rar", null, null, null, naming, idBuilder);
208 }
209
210 public Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, Environment environment, Object moduleContextInfo, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
211 return createModule(plan, moduleFile, targetPath, specDDUrl, environment, earName, naming, idBuilder);
212 }
213
214 private Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, Environment earEnvironment, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
215 assert moduleFile != null : "moduleFile is null";
216 assert targetPath != null : "targetPath is null";
217 assert !targetPath.endsWith("/") : "targetPath must not end with a '/'";
218
219 String specDD;
220 XmlObject connector;
221 try {
222 if (specDDUrl == null) {
223 specDDUrl = DeploymentUtil.createJarURL(moduleFile, "META-INF/ra.xml");
224 }
225
226 // read in the entire specDD as a string, we need this for getDeploymentDescriptor
227 // on the J2ee management object
228 specDD = DeploymentUtil.readAll(specDDUrl);
229 } catch (Exception e) {
230 //no ra.xml, not for us.
231 return null;
232 }
233 //we found ra.xml, if it won't parse it's an error.
234 try {
235 // parse it
236 XmlObject xmlObject = XmlBeansUtil.parse(specDD);
237 ConnectorDocument connectorDoc = convertToConnectorSchema(xmlObject);
238 connector = connectorDoc.getConnector();
239 } catch (XmlException e) {
240 throw new DeploymentException("Could not parse ra.xml descriptor", e);
241 }
242 GerConnectorType gerConnector = null;
243 try {
244 // load the geronimo connector plan from either the supplied plan or from the earFile
245 try {
246 if (plan instanceof XmlObject) {
247 gerConnector = (GerConnectorType) SchemaConversionUtils.getNestedObjectAsType((XmlObject) plan,
248 CONNECTOR_QNAME,
249 GerConnectorType.type);
250 } else {
251 GerConnectorDocument gerConnectorDoc;
252 ArrayList errors = new ArrayList();
253 if (plan != null) {
254 gerConnectorDoc = GerConnectorDocument.Factory.parse((File) plan, XmlBeansUtil.createXmlOptions(errors));
255 } else {
256 URL path = DeploymentUtil.createJarURL(moduleFile, "META-INF/geronimo-ra.xml");
257 gerConnectorDoc = GerConnectorDocument.Factory.parse(path, XmlBeansUtil.createXmlOptions(errors));
258 }
259 if (errors.size() > 0) {
260 throw new DeploymentException("Could not parse connector doc: " + errors);
261 }
262 if (gerConnectorDoc != null) {
263 gerConnector = gerConnectorDoc.getConnector();
264 }
265 }
266 } catch (IOException e) {
267 //do nothing
268 }
269
270 // if we got one extract the validate it otherwise create a default one
271 if (gerConnector == null) {
272 throw new DeploymentException("A connector module must be deployed using a Geronimo deployment plan" +
273 " (either META-INF/geronimo-ra.xml in the RAR file or a standalone deployment plan passed to the deployer).");
274 }
275 ConnectorPlanRectifier.rectifyPlan(gerConnector);
276 XmlCursor cursor = gerConnector.newCursor();
277 try {
278 SchemaConversionUtils.convertToGeronimoSubSchemas(cursor);
279 } finally {
280 cursor.dispose();
281 }
282
283 XmlBeansUtil.validateDD(gerConnector);
284 } catch (XmlException e) {
285 throw new DeploymentException("Could not parse module descriptor", e);
286 }
287
288 EnvironmentType environmentType = gerConnector.getEnvironment();
289 Environment environment = EnvironmentBuilder.buildEnvironment(environmentType, defaultEnvironment);
290 if (earEnvironment != null) {
291 EnvironmentBuilder.mergeEnvironments(earEnvironment, environment);
292 environment = earEnvironment;
293 if (!environment.getConfigId().isResolved()) {
294 throw new IllegalStateException("Connector module ID should be fully resolved (not " + environment.getConfigId() + ")");
295 }
296 } else {
297 idBuilder.resolve(environment, new File(moduleFile.getName()).getName(), "rar");
298 }
299
300 AbstractName moduleName;
301 if (earName == null) {
302 earName = naming.createRootName(environment.getConfigId(), NameFactory.NULL, NameFactory.J2EE_APPLICATION);
303 moduleName = naming.createChildName(earName, environment.getConfigId().toString(), NameFactory.RESOURCE_ADAPTER_MODULE);
304 } else {
305 moduleName = naming.createChildName(earName, targetPath, NameFactory.RESOURCE_ADAPTER_MODULE);
306 }
307
308 boolean standAlone = earEnvironment == null;
309 AnnotatedApp annotatedApp = null;
310 return new ConnectorModule(standAlone, moduleName, environment, moduleFile, targetPath, connector, gerConnector, specDD, annotatedApp);
311
312 }
313
314 static ConnectorDocument convertToConnectorSchema(XmlObject xmlObject) throws XmlException {
315 if (ConnectorDocument.type.equals(xmlObject.schemaType())) {
316 XmlBeansUtil.validateDD(xmlObject);
317 return (ConnectorDocument) xmlObject;
318 }
319 XmlCursor cursor = xmlObject.newCursor();
320 XmlDocumentProperties xmlDocumentProperties = cursor.documentProperties();
321 String publicId = xmlDocumentProperties.getDoctypePublicId();
322 try {
323 if ("-//Sun Microsystems, Inc.//DTD Connector 1.0//EN".equals(publicId)) {
324 XmlCursor moveable = xmlObject.newCursor();
325 try {
326 String schemaLocationURL = "http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd";
327 String version = "1.5";
328 SchemaConversionUtils.convertToSchema(cursor, SchemaConversionUtils.J2EE_NAMESPACE, schemaLocationURL, version);
329 cursor.toStartDoc();
330 cursor.toChild(SchemaConversionUtils.J2EE_NAMESPACE, "connector");
331 cursor.toFirstChild();
332 SchemaConversionUtils.convertToDescriptionGroup(SchemaConversionUtils.J2EE_NAMESPACE, cursor, moveable);
333 cursor.toNextSibling(SchemaConversionUtils.J2EE_NAMESPACE, "spec-version");
334 cursor.removeXml();
335 cursor.toNextSibling(SchemaConversionUtils.J2EE_NAMESPACE, "version");
336 cursor.setName(RESOURCE_ADAPTER_VERSION);
337 cursor.toNextSibling(SchemaConversionUtils.J2EE_NAMESPACE, "resourceadapter");
338 moveable.toCursor(cursor);
339 cursor.toFirstChild();
340 cursor.beginElement("outbound-resourceadapter", SchemaConversionUtils.J2EE_NAMESPACE);
341 cursor.beginElement("connection-definition", SchemaConversionUtils.J2EE_NAMESPACE);
342 moveable.toChild(SchemaConversionUtils.J2EE_NAMESPACE, "managedconnectionfactory-class");
343 moveable.push();
344 //from moveable to cursor
345 moveable.moveXml(cursor);
346 while (moveable.toNextSibling(SchemaConversionUtils.J2EE_NAMESPACE, "config-property")) {
347 moveable.moveXml(cursor);
348 }
349 moveable.pop();
350 moveable.toNextSibling(SchemaConversionUtils.J2EE_NAMESPACE, "connectionfactory-interface");
351 moveable.moveXml(cursor);
352 moveable.toNextSibling(SchemaConversionUtils.J2EE_NAMESPACE, "connectionfactory-impl-class");
353 moveable.moveXml(cursor);
354 moveable.toNextSibling(SchemaConversionUtils.J2EE_NAMESPACE, "connection-interface");
355 moveable.moveXml(cursor);
356 moveable.toNextSibling(SchemaConversionUtils.J2EE_NAMESPACE, "connection-impl-class");
357 moveable.moveXml(cursor);
358 //get out of connection-definition element
359 cursor.toNextToken();
360 moveable.toNextSibling(SchemaConversionUtils.J2EE_NAMESPACE, "transaction-support");
361 moveable.moveXml(cursor);
362 while (moveable.toNextSibling(SchemaConversionUtils.J2EE_NAMESPACE, "authentication-mechanism")) {
363 moveable.moveXml(cursor);
364 }
365 moveable.toNextSibling(SchemaConversionUtils.J2EE_NAMESPACE, "reauthentication-support");
366 moveable.moveXml(cursor);
367 } finally {
368 moveable.dispose();
369 }
370
371 }
372 } finally {
373 cursor.dispose();
374 }
375 XmlObject result = xmlObject.changeType(ConnectorDocument.type);
376 if (result != null) {
377 XmlBeansUtil.validateDD(result);
378 return (ConnectorDocument) result;
379 }
380 XmlBeansUtil.validateDD(xmlObject);
381 return (ConnectorDocument) xmlObject;
382
383 }
384
385 public void installModule(JarFile earFile, EARContext earContext, Module module, Collection configurationStores, ConfigurationStore targetConfigurationStore, Collection repository) throws DeploymentException {
386 try {
387 JarFile moduleFile = module.getModuleFile();
388
389 // add the manifest classpath entries declared in the connector to the class loader
390 // we have to explicitly add these since we are unpacking the connector module
391 // and the url class loader will not pick up a manifiest from an unpacked dir
392 // N.B. If we ever introduce a separate configuration/module for a rar inside an ear
393 // this will need to be modified to use "../" instead of module.getTargetPath().
394 // See AbstractWebModuleBuilder.
395 earContext.addManifestClassPath(moduleFile, URI.create(module.getTargetPath()));
396
397 URI targetURI = URI.create(module.getTargetPath() + "/");
398 Enumeration entries = moduleFile.entries();
399 while (entries.hasMoreElements()) {
400 ZipEntry entry = (ZipEntry) entries.nextElement();
401 URI target = targetURI.resolve(entry.getName());
402 if (entry.getName().endsWith(".jar")) {
403 earContext.addInclude(target, moduleFile, entry);
404 } else {
405 earContext.addFile(target, moduleFile, entry);
406 }
407 }
408
409 } catch (IOException e) {
410 throw new DeploymentException("Problem deploying connector", e);
411 }
412 }
413
414 public void initContext(EARContext earContext, Module module, ClassLoader cl) throws DeploymentException {
415 ConnectorModule resourceModule = (ConnectorModule) module;
416
417 final ConnectorType connector = (ConnectorType) module.getSpecDD();
418
419 /*
420 The chain of idiotic jsr-77 meaningless objects is:
421 ResourceAdapterModule (1) >
422 ResourceAdapter (n, but there can only be 1 resource adapter in a rar, so we use 1) >
423 JCAResource (1) >
424 JCAConnectionFactory (n) >
425 JCAManagedConnectionFactory (1)
426 We also include:
427 JCAResourceAdapter (n) (from JCAResource) (actual instance of ResourceAdapter)
428 TODO include admin objects (n) from JCAResource presumably
429 */
430 AbstractName resourceAdapterModuleName = resourceModule.getModuleName();
431
432 AbstractName resourceAdapterjsr77Name = earContext.getNaming().createChildName(resourceAdapterModuleName, module.getName(), NameFactory.RESOURCE_ADAPTER);
433 AbstractName jcaResourcejsr77Name = earContext.getNaming().createChildName(resourceAdapterjsr77Name, module.getName(), NameFactory.JCA_RESOURCE);
434
435 //set up the metadata for the ResourceAdapterModule
436 GBeanData resourceAdapterModuleData = new GBeanData(resourceAdapterModuleName, ResourceAdapterModuleImplGBean.GBEAN_INFO);
437 // initalize the GBean
438 if (earContext.getServerName() != null) {
439 //app clients don't have a Server gbean
440 resourceAdapterModuleData.setReferencePattern(NameFactory.J2EE_SERVER, earContext.getServerName());
441 //app clients don't have an application name either
442 if (!earContext.getModuleName().equals(resourceAdapterModuleName)) {
443 resourceAdapterModuleData.setReferencePattern(NameFactory.J2EE_APPLICATION, earContext.getModuleName());
444 }
445 }
446 resourceAdapterModuleData.setReferencePattern("ResourceAdapter", resourceAdapterjsr77Name);
447
448 resourceAdapterModuleData.setAttribute("deploymentDescriptor", module.getOriginalSpecDD());
449 resourceAdapterModuleData.setAttribute("displayName", connector.getDisplayNameArray().length == 0 ? null : connector.getDisplayNameArray(0).getStringValue());
450 resourceAdapterModuleData.setAttribute("description", connector.getDescriptionArray().length == 0 ? null : connector.getDescriptionArray(0).getStringValue());
451 resourceAdapterModuleData.setAttribute("vendorName", connector.getVendorName().getStringValue());
452 resourceAdapterModuleData.setAttribute("EISType", connector.getEisType().getStringValue());
453 resourceAdapterModuleData.setAttribute("resourceAdapterVersion", connector.getResourceadapterVersion().getStringValue());
454
455 ResourceadapterType resourceadapter = connector.getResourceadapter();
456 // Create the resource adapter gbean
457 if (resourceadapter.isSetResourceadapterClass()) {
458 GBeanInfoBuilder resourceAdapterInfoBuilder = new GBeanInfoBuilder(ResourceAdapterWrapperGBean.class, ResourceAdapterWrapperGBean.GBEAN_INFO);
459 String resourceAdapterClassName = resourceadapter.getResourceadapterClass().getStringValue().trim();
460 GBeanData resourceAdapterGBeanData = setUpDynamicGBeanWithProperties(resourceAdapterClassName, resourceAdapterInfoBuilder, resourceadapter.getConfigPropertyArray(), cl, Collections.<String>emptySet());
461
462 resourceAdapterGBeanData.setAttribute("resourceAdapterClass", resourceAdapterClassName);
463
464 // Add map from messageListenerInterface to activationSpec class
465 Map<String, String> messageListenerToActivationSpecMap = new TreeMap<String, String>();
466 if (resourceadapter.isSetInboundResourceadapter() && resourceadapter.getInboundResourceadapter().isSetMessageadapter()) {
467 for (MessagelistenerType messagelistenerType : resourceadapter.getInboundResourceadapter().getMessageadapter().getMessagelistenerArray()) {
468 String messageListenerInterface = messagelistenerType.getMessagelistenerType().getStringValue().trim();
469 ActivationspecType activationspec = messagelistenerType.getActivationspec();
470 String activationSpecClassName = activationspec.getActivationspecClass().getStringValue().trim();
471 messageListenerToActivationSpecMap.put(messageListenerInterface, activationSpecClassName);
472 resourceAdapterGBeanData.setAttribute("messageListenerToActivationSpecMap", messageListenerToActivationSpecMap);
473 resourceAdapterGBeanData.setReferencePattern("TransactionManager", earContext.getTransactionManagerName());
474 }
475 }
476
477 resourceAdapterModuleData.setAttribute("resourceAdapterGBeanData", resourceAdapterGBeanData);
478 }
479
480 if (resourceadapter.isSetInboundResourceadapter() && resourceadapter.getInboundResourceadapter().isSetMessageadapter()) {
481 Map activationSpecInfoMap = getActivationSpecInfoMap(resourceadapter.getInboundResourceadapter().getMessageadapter().getMessagelistenerArray(), cl);
482 resourceAdapterModuleData.setAttribute("activationSpecInfoMap", activationSpecInfoMap);
483 }
484 Map adminObjectInfoMap = getAdminObjectInfoMap(resourceadapter.getAdminobjectArray(), cl);
485 resourceAdapterModuleData.setAttribute("adminObjectInfoMap", adminObjectInfoMap);
486 if (resourceadapter.isSetOutboundResourceadapter()) {
487 Map managedConnectionFactoryInfoMap = getManagedConnectionFactoryInfoMap(resourceadapter.getOutboundResourceadapter().getConnectionDefinitionArray(), cl);
488 resourceAdapterModuleData.setAttribute("managedConnectionFactoryInfoMap", managedConnectionFactoryInfoMap);
489 }
490
491 try {
492 earContext.addGBean(resourceAdapterModuleData);
493 } catch (GBeanAlreadyExistsException e) {
494 throw new DeploymentException("Could not add resource adapter module gbean to context", e);
495 }
496
497 //construct the bogus resource adapter and jca resource placeholders
498 GBeanData resourceAdapterData = new GBeanData(resourceAdapterjsr77Name, ResourceAdapterImplGBean.GBEAN_INFO);
499 resourceAdapterData.setReferencePattern("JCAResource", jcaResourcejsr77Name);
500 try {
501 earContext.addGBean(resourceAdapterData);
502 } catch (GBeanAlreadyExistsException e) {
503 throw new DeploymentException("Could not add resource adapter gbean to context", e);
504 }
505
506 GBeanData jcaResourceData = new GBeanData(jcaResourcejsr77Name, JCAResourceImplGBean.GBEAN_INFO);
507 Map<String, String> thisModule = new LinkedHashMap<String, String>(2);
508 thisModule.put(NameFactory.J2EE_APPLICATION, resourceAdapterModuleName.getNameProperty(NameFactory.J2EE_APPLICATION));
509 thisModule.put(NameFactory.RESOURCE_ADAPTER_MODULE, resourceAdapterModuleName.getNameProperty(NameFactory.J2EE_NAME));
510 jcaResourceData.setReferencePattern("ConnectionFactories", new AbstractNameQuery(resourceAdapterModuleName.getArtifact(), thisModule, JCAConnectionFactory.class.getName()));
511 jcaResourceData.setReferencePattern("ResourceAdapters", new AbstractNameQuery(resourceAdapterModuleName.getArtifact(), thisModule, JCAResourceAdapter.class.getName()));
512 jcaResourceData.setReferencePattern("AdminObjects", new AbstractNameQuery(resourceAdapterModuleName.getArtifact(), thisModule, JCAAdminObject.class.getName()));
513
514 try {
515 earContext.addGBean(jcaResourceData);
516 } catch (GBeanAlreadyExistsException e) {
517 throw new DeploymentException("Could not add jca resource gbean to context", e);
518 }
519
520 GerConnectorType geronimoConnector = (GerConnectorType) module.getVendorDD();
521
522 serviceBuilders.build(geronimoConnector, earContext, earContext);
523
524 addConnectorGBeans(earContext, jcaResourcejsr77Name, resourceAdapterModuleData, connector, geronimoConnector, cl);
525
526 }
527
528 public void addGBeans(EARContext earContext, Module module, ClassLoader cl, Collection repository) throws DeploymentException {
529 //all our gbeans are added in the initContext step
530 }
531
532 public String getSchemaNamespace() {
533 return GERCONNECTOR_NAMESPACE;
534 }
535
536 private void addConnectorGBeans(EARContext earContext, AbstractName jcaResourceName, GBeanData resourceAdapterModuleData, ConnectorType connector, GerConnectorType geronimoConnector, ClassLoader cl) throws DeploymentException {
537 ResourceadapterType resourceadapter = connector.getResourceadapter();
538
539 GerResourceadapterType[] geronimoResourceAdapters = geronimoConnector.getResourceadapterArray();
540 for (GerResourceadapterType geronimoResourceAdapter : geronimoResourceAdapters) {
541 // Resource Adapter
542 AbstractName resourceAdapterAbstractName = null;
543 if (resourceadapter.isSetResourceadapterClass()) {
544 GBeanData resourceAdapterGBeanData = locateResourceAdapterGBeanData(resourceAdapterModuleData);
545 GBeanData resourceAdapterInstanceGBeanData = new GBeanData(resourceAdapterGBeanData);
546
547 String resourceAdapterName;
548 AbstractNameQuery workManagerName;
549 if (geronimoResourceAdapter.isSetResourceadapterInstance()) {
550 GerResourceadapterInstanceType resourceAdapterInstance = geronimoResourceAdapter.getResourceadapterInstance();
551 setDynamicGBeanDataAttributes(resourceAdapterInstanceGBeanData, resourceAdapterInstance.getConfigPropertySettingArray(), cl);
552 workManagerName = ENCConfigBuilder.getGBeanQuery(NameFactory.JCA_WORK_MANAGER, resourceAdapterInstance.getWorkmanager());
553 resourceAdapterName = resourceAdapterInstance.getResourceadapterName();
554 } else {
555 workManagerName = ENCConfigBuilder.buildAbstractNameQuery(null, null, defaultWorkManagerName, NameFactory.JCA_WORK_MANAGER, null);
556 resourceAdapterName = "ResourceAdapterInstance-" + System.currentTimeMillis();
557 log.warn("Resource adapter instance information was not specified in Geronimo plan. Using defaults.");
558 }
559
560 // set the work manager name
561 resourceAdapterInstanceGBeanData.setReferencePattern("WorkManager", workManagerName);
562
563 // set the xa terminator name which is the same as our transaction manager
564 resourceAdapterInstanceGBeanData.setReferencePattern("XATerminator", earContext.getTransactionManagerName());
565
566 resourceAdapterAbstractName = earContext.getNaming().createChildName(jcaResourceName, resourceAdapterName, NameFactory.JCA_RESOURCE_ADAPTER);
567 resourceAdapterInstanceGBeanData.setAbstractName(resourceAdapterAbstractName);
568 try {
569 earContext.addGBean(resourceAdapterInstanceGBeanData);
570 } catch (GBeanAlreadyExistsException e) {
571 throw new DeploymentException("Could not add resource adapter instance gbean to context", e);
572 }
573 }
574
575 // Outbound Managed Connection Factories (think JDBC data source or JMS connection factory)
576
577 // ManagedConnectionFactory setup
578 if (geronimoResourceAdapter.isSetOutboundResourceadapter()) {
579 if (!resourceadapter.isSetOutboundResourceadapter()) {
580 throw new DeploymentException("Geronimo plan configures an outbound resource adapter but ra.xml does not describe any");
581 }
582 String transactionSupport = resourceadapter.getOutboundResourceadapter().getTransactionSupport().getStringValue().trim();
583 for (int i = 0; i < geronimoResourceAdapter.getOutboundResourceadapter().getConnectionDefinitionArray().length; i++) {
584 GerConnectionDefinitionType geronimoConnectionDefinition = geronimoResourceAdapter.getOutboundResourceadapter().getConnectionDefinitionArray(i);
585 assert geronimoConnectionDefinition != null : "Null GeronimoConnectionDefinition";
586
587 String connectionFactoryInterfaceName = geronimoConnectionDefinition.getConnectionfactoryInterface().trim();
588 GBeanData connectionFactoryGBeanData = locateConnectionFactoryInfo(resourceAdapterModuleData, connectionFactoryInterfaceName);
589
590 if (connectionFactoryGBeanData == null) {
591 throw new DeploymentException("No connection definition for ConnectionFactory class: " + connectionFactoryInterfaceName);
592 }
593
594 for (int j = 0; j < geronimoConnectionDefinition.getConnectiondefinitionInstanceArray().length; j++) {
595 GerConnectiondefinitionInstanceType connectionfactoryInstance = geronimoConnectionDefinition.getConnectiondefinitionInstanceArray()[j];
596
597 addOutboundGBeans(earContext, jcaResourceName, resourceAdapterAbstractName, connectionFactoryGBeanData, connectionfactoryInstance, transactionSupport, cl);
598 }
599 }
600 }
601 }
602 // admin objects (think message queues and topics)
603
604 // add configured admin objects
605 for (int i = 0; i < geronimoConnector.getAdminobjectArray().length; i++) {
606 GerAdminobjectType gerAdminObject = geronimoConnector.getAdminobjectArray()[i];
607
608 String adminObjectInterface = gerAdminObject.getAdminobjectInterface().trim();
609 GBeanData adminObjectGBeanData = locateAdminObjectInfo(resourceAdapterModuleData, adminObjectInterface);
610
611 if (adminObjectGBeanData == null) {
612 throw new DeploymentException("No admin object declared for interface: " + adminObjectInterface);
613 }
614
615 for (GerAdminobjectInstanceType gerAdminObjectInstance: gerAdminObject.getAdminobjectInstanceArray()) {
616 GBeanData adminObjectInstanceGBeanData = new GBeanData(adminObjectGBeanData);
617 setDynamicGBeanDataAttributes(adminObjectInstanceGBeanData, gerAdminObjectInstance.getConfigPropertySettingArray(), cl);
618 // add it
619 AbstractName adminObjectAbstractName = earContext.getNaming().createChildName(jcaResourceName, gerAdminObjectInstance.getMessageDestinationName().trim(), NameFactory.JCA_ADMIN_OBJECT);
620 adminObjectInstanceGBeanData.setAbstractName(adminObjectAbstractName);
621 try {
622 earContext.addGBean(adminObjectInstanceGBeanData);
623 } catch (GBeanAlreadyExistsException e) {
624 throw new DeploymentException("Could not add admin object gbean to context", e);
625 }
626 }
627 }
628 }
629
630 private Map getActivationSpecInfoMap(MessagelistenerType[] messagelistenerArray, ClassLoader cl) throws DeploymentException {
631 Map<String, GBeanData> activationSpecInfos = new HashMap<String, GBeanData>();
632 for (MessagelistenerType messagelistenerType : messagelistenerArray) {
633 String messageListenerInterface = messagelistenerType.getMessagelistenerType().getStringValue().trim();
634 ActivationspecType activationspec = messagelistenerType.getActivationspec();
635 String activationSpecClassName = activationspec.getActivationspecClass().getStringValue().trim();
636 GBeanInfoBuilder infoBuilder = new GBeanInfoBuilder(ActivationSpecWrapperGBean.class, ActivationSpecWrapperGBean.GBEAN_INFO);
637 Set<String> ignore = Collections.singleton("resourceAdapter");
638 setUpDynamicGBean(activationSpecClassName, infoBuilder, ignore, cl, true);
639
640
641 GBeanInfo gbeanInfo = infoBuilder.getBeanInfo();
642
643 GBeanData activationSpecInfo = new GBeanData(gbeanInfo);
644 activationSpecInfo.setAttribute("activationSpecClass", activationSpecClassName);
645 activationSpecInfos.put(messageListenerInterface, activationSpecInfo);
646 }
647 return activationSpecInfos;
648 }
649
650 private void setUpDynamicGBean(String activationSpecClassName, GBeanInfoBuilder infoBuilder, Set<String> ignore, ClassLoader cl, boolean decapitalize) throws DeploymentException {
651 //add all javabean properties that have both getter and setter. Ignore the "required" flag from the dd.
652 Map<String, String> getters = new HashMap<String, String>();
653 Set<String> setters = new HashSet<String>();
654 Method[] methods;
655 try {
656 Class activationSpecClass = cl.loadClass(activationSpecClassName);
657 methods = activationSpecClass.getMethods();
658 } catch (ClassNotFoundException e) {
659 throw new DeploymentException("Can not load activation spec class", e);
660 }
661 for (Method method : methods) {
662 String methodName = method.getName();
663 if ((methodName.startsWith("get") || methodName.startsWith("is")) && method.getParameterTypes().length == 0) {
664 String attributeName = (methodName.startsWith("get")) ? methodName.substring(3) : methodName.substring(2);
665 getters.put(setCase(attributeName, decapitalize), method.getReturnType().getName());
666 } else if (methodName.startsWith("set") && method.getParameterTypes().length == 1) {
667 setters.add(setCase(methodName.substring(3), decapitalize));
668 }
669 }
670 getters.keySet().retainAll(setters);
671 getters.keySet().removeAll(ignore);
672
673 for (Map.Entry<String, String> entry : getters.entrySet()) {
674 infoBuilder.addAttribute(new DynamicGAttributeInfo(entry.getKey(), entry.getValue(), true, true, true, true));
675 }
676 }
677
678 private String setCase(String attributeName, boolean decapitalize) {
679 if (decapitalize) {
680 return Introspector.decapitalize(attributeName);
681 } else {
682 return attributeName;
683 }
684 }
685
686 private static String switchCase(String name) {
687 if (name == null || name.length() == 0) {
688 return name;
689 }
690 if (Character.isUpperCase(name.charAt(0))) {
691 char chars[] = name.toCharArray();
692 chars[0] = Character.toLowerCase(chars[0]);
693 return new String(chars);
694 } else if (Character.isLowerCase(name.charAt(0))) {
695 char chars[] = name.toCharArray();
696 chars[0] = Character.toUpperCase(chars[0]);
697 return new String(chars);
698 } else{
699 return name;
700 }
701 }
702
703 private Map getManagedConnectionFactoryInfoMap(ConnectionDefinitionType[] connectionDefinitionArray, ClassLoader cl) throws DeploymentException {
704 Map<String, GBeanData> managedConnectionFactoryInfos = new HashMap<String, GBeanData>();
705 for (ConnectionDefinitionType connectionDefinition : connectionDefinitionArray) {
706 GBeanInfoBuilder managedConnectionFactoryInfoBuilder = new GBeanInfoBuilder(ManagedConnectionFactoryWrapper.class, ManagedConnectionFactoryWrapperGBean.GBEAN_INFO);
707 String managedConnectionfactoryClassName = connectionDefinition.getManagedconnectionfactoryClass().getStringValue().trim();
708 Set<String> ignore = new HashSet<String>();
709 ignore.add("ResourceAdapter");
710 ignore.add("LogWriter");
711 GBeanData managedConnectionFactoryGBeanData = setUpDynamicGBeanWithProperties(managedConnectionfactoryClassName, managedConnectionFactoryInfoBuilder, connectionDefinition.getConfigPropertyArray(), cl, ignore);
712
713 // set the standard properties
714 String connectionfactoryInterface = connectionDefinition.getConnectionfactoryInterface().getStringValue().trim();
715 managedConnectionFactoryGBeanData.setAttribute("managedConnectionFactoryClass", managedConnectionfactoryClassName);
716 managedConnectionFactoryGBeanData.setAttribute("connectionFactoryInterface", connectionfactoryInterface);
717 managedConnectionFactoryGBeanData.setAttribute("connectionFactoryImplClass", connectionDefinition.getConnectionfactoryImplClass().getStringValue().trim());
718 managedConnectionFactoryGBeanData.setAttribute("connectionInterface", connectionDefinition.getConnectionInterface().getStringValue().trim());
719 managedConnectionFactoryGBeanData.setAttribute("connectionImplClass", connectionDefinition.getConnectionImplClass().getStringValue().trim());
720 managedConnectionFactoryInfos.put(connectionfactoryInterface, managedConnectionFactoryGBeanData);
721 }
722 return managedConnectionFactoryInfos;
723 }
724
725 private Map getAdminObjectInfoMap(AdminobjectType[] adminobjectArray, ClassLoader cl) throws DeploymentException {
726 Map<String, GBeanData> adminObjectInfos = new HashMap<String, GBeanData>();
727 for (AdminobjectType adminObject : adminobjectArray) {
728 GBeanInfoBuilder adminObjectInfoBuilder = new GBeanInfoBuilder(AdminObjectWrapper.class, AdminObjectWrapperGBean.GBEAN_INFO);
729 String adminObjectClassName = adminObject.getAdminobjectClass().getStringValue().trim();
730 GBeanData adminObjectGBeanData = setUpDynamicGBeanWithProperties(adminObjectClassName, adminObjectInfoBuilder, adminObject.getConfigPropertyArray(), cl, Collections.<String>emptySet());
731
732 // set the standard properties
733 String adminObjectInterface = adminObject.getAdminobjectInterface().getStringValue().trim();
734 adminObjectGBeanData.setAttribute("adminObjectInterface", adminObjectInterface);
735 adminObjectGBeanData.setAttribute("adminObjectClass", adminObjectClassName);
736 adminObjectInfos.put(adminObjectInterface, adminObjectGBeanData);
737 }
738 return adminObjectInfos;
739 }
740
741
742 private GBeanData setUpDynamicGBeanWithProperties(String className, GBeanInfoBuilder infoBuilder, ConfigPropertyType[] configProperties, ClassLoader cl, Set<String> ignore) throws DeploymentException {
743 setUpDynamicGBean(className, infoBuilder, ignore, cl, false);
744
745 GBeanInfo gbeanInfo = infoBuilder.getBeanInfo();
746 GBeanData gbeanData = new GBeanData(gbeanInfo);
747 for (ConfigPropertyType configProperty : configProperties) {
748 if (configProperty.isSetConfigPropertyValue()) {
749 String name = configProperty.getConfigPropertyName().getStringValue();
750 if (gbeanInfo.getAttribute(name) == null) {
751 String originalName = name;
752 name = switchCase(name);
753 if (gbeanInfo.getAttribute(name) == null) {
754 log.warn("Unsupported config-property: " + originalName);
755 continue;
756 }
757 }
758 String type = configProperty.getConfigPropertyType().getStringValue();
759 String value = configProperty.getConfigPropertyValue().getStringValue();
760 gbeanData.setAttribute(name, getValue(type, value, cl));
761 }
762 }
763 return gbeanData;
764 }
765
766 private void setDynamicGBeanDataAttributes(GBeanData gbeanData, GerConfigPropertySettingType[] configProperties, ClassLoader cl) throws DeploymentException {
767 List<String> unknownNames = new ArrayList<String>();
768 for (GerConfigPropertySettingType configProperty : configProperties) {
769 String name = configProperty.getName();
770 GAttributeInfo attributeInfo = gbeanData.getGBeanInfo().getAttribute(name);
771 if (attributeInfo == null) {
772 String originalName = name;
773 name = switchCase(name);
774 attributeInfo = gbeanData.getGBeanInfo().getAttribute(name);
775 if (attributeInfo == null) {
776 unknownNames.add(originalName);
777 continue;
778 }
779 }
780
781 String type = attributeInfo.getType();
782 gbeanData.setAttribute(name, getValue(type, configProperty.getStringValue().trim(), cl));
783 }
784 if (unknownNames.size() > 0) {
785 StringBuffer buf = new StringBuffer("The plan is trying to set attributes: ").append(unknownNames).append("\n");
786 buf.append("Known attributes: \n");
787 for (GAttributeInfo attributeInfo: gbeanData.getGBeanInfo().getAttributes()) {
788 buf.append(attributeInfo).append("\n");
789 }
790 throw new DeploymentException(buf.toString());
791 }
792 }
793
794 private Object getValue(String type, String value, ClassLoader cl) throws DeploymentException {
795 if (value == null) {
796 return null;
797 }
798
799 Class clazz = TYPE_LOOKUP.get(type);
800 if (clazz == null) {
801 try {
802 clazz = cl.loadClass(type);
803 } catch (ClassNotFoundException e) {
804 throw new DeploymentException("Could not load attribute class: type: " + type, e);
805 }
806 }
807
808 // Handle numeric fields with no value set
809 if (value.equals("")) {
810 if (Number.class.isAssignableFrom(clazz) || Date.class.isAssignableFrom(clazz)) {
811 return null;
812 }
813 }
814
815 PropertyEditor editor = PropertyEditors.getEditor(clazz);
816 editor.setAsText(value);
817 return editor.getValue();
818 }
819
820 private AbstractName configureConnectionManager(EARContext earContext, AbstractName jcaResourceName, String ddTransactionSupport, GerConnectiondefinitionInstanceType connectionfactoryInstance, ClassLoader cl) throws DeploymentException {
821 // if (connectionfactoryInstance.getConnectionmanagerRef() != null) {
822 //we don't configure anything, just use the supplied gbean
823 // try {
824 // return AbstractName.getInstance(connectionfactoryInstance.getConnectionmanagerRef());
825 // } catch (MalformedAbstractNameException e) {
826 // throw new DeploymentException("Invalid AbstractName string supplied for ConnectionManager reference", e);
827 // }
828 // }
829
830 // create the object name for our connection manager
831 AbstractName connectionManagerAbstractName = earContext.getNaming().createChildName(jcaResourceName, connectionfactoryInstance.getName().trim(), NameFactory.JCA_CONNECTION_MANAGER);
832
833 // create the data holder for our connection manager
834 GBeanInfo gbeanInfo;
835 try {
836 gbeanInfo = GBeanInfo.getGBeanInfo("org.apache.geronimo.connector.outbound.GenericConnectionManagerGBean", cl);
837 } catch (InvalidConfigurationException e) {
838 throw new DeploymentException("Unable to create GMBean", e);
839 }
840 GBeanData connectionManagerGBean = new GBeanData(connectionManagerAbstractName, gbeanInfo);
841
842 //we configure our connection manager
843 GerConnectionmanagerType connectionManager = connectionfactoryInstance.getConnectionmanager();
844 TransactionSupport transactionSupport;
845 if (connectionManager.isSetNoTransaction()) {
846 transactionSupport = NoTransactions.INSTANCE;
847 } else if (connectionManager.isSetLocalTransaction()) {
848 if ("NoTransaction".equals(ddTransactionSupport)) {
849 throw new DeploymentException("You are requesting local transaction support for a connector that does not support transactions: named: " + connectionfactoryInstance.getName().trim());
850 }
851 transactionSupport = LocalTransactions.INSTANCE;
852 } else if (connectionManager.isSetTransactionLog()) {
853 if ("NoTransaction".equals(ddTransactionSupport)) {
854 throw new DeploymentException("You are requesting local transaction support for a connector that does not support transactions: named: " + connectionfactoryInstance.getName().trim());
855 }
856 transactionSupport = TransactionLog.INSTANCE;
857 } else if (connectionManager.isSetXaTransaction()) {
858 if ("NoTransaction".equals(ddTransactionSupport)) {
859 throw new DeploymentException("You are requesting xa transaction support for a connector that does not support transactions: named: " + connectionfactoryInstance.getName().trim());
860 }
861 if ("LocalTransaction".equals(ddTransactionSupport)) {
862 throw new DeploymentException("You are requesting xa transaction support for a connector that supports only local transactions: named: " + connectionfactoryInstance.getName().trim());
863 }
864 transactionSupport = new XATransactions(connectionManager.getXaTransaction().isSetTransactionCaching(),
865 connectionManager.getXaTransaction().isSetThreadCaching());
866 } else if ("NoTransaction".equals(ddTransactionSupport)) {
867 transactionSupport = NoTransactions.INSTANCE;
868 } else if ("LocalTransaction".equals(ddTransactionSupport)) {
869 transactionSupport = LocalTransactions.INSTANCE;
870 } else if ("XATransaction".equals(ddTransactionSupport)) {
871 transactionSupport = new XATransactions(defaultXATransactionCaching, defaultXAThreadCaching);
872 } else {
873 //this should not happen
874 throw new DeploymentException("Unexpected transaction support element in connector named: " + connectionfactoryInstance.getName().trim());
875 }
876 PoolingSupport pooling;
877 if (connectionManager.getSinglePool() != null) {
878 GerSinglepoolType pool = connectionManager.getSinglePool();
879
880 pooling = new SinglePool(pool.isSetMaxSize() ? pool.getMaxSize() : defaultMaxSize,
881 pool.isSetMinSize() ? pool.getMinSize() : defaultMinSize,
882 pool.isSetBlockingTimeoutMilliseconds() ? pool.getBlockingTimeoutMilliseconds() : defaultBlockingTimeoutMilliseconds,
883 pool.isSetIdleTimeoutMinutes() ? pool.getIdleTimeoutMinutes() : defaultIdleTimeoutMinutes,
884 pool.getMatchOne() != null,
885 pool.getMatchAll() != null,
886 pool.getSelectOneAssumeMatch() != null);
887 } else if (connectionManager.getPartitionedPool() != null) {
888 GerPartitionedpoolType pool = connectionManager.getPartitionedPool();
889 pooling = new PartitionedPool(pool.isSetMaxSize() ? pool.getMaxSize() : defaultMaxSize,
890 pool.isSetMinSize() ? pool.getMinSize() : defaultMinSize,
891 pool.isSetBlockingTimeoutMilliseconds() ? pool.getBlockingTimeoutMilliseconds() : defaultBlockingTimeoutMilliseconds,
892 pool.isSetIdleTimeoutMinutes() ? pool.getIdleTimeoutMinutes() : defaultIdleTimeoutMinutes,
893 pool.getMatchOne() != null,
894 pool.getMatchAll() != null,
895 pool.getSelectOneAssumeMatch() != null,
896 pool.isSetPartitionByConnectionrequestinfo(),
897 pool.isSetPartitionBySubject());
898 } else if (connectionManager.getNoPool() != null) {
899 pooling = new NoPool();
900 } else {
901 throw new DeploymentException("Unexpected pooling support element in connector named " + connectionfactoryInstance.getName().trim());
902 }
903 try {
904 connectionManagerGBean.setAttribute("transactionSupport", transactionSupport);
905 connectionManagerGBean.setAttribute("pooling", pooling);
906 connectionManagerGBean.setReferencePattern("ConnectionTracker", earContext.getConnectionTrackerName());
907 connectionManagerGBean.setAttribute("containerManagedSecurity", connectionManager.isSetContainerManagedSecurity());
908 connectionManagerGBean.setReferencePattern("TransactionManager", earContext.getTransactionManagerName());
909 } catch (Exception e) {
910 throw new DeploymentException("Problem setting up ConnectionManager named " + connectionfactoryInstance.getName().trim(), e);
911 }
912
913 try {
914 earContext.addGBean(connectionManagerGBean);
915 } catch (GBeanAlreadyExistsException e) {
916 throw new DeploymentException("Could not add connection manager gbean to context: name: " + connectionfactoryInstance.getName().trim(), e);
917 }
918 return connectionManagerAbstractName;
919 }
920
921 private void addOutboundGBeans(EARContext earContext, AbstractName jcaResourceName, AbstractName resourceAdapterAbstractName, GBeanData managedConnectionFactoryPrototypeGBeanData, GerConnectiondefinitionInstanceType connectiondefinitionInstance, String transactionSupport, ClassLoader cl) throws DeploymentException {
922 GBeanData managedConnectionFactoryInstanceGBeanData = new GBeanData(managedConnectionFactoryPrototypeGBeanData);
923 AbstractName connectionFactoryAbstractName = earContext.getNaming().createChildName(jcaResourceName, connectiondefinitionInstance.getName().trim(), NameFactory.JCA_CONNECTION_FACTORY);
924 AbstractName managedConnectionFactoryAbstractName = earContext.getNaming().createChildName(connectionFactoryAbstractName, connectiondefinitionInstance.getName().trim(), NameFactory.JCA_MANAGED_CONNECTION_FACTORY);
925 // ConnectionManager
926 AbstractName connectionManagerAbstractName = configureConnectionManager(earContext, managedConnectionFactoryAbstractName, transactionSupport, connectiondefinitionInstance, cl);
927
928 // ManagedConnectionFactory
929 setDynamicGBeanDataAttributes(managedConnectionFactoryInstanceGBeanData, connectiondefinitionInstance.getConfigPropertySettingArray(), cl);
930
931 //Check if Driver class is available here. This should be available in cl. If not log a warning as
932 //the plan gets deployed and while starting GBean an error is thrown
933
934 Object driver = managedConnectionFactoryInstanceGBeanData.getAttribute("Driver");
935 if (driver != null && driver instanceof String) {
936 try {
937 cl.loadClass((String) driver);
938 } catch (ClassNotFoundException e1) {
939 log.warn("Problem loading driver class '" + driver + "', possibly due to a missing dependency on the driver jar!!", e1);
940 }
941 }
942
943 try {
944 if (resourceAdapterAbstractName != null) {
945 managedConnectionFactoryInstanceGBeanData.setReferencePattern("ResourceAdapterWrapper", resourceAdapterAbstractName);
946 }
947 managedConnectionFactoryInstanceGBeanData.setReferencePattern("ConnectionManagerContainer", connectionManagerAbstractName);
948 //additional interfaces implemented by connection factory
949 String[] implementedInterfaces = connectiondefinitionInstance.getImplementedInterfaceArray();
950 if (implementedInterfaces != null) {
951 for (int i = 0; i < implementedInterfaces.length; i++) {
952 implementedInterfaces[i] = implementedInterfaces[i].trim();
953 }
954 } else {
955 implementedInterfaces = new String[0];
956 }
957 managedConnectionFactoryInstanceGBeanData.setAttribute("implementedInterfaces", implementedInterfaces);
958
959 } catch (Exception e) {
960 throw new DeploymentException(e);
961 }
962
963 managedConnectionFactoryInstanceGBeanData.setAbstractName(managedConnectionFactoryAbstractName);
964 try {
965 earContext.addGBean(managedConnectionFactoryInstanceGBeanData);
966 } catch (GBeanAlreadyExistsException e) {
967 throw new DeploymentException("Could not add managed connection factory gbean to context", e);
968 }
969
970 // ConnectionFactory
971 GBeanData connectionFactoryGBeanData = new GBeanData(connectionFactoryAbstractName, JCAConnectionFactoryImplGBean.GBEAN_INFO);
972 connectionFactoryGBeanData.setReferencePattern("JCAManagedConnectionFactory", managedConnectionFactoryAbstractName);
973
974 try {
975 earContext.addGBean(connectionFactoryGBeanData);
976 } catch (GBeanAlreadyExistsException e) {
977 throw new DeploymentException("Could not add connection factory gbean to context", e);
978 }
979 }
980
981 public GBeanData locateActivationSpecInfo(AbstractNameQuery resourceAdapterInstanceQuery, String messageListenerInterface, Configuration configuration) throws DeploymentException {
982 //First, locate the module gbean from the JCAResourceAdapter instance
983 AbstractName instanceName;
984 try {
985 instanceName = configuration.findGBean(resourceAdapterInstanceQuery);
986 } catch (GBeanNotFoundException e) {
987 throw new DeploymentException("No resource adapter instance gbean found matching " + resourceAdapterInstanceQuery + " from configuration " + configuration.getId(), e);
988 }
989 String moduleName = (String) instanceName.getName().get(NameFactory.RESOURCE_ADAPTER_MODULE);
990 Map<String, String> moduleNameMap = new HashMap<String, String>(instanceName.getName());
991 moduleNameMap.remove(NameFactory.JCA_RESOURCE);
992 moduleNameMap.remove(NameFactory.RESOURCE_ADAPTER);
993 moduleNameMap.remove(NameFactory.RESOURCE_ADAPTER_MODULE);
994 moduleNameMap.put(NameFactory.J2EE_TYPE, NameFactory.RESOURCE_ADAPTER_MODULE);
995 moduleNameMap.put(NameFactory.J2EE_NAME, moduleName);
996 AbstractNameQuery nameQuery = new AbstractNameQuery(instanceName.getArtifact(), moduleNameMap, ResourceAdapterModule.class.getName());
997 //now find the gbeandata and extract the activation spec info.
998 GBeanData resourceModuleData;
999 try {
1000 resourceModuleData = configuration.findGBeanData(nameQuery);
1001 } catch (GBeanNotFoundException e) {
1002 throw new DeploymentException("No resource module gbean found matching " + nameQuery + " from configuration " + configuration.getId(), e);
1003 }
1004 Map activationSpecInfos = (Map) resourceModuleData.getAttribute("activationSpecInfoMap");
1005 if (activationSpecInfos == null) {
1006 throw new DeploymentException("No activation spec info map found in resource adapter module: " + resourceModuleData.getAbstractName());
1007 }
1008 return (GBeanData) activationSpecInfos.get(messageListenerInterface);
1009 }
1010
1011 private GBeanData locateResourceAdapterGBeanData(GBeanData resourceAdapterModuleData) throws DeploymentException {
1012 GBeanData data = (GBeanData) resourceAdapterModuleData.getAttribute("resourceAdapterGBeanData");
1013 if (data == null) {
1014 throw new DeploymentException("No resource adapter info found for resource adapter module: " + resourceAdapterModuleData.getAbstractName());
1015 }
1016 return data;
1017 }
1018
1019 private GBeanData locateAdminObjectInfo(GBeanData resourceAdapterModuleData, String adminObjectInterfaceName) throws DeploymentException {
1020 Map adminObjectInfos = (Map) resourceAdapterModuleData.getAttribute("adminObjectInfoMap");
1021 if (adminObjectInfos == null) {
1022 throw new DeploymentException("No admin object infos found for resource adapter module: " + resourceAdapterModuleData.getAbstractName());
1023 }
1024 return (GBeanData) adminObjectInfos.get(adminObjectInterfaceName);
1025 }
1026
1027 private GBeanData locateConnectionFactoryInfo(GBeanData resourceAdapterModuleData, String connectionFactoryInterfaceName) throws DeploymentException {
1028 Map managedConnectionFactoryInfos = (Map) resourceAdapterModuleData.getAttribute("managedConnectionFactoryInfoMap");
1029 if (managedConnectionFactoryInfos == null) {
1030 throw new DeploymentException("No managed connection factory infos found for resource adapter module: " + resourceAdapterModuleData.getAbstractName());
1031 }
1032 return (GBeanData) managedConnectionFactoryInfos.get(connectionFactoryInterfaceName);
1033 }
1034
1035 public static final GBeanInfo GBEAN_INFO;
1036
1037 static {
1038 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(ConnectorModuleBuilder.class, NameFactory.MODULE_BUILDER);
1039
1040 infoBuilder.addAttribute("defaultEnvironment", Environment.class, true, true);
1041 infoBuilder.addAttribute("defaultMaxSize", int.class, true, true);
1042 infoBuilder.addAttribute("defaultMinSize", int.class, true, true);
1043 infoBuilder.addAttribute("defaultBlockingTimeoutMilliseconds", int.class, true, true);
1044 infoBuilder.addAttribute("defaultIdleTimeoutMinutes", int.class, true, true);
1045 infoBuilder.addAttribute("defaultXATransactionCaching", boolean.class, true, true);
1046 infoBuilder.addAttribute("defaultXAThreadCaching", boolean.class, true, true);
1047 infoBuilder.addAttribute("defaultWorkManagerName", String.class, true, true);
1048
1049 infoBuilder.addReference("ServiceBuilders", NamespaceDrivenBuilder.class, NameFactory.MODULE_BUILDER);
1050
1051 infoBuilder.addInterface(ModuleBuilder.class);
1052 infoBuilder.addInterface(ActivationSpecInfoLocator.class);
1053
1054 infoBuilder.setConstructor(new String[]{"defaultEnvironment",
1055 "defaultMaxSize",
1056 "defaultMinSize",
1057 "defaultBlockingTimeoutMilliseconds",
1058 "defaultIdleTimeoutMinutes",
1059 "defaultXATransactionCaching",
1060 "defaultXAThreadCaching",
1061 "defaultWorkManagerName",
1062 "ServiceBuilders"});
1063 GBEAN_INFO = infoBuilder.getBeanInfo();
1064 }
1065
1066 public static GBeanInfo getGBeanInfo() {
1067 return GBEAN_INFO;
1068 }
1069
1070 }