1 /**
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one or more
4 * contributor license agreements. See the NOTICE file distributed with
5 * this work for additional information regarding copyright ownership.
6 * The ASF licenses this file to You under the Apache License, Version 2.0
7 * (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 package org.apache.geronimo.clustering.wadi.jetty;
19
20 import java.util.Collections;
21 import java.util.HashSet;
22 import java.util.Set;
23
24 import javax.xml.namespace.QName;
25
26 import org.apache.geronimo.clustering.wadi.BasicWADISessionManager;
27 import org.apache.geronimo.clustering.wadi.WADISessionManagerConfigInfo;
28 import org.apache.geronimo.common.DeploymentException;
29 import org.apache.geronimo.deployment.DeploymentContext;
30 import org.apache.geronimo.deployment.NamespaceDrivenBuilder;
31 import org.apache.geronimo.deployment.service.EnvironmentBuilder;
32 import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
33 import org.apache.geronimo.gbean.AbstractName;
34 import org.apache.geronimo.gbean.AbstractNameQuery;
35 import org.apache.geronimo.gbean.GBeanData;
36 import org.apache.geronimo.gbean.GBeanInfo;
37 import org.apache.geronimo.gbean.GBeanInfoBuilder;
38 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
39 import org.apache.geronimo.jetty.JettyWebAppContext;
40 import org.apache.geronimo.jetty.cluster.ClusteredWebApplicationHandlerFactory;
41 import org.apache.geronimo.jetty.cluster.wadi.WADIClusteredHandleInterceptor;
42 import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
43 import org.apache.geronimo.kernel.GBeanNotFoundException;
44 import org.apache.geronimo.kernel.config.Configuration;
45 import org.apache.geronimo.kernel.repository.Environment;
46 import org.apache.geronimo.naming.deployment.ENCConfigBuilder;
47 import org.apache.geronimo.schema.NamespaceElementConverter;
48 import org.apache.geronimo.schema.SchemaConversionUtils;
49 import org.apache.geronimo.xbeans.geronimo.GerClusteringWadiDocument;
50 import org.apache.geronimo.xbeans.geronimo.GerClusteringWadiType;
51 import org.apache.geronimo.xbeans.geronimo.naming.GerPatternType;
52 import org.apache.xmlbeans.QNameSet;
53 import org.apache.xmlbeans.XmlObject;
54
55 /**
56 *
57 * @version $Rev$ $Date$
58 */
59 public class WADIJettyClusteringBuilder implements NamespaceDrivenBuilder {
60 private static final QName CLUSTERING_WADI_QNAME = GerClusteringWadiDocument.type.getDocumentElementName();
61 private static final QNameSet CLUSTERING_WADI_QNAME_SET = QNameSet.singleton(CLUSTERING_WADI_QNAME);
62
63 private final int defaultSweepInterval;
64 private final int defaultNumPartitions;
65 private final AbstractNameQuery defaultRepManagerFactoryName;
66 private final AbstractNameQuery defaultRepStorageFactoryName;
67 private final AbstractNameQuery defaultBackingStrategyFactoryName;
68 private final AbstractNameQuery defaultDispatcherHolderName;
69 private final Environment defaultEnvironment;
70
71 public WADIJettyClusteringBuilder(int defaultSweepInterval,
72 int defaultNumPartitions,
73 AbstractNameQuery defaultRepManagerFactoryName,
74 AbstractNameQuery defaultRepStorageFactoryName,
75 AbstractNameQuery defaultBackingStrategyFactoryName,
76 AbstractNameQuery defaultDispatcherHolderName,
77 Environment defaultEnvironment) {
78 this.defaultSweepInterval = defaultSweepInterval;
79 this.defaultNumPartitions = defaultNumPartitions;
80 this.defaultRepManagerFactoryName = defaultRepManagerFactoryName;
81 this.defaultRepStorageFactoryName = defaultRepStorageFactoryName;
82 this.defaultBackingStrategyFactoryName = defaultBackingStrategyFactoryName;
83 this.defaultDispatcherHolderName = defaultDispatcherHolderName;
84 this.defaultEnvironment = defaultEnvironment;
85 SchemaConversionUtils.registerNamespaceConversions(Collections.singletonMap(CLUSTERING_WADI_QNAME.getLocalPart(), new NamespaceElementConverter(CLUSTERING_WADI_QNAME.getNamespaceURI())));
86 }
87
88 public void buildEnvironment(XmlObject container, Environment environment) throws DeploymentException {
89 if (getWadiClusterConfig(container) != null) {
90 EnvironmentBuilder.mergeEnvironments(environment, defaultEnvironment);
91 }
92 }
93
94 public void build(XmlObject container, DeploymentContext applicationContext, DeploymentContext moduleContext) throws DeploymentException {
95 GerClusteringWadiType clusteringWadiType = getWadiClusterConfig(container);
96 if (clusteringWadiType != null) {
97 GBeanData webModuleData = extractWebModule(moduleContext);
98 try {
99 AbstractName sessionManagerName = addSessionManager(clusteringWadiType, webModuleData, moduleContext);
100 addHandlerFactory(moduleContext, webModuleData, sessionManagerName);
101 addInterceptor(moduleContext, webModuleData, sessionManagerName);
102 } catch (GBeanAlreadyExistsException e) {
103 throw new DeploymentException("Duplicate GBean", e);
104 }
105 }
106 }
107
108 private GBeanData extractWebModule(DeploymentContext moduleContext) throws DeploymentException {
109 Configuration configuration = moduleContext.getConfiguration();
110 AbstractNameQuery webModuleQuery = new AbstractNameQuery(configuration.getId(), Collections.EMPTY_MAP, Collections.singleton(JettyWebAppContext.class.getName()));
111 try {
112 return configuration.findGBeanData(webModuleQuery);
113 } catch (GBeanNotFoundException e) {
114 throw new DeploymentException("Could not locate web module gbean in web app configuration", e);
115 }
116 }
117
118 public String getNamespace() {
119 XmlBeansUtil.registerSubstitutionGroupElements(org.apache.geronimo.xbeans.geronimo.j2ee.GerClusteringDocument.type.getDocumentElementName(), CLUSTERING_WADI_QNAME_SET);
120 return CLUSTERING_WADI_QNAME.getNamespaceURI();
121 }
122
123 private GerClusteringWadiType getWadiClusterConfig(XmlObject container) throws DeploymentException {
124 XmlObject[] items = container.selectChildren(CLUSTERING_WADI_QNAME_SET);
125 if (items.length > 1) {
126 throw new DeploymentException("Unexpected count of clustering elements in geronimo plan " + items.length + " qnameset: " + CLUSTERING_WADI_QNAME_SET);
127 }
128 if (items.length == 1) {
129 return (GerClusteringWadiType) items[0].copy().changeType(GerClusteringWadiType.type);
130 }
131 return null;
132 }
133
134 private AbstractName addSessionManager(GerClusteringWadiType clustering, GBeanData webModuleData,
135 DeploymentContext moduleContext) throws GBeanAlreadyExistsException {
136 AbstractName name = moduleContext.getNaming().createChildName(moduleContext.getModuleName(),
137 "WADISessionManager", NameFactory.GERONIMO_SERVICE);
138
139 GBeanData beanData = new GBeanData(name, BasicWADISessionManager.GBEAN_INFO);
140
141 setConfigInfo(clustering, webModuleData, beanData);
142 setReplicationManagerFactory(clustering, beanData);
143 setReplicaStorageFactory(clustering, beanData);
144 setBackingStrategyFactory(clustering, beanData);
145 setDispatcher(clustering, beanData);
146
147 moduleContext.addGBean(beanData);
148
149 return name;
150 }
151
152 private void setConfigInfo(GerClusteringWadiType clustering, GBeanData webModuleData, GBeanData beanData) {
153 int sweepInterval = defaultSweepInterval;
154 if (clustering.isSetSweepInterval()) {
155 sweepInterval = clustering.getSweepInterval().intValue();
156 }
157 int numPartitions = defaultNumPartitions;
158 if (clustering.isSetNumPartitions()) {
159 numPartitions = clustering.getNumPartitions().intValue();
160 }
161 Integer sessionTimeout = (Integer) webModuleData.getAttribute(JettyWebAppContext.GBEAN_ATTR_SESSION_TIMEOUT);
162 if (null == sessionTimeout) {
163 throw new AssertionError();
164 }
165
166 WADISessionManagerConfigInfo configInfo = new WADISessionManagerConfigInfo(
167 beanData.getAbstractName().toURI(),
168 sweepInterval,
169 numPartitions,
170 sessionTimeout.intValue());
171 beanData.setAttribute(BasicWADISessionManager.GBEAN_ATTR_WADI_CONFIG_INFO, configInfo);
172 }
173
174 private void setDispatcher(GerClusteringWadiType clustering, GBeanData beanData) {
175 Set patterns = new HashSet();
176 if (clustering.isSetDispatcher()) {
177 addAbstractNameQueries(patterns, clustering.getDispatcher().getPatternArray());
178 } else {
179 patterns.add(defaultDispatcherHolderName);
180 }
181 beanData.setReferencePatterns(BasicWADISessionManager.GBEAN_REF_DISPATCHER_HOLDER, patterns);
182 }
183
184 private void setBackingStrategyFactory(GerClusteringWadiType clustering, GBeanData beanData) {
185 Set patterns = new HashSet();
186 if (clustering.isSetBackingStrategyFactory()) {
187 addAbstractNameQueries(patterns, clustering.getBackingStrategyFactory().getPatternArray());
188 } else {
189 patterns.add(defaultBackingStrategyFactoryName);
190 }
191 beanData.setReferencePatterns(BasicWADISessionManager.GBEAN_REF_BACKING_STRATEGY_FACTORY, patterns);
192 }
193
194 private void setReplicaStorageFactory(GerClusteringWadiType clustering, GBeanData beanData) {
195 Set patterns = new HashSet();
196 if (clustering.isSetReplicaStorageFactory()) {
197 addAbstractNameQueries(patterns, clustering.getReplicaStorageFactory().getPatternArray());
198 } else {
199 patterns.add(defaultRepStorageFactoryName);
200 }
201 beanData.setReferencePatterns(BasicWADISessionManager.GBEAN_REF_REPLICA_STORAGE_FACTORY, patterns);
202 }
203
204 private void setReplicationManagerFactory(GerClusteringWadiType clustering, GBeanData beanData) {
205 Set patterns = new HashSet();
206 if (clustering.isSetReplicationManagerFactory()) {
207 addAbstractNameQueries(patterns, clustering.getReplicationManagerFactory().getPatternArray());
208 } else {
209 patterns.add(defaultRepManagerFactoryName);
210 }
211 beanData.setReferencePatterns(BasicWADISessionManager.GBEAN_REF_REPLICATION_MANAGER_FACTORY, patterns);
212 }
213
214 private AbstractName addHandlerFactory(DeploymentContext moduleContext,
215 GBeanData webModuleData, AbstractName sessionManagerName) throws GBeanAlreadyExistsException {
216 AbstractName name = moduleContext.getNaming().createChildName(moduleContext.getModuleName(),
217 "ClusteredWebApplicationHandlerFactory", NameFactory.GERONIMO_SERVICE);
218
219 GBeanData beanData = new GBeanData(name, ClusteredWebApplicationHandlerFactory.GBEAN_INFO);
220 beanData.setReferencePattern(ClusteredWebApplicationHandlerFactory.GBEAN_REF_SESSION_MANAGER, sessionManagerName);
221
222 webModuleData.setReferencePattern(JettyWebAppContext.GBEAN_REF_WEB_APPLICATION_HANDLER_FACTORY, name);
223
224 moduleContext.addGBean(beanData);
225
226 return name;
227 }
228
229 private AbstractName addInterceptor(DeploymentContext moduleContext,
230 GBeanData webModuleData, AbstractName sessionManagerName) throws GBeanAlreadyExistsException {
231 AbstractName name = moduleContext.getNaming().createChildName(moduleContext.getModuleName(),
232 "WADIClusteredHandleInterceptor", NameFactory.GERONIMO_SERVICE);
233
234 GBeanData beanData = new GBeanData(name, WADIClusteredHandleInterceptor.GBEAN_INFO);
235 beanData.setReferencePattern(WADIClusteredHandleInterceptor.GBEAN_REF_WADI_SESSION_MANAGER, sessionManagerName);
236
237 webModuleData.setReferencePattern(JettyWebAppContext.GBEAN_REF_HANDLE_INTERCEPTOR, name);
238
239 moduleContext.addGBean(beanData);
240
241 return name;
242 }
243
244 private void addAbstractNameQueries(Set patterns, GerPatternType[] patternTypes) {
245 for (int i = 0; i < patternTypes.length; i++) {
246 AbstractNameQuery query = ENCConfigBuilder.buildAbstractNameQuery(patternTypes[i], null, null, null);
247 patterns.add(query);
248 }
249 }
250
251 public static final GBeanInfo GBEAN_INFO;
252
253 public static final String GBEAN_ATTR_DFT_SWEEP_INTERVAL = "defaultSweepInterval";
254 public static final String GBEAN_ATTR_DFT_NUM_PARTITIONS = "defaultNumPartitions";
255 public static final String GBEAN_ATTR_DFT_REP_MANAGER_FACTORY_NAME = "defaultReplicationManagerFactoryName";
256 public static final String GBEAN_ATTR_DFT_REP_STORAGE_FACTORY_NAME = "defaultReplicaStorageFactoryName";
257 public static final String GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME = "defaultBackingStrategyFactoryName";
258 public static final String GBEAN_ATTR_DFT_DISPATCHER_HOLDER_NAME = "defaultDispatcherHolderName";
259 public static final String GBEAN_ATTR_DFT_ENVIRONMENT = "defaultEnvironment";
260
261 static {
262 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic("WADI Session Manager",
263 WADIJettyClusteringBuilder.class,
264 NameFactory.MODULE_BUILDER);
265
266 infoBuilder.addAttribute(GBEAN_ATTR_DFT_SWEEP_INTERVAL, int.class, true);
267 infoBuilder.addAttribute(GBEAN_ATTR_DFT_NUM_PARTITIONS, int.class, true);
268 infoBuilder.addAttribute(GBEAN_ATTR_DFT_REP_MANAGER_FACTORY_NAME, AbstractNameQuery.class, true);
269 infoBuilder.addAttribute(GBEAN_ATTR_DFT_REP_STORAGE_FACTORY_NAME, AbstractNameQuery.class, true);
270 infoBuilder.addAttribute(GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME, AbstractNameQuery.class, true);
271 infoBuilder.addAttribute(GBEAN_ATTR_DFT_DISPATCHER_HOLDER_NAME, AbstractNameQuery.class, true);
272 infoBuilder.addAttribute(GBEAN_ATTR_DFT_ENVIRONMENT, Environment.class, true);
273
274 infoBuilder.setConstructor(new String[]{GBEAN_ATTR_DFT_SWEEP_INTERVAL,
275 GBEAN_ATTR_DFT_NUM_PARTITIONS,
276 GBEAN_ATTR_DFT_REP_MANAGER_FACTORY_NAME,
277 GBEAN_ATTR_DFT_REP_STORAGE_FACTORY_NAME,
278 GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME,
279 GBEAN_ATTR_DFT_DISPATCHER_HOLDER_NAME,
280 GBEAN_ATTR_DFT_ENVIRONMENT});
281
282 GBEAN_INFO = infoBuilder.getBeanInfo();
283 }
284
285 public static GBeanInfo getGBeanInfo() {
286 return GBEAN_INFO;
287 }
288
289 }