001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019:
020: package org.apache.geronimo.openejb.deployment.cluster;
021:
022: import java.net.URI;
023: import java.net.URISyntaxException;
024: import java.net.URL;
025: import java.util.Collection;
026: import java.util.Collections;
027: import java.util.HashSet;
028: import java.util.Set;
029: import java.util.jar.JarFile;
030:
031: import javax.xml.namespace.QName;
032:
033: import org.apache.geronimo.clustering.wadi.BasicWADISessionManager;
034: import org.apache.geronimo.clustering.wadi.WADISessionManagerConfigInfo;
035: import org.apache.geronimo.common.DeploymentException;
036: import org.apache.geronimo.deployment.DeploymentContext;
037: import org.apache.geronimo.deployment.ModuleIDBuilder;
038: import org.apache.geronimo.deployment.NamespaceDrivenBuilder;
039: import org.apache.geronimo.deployment.NamespaceDrivenBuilderCollection;
040: import org.apache.geronimo.deployment.service.EnvironmentBuilder;
041: import org.apache.geronimo.gbean.AbstractName;
042: import org.apache.geronimo.gbean.AbstractNameQuery;
043: import org.apache.geronimo.gbean.GBeanData;
044: import org.apache.geronimo.gbean.GBeanInfo;
045: import org.apache.geronimo.gbean.GBeanInfoBuilder;
046: import org.apache.geronimo.j2ee.deployment.EARContext;
047: import org.apache.geronimo.j2ee.deployment.Module;
048: import org.apache.geronimo.j2ee.deployment.ModuleBuilderExtension;
049: import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
050: import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
051: import org.apache.geronimo.kernel.GBeanNotFoundException;
052: import org.apache.geronimo.kernel.Naming;
053: import org.apache.geronimo.kernel.config.ConfigurationStore;
054: import org.apache.geronimo.kernel.repository.Environment;
055: import org.apache.geronimo.naming.deployment.ENCConfigBuilder;
056: import org.apache.geronimo.openejb.cluster.infra.BasicNetworkConnectorTrackerServiceHolder;
057: import org.apache.geronimo.openejb.cluster.infra.NetworkConnectorMonitor;
058: import org.apache.geronimo.openejb.cluster.stateful.deployment.ClusteredStatefulDeployment;
059: import org.apache.geronimo.openejb.deployment.BasicEjbDeploymentGBeanNameBuilder;
060: import org.apache.geronimo.openejb.deployment.EjbDeploymentGBeanNameBuilder;
061: import org.apache.geronimo.openejb.deployment.EjbModule;
062: import org.apache.geronimo.openejb.deployment.XmlUtil;
063: import org.apache.geronimo.openejb.xbeans.ejbjar.OpenejbGeronimoEjbJarType;
064: import org.apache.geronimo.schema.SchemaConversionUtils;
065: import org.apache.geronimo.xbeans.geronimo.GerOpenejbClusteringWadiDocument;
066: import org.apache.geronimo.xbeans.geronimo.GerOpenejbClusteringWadiType;
067: import org.apache.geronimo.xbeans.geronimo.j2ee.GerClusteringDocument;
068: import org.apache.geronimo.xbeans.geronimo.naming.GerPatternType;
069: import org.apache.openejb.jee.EjbJar;
070: import org.apache.openejb.jee.EnterpriseBean;
071: import org.apache.openejb.jee.SessionBean;
072: import org.apache.openejb.jee.oejb2.GeronimoEjbJarType;
073: import org.apache.xmlbeans.QNameSet;
074: import org.apache.xmlbeans.XmlObject;
075:
076: /**
077: *
078: * @version $Rev:$ $Date:$
079: */
080: public class WADIOpenEJBClusteringBuilder implements
081: ModuleBuilderExtension {
082: private static final QName CLUSTERING_WADI_QNAME = GerOpenejbClusteringWadiDocument.type
083: .getDocumentElementName();
084: private static final QNameSet CLUSTERING_WADI_QNAME_SET = QNameSet
085: .singleton(CLUSTERING_WADI_QNAME);
086:
087: static {
088: SchemaConversionUtils.registerNamespaceConversions(Collections
089: .singletonMap(CLUSTERING_WADI_QNAME.getLocalPart(),
090: new OpenEJBClusteringWADIConverter()));
091: }
092:
093: private final String defaultClusteredStatefulContainerId;
094: private final EjbDeploymentGBeanNameBuilder beanNameBuilder;
095: private final int defaultSweepInterval;
096: private final int defaultSessionTimeout;
097: private final int defaultNumPartitions;
098: private final AbstractNameQuery defaultBackingStrategyFactoryName;
099: private final AbstractNameQuery defaultClusterName;
100: private final AbstractNameQuery defaultNetworkConnectorName;
101: private final Environment defaultEnvironment;
102:
103: public WADIOpenEJBClusteringBuilder(
104: String defaultClusteredStatefulContainerId,
105: int defaultSweepInterval, int defaultSessionTimeout,
106: int defaultNumPartitions,
107: AbstractNameQuery defaultBackingStrategyFactoryName,
108: AbstractNameQuery defaultClusterName,
109: AbstractNameQuery defaultNetworkConnectorName,
110: Environment defaultEnvironment) {
111: if (null == defaultClusteredStatefulContainerId) {
112: throw new IllegalArgumentException(
113: "defaultClusteredStatefulContainerId is required");
114: } else if (defaultSweepInterval < 1) {
115: throw new IllegalArgumentException(
116: "defaultSweepInterval is lower than 1");
117: } else if (defaultSessionTimeout < 1) {
118: throw new IllegalArgumentException(
119: "defaultSessionTimeout is lower than 1");
120: } else if (defaultNumPartitions < 1) {
121: throw new IllegalArgumentException(
122: "defaultNumPartitions is lower than 1");
123: } else if (null == defaultBackingStrategyFactoryName) {
124: throw new IllegalArgumentException(
125: "defaultBackingStrategyFactoryName is required");
126: } else if (null == defaultClusterName) {
127: throw new IllegalArgumentException(
128: "defaultClusterName is required");
129: } else if (null == defaultEnvironment) {
130: throw new IllegalArgumentException(
131: "defaultEnvironment is required");
132: } else if (null == defaultNetworkConnectorName) {
133: throw new IllegalArgumentException(
134: "defaultNetworkConnectorName is required");
135: }
136: this .defaultClusteredStatefulContainerId = defaultClusteredStatefulContainerId;
137: this .defaultSweepInterval = defaultSweepInterval;
138: this .defaultSessionTimeout = defaultSessionTimeout;
139: this .defaultNumPartitions = defaultNumPartitions;
140: this .defaultBackingStrategyFactoryName = defaultBackingStrategyFactoryName;
141: this .defaultClusterName = defaultClusterName;
142: this .defaultNetworkConnectorName = defaultNetworkConnectorName;
143: this .defaultEnvironment = defaultEnvironment;
144:
145: beanNameBuilder = new BasicEjbDeploymentGBeanNameBuilder();
146:
147: new NamespaceDrivenBuilderCollection(Collections
148: .singleton(new NamespaceDrivenBuilder() {
149: public void build(XmlObject container,
150: DeploymentContext applicationContext,
151: DeploymentContext moduleContext)
152: throws DeploymentException {
153: }
154:
155: public void buildEnvironment(XmlObject container,
156: Environment environment)
157: throws DeploymentException {
158: }
159:
160: public QNameSet getPlanQNameSet() {
161: return CLUSTERING_WADI_QNAME_SET;
162: }
163:
164: public QNameSet getSpecQNameSet() {
165: return QNameSet.EMPTY;
166: }
167: }), GerClusteringDocument.type.getDocumentElementName());
168: }
169:
170: public void addGBeans(EARContext earContext, Module module,
171: ClassLoader cl, Collection repository)
172: throws DeploymentException {
173: EjbModule ejbModule = (EjbModule) module;
174:
175: OpenejbGeronimoEjbJarType geronimoEjbJarType = ejbModule
176: .getVendorDD();
177: GerOpenejbClusteringWadiType clusteringWadiType = getWadiClusterConfig(geronimoEjbJarType);
178: AbstractName sessionManagerName = addSessionManager(
179: clusteringWadiType, ejbModule, earContext);
180:
181: addNetworkConnectorMonitor(earContext, sessionManagerName);
182:
183: EjbJar ejbJar = ejbModule.getEjbJar();
184: for (EnterpriseBean enterpriseBean : ejbJar
185: .getEnterpriseBeans()) {
186: if (enterpriseBean instanceof SessionBean) {
187: SessionBean sessionBean = (SessionBean) enterpriseBean;
188: switch (sessionBean.getSessionType()) {
189: case STATEFUL:
190: replaceByClusteredDeploymentGBean(earContext,
191: ejbModule, sessionManagerName,
192: enterpriseBean);
193: }
194: }
195: }
196: }
197:
198: protected void replaceByClusteredDeploymentGBean(
199: EARContext earContext, EjbModule ejbModule,
200: AbstractName sessionManagerName,
201: EnterpriseBean enterpriseBean) throws DeploymentException {
202: AbstractName name = beanNameBuilder.createEjbName(earContext,
203: ejbModule, enterpriseBean);
204: GBeanData beanInstance;
205: try {
206: beanInstance = earContext.getGBeanInstance(name);
207: earContext.removeGBean(name);
208: } catch (GBeanNotFoundException e) {
209: throw new DeploymentException("No GBean [" + name + "]", e);
210: }
211: GBeanData clusteredDeploymentGBean = new GBeanData(beanInstance);
212: clusteredDeploymentGBean
213: .setGBeanInfo(ClusteredStatefulDeployment.GBEAN_INFO);
214: clusteredDeploymentGBean.setReferencePattern(
215: ClusteredStatefulDeployment.GBEAN_REF_SESSION_MANAGER,
216: sessionManagerName);
217: try {
218: earContext.addGBean(clusteredDeploymentGBean);
219: } catch (GBeanAlreadyExistsException e) {
220: throw new DeploymentException("See nested", e);
221: }
222: }
223:
224: public void createModule(Module module, Object plan,
225: JarFile moduleFile, String targetPath, URL specDDUrl,
226: Environment environment, Object moduleContextInfo,
227: AbstractName earName, Naming naming,
228: ModuleIDBuilder idBuilder) throws DeploymentException {
229: EjbModule ejbModule = (EjbModule) module;
230: GeronimoEjbJarType tmpGeronimoEjbJarType = (GeronimoEjbJarType) ejbModule
231: .getEjbModule().getAltDDs().get("geronimo-openejb.xml");
232: OpenejbGeronimoEjbJarType geronimoEjbJarType = XmlUtil
233: .convertToXmlbeans(tmpGeronimoEjbJarType);
234: GerOpenejbClusteringWadiType clusteringWadiType = getWadiClusterConfig(geronimoEjbJarType);
235: if (null == clusteringWadiType) {
236: return;
237: }
238:
239: EnvironmentBuilder.mergeEnvironments(environment,
240: defaultEnvironment);
241:
242: ejbModule.getPreAutoConfigDeployer().add(
243: new MapSFSBToContainerIDDeployer(
244: defaultClusteredStatefulContainerId));
245: }
246:
247: public void initContext(EARContext earContext, Module module,
248: ClassLoader cl) throws DeploymentException {
249: }
250:
251: public void installModule(JarFile earFile, EARContext earContext,
252: Module module, Collection configurationStores,
253: ConfigurationStore targetConfigurationStore,
254: Collection repository) throws DeploymentException {
255: }
256:
257: protected AbstractName addSessionManager(
258: GerOpenejbClusteringWadiType clustering,
259: EjbModule ejbModule, DeploymentContext moduleContext)
260: throws DeploymentException {
261: AbstractName name = newGBeanName(moduleContext,
262: "WADISessionManager");
263:
264: GBeanData beanData = new GBeanData(name,
265: BasicWADISessionManager.GBEAN_INFO);
266:
267: setConfigInfo(clustering, ejbModule, beanData);
268: setCluster(clustering, beanData);
269: setBackingStrategyFactory(clustering, beanData);
270: setClusteredServiceHolders(moduleContext, beanData);
271:
272: addGBean(moduleContext, beanData);
273:
274: return name;
275: }
276:
277: protected void setClusteredServiceHolders(
278: DeploymentContext moduleContext, GBeanData beanData)
279: throws DeploymentException {
280: AbstractName name = newGBeanName(moduleContext,
281: "NetworkConnectorTrackerHolder");
282:
283: GBeanData serviceHolder = new GBeanData(name,
284: BasicNetworkConnectorTrackerServiceHolder.GBEAN_INFO);
285: addGBean(moduleContext, serviceHolder);
286:
287: beanData
288: .setReferencePattern(
289: BasicWADISessionManager.GBEAN_REF_SERVICE_HOLDERS,
290: name);
291: }
292:
293: protected void addNetworkConnectorMonitor(
294: DeploymentContext moduleContext,
295: AbstractName sessionManagerName) throws DeploymentException {
296: AbstractName name = newGBeanName(moduleContext,
297: "NetworkConnectorMonitor");
298:
299: GBeanData networkConnectorMonitor = new GBeanData(name,
300: NetworkConnectorMonitor.GBEAN_INFO);
301: networkConnectorMonitor.setReferencePattern(
302: NetworkConnectorMonitor.GBEAN_REF_NETWORK_CONNECTORS,
303: defaultNetworkConnectorName);
304: networkConnectorMonitor.setReferencePattern(
305: NetworkConnectorMonitor.GBEAN_REF_EJB_DEP_ID_ACCESSOR,
306: new AbstractNameQuery(ClusteredStatefulDeployment.class
307: .getName()));
308: networkConnectorMonitor.setReferencePattern(
309: NetworkConnectorMonitor.GBEAN_REF_WADI_SESSION_MANAGER,
310: sessionManagerName);
311:
312: addGBean(moduleContext, networkConnectorMonitor);
313: }
314:
315: protected AbstractName newGBeanName(
316: DeploymentContext moduleContext, String name) {
317: return moduleContext.getNaming().createChildName(
318: moduleContext.getModuleName(), name,
319: NameFactory.GERONIMO_SERVICE);
320: }
321:
322: protected void addGBean(DeploymentContext moduleContext,
323: GBeanData beanData) throws DeploymentException {
324: try {
325: moduleContext.addGBean(beanData);
326: } catch (GBeanAlreadyExistsException e) {
327: throw new DeploymentException(e);
328: }
329: }
330:
331: protected void setCluster(GerOpenejbClusteringWadiType clustering,
332: GBeanData beanData) {
333: Set<AbstractNameQuery> patterns = new HashSet<AbstractNameQuery>();
334: if (clustering.isSetCluster()) {
335: addAbstractNameQueries(patterns, clustering.getCluster());
336: } else {
337: patterns.add(defaultClusterName);
338: }
339: beanData.setReferencePatterns(
340: BasicWADISessionManager.GBEAN_REF_CLUSTER, patterns);
341: }
342:
343: protected void setBackingStrategyFactory(
344: GerOpenejbClusteringWadiType clustering, GBeanData beanData) {
345: Set<AbstractNameQuery> patterns = new HashSet<AbstractNameQuery>();
346: if (clustering.isSetBackingStrategyFactory()) {
347: addAbstractNameQueries(patterns, clustering
348: .getBackingStrategyFactory());
349: } else {
350: patterns.add(defaultBackingStrategyFactoryName);
351: }
352: beanData
353: .setReferencePatterns(
354: BasicWADISessionManager.GBEAN_REF_BACKING_STRATEGY_FACTORY,
355: patterns);
356: }
357:
358: protected void addAbstractNameQueries(
359: Set<AbstractNameQuery> patterns, GerPatternType patternType) {
360: AbstractNameQuery query = ENCConfigBuilder
361: .buildAbstractNameQuery(patternType, null, null, null);
362: patterns.add(query);
363: }
364:
365: protected void setConfigInfo(
366: GerOpenejbClusteringWadiType clustering,
367: EjbModule ejbModule, GBeanData beanData) {
368: int sweepInterval = getSweepInterval(clustering);
369: int numPartitions = getNumberOfPartitions(clustering);
370: Integer sessionTimeout = getSessionTimeout();
371: boolean disableReplication = isDisableReplication(clustering);
372: boolean deltaReplication = isDeltaReplication(clustering);
373:
374: String ejbModuleName = (String) ejbModule.getName();
375: URI serviceSpaceName;
376: try {
377: serviceSpaceName = new URI(ejbModuleName);
378: } catch (URISyntaxException e) {
379: AssertionError error = new AssertionError("contextPath ["
380: + ejbModuleName + "] cannot be parsed as an URI.");
381: throw (AssertionError) error.initCause(e);
382: }
383:
384: WADISessionManagerConfigInfo configInfo = new WADISessionManagerConfigInfo(
385: serviceSpaceName, sweepInterval, numPartitions,
386: sessionTimeout.intValue(), disableReplication,
387: deltaReplication);
388: beanData.setAttribute(
389: BasicWADISessionManager.GBEAN_ATTR_WADI_CONFIG_INFO,
390: configInfo);
391: }
392:
393: protected Integer getSessionTimeout() throws AssertionError {
394: return defaultSessionTimeout;
395: }
396:
397: protected int getSweepInterval(
398: GerOpenejbClusteringWadiType clustering) {
399: if (clustering.isSetSweepInterval()) {
400: return clustering.getSweepInterval().intValue();
401: }
402: return defaultSweepInterval;
403: }
404:
405: protected boolean isDeltaReplication(
406: GerOpenejbClusteringWadiType clustering) {
407: if (clustering.isSetDeltaReplication()) {
408: return clustering.getDeltaReplication();
409: }
410: return false;
411: }
412:
413: protected boolean isDisableReplication(
414: GerOpenejbClusteringWadiType clustering) {
415: if (clustering.isSetDisableReplication()) {
416: return clustering.getDisableReplication();
417: }
418: return false;
419: }
420:
421: protected int getNumberOfPartitions(
422: GerOpenejbClusteringWadiType clustering) {
423: if (clustering.isSetNumPartitions()) {
424: return clustering.getNumPartitions().intValue();
425: }
426: return defaultNumPartitions;
427: }
428:
429: protected GerOpenejbClusteringWadiType getWadiClusterConfig(
430: XmlObject container) throws DeploymentException {
431: XmlObject[] items = container
432: .selectChildren(CLUSTERING_WADI_QNAME_SET);
433: if (items.length > 1) {
434: throw new DeploymentException(
435: "Unexpected count of clustering elements in geronimo plan "
436: + items.length + " qnameset: "
437: + CLUSTERING_WADI_QNAME_SET);
438: }
439: if (items.length == 1) {
440: return (GerOpenejbClusteringWadiType) items[0].copy()
441: .changeType(GerOpenejbClusteringWadiType.type);
442: }
443: return null;
444: }
445:
446: public static final GBeanInfo GBEAN_INFO;
447:
448: public static final String GBEAN_ATTR_DFT_CLUSTERED_SFSB_CONT_ID = "defaultClusteredStatefulContainerId";
449: public static final String GBEAN_ATTR_DFT_SWEEP_INTERVAL = "defaultSweepInterval";
450: public static final String GBEAN_ATTR_DFT_SESSION_TIMEOUT = "defaultSessionTimeout";
451: public static final String GBEAN_ATTR_DFT_NUM_PARTITIONS = "defaultNumPartitions";
452: public static final String GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME = "defaultBackingStrategyFactoryName";
453: public static final String GBEAN_ATTR_DFT_CLUSTER_NAME = "defaultClusterName";
454: public static final String GBEAN_ATTR_DFT_NETWORK_CONNECTOR_NAME = "defaultNetworkConnectorName";
455: public static final String GBEAN_ATTR_DFT_ENVIRONMENT = "defaultEnvironment";
456:
457: static {
458: GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(
459: "WADI OpenEJB Clusteting Builder",
460: WADIOpenEJBClusteringBuilder.class,
461: NameFactory.MODULE_BUILDER);
462:
463: infoBuilder.addAttribute(GBEAN_ATTR_DFT_CLUSTERED_SFSB_CONT_ID,
464: String.class, true);
465: infoBuilder.addAttribute(GBEAN_ATTR_DFT_SWEEP_INTERVAL,
466: int.class, true);
467: infoBuilder.addAttribute(GBEAN_ATTR_DFT_SESSION_TIMEOUT,
468: int.class, true);
469: infoBuilder.addAttribute(GBEAN_ATTR_DFT_NUM_PARTITIONS,
470: int.class, true);
471: infoBuilder.addAttribute(
472: GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME,
473: AbstractNameQuery.class, true);
474: infoBuilder.addAttribute(GBEAN_ATTR_DFT_CLUSTER_NAME,
475: AbstractNameQuery.class, true);
476: infoBuilder.addAttribute(GBEAN_ATTR_DFT_NETWORK_CONNECTOR_NAME,
477: AbstractNameQuery.class, true);
478: infoBuilder.addAttribute(GBEAN_ATTR_DFT_ENVIRONMENT,
479: Environment.class, true);
480:
481: infoBuilder.setConstructor(new String[] {
482: GBEAN_ATTR_DFT_CLUSTERED_SFSB_CONT_ID,
483: GBEAN_ATTR_DFT_SWEEP_INTERVAL,
484: GBEAN_ATTR_DFT_SESSION_TIMEOUT,
485: GBEAN_ATTR_DFT_NUM_PARTITIONS,
486: GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME,
487: GBEAN_ATTR_DFT_CLUSTER_NAME,
488: GBEAN_ATTR_DFT_NETWORK_CONNECTOR_NAME,
489: GBEAN_ATTR_DFT_ENVIRONMENT });
490:
491: GBEAN_INFO = infoBuilder.getBeanInfo();
492: }
493:
494: public static GBeanInfo getGBeanInfo() {
495: return GBEAN_INFO;
496: }
497:
498: }
|