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.net.URI; 020 import java.net.URISyntaxException; 021 import java.util.Collections; 022 import java.util.HashSet; 023 import java.util.Set; 024 025 import javax.xml.namespace.QName; 026 027 import org.apache.geronimo.clustering.wadi.BasicWADISessionManager; 028 import org.apache.geronimo.clustering.wadi.WADISessionManagerConfigInfo; 029 import org.apache.geronimo.common.DeploymentException; 030 import org.apache.geronimo.deployment.DeploymentContext; 031 import org.apache.geronimo.deployment.NamespaceDrivenBuilder; 032 import org.apache.geronimo.deployment.service.EnvironmentBuilder; 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.jetty6.JettyWebAppContext; 040 import org.apache.geronimo.jetty6.cluster.ClusteredSessionHandlerFactory; 041 import org.apache.geronimo.jetty6.cluster.wadi.WADIClusteredPreHandlerFactory; 042 import org.apache.geronimo.kernel.GBeanAlreadyExistsException; 043 import org.apache.geronimo.kernel.GBeanNotFoundException; 044 import org.apache.geronimo.kernel.Jsr77Naming; 045 import org.apache.geronimo.kernel.config.Configuration; 046 import org.apache.geronimo.kernel.repository.Environment; 047 import org.apache.geronimo.naming.deployment.ENCConfigBuilder; 048 import org.apache.geronimo.schema.NamespaceElementConverter; 049 import org.apache.geronimo.schema.SchemaConversionUtils; 050 import org.apache.geronimo.xbeans.geronimo.GerClusteringWadiDocument; 051 import org.apache.geronimo.xbeans.geronimo.GerClusteringWadiType; 052 import org.apache.geronimo.xbeans.geronimo.naming.GerPatternType; 053 import org.apache.xmlbeans.QNameSet; 054 import org.apache.xmlbeans.XmlObject; 055 056 /** 057 * 058 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 059 */ 060 public class WADIJettyClusteringBuilder implements NamespaceDrivenBuilder { 061 private static final QName CLUSTERING_WADI_QNAME = GerClusteringWadiDocument.type.getDocumentElementName(); 062 private static final QNameSet CLUSTERING_WADI_QNAME_SET = QNameSet.singleton(CLUSTERING_WADI_QNAME); 063 064 static { 065 SchemaConversionUtils.registerNamespaceConversions( 066 Collections.singletonMap(CLUSTERING_WADI_QNAME.getLocalPart(), 067 new NamespaceElementConverter(CLUSTERING_WADI_QNAME.getNamespaceURI()))); 068 } 069 070 private final int defaultSweepInterval; 071 private final int defaultNumPartitions; 072 private final AbstractNameQuery defaultBackingStrategyFactoryName; 073 private final AbstractNameQuery defaultClusterName; 074 private final Environment defaultEnvironment; 075 076 public WADIJettyClusteringBuilder(int defaultSweepInterval, 077 int defaultNumPartitions, 078 AbstractNameQuery defaultBackingStrategyFactoryName, 079 AbstractNameQuery defaultClusterName, 080 Environment defaultEnvironment) { 081 if (defaultSweepInterval < 1) { 082 throw new IllegalArgumentException("defaultSweepInterval is lower than 1"); 083 } else if (defaultNumPartitions < 1) { 084 throw new IllegalArgumentException("defaultNumPartitions is lower than 1"); 085 } else if (null == defaultBackingStrategyFactoryName) { 086 throw new IllegalArgumentException("defaultBackingStrategyFactoryName is required"); 087 } else if (null == defaultClusterName) { 088 throw new IllegalArgumentException("defaultClusterName is required"); 089 } else if (null == defaultEnvironment) { 090 throw new IllegalArgumentException("defaultEnvironment is required"); 091 } 092 this.defaultSweepInterval = defaultSweepInterval; 093 this.defaultNumPartitions = defaultNumPartitions; 094 this.defaultBackingStrategyFactoryName = defaultBackingStrategyFactoryName; 095 this.defaultClusterName = defaultClusterName; 096 this.defaultEnvironment = defaultEnvironment; 097 } 098 099 public void buildEnvironment(XmlObject container, Environment environment) throws DeploymentException { 100 if (getWadiClusterConfig(container) != null) { 101 EnvironmentBuilder.mergeEnvironments(environment, defaultEnvironment); 102 } 103 } 104 105 public void build(XmlObject container, DeploymentContext applicationContext, DeploymentContext moduleContext) throws DeploymentException { 106 GerClusteringWadiType clusteringWadiType = getWadiClusterConfig(container); 107 if (clusteringWadiType != null) { 108 GBeanData webModuleData = extractWebModule(moduleContext); 109 try { 110 AbstractName sessionManagerName = addSessionManager(clusteringWadiType, webModuleData, moduleContext); 111 addSessionHandlerFactory(moduleContext, webModuleData, sessionManagerName); 112 addPreHandlerFactory(moduleContext, webModuleData, sessionManagerName); 113 } catch (GBeanAlreadyExistsException e) { 114 throw new DeploymentException("Duplicate GBean", e); 115 } 116 } 117 } 118 119 protected GBeanData extractWebModule(DeploymentContext moduleContext) throws DeploymentException { 120 AbstractNameQuery webModuleQuery = createJettyWebAppContextNameQuery(moduleContext); 121 Configuration configuration = moduleContext.getConfiguration(); 122 try { 123 return configuration.findGBeanData(webModuleQuery); 124 } catch (GBeanNotFoundException e) { 125 throw new DeploymentException("Could not locate web module gbean in web app configuration", e); 126 } 127 } 128 129 protected AbstractNameQuery createJettyWebAppContextNameQuery(DeploymentContext moduleContext) { 130 String name = moduleContext.getModuleName().getNameProperty(Jsr77Naming.J2EE_NAME); 131 return new AbstractNameQuery(null, 132 Collections.singletonMap(Jsr77Naming.J2EE_NAME, name), 133 Collections.singleton(JettyWebAppContext.class.getName())); 134 } 135 136 public QNameSet getSpecQNameSet() { 137 return QNameSet.EMPTY; 138 } 139 140 public QNameSet getPlanQNameSet() { 141 return CLUSTERING_WADI_QNAME_SET; 142 } 143 144 protected GerClusteringWadiType getWadiClusterConfig(XmlObject container) throws DeploymentException { 145 XmlObject[] items = container.selectChildren(CLUSTERING_WADI_QNAME_SET); 146 if (items.length > 1) { 147 throw new DeploymentException("Unexpected count of clustering elements in geronimo plan " + items.length + " qnameset: " + CLUSTERING_WADI_QNAME_SET); 148 } 149 if (items.length == 1) { 150 return (GerClusteringWadiType) items[0].copy().changeType(GerClusteringWadiType.type); 151 } 152 return null; 153 } 154 155 protected AbstractName addSessionManager(GerClusteringWadiType clustering, 156 GBeanData webModuleData, 157 DeploymentContext moduleContext) throws GBeanAlreadyExistsException { 158 AbstractName name = moduleContext.getNaming().createChildName(moduleContext.getModuleName(), 159 "WADISessionManager", NameFactory.GERONIMO_SERVICE); 160 161 GBeanData beanData = new GBeanData(name, BasicWADISessionManager.GBEAN_INFO); 162 163 setConfigInfo(clustering, webModuleData, beanData); 164 setCluster(clustering, beanData); 165 setBackingStrategyFactory(clustering, beanData); 166 167 moduleContext.addGBean(beanData); 168 169 return name; 170 } 171 172 protected void setConfigInfo(GerClusteringWadiType clustering, GBeanData webModuleData, GBeanData beanData) { 173 int sweepInterval = getSweepInterval(clustering); 174 int numPartitions = getNumberOfPartitions(clustering); 175 Integer sessionTimeout = getSessionTimeout(webModuleData); 176 boolean disableReplication = isDisableReplication(clustering); 177 boolean deltaReplication = isDeltaReplication(clustering); 178 179 String contextPath = (String) webModuleData.getAttribute("contextPath"); 180 URI serviceSpaceName; 181 try { 182 serviceSpaceName = new URI(contextPath); 183 } catch (URISyntaxException e) { 184 throw (AssertionError) new AssertionError("contextPath [" + contextPath + "] cannot be parsed as an URI.").initCause(e); 185 } 186 187 WADISessionManagerConfigInfo configInfo = new WADISessionManagerConfigInfo(serviceSpaceName, 188 sweepInterval, 189 numPartitions, 190 sessionTimeout.intValue(), 191 disableReplication, 192 deltaReplication); 193 beanData.setAttribute(BasicWADISessionManager.GBEAN_ATTR_WADI_CONFIG_INFO, configInfo); 194 } 195 196 protected Integer getSessionTimeout(GBeanData webModuleData) throws AssertionError { 197 Integer sessionTimeout = (Integer) webModuleData.getAttribute(JettyWebAppContext.GBEAN_ATTR_SESSION_TIMEOUT); 198 if (null == sessionTimeout) { 199 throw new AssertionError(); 200 } 201 return sessionTimeout; 202 } 203 204 protected boolean isDeltaReplication(GerClusteringWadiType clustering) { 205 if (clustering.isSetDeltaReplication()) { 206 return clustering.getDeltaReplication(); 207 } 208 return false; 209 } 210 211 protected boolean isDisableReplication(GerClusteringWadiType clustering) { 212 if (clustering.isSetDisableReplication()) { 213 return clustering.getDisableReplication(); 214 } 215 return false; 216 } 217 218 protected int getNumberOfPartitions(GerClusteringWadiType clustering) { 219 if (clustering.isSetNumPartitions()) { 220 return clustering.getNumPartitions().intValue(); 221 } 222 return defaultNumPartitions; 223 } 224 225 protected int getSweepInterval(GerClusteringWadiType clustering) { 226 if (clustering.isSetSweepInterval()) { 227 return clustering.getSweepInterval().intValue(); 228 } 229 return defaultSweepInterval; 230 } 231 232 protected void setCluster(GerClusteringWadiType clustering, GBeanData beanData) { 233 Set patterns = new HashSet(); 234 if (clustering.isSetCluster()) { 235 addAbstractNameQueries(patterns, clustering.getCluster().getPatternArray()); 236 } else { 237 patterns.add(defaultClusterName); 238 } 239 beanData.setReferencePatterns(BasicWADISessionManager.GBEAN_REF_CLUSTER, patterns); 240 } 241 242 protected void setBackingStrategyFactory(GerClusteringWadiType clustering, GBeanData beanData) { 243 Set patterns = new HashSet(); 244 if (clustering.isSetBackingStrategyFactory()) { 245 addAbstractNameQueries(patterns, clustering.getBackingStrategyFactory().getPatternArray()); 246 } else { 247 patterns.add(defaultBackingStrategyFactoryName); 248 } 249 beanData.setReferencePatterns(BasicWADISessionManager.GBEAN_REF_BACKING_STRATEGY_FACTORY, patterns); 250 } 251 252 protected AbstractName addPreHandlerFactory(DeploymentContext moduleContext, 253 GBeanData webModuleData, AbstractName sessionManagerName) throws GBeanAlreadyExistsException { 254 AbstractName name = moduleContext.getNaming().createChildName(moduleContext.getModuleName(), 255 "WADIClusteredPreHandlerFactory", NameFactory.GERONIMO_SERVICE); 256 257 GBeanData beanData = new GBeanData(name, WADIClusteredPreHandlerFactory.GBEAN_INFO); 258 beanData.setReferencePattern(WADIClusteredPreHandlerFactory.GBEAN_REF_WADI_SESSION_MANAGER, sessionManagerName); 259 260 webModuleData.setReferencePattern(JettyWebAppContext.GBEAN_REF_PRE_HANDLER_FACTORY, name); 261 262 moduleContext.addGBean(beanData); 263 264 return name; 265 } 266 267 protected AbstractName addSessionHandlerFactory(DeploymentContext moduleContext, 268 GBeanData webModuleData, AbstractName sessionManagerName) throws GBeanAlreadyExistsException { 269 AbstractName name = moduleContext.getNaming().createChildName(moduleContext.getModuleName(), 270 "ClusteredSessionHandlerFactory", NameFactory.GERONIMO_SERVICE); 271 272 GBeanData beanData = new GBeanData(name, ClusteredSessionHandlerFactory.GBEAN_INFO); 273 beanData.setReferencePattern(ClusteredSessionHandlerFactory.GBEAN_REF_SESSION_MANAGER, sessionManagerName); 274 275 webModuleData.setReferencePattern(JettyWebAppContext.GBEAN_REF_SESSION_HANDLER_FACTORY, name); 276 277 moduleContext.addGBean(beanData); 278 279 return name; 280 } 281 282 protected void addAbstractNameQueries(Set patterns, GerPatternType[] patternTypes) { 283 for (int i = 0; i < patternTypes.length; i++) { 284 AbstractNameQuery query = ENCConfigBuilder.buildAbstractNameQuery(patternTypes[i], null, null, null); 285 patterns.add(query); 286 } 287 } 288 289 public static final GBeanInfo GBEAN_INFO; 290 291 public static final String GBEAN_ATTR_DFT_SWEEP_INTERVAL = "defaultSweepInterval"; 292 public static final String GBEAN_ATTR_DFT_NUM_PARTITIONS = "defaultNumPartitions"; 293 public static final String GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME = "defaultBackingStrategyFactoryName"; 294 public static final String GBEAN_ATTR_DFT_CLUSTER_NAME = "defaultClusterName"; 295 public static final String GBEAN_ATTR_DFT_ENVIRONMENT = "defaultEnvironment"; 296 297 static { 298 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic("WADI Session Manager", 299 WADIJettyClusteringBuilder.class, 300 NameFactory.MODULE_BUILDER); 301 302 infoBuilder.addAttribute(GBEAN_ATTR_DFT_SWEEP_INTERVAL, int.class, true); 303 infoBuilder.addAttribute(GBEAN_ATTR_DFT_NUM_PARTITIONS, int.class, true); 304 infoBuilder.addAttribute(GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME, AbstractNameQuery.class, true); 305 infoBuilder.addAttribute(GBEAN_ATTR_DFT_CLUSTER_NAME, AbstractNameQuery.class, true); 306 infoBuilder.addAttribute(GBEAN_ATTR_DFT_ENVIRONMENT, Environment.class, true); 307 308 infoBuilder.setConstructor(new String[]{GBEAN_ATTR_DFT_SWEEP_INTERVAL, 309 GBEAN_ATTR_DFT_NUM_PARTITIONS, 310 GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME, 311 GBEAN_ATTR_DFT_CLUSTER_NAME, 312 GBEAN_ATTR_DFT_ENVIRONMENT}); 313 314 GBEAN_INFO = infoBuilder.getBeanInfo(); 315 } 316 317 public static GBeanInfo getGBeanInfo() { 318 return GBEAN_INFO; 319 } 320 321 }