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 }