View Javadoc

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 }