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