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