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.util.Collections; 020 import java.util.HashSet; 021 import java.util.Set; 022 023 import javax.xml.namespace.QName; 024 025 import org.apache.geronimo.clustering.wadi.BasicWADISessionManager; 026 import org.apache.geronimo.clustering.wadi.WADISessionManagerConfigInfo; 027 import org.apache.geronimo.common.DeploymentException; 028 import org.apache.geronimo.deployment.DeploymentContext; 029 import org.apache.geronimo.deployment.NamespaceDrivenBuilder; 030 import org.apache.geronimo.deployment.service.EnvironmentBuilder; 031 import org.apache.geronimo.gbean.AbstractName; 032 import org.apache.geronimo.gbean.AbstractNameQuery; 033 import org.apache.geronimo.gbean.GBeanData; 034 import org.apache.geronimo.gbean.GBeanInfo; 035 import org.apache.geronimo.gbean.GBeanInfoBuilder; 036 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 037 import org.apache.geronimo.jetty6.JettyWebAppContext; 038 import org.apache.geronimo.jetty6.cluster.ClusteredSessionHandlerFactory; 039 import org.apache.geronimo.jetty6.cluster.wadi.WADIClusteredPreHandlerFactory; 040 import org.apache.geronimo.kernel.GBeanAlreadyExistsException; 041 import org.apache.geronimo.kernel.GBeanNotFoundException; 042 import org.apache.geronimo.kernel.config.Configuration; 043 import org.apache.geronimo.kernel.repository.Environment; 044 import org.apache.geronimo.naming.deployment.ENCConfigBuilder; 045 import org.apache.geronimo.schema.NamespaceElementConverter; 046 import org.apache.geronimo.schema.SchemaConversionUtils; 047 import org.apache.geronimo.xbeans.geronimo.GerClusteringWadiDocument; 048 import org.apache.geronimo.xbeans.geronimo.GerClusteringWadiType; 049 import org.apache.geronimo.xbeans.geronimo.naming.GerPatternType; 050 import org.apache.xmlbeans.QNameSet; 051 import org.apache.xmlbeans.XmlObject; 052 053 /** 054 * 055 * @version $Rev$ $Date$ 056 */ 057 public class WADIJettyClusteringBuilder implements NamespaceDrivenBuilder { 058 private static final QName CLUSTERING_WADI_QNAME = GerClusteringWadiDocument.type.getDocumentElementName(); 059 private static final QNameSet CLUSTERING_WADI_QNAME_SET = QNameSet.singleton(CLUSTERING_WADI_QNAME); 060 061 private final int defaultSweepInterval; 062 private final int defaultNumPartitions; 063 private final AbstractNameQuery defaultBackingStrategyFactoryName; 064 private final AbstractNameQuery defaultClusterName; 065 private final Environment defaultEnvironment; 066 067 public WADIJettyClusteringBuilder(int defaultSweepInterval, 068 int defaultNumPartitions, 069 AbstractNameQuery defaultBackingStrategyFactoryName, 070 AbstractNameQuery defaultClusterName, 071 Environment defaultEnvironment) { 072 this.defaultSweepInterval = defaultSweepInterval; 073 this.defaultNumPartitions = defaultNumPartitions; 074 this.defaultBackingStrategyFactoryName = defaultBackingStrategyFactoryName; 075 this.defaultClusterName = defaultClusterName; 076 this.defaultEnvironment = defaultEnvironment; 077 078 SchemaConversionUtils.registerNamespaceConversions( 079 Collections.singletonMap(CLUSTERING_WADI_QNAME.getLocalPart(), 080 new NamespaceElementConverter(CLUSTERING_WADI_QNAME.getNamespaceURI()))); 081 } 082 083 public void buildEnvironment(XmlObject container, Environment environment) throws DeploymentException { 084 if (getWadiClusterConfig(container) != null) { 085 EnvironmentBuilder.mergeEnvironments(environment, defaultEnvironment); 086 } 087 } 088 089 public void build(XmlObject container, DeploymentContext applicationContext, DeploymentContext moduleContext) throws DeploymentException { 090 GerClusteringWadiType clusteringWadiType = getWadiClusterConfig(container); 091 if (clusteringWadiType != null) { 092 GBeanData webModuleData = extractWebModule(moduleContext); 093 try { 094 AbstractName sessionManagerName = addSessionManager(clusteringWadiType, webModuleData, moduleContext); 095 addSessionHandlerFactory(moduleContext, webModuleData, sessionManagerName); 096 addPreHandlerFactory(moduleContext, webModuleData, sessionManagerName); 097 } catch (GBeanAlreadyExistsException e) { 098 throw new DeploymentException("Duplicate GBean", e); 099 } 100 } 101 } 102 103 private GBeanData extractWebModule(DeploymentContext moduleContext) throws DeploymentException { 104 Configuration configuration = moduleContext.getConfiguration(); 105 AbstractNameQuery webModuleQuery = new AbstractNameQuery(configuration.getId(), Collections.EMPTY_MAP, Collections.singleton(JettyWebAppContext.class.getName())); 106 try { 107 return configuration.findGBeanData(webModuleQuery); 108 } catch (GBeanNotFoundException e) { 109 throw new DeploymentException("Could not locate web module gbean in web app configuration", e); 110 } 111 } 112 113 public QNameSet getSpecQNameSet() { 114 return QNameSet.EMPTY; 115 } 116 117 public QNameSet getPlanQNameSet() { 118 return CLUSTERING_WADI_QNAME_SET; 119 } 120 121 private GerClusteringWadiType getWadiClusterConfig(XmlObject container) throws DeploymentException { 122 XmlObject[] items = container.selectChildren(CLUSTERING_WADI_QNAME_SET); 123 if (items.length > 1) { 124 throw new DeploymentException("Unexpected count of clustering elements in geronimo plan " + items.length + " qnameset: " + CLUSTERING_WADI_QNAME_SET); 125 } 126 if (items.length == 1) { 127 return (GerClusteringWadiType) items[0].copy().changeType(GerClusteringWadiType.type); 128 } 129 return null; 130 } 131 132 private AbstractName addSessionManager(GerClusteringWadiType clustering, 133 GBeanData webModuleData, 134 DeploymentContext moduleContext) throws GBeanAlreadyExistsException { 135 AbstractName name = moduleContext.getNaming().createChildName(moduleContext.getModuleName(), 136 "WADISessionManager", NameFactory.GERONIMO_SERVICE); 137 138 GBeanData beanData = new GBeanData(name, BasicWADISessionManager.GBEAN_INFO); 139 140 setConfigInfo(clustering, webModuleData, beanData); 141 setCluster(clustering, beanData); 142 setBackingStrategyFactory(clustering, beanData); 143 144 moduleContext.addGBean(beanData); 145 146 return name; 147 } 148 149 private void setConfigInfo(GerClusteringWadiType clustering, GBeanData webModuleData, GBeanData beanData) { 150 int sweepInterval = defaultSweepInterval; 151 if (clustering.isSetSweepInterval()) { 152 sweepInterval = clustering.getSweepInterval().intValue(); 153 } 154 int numPartitions = defaultNumPartitions; 155 if (clustering.isSetNumPartitions()) { 156 numPartitions = clustering.getNumPartitions().intValue(); 157 } 158 Integer sessionTimeout = (Integer) webModuleData.getAttribute(JettyWebAppContext.GBEAN_ATTR_SESSION_TIMEOUT); 159 if (null == sessionTimeout) { 160 throw new AssertionError(); 161 } 162 163 WADISessionManagerConfigInfo configInfo = new WADISessionManagerConfigInfo( 164 beanData.getAbstractName().toURI(), 165 sweepInterval, 166 numPartitions, 167 sessionTimeout.intValue()); 168 beanData.setAttribute(BasicWADISessionManager.GBEAN_ATTR_WADI_CONFIG_INFO, configInfo); 169 } 170 171 private void setCluster(GerClusteringWadiType clustering, GBeanData beanData) { 172 Set patterns = new HashSet(); 173 if (clustering.isSetCluster()) { 174 addAbstractNameQueries(patterns, clustering.getCluster().getPatternArray()); 175 } else { 176 patterns.add(defaultClusterName); 177 } 178 beanData.setReferencePatterns(BasicWADISessionManager.GBEAN_REF_CLUSTER, patterns); 179 } 180 181 private void setBackingStrategyFactory(GerClusteringWadiType clustering, GBeanData beanData) { 182 Set patterns = new HashSet(); 183 if (clustering.isSetBackingStrategyFactory()) { 184 addAbstractNameQueries(patterns, clustering.getBackingStrategyFactory().getPatternArray()); 185 } else { 186 patterns.add(defaultBackingStrategyFactoryName); 187 } 188 beanData.setReferencePatterns(BasicWADISessionManager.GBEAN_REF_BACKING_STRATEGY_FACTORY, patterns); 189 } 190 191 private AbstractName addPreHandlerFactory(DeploymentContext moduleContext, 192 GBeanData webModuleData, AbstractName sessionManagerName) throws GBeanAlreadyExistsException { 193 AbstractName name = moduleContext.getNaming().createChildName(moduleContext.getModuleName(), 194 "WADIClusteredPreHandlerFactory", NameFactory.GERONIMO_SERVICE); 195 196 GBeanData beanData = new GBeanData(name, WADIClusteredPreHandlerFactory.GBEAN_INFO); 197 beanData.setReferencePattern(WADIClusteredPreHandlerFactory.GBEAN_REF_WADI_SESSION_MANAGER, sessionManagerName); 198 199 webModuleData.setReferencePattern(JettyWebAppContext.GBEAN_REF_PRE_HANDLER_FACTORY, name); 200 201 moduleContext.addGBean(beanData); 202 203 return name; 204 } 205 206 private AbstractName addSessionHandlerFactory(DeploymentContext moduleContext, 207 GBeanData webModuleData, AbstractName sessionManagerName) throws GBeanAlreadyExistsException { 208 AbstractName name = moduleContext.getNaming().createChildName(moduleContext.getModuleName(), 209 "ClusteredSessionHandlerFactory", NameFactory.GERONIMO_SERVICE); 210 211 GBeanData beanData = new GBeanData(name, ClusteredSessionHandlerFactory.GBEAN_INFO); 212 beanData.setReferencePattern(ClusteredSessionHandlerFactory.GBEAN_REF_SESSION_MANAGER, sessionManagerName); 213 214 webModuleData.setReferencePattern(JettyWebAppContext.GBEAN_REF_SESSION_HANDLER_FACTORY, name); 215 216 moduleContext.addGBean(beanData); 217 218 return name; 219 } 220 221 private void addAbstractNameQueries(Set patterns, GerPatternType[] patternTypes) { 222 for (int i = 0; i < patternTypes.length; i++) { 223 AbstractNameQuery query = ENCConfigBuilder.buildAbstractNameQuery(patternTypes[i], null, null, null); 224 patterns.add(query); 225 } 226 } 227 228 public static final GBeanInfo GBEAN_INFO; 229 230 public static final String GBEAN_ATTR_DFT_SWEEP_INTERVAL = "defaultSweepInterval"; 231 public static final String GBEAN_ATTR_DFT_NUM_PARTITIONS = "defaultNumPartitions"; 232 public static final String GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME = "defaultBackingStrategyFactoryName"; 233 public static final String GBEAN_ATTR_DFT_CLUSTER_NAME = "defaultClusterName"; 234 public static final String GBEAN_ATTR_DFT_ENVIRONMENT = "defaultEnvironment"; 235 236 static { 237 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic("WADI Session Manager", 238 WADIJettyClusteringBuilder.class, 239 NameFactory.MODULE_BUILDER); 240 241 infoBuilder.addAttribute(GBEAN_ATTR_DFT_SWEEP_INTERVAL, int.class, true); 242 infoBuilder.addAttribute(GBEAN_ATTR_DFT_NUM_PARTITIONS, int.class, true); 243 infoBuilder.addAttribute(GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME, AbstractNameQuery.class, true); 244 infoBuilder.addAttribute(GBEAN_ATTR_DFT_CLUSTER_NAME, AbstractNameQuery.class, true); 245 infoBuilder.addAttribute(GBEAN_ATTR_DFT_ENVIRONMENT, Environment.class, true); 246 247 infoBuilder.setConstructor(new String[]{GBEAN_ATTR_DFT_SWEEP_INTERVAL, 248 GBEAN_ATTR_DFT_NUM_PARTITIONS, 249 GBEAN_ATTR_DFT_BACKING_STRATEGY_FACTORY_NAME, 250 GBEAN_ATTR_DFT_CLUSTER_NAME, 251 GBEAN_ATTR_DFT_ENVIRONMENT}); 252 253 GBEAN_INFO = infoBuilder.getBeanInfo(); 254 } 255 256 public static GBeanInfo getGBeanInfo() { 257 return GBEAN_INFO; 258 } 259 260 }