001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with 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, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020 package org.apache.geronimo.tomcat.cluster.wadi.builder; 021 022 import java.net.URI; 023 import java.net.URISyntaxException; 024 import java.util.ArrayList; 025 import java.util.Collections; 026 import java.util.HashSet; 027 import java.util.Iterator; 028 import java.util.List; 029 import java.util.Set; 030 031 import javax.xml.namespace.QName; 032 033 import org.apache.geronimo.clustering.wadi.BasicWADISessionManager; 034 import org.apache.geronimo.clustering.wadi.WADISessionManagerConfigInfo; 035 import org.apache.geronimo.common.DeploymentException; 036 import org.apache.geronimo.deployment.DeploymentContext; 037 import org.apache.geronimo.deployment.NamespaceDrivenBuilder; 038 import org.apache.geronimo.deployment.service.EnvironmentBuilder; 039 import org.apache.geronimo.gbean.AbstractName; 040 import org.apache.geronimo.gbean.AbstractNameQuery; 041 import org.apache.geronimo.gbean.GBeanData; 042 import org.apache.geronimo.gbean.GBeanInfo; 043 import org.apache.geronimo.gbean.GBeanInfoBuilder; 044 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 045 import org.apache.geronimo.kernel.GBeanAlreadyExistsException; 046 import org.apache.geronimo.kernel.GBeanNotFoundException; 047 import org.apache.geronimo.kernel.Jsr77Naming; 048 import org.apache.geronimo.kernel.config.Configuration; 049 import org.apache.geronimo.kernel.repository.Artifact; 050 import org.apache.geronimo.kernel.repository.Dependency; 051 import org.apache.geronimo.kernel.repository.Environment; 052 import org.apache.geronimo.naming.deployment.ENCConfigBuilder; 053 import org.apache.geronimo.schema.SchemaConversionUtils; 054 import org.apache.geronimo.tomcat.TomcatWebAppContext; 055 import org.apache.geronimo.tomcat.cluster.ClusteredManagerRetriever; 056 import org.apache.geronimo.tomcat.cluster.wadi.WADIClusteredValveRetriever; 057 import org.apache.geronimo.xbeans.geronimo.GerTomcatClusteringWadiDocument; 058 import org.apache.geronimo.xbeans.geronimo.GerTomcatClusteringWadiType; 059 import org.apache.geronimo.xbeans.geronimo.naming.GerPatternType; 060 import org.apache.xmlbeans.QNameSet; 061 import org.apache.xmlbeans.XmlObject; 062 063 /** 064 * 065 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 066 */ 067 public class WADITomcatClusteringBuilder implements NamespaceDrivenBuilder { 068 private static final QName CLUSTERING_WADI_QNAME = GerTomcatClusteringWadiDocument.type.getDocumentElementName(); 069 private static final QNameSet CLUSTERING_WADI_QNAME_SET = QNameSet.singleton(CLUSTERING_WADI_QNAME); 070 071 static { 072 SchemaConversionUtils.registerNamespaceConversions( 073 Collections.singletonMap(CLUSTERING_WADI_QNAME.getLocalPart(), 074 new TomcatClusteringWADIConverter())); 075 } 076 077 private final int defaultSweepInterval; 078 private final int defaultSessionTimeout; 079 private final int defaultNumPartitions; 080 private final AbstractNameQuery defaultBackingStrategyFactoryName; 081 private final AbstractNameQuery defaultClusterName; 082 private final Artifact artifactToRemoveFromEnvironment; 083 private final Environment defaultEnvironment; 084 085 public WADITomcatClusteringBuilder(int defaultSweepInterval, 086 int defaultSessionTimeout, 087 int defaultNumPartitions, 088 AbstractNameQuery defaultBackingStrategyFactoryName, 089 AbstractNameQuery defaultClusterName, 090 Artifact artifactToRemoveFromEnvironment, 091 Environment defaultEnvironment) { 092 if (defaultSweepInterval < 1) { 093 throw new IllegalArgumentException("defaultSweepInterval is lower than 1"); 094 } else if (defaultSessionTimeout < 1) { 095 throw new IllegalArgumentException("defaultSessionTimeout is lower than 1"); 096 } else if (defaultNumPartitions < 1) { 097 throw new IllegalArgumentException("defaultNumPartitions is lower than 1"); 098 } else if (null == defaultBackingStrategyFactoryName) { 099 throw new IllegalArgumentException("defaultBackingStrategyFactoryName is required"); 100 } else if (null == defaultClusterName) { 101 throw new IllegalArgumentException("defaultClusterName is required"); 102 } else if (null == artifactToRemoveFromEnvironment) { 103 throw new IllegalArgumentException("artifactToRemoveFromEnvironment is required"); 104 } else if (null == defaultEnvironment) { 105 throw new IllegalArgumentException("defaultEnvironment is required"); 106 } 107 this.defaultSweepInterval = defaultSweepInterval; 108 this.defaultSessionTimeout = defaultSessionTimeout; 109 this.defaultNumPartitions = defaultNumPartitions; 110 this.defaultBackingStrategyFactoryName = defaultBackingStrategyFactoryName; 111 this.defaultClusterName = defaultClusterName; 112 this.artifactToRemoveFromEnvironment = artifactToRemoveFromEnvironment; 113 this.defaultEnvironment = defaultEnvironment; 114 } 115 116 public void buildEnvironment(XmlObject container, Environment environment) throws DeploymentException { 117 if (getWadiClusterConfig(container) != null) { 118 filterDependencies(environment); 119 EnvironmentBuilder.mergeEnvironments(environment, defaultEnvironment); 120 } 121 } 122 123 public void build(XmlObject container, DeploymentContext applicationContext, DeploymentContext moduleContext) 124 throws DeploymentException { 125 GerTomcatClusteringWadiType clusteringWadiType = getWadiClusterConfig(container); 126 if (clusteringWadiType != null) { 127 GBeanData webModuleData = extractWebModule(moduleContext); 128 try { 129 AbstractName sessionManagerName = addSessionManager(clusteringWadiType, webModuleData, moduleContext); 130 addClusteredManagerRetriever(moduleContext, webModuleData, sessionManagerName); 131 addClusteredValveRetriever(moduleContext, webModuleData, sessionManagerName); 132 } catch (GBeanAlreadyExistsException e) { 133 throw new DeploymentException("Duplicate GBean", e); 134 } 135 } 136 } 137 138 protected void filterDependencies(Environment environment) { 139 List<Dependency> dependencies = environment.getDependencies(); 140 dependencies = new ArrayList<Dependency>(dependencies); 141 for (Iterator<Dependency> iterator = dependencies.iterator(); iterator.hasNext();) { 142 Dependency dependency = iterator.next(); 143 Artifact dependencyArtifact = dependency.getArtifact(); 144 if (artifactToRemoveFromEnvironment.matches(dependencyArtifact)) { 145 iterator.remove(); 146 } 147 } 148 environment.setDependencies(dependencies); 149 } 150 151 protected GBeanData extractWebModule(DeploymentContext moduleContext) throws DeploymentException { 152 AbstractNameQuery webModuleQuery = createTomcatWebAppContextNameQuery(moduleContext); 153 Configuration configuration = moduleContext.getConfiguration(); 154 try { 155 return configuration.findGBeanData(webModuleQuery); 156 } catch (GBeanNotFoundException e) { 157 throw new DeploymentException("Could not locate web module gbean in web app configuration", e); 158 } 159 } 160 161 protected AbstractNameQuery createTomcatWebAppContextNameQuery(DeploymentContext moduleContext) { 162 String name = moduleContext.getModuleName().getNameProperty(Jsr77Naming.J2EE_NAME); 163 return new AbstractNameQuery(null, 164 Collections.singletonMap(Jsr77Naming.J2EE_NAME, name), 165 Collections.singleton(TomcatWebAppContext.class.getName())); 166 } 167 168 public QNameSet getSpecQNameSet() { 169 return QNameSet.EMPTY; 170 } 171 172 public QNameSet getPlanQNameSet() { 173 return CLUSTERING_WADI_QNAME_SET; 174 } 175 176 protected GerTomcatClusteringWadiType getWadiClusterConfig(XmlObject container) throws DeploymentException { 177 XmlObject[] items = container.selectChildren(CLUSTERING_WADI_QNAME_SET); 178 if (items.length > 1) { 179 throw new DeploymentException("Unexpected count of clustering elements in geronimo plan " + items.length 180 + " qnameset: " + CLUSTERING_WADI_QNAME_SET); 181 } 182 if (items.length == 1) { 183 return (GerTomcatClusteringWadiType) items[0].copy().changeType(GerTomcatClusteringWadiType.type); 184 } 185 return null; 186 } 187 188 protected AbstractName addSessionManager(GerTomcatClusteringWadiType clustering, 189 GBeanData webModuleData, 190 DeploymentContext moduleContext) throws GBeanAlreadyExistsException { 191 AbstractName name = newGBeanName(moduleContext, "WADISessionManager"); 192 193 GBeanData beanData = new GBeanData(name, BasicWADISessionManager.GBEAN_INFO); 194 195 setConfigInfo(clustering, webModuleData, beanData); 196 setCluster(clustering, beanData); 197 setBackingStrategyFactory(clustering, beanData); 198 199 addGBean(moduleContext, beanData); 200 201 return name; 202 } 203 204 protected void setConfigInfo(GerTomcatClusteringWadiType clustering, GBeanData webModuleData, GBeanData beanData) { 205 int sweepInterval = getSweepInterval(clustering); 206 int numPartitions = getNumberOfPartitions(clustering); 207 Integer sessionTimeout = getSessionTimeout(webModuleData); 208 boolean disableReplication = isDisableReplication(clustering); 209 boolean deltaReplication = isDeltaReplication(clustering); 210 211 String contextPath = (String) webModuleData.getAttribute("contextPath"); 212 URI serviceSpaceName; 213 try { 214 serviceSpaceName = new URI(contextPath); 215 } catch (URISyntaxException e) { 216 AssertionError error = new AssertionError("contextPath [" + contextPath + "] cannot be parsed as an URI."); 217 throw (AssertionError) error.initCause(e); 218 } 219 220 WADISessionManagerConfigInfo configInfo = new WADISessionManagerConfigInfo(serviceSpaceName, 221 sweepInterval, 222 numPartitions, 223 sessionTimeout.intValue(), 224 disableReplication, 225 deltaReplication); 226 beanData.setAttribute(BasicWADISessionManager.GBEAN_ATTR_WADI_CONFIG_INFO, configInfo); 227 } 228 229 protected Integer getSessionTimeout(GBeanData webModuleData) throws AssertionError { 230 return defaultSessionTimeout; 231 } 232 233 protected boolean isDeltaReplication(GerTomcatClusteringWadiType clustering) { 234 if (clustering.isSetDeltaReplication()) { 235 return clustering.getDeltaReplication(); 236 } 237 return false; 238 } 239 240 protected boolean isDisableReplication(GerTomcatClusteringWadiType clustering) { 241 if (clustering.isSetDisableReplication()) { 242 return clustering.getDisableReplication(); 243 } 244 return false; 245 } 246 247 protected int getNumberOfPartitions(GerTomcatClusteringWadiType clustering) { 248 if (clustering.isSetNumPartitions()) { 249 return clustering.getNumPartitions().intValue(); 250 } 251 return defaultNumPartitions; 252 } 253 254 protected int getSweepInterval(GerTomcatClusteringWadiType clustering) { 255 if (clustering.isSetSweepInterval()) { 256 return clustering.getSweepInterval().intValue(); 257 } 258 return defaultSweepInterval; 259 } 260 261 protected void setCluster(GerTomcatClusteringWadiType clustering, GBeanData beanData) { 262 Set patterns = new HashSet(); 263 if (clustering.isSetCluster()) { 264 addAbstractNameQueries(patterns, clustering.getCluster()); 265 } else { 266 patterns.add(defaultClusterName); 267 } 268 beanData.setReferencePatterns(BasicWADISessionManager.GBEAN_REF_CLUSTER, patterns); 269 } 270 271 protected void setBackingStrategyFactory(GerTomcatClusteringWadiType clustering, GBeanData beanData) { 272 Set patterns = new HashSet(); 273 if (clustering.isSetBackingStrategyFactory()) { 274 addAbstractNameQueries(patterns, clustering.getBackingStrategyFactory()); 275 } else { 276 patterns.add(defaultBackingStrategyFactoryName); 277 } 278 beanData.setReferencePatterns(BasicWADISessionManager.GBEAN_REF_BACKING_STRATEGY_FACTORY, patterns); 279 } 280 281 protected AbstractName addClusteredValveRetriever(DeploymentContext moduleContext, 282 GBeanData webModuleData, 283 AbstractName sessionManagerName) throws GBeanAlreadyExistsException { 284 AbstractName name = newGBeanName(moduleContext, "WADIClusteredValveRetriever"); 285 286 GBeanData beanData = new GBeanData(name, WADIClusteredValveRetriever.GBEAN_INFO); 287 beanData.setReferencePattern(WADIClusteredValveRetriever.GBEAN_REF_WADI_SESSION_MANAGER, sessionManagerName); 288 289 webModuleData.setReferencePattern(TomcatWebAppContext.GBEAN_REF_CLUSTERED_VALVE_RETRIEVER, name); 290 291 addGBean(moduleContext, beanData); 292 293 return name; 294 } 295 296 protected AbstractName addClusteredManagerRetriever(DeploymentContext moduleContext, 297 GBeanData webModuleData, 298 AbstractName sessionManagerName) throws GBeanAlreadyExistsException { 299 AbstractName name = newGBeanName(moduleContext, "ClusteredManagerRetriever"); 300 301 GBeanData beanData = new GBeanData(name, ClusteredManagerRetriever.GBEAN_INFO); 302 beanData.setReferencePattern(ClusteredManagerRetriever.GBEAN_REF_SESSION_MANAGER, sessionManagerName); 303 304 webModuleData.setReferencePattern(TomcatWebAppContext.GBEAN_REF_MANAGER_RETRIEVER, name); 305 306 addGBean(moduleContext, beanData); 307 308 return name; 309 } 310 311 protected void addGBean(DeploymentContext moduleContext, GBeanData beanData) throws GBeanAlreadyExistsException { 312 moduleContext.addGBean(beanData); 313 } 314 315 protected AbstractName newGBeanName(DeploymentContext moduleContext, String name) { 316 return moduleContext.getNaming().createChildName(moduleContext.getModuleName(), 317 name, 318 NameFactory.GERONIMO_SERVICE); 319 } 320 321 protected void addAbstractNameQueries(Set patterns, GerPatternType patternType) { 322 AbstractNameQuery query = ENCConfigBuilder.buildAbstractNameQuery(patternType, null, null, null); 323 patterns.add(query); 324 } 325 326 public static final GBeanInfo GBEAN_INFO; 327 328 public static final String GBEAN_ATTR_DFT_SWEEP_INTERVAL = "defaultSweepInterval"; 329 public static final String GBEAN_ATTR_DFT_SESSION_TIMEOUT = "defaultSessionTimeout"; 330 public static final String GBEAN_ATTR_DFT_NUM_PARTITIONS = "defaultNumPartitions"; 331 public static final String GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME = "defaultBackingStrategyFactoryName"; 332 public static final String GBEAN_ATTR_DFT_CLUSTER_NAME = "defaultClusterName"; 333 public static final String GBEAN_ATTR_ARTIFACT_TO_REMOVE = "artifactToRemoveFromEnvironment"; 334 public static final String GBEAN_ATTR_DFT_ENVIRONMENT = "defaultEnvironment"; 335 336 static { 337 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic("WADI Session Manager", 338 WADITomcatClusteringBuilder.class, 339 NameFactory.MODULE_BUILDER); 340 341 infoBuilder.addAttribute(GBEAN_ATTR_DFT_SWEEP_INTERVAL, int.class, true); 342 infoBuilder.addAttribute(GBEAN_ATTR_DFT_SESSION_TIMEOUT, int.class, true); 343 infoBuilder.addAttribute(GBEAN_ATTR_DFT_NUM_PARTITIONS, int.class, true); 344 infoBuilder.addAttribute(GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME, AbstractNameQuery.class, true); 345 infoBuilder.addAttribute(GBEAN_ATTR_DFT_CLUSTER_NAME, AbstractNameQuery.class, true); 346 infoBuilder.addAttribute(GBEAN_ATTR_ARTIFACT_TO_REMOVE, Artifact.class, true); 347 infoBuilder.addAttribute(GBEAN_ATTR_DFT_ENVIRONMENT, Environment.class, true); 348 349 infoBuilder.setConstructor(new String[]{GBEAN_ATTR_DFT_SWEEP_INTERVAL, 350 GBEAN_ATTR_DFT_SESSION_TIMEOUT, 351 GBEAN_ATTR_DFT_NUM_PARTITIONS, 352 GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME, 353 GBEAN_ATTR_DFT_CLUSTER_NAME, 354 GBEAN_ATTR_ARTIFACT_TO_REMOVE, 355 GBEAN_ATTR_DFT_ENVIRONMENT}); 356 357 GBEAN_INFO = infoBuilder.getBeanInfo(); 358 } 359 360 public static GBeanInfo getGBeanInfo() { 361 return GBEAN_INFO; 362 } 363 364 }