001 /** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 package org.apache.geronimo.clustering.wadi.jetty; 019 020 import java.util.Collections; 021 import java.util.HashSet; 022 import java.util.Set; 023 024 import javax.xml.namespace.QName; 025 026 import org.apache.geronimo.clustering.wadi.BasicWADISessionManager; 027 import org.apache.geronimo.clustering.wadi.WADISessionManagerConfigInfo; 028 import org.apache.geronimo.common.DeploymentException; 029 import org.apache.geronimo.deployment.DeploymentContext; 030 import org.apache.geronimo.deployment.NamespaceDrivenBuilder; 031 import org.apache.geronimo.deployment.service.EnvironmentBuilder; 032 import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil; 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.jetty.JettyWebAppContext; 040 import org.apache.geronimo.jetty.cluster.ClusteredWebApplicationHandlerFactory; 041 import org.apache.geronimo.jetty.cluster.wadi.WADIClusteredHandleInterceptor; 042 import org.apache.geronimo.kernel.GBeanAlreadyExistsException; 043 import org.apache.geronimo.kernel.GBeanNotFoundException; 044 import org.apache.geronimo.kernel.config.Configuration; 045 import org.apache.geronimo.kernel.repository.Environment; 046 import org.apache.geronimo.naming.deployment.ENCConfigBuilder; 047 import org.apache.geronimo.schema.NamespaceElementConverter; 048 import org.apache.geronimo.schema.SchemaConversionUtils; 049 import org.apache.geronimo.xbeans.geronimo.GerClusteringWadiDocument; 050 import org.apache.geronimo.xbeans.geronimo.GerClusteringWadiType; 051 import org.apache.geronimo.xbeans.geronimo.naming.GerPatternType; 052 import org.apache.xmlbeans.QNameSet; 053 import org.apache.xmlbeans.XmlObject; 054 055 /** 056 * 057 * @version $Rev$ $Date$ 058 */ 059 public class WADIJettyClusteringBuilder implements NamespaceDrivenBuilder { 060 private static final QName CLUSTERING_WADI_QNAME = GerClusteringWadiDocument.type.getDocumentElementName(); 061 private static final QNameSet CLUSTERING_WADI_QNAME_SET = QNameSet.singleton(CLUSTERING_WADI_QNAME); 062 063 private final int defaultSweepInterval; 064 private final int defaultNumPartitions; 065 private final AbstractNameQuery defaultRepManagerFactoryName; 066 private final AbstractNameQuery defaultRepStorageFactoryName; 067 private final AbstractNameQuery defaultBackingStrategyFactoryName; 068 private final AbstractNameQuery defaultDispatcherHolderName; 069 private final Environment defaultEnvironment; 070 071 public WADIJettyClusteringBuilder(int defaultSweepInterval, 072 int defaultNumPartitions, 073 AbstractNameQuery defaultRepManagerFactoryName, 074 AbstractNameQuery defaultRepStorageFactoryName, 075 AbstractNameQuery defaultBackingStrategyFactoryName, 076 AbstractNameQuery defaultDispatcherHolderName, 077 Environment defaultEnvironment) { 078 this.defaultSweepInterval = defaultSweepInterval; 079 this.defaultNumPartitions = defaultNumPartitions; 080 this.defaultRepManagerFactoryName = defaultRepManagerFactoryName; 081 this.defaultRepStorageFactoryName = defaultRepStorageFactoryName; 082 this.defaultBackingStrategyFactoryName = defaultBackingStrategyFactoryName; 083 this.defaultDispatcherHolderName = defaultDispatcherHolderName; 084 this.defaultEnvironment = defaultEnvironment; 085 SchemaConversionUtils.registerNamespaceConversions(Collections.singletonMap(CLUSTERING_WADI_QNAME.getLocalPart(), new NamespaceElementConverter(CLUSTERING_WADI_QNAME.getNamespaceURI()))); 086 } 087 088 public void buildEnvironment(XmlObject container, Environment environment) throws DeploymentException { 089 if (getWadiClusterConfig(container) != null) { 090 EnvironmentBuilder.mergeEnvironments(environment, defaultEnvironment); 091 } 092 } 093 094 public void build(XmlObject container, DeploymentContext applicationContext, DeploymentContext moduleContext) throws DeploymentException { 095 GerClusteringWadiType clusteringWadiType = getWadiClusterConfig(container); 096 if (clusteringWadiType != null) { 097 GBeanData webModuleData = extractWebModule(moduleContext); 098 try { 099 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 }