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.tomcat.cluster.wadi.builder;
021:
022: import java.net.URI;
023: import java.net.URISyntaxException;
024: import java.util.Collections;
025: import java.util.HashSet;
026: import java.util.Set;
027:
028: import javax.xml.namespace.QName;
029:
030: import org.apache.geronimo.clustering.wadi.BasicWADISessionManager;
031: import org.apache.geronimo.clustering.wadi.WADISessionManagerConfigInfo;
032: import org.apache.geronimo.common.DeploymentException;
033: import org.apache.geronimo.deployment.DeploymentContext;
034: import org.apache.geronimo.deployment.NamespaceDrivenBuilder;
035: import org.apache.geronimo.deployment.service.EnvironmentBuilder;
036: import org.apache.geronimo.gbean.AbstractName;
037: import org.apache.geronimo.gbean.AbstractNameQuery;
038: import org.apache.geronimo.gbean.GBeanData;
039: import org.apache.geronimo.gbean.GBeanInfo;
040: import org.apache.geronimo.gbean.GBeanInfoBuilder;
041: import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
042: import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
043: import org.apache.geronimo.kernel.GBeanNotFoundException;
044: import org.apache.geronimo.kernel.config.Configuration;
045: import org.apache.geronimo.kernel.repository.Environment;
046: import org.apache.geronimo.naming.deployment.ENCConfigBuilder;
047: import org.apache.geronimo.schema.SchemaConversionUtils;
048: import org.apache.geronimo.tomcat.TomcatWebAppContext;
049: import org.apache.geronimo.tomcat.cluster.ClusteredManagerRetriever;
050: import org.apache.geronimo.tomcat.cluster.wadi.WADIClusteredValveRetriever;
051: import org.apache.geronimo.xbeans.geronimo.GerTomcatClusteringWadiDocument;
052: import org.apache.geronimo.xbeans.geronimo.GerTomcatClusteringWadiType;
053: import org.apache.geronimo.xbeans.geronimo.naming.GerPatternType;
054: import org.apache.xmlbeans.QNameSet;
055: import org.apache.xmlbeans.XmlObject;
056:
057: /**
058: *
059: * @version $Rev:$ $Date:$
060: */
061: public class WADITomcatClusteringBuilder implements
062: NamespaceDrivenBuilder {
063: private static final QName CLUSTERING_WADI_QNAME = GerTomcatClusteringWadiDocument.type
064: .getDocumentElementName();
065: private static final QNameSet CLUSTERING_WADI_QNAME_SET = QNameSet
066: .singleton(CLUSTERING_WADI_QNAME);
067:
068: static {
069: SchemaConversionUtils.registerNamespaceConversions(Collections
070: .singletonMap(CLUSTERING_WADI_QNAME.getLocalPart(),
071: new TomcatClusteringWADIConverter()));
072: }
073:
074: private final int defaultSweepInterval;
075: private final int defaultSessionTimeout;
076: private final int defaultNumPartitions;
077: private final AbstractNameQuery defaultBackingStrategyFactoryName;
078: private final AbstractNameQuery defaultClusterName;
079: private final Environment defaultEnvironment;
080:
081: public WADITomcatClusteringBuilder(int defaultSweepInterval,
082: int defaultSessionTimeout, int defaultNumPartitions,
083: AbstractNameQuery defaultBackingStrategyFactoryName,
084: AbstractNameQuery defaultClusterName,
085: Environment defaultEnvironment) {
086: if (defaultSweepInterval < 1) {
087: throw new IllegalArgumentException(
088: "defaultSweepInterval is lower than 1");
089: } else if (defaultSessionTimeout < 1) {
090: throw new IllegalArgumentException(
091: "defaultSessionTimeout is lower than 1");
092: } else if (defaultNumPartitions < 1) {
093: throw new IllegalArgumentException(
094: "defaultNumPartitions is lower than 1");
095: } else if (null == defaultBackingStrategyFactoryName) {
096: throw new IllegalArgumentException(
097: "defaultBackingStrategyFactoryName is required");
098: } else if (null == defaultClusterName) {
099: throw new IllegalArgumentException(
100: "defaultClusterName is required");
101: } else if (null == defaultEnvironment) {
102: throw new IllegalArgumentException(
103: "defaultEnvironment is required");
104: }
105: this .defaultSweepInterval = defaultSweepInterval;
106: this .defaultSessionTimeout = defaultSessionTimeout;
107: this .defaultNumPartitions = defaultNumPartitions;
108: this .defaultBackingStrategyFactoryName = defaultBackingStrategyFactoryName;
109: this .defaultClusterName = defaultClusterName;
110: this .defaultEnvironment = defaultEnvironment;
111: }
112:
113: public void buildEnvironment(XmlObject container,
114: Environment environment) throws DeploymentException {
115: if (getWadiClusterConfig(container) != null) {
116: EnvironmentBuilder.mergeEnvironments(environment,
117: defaultEnvironment);
118: }
119: }
120:
121: public void build(XmlObject container,
122: DeploymentContext applicationContext,
123: DeploymentContext moduleContext) throws DeploymentException {
124: GerTomcatClusteringWadiType clusteringWadiType = getWadiClusterConfig(container);
125: if (clusteringWadiType != null) {
126: GBeanData webModuleData = extractWebModule(moduleContext);
127: try {
128: AbstractName sessionManagerName = addSessionManager(
129: clusteringWadiType, webModuleData,
130: moduleContext);
131: addClusteredManagerRetriever(moduleContext,
132: webModuleData, sessionManagerName);
133: addClusteredValveRetriever(moduleContext,
134: webModuleData, sessionManagerName);
135: } catch (GBeanAlreadyExistsException e) {
136: throw new DeploymentException("Duplicate GBean", e);
137: }
138: }
139: }
140:
141: protected GBeanData extractWebModule(DeploymentContext moduleContext)
142: throws DeploymentException {
143: Configuration configuration = moduleContext.getConfiguration();
144: AbstractNameQuery webModuleQuery = new AbstractNameQuery(
145: configuration.getId(), Collections.EMPTY_MAP,
146: Collections.singleton(TomcatWebAppContext.class
147: .getName()));
148: try {
149: return configuration.findGBeanData(webModuleQuery);
150: } catch (GBeanNotFoundException e) {
151: throw new DeploymentException(
152: "Could not locate web module gbean in web app configuration",
153: e);
154: }
155: }
156:
157: public QNameSet getSpecQNameSet() {
158: return QNameSet.EMPTY;
159: }
160:
161: public QNameSet getPlanQNameSet() {
162: return CLUSTERING_WADI_QNAME_SET;
163: }
164:
165: protected GerTomcatClusteringWadiType getWadiClusterConfig(
166: XmlObject container) throws DeploymentException {
167: XmlObject[] items = container
168: .selectChildren(CLUSTERING_WADI_QNAME_SET);
169: if (items.length > 1) {
170: throw new DeploymentException(
171: "Unexpected count of clustering elements in geronimo plan "
172: + items.length + " qnameset: "
173: + CLUSTERING_WADI_QNAME_SET);
174: }
175: if (items.length == 1) {
176: return (GerTomcatClusteringWadiType) items[0].copy()
177: .changeType(GerTomcatClusteringWadiType.type);
178: }
179: return null;
180: }
181:
182: protected AbstractName addSessionManager(
183: GerTomcatClusteringWadiType clustering,
184: GBeanData webModuleData, DeploymentContext moduleContext)
185: throws GBeanAlreadyExistsException {
186: AbstractName name = newGBeanName(moduleContext,
187: "WADISessionManager");
188:
189: GBeanData beanData = new GBeanData(name,
190: BasicWADISessionManager.GBEAN_INFO);
191:
192: setConfigInfo(clustering, webModuleData, beanData);
193: setCluster(clustering, beanData);
194: setBackingStrategyFactory(clustering, beanData);
195:
196: addGBean(moduleContext, beanData);
197:
198: return name;
199: }
200:
201: protected void setConfigInfo(
202: GerTomcatClusteringWadiType clustering,
203: GBeanData webModuleData, GBeanData beanData) {
204: int sweepInterval = getSweepInterval(clustering);
205: int numPartitions = getNumberOfPartitions(clustering);
206: Integer sessionTimeout = getSessionTimeout(webModuleData);
207: boolean disableReplication = isDisableReplication(clustering);
208: boolean deltaReplication = isDeltaReplication(clustering);
209:
210: String contextPath = (String) webModuleData
211: .getAttribute("contextPath");
212: URI serviceSpaceName;
213: try {
214: serviceSpaceName = new URI(contextPath);
215: } catch (URISyntaxException e) {
216: AssertionError error = new AssertionError("contextPath ["
217: + contextPath + "] cannot be parsed as an URI.");
218: throw (AssertionError) error.initCause(e);
219: }
220:
221: WADISessionManagerConfigInfo configInfo = new WADISessionManagerConfigInfo(
222: serviceSpaceName, sweepInterval, numPartitions,
223: sessionTimeout.intValue(), disableReplication,
224: deltaReplication);
225: beanData.setAttribute(
226: BasicWADISessionManager.GBEAN_ATTR_WADI_CONFIG_INFO,
227: configInfo);
228: }
229:
230: protected Integer getSessionTimeout(GBeanData webModuleData)
231: throws AssertionError {
232: return defaultSessionTimeout;
233: }
234:
235: protected boolean isDeltaReplication(
236: GerTomcatClusteringWadiType clustering) {
237: if (clustering.isSetDeltaReplication()) {
238: return clustering.getDeltaReplication();
239: }
240: return false;
241: }
242:
243: protected boolean isDisableReplication(
244: GerTomcatClusteringWadiType clustering) {
245: if (clustering.isSetDisableReplication()) {
246: return clustering.getDisableReplication();
247: }
248: return false;
249: }
250:
251: protected int getNumberOfPartitions(
252: GerTomcatClusteringWadiType clustering) {
253: if (clustering.isSetNumPartitions()) {
254: return clustering.getNumPartitions().intValue();
255: }
256: return defaultNumPartitions;
257: }
258:
259: protected int getSweepInterval(
260: GerTomcatClusteringWadiType clustering) {
261: if (clustering.isSetSweepInterval()) {
262: return clustering.getSweepInterval().intValue();
263: }
264: return defaultSweepInterval;
265: }
266:
267: protected void setCluster(GerTomcatClusteringWadiType clustering,
268: GBeanData beanData) {
269: Set patterns = new HashSet();
270: if (clustering.isSetCluster()) {
271: addAbstractNameQueries(patterns, clustering.getCluster());
272: } else {
273: patterns.add(defaultClusterName);
274: }
275: beanData.setReferencePatterns(
276: BasicWADISessionManager.GBEAN_REF_CLUSTER, patterns);
277: }
278:
279: protected void setBackingStrategyFactory(
280: GerTomcatClusteringWadiType clustering, GBeanData beanData) {
281: Set patterns = new HashSet();
282: if (clustering.isSetBackingStrategyFactory()) {
283: addAbstractNameQueries(patterns, clustering
284: .getBackingStrategyFactory());
285: } else {
286: patterns.add(defaultBackingStrategyFactoryName);
287: }
288: beanData
289: .setReferencePatterns(
290: BasicWADISessionManager.GBEAN_REF_BACKING_STRATEGY_FACTORY,
291: patterns);
292: }
293:
294: protected AbstractName addClusteredValveRetriever(
295: DeploymentContext moduleContext, GBeanData webModuleData,
296: AbstractName sessionManagerName)
297: throws GBeanAlreadyExistsException {
298: AbstractName name = newGBeanName(moduleContext,
299: "WADIClusteredValveRetriever");
300:
301: GBeanData beanData = new GBeanData(name,
302: WADIClusteredValveRetriever.GBEAN_INFO);
303: beanData
304: .setReferencePattern(
305: WADIClusteredValveRetriever.GBEAN_REF_WADI_SESSION_MANAGER,
306: sessionManagerName);
307:
308: webModuleData
309: .setReferencePattern(
310: TomcatWebAppContext.GBEAN_REF_CLUSTERED_VALVE_RETRIEVER,
311: name);
312:
313: addGBean(moduleContext, beanData);
314:
315: return name;
316: }
317:
318: protected AbstractName addClusteredManagerRetriever(
319: DeploymentContext moduleContext, GBeanData webModuleData,
320: AbstractName sessionManagerName)
321: throws GBeanAlreadyExistsException {
322: AbstractName name = newGBeanName(moduleContext,
323: "ClusteredManagerRetriever");
324:
325: GBeanData beanData = new GBeanData(name,
326: ClusteredManagerRetriever.GBEAN_INFO);
327: beanData.setReferencePattern(
328: ClusteredManagerRetriever.GBEAN_REF_SESSION_MANAGER,
329: sessionManagerName);
330:
331: webModuleData.setReferencePattern(
332: TomcatWebAppContext.GBEAN_REF_MANAGER_RETRIEVER, name);
333:
334: addGBean(moduleContext, beanData);
335:
336: return name;
337: }
338:
339: protected void addGBean(DeploymentContext moduleContext,
340: GBeanData beanData) throws GBeanAlreadyExistsException {
341: moduleContext.addGBean(beanData);
342: }
343:
344: protected AbstractName newGBeanName(
345: DeploymentContext moduleContext, String name) {
346: return moduleContext.getNaming().createChildName(
347: moduleContext.getModuleName(), name,
348: NameFactory.GERONIMO_SERVICE);
349: }
350:
351: protected void addAbstractNameQueries(Set patterns,
352: GerPatternType patternType) {
353: AbstractNameQuery query = ENCConfigBuilder
354: .buildAbstractNameQuery(patternType, null, null, null);
355: patterns.add(query);
356: }
357:
358: public static final GBeanInfo GBEAN_INFO;
359:
360: public static final String GBEAN_ATTR_DFT_SWEEP_INTERVAL = "defaultSweepInterval";
361: public static final String GBEAN_ATTR_DFT_SESSION_TIMEOUT = "defaultSessionTimeout";
362: public static final String GBEAN_ATTR_DFT_NUM_PARTITIONS = "defaultNumPartitions";
363: public static final String GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME = "defaultBackingStrategyFactoryName";
364: public static final String GBEAN_ATTR_DFT_CLUSTER_NAME = "defaultClusterName";
365: public static final String GBEAN_ATTR_DFT_ENVIRONMENT = "defaultEnvironment";
366:
367: static {
368: GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(
369: "WADI Session Manager",
370: WADITomcatClusteringBuilder.class,
371: NameFactory.MODULE_BUILDER);
372:
373: infoBuilder.addAttribute(GBEAN_ATTR_DFT_SWEEP_INTERVAL,
374: int.class, true);
375: infoBuilder.addAttribute(GBEAN_ATTR_DFT_SESSION_TIMEOUT,
376: int.class, true);
377: infoBuilder.addAttribute(GBEAN_ATTR_DFT_NUM_PARTITIONS,
378: int.class, true);
379: infoBuilder.addAttribute(
380: GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME,
381: AbstractNameQuery.class, true);
382: infoBuilder.addAttribute(GBEAN_ATTR_DFT_CLUSTER_NAME,
383: AbstractNameQuery.class, true);
384: infoBuilder.addAttribute(GBEAN_ATTR_DFT_ENVIRONMENT,
385: Environment.class, true);
386:
387: infoBuilder
388: .setConstructor(new String[] {
389: GBEAN_ATTR_DFT_SWEEP_INTERVAL,
390: GBEAN_ATTR_DFT_SESSION_TIMEOUT,
391: GBEAN_ATTR_DFT_NUM_PARTITIONS,
392: GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME,
393: GBEAN_ATTR_DFT_CLUSTER_NAME,
394: GBEAN_ATTR_DFT_ENVIRONMENT });
395:
396: GBEAN_INFO = infoBuilder.getBeanInfo();
397: }
398:
399: public static GBeanInfo getGBeanInfo() {
400: return GBEAN_INFO;
401: }
402:
403: }
|