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