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.farm.deployment; 021 022 import java.io.File; 023 import java.io.IOException; 024 import java.io.OutputStream; 025 import java.net.MalformedURLException; 026 import java.net.URL; 027 import java.util.ArrayList; 028 import java.util.Collections; 029 import java.util.LinkedHashSet; 030 import java.util.List; 031 import java.util.Set; 032 033 import org.apache.commons.logging.Log; 034 import org.apache.commons.logging.LogFactory; 035 import org.apache.geronimo.farm.config.ClusterInfo; 036 import org.apache.geronimo.farm.config.NodeInfo; 037 import org.apache.geronimo.gbean.AbstractName; 038 import org.apache.geronimo.gbean.GBeanData; 039 import org.apache.geronimo.gbean.GBeanInfo; 040 import org.apache.geronimo.gbean.GBeanInfoBuilder; 041 import org.apache.geronimo.kernel.Kernel; 042 import org.apache.geronimo.kernel.config.ConfigurationAlreadyExistsException; 043 import org.apache.geronimo.kernel.config.ConfigurationData; 044 import org.apache.geronimo.kernel.config.ConfigurationInfo; 045 import org.apache.geronimo.kernel.config.ConfigurationModuleType; 046 import org.apache.geronimo.kernel.config.ConfigurationStore; 047 import org.apache.geronimo.kernel.config.InvalidConfigException; 048 import org.apache.geronimo.kernel.config.NoSuchConfigException; 049 import org.apache.geronimo.kernel.repository.Artifact; 050 import org.apache.geronimo.kernel.repository.Environment; 051 import org.apache.geronimo.kernel.repository.WritableListableRepository; 052 import org.apache.geronimo.system.configuration.RepositoryConfigurationStore; 053 054 /** 055 * 056 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 057 */ 058 public class MasterConfigurationStore implements ConfigurationStore { 059 private static final Log log = LogFactory.getLog(MasterConfigurationStore.class); 060 061 private final ConfigurationStore delegate; 062 private final Environment defaultEnvironment; 063 private final ClusterInfo clusterInfo; 064 private final AbstractName clusterInfoName; 065 private final ClusterConfigurationStoreClient storeDelegate; 066 private final SlaveConfigurationNameBuilder slaveConfigNameBuilder; 067 068 public MasterConfigurationStore(Kernel kernel, 069 String objectName, 070 AbstractName abstractName, 071 WritableListableRepository repository, 072 Environment defaultEnvironment, 073 ClusterInfo clusterInfo, 074 ClusterConfigurationStoreClient storeDelegate) { 075 if (null == kernel) { 076 throw new IllegalArgumentException("kernel is required"); 077 } else if (null == objectName) { 078 throw new IllegalArgumentException("objectName is required"); 079 } else if (null == repository) { 080 throw new IllegalArgumentException("repository is required"); 081 } else if (null == defaultEnvironment) { 082 throw new IllegalArgumentException("defaultEnvironment is required"); 083 } else if (null == clusterInfo) { 084 throw new IllegalArgumentException("clusterInfo is required"); 085 } else if (null == storeDelegate) { 086 throw new IllegalArgumentException("storeDelegate is required"); 087 } 088 this.defaultEnvironment = defaultEnvironment; 089 this.clusterInfo = clusterInfo; 090 this.storeDelegate = storeDelegate; 091 092 slaveConfigNameBuilder = newSlaveConfigurationNameBuilder(); 093 clusterInfoName = kernel.getAbstractNameFor(clusterInfo); 094 delegate = newConfigurationStore(kernel, objectName, abstractName, repository); 095 } 096 097 public boolean containsConfiguration(Artifact configId) { 098 if (slaveConfigNameBuilder.isSlaveConfigurationName(configId)) { 099 return false; 100 } 101 return delegate.containsConfiguration(configId); 102 } 103 104 public File createNewConfigurationDir(Artifact configId) throws ConfigurationAlreadyExistsException { 105 Artifact slaveConfigId = slaveConfigNameBuilder.buildSlaveConfigurationName(configId); 106 return delegate.createNewConfigurationDir(slaveConfigId); 107 } 108 109 public void exportConfiguration(Artifact configId, OutputStream output) throws IOException, NoSuchConfigException { 110 ensureArtifactForMasterConfiguration(configId); 111 delegate.exportConfiguration(configId, output); 112 } 113 114 public AbstractName getAbstractName() { 115 return delegate.getAbstractName(); 116 } 117 118 public String getObjectName() { 119 return delegate.getObjectName(); 120 } 121 122 public void install(ConfigurationData configurationData) throws IOException, InvalidConfigException { 123 Environment environment = configurationData.getEnvironment(); 124 Artifact actualConfigId = environment.getConfigId(); 125 Artifact slaveConfigId = slaveConfigNameBuilder.buildSlaveConfigurationName(actualConfigId); 126 environment.setConfigId(slaveConfigId); 127 128 storeDelegate.install(clusterInfo, configurationData); 129 installSlaveConfiguration(configurationData); 130 131 environment.setConfigId(actualConfigId); 132 133 installMasterConfiguration(configurationData, slaveConfigId); 134 } 135 136 public boolean isInPlaceConfiguration(Artifact configId) throws NoSuchConfigException, IOException { 137 ensureArtifactForMasterConfiguration(configId); 138 return false; 139 } 140 141 public List<ConfigurationInfo> listConfigurations() { 142 List<ConfigurationInfo> configurationInfos = delegate.listConfigurations(); 143 144 List<ConfigurationInfo> filteredConfigurationInfos = new ArrayList<ConfigurationInfo>(); 145 for (ConfigurationInfo configurationInfo : configurationInfos) { 146 if (!slaveConfigNameBuilder.isSlaveConfigurationName(configurationInfo.getConfigID())) { 147 filteredConfigurationInfos.add(configurationInfo); 148 } 149 } 150 151 return filteredConfigurationInfos; 152 } 153 154 public ConfigurationData loadConfiguration(Artifact configId) 155 throws NoSuchConfigException, IOException, InvalidConfigException { 156 ensureArtifactForMasterConfiguration(configId); 157 return delegate.loadConfiguration(configId); 158 } 159 160 public Set<URL> resolve(Artifact configId, String moduleName, String path) 161 throws NoSuchConfigException, MalformedURLException { 162 ensureArtifactForMasterConfiguration(configId); 163 return delegate.resolve(configId, moduleName, path); 164 } 165 166 public void uninstall(Artifact configId) throws NoSuchConfigException, IOException { 167 ensureArtifactForMasterConfiguration(configId); 168 169 Artifact slaveConfigId = slaveConfigNameBuilder.buildSlaveConfigurationName(configId); 170 storeDelegate.uninstall(clusterInfo, slaveConfigId); 171 172 try { 173 delegate.uninstall(slaveConfigId); 174 } catch (Exception e) { 175 log.warn("Exception when uninstalling [" + slaveConfigId + "]", e); 176 } 177 delegate.uninstall(configId); 178 } 179 180 protected void ensureArtifactForMasterConfiguration(Artifact configId) throws NoSuchConfigException { 181 if (slaveConfigNameBuilder.isSlaveConfigurationName(configId)) { 182 throw new NoSuchConfigException(configId); 183 } 184 } 185 186 protected ConfigurationStore newConfigurationStore(Kernel kernel, 187 String objectName, 188 AbstractName abstractName, 189 WritableListableRepository repository) { 190 return new RepositoryConfigurationStore(kernel, objectName, abstractName, repository); 191 } 192 193 protected SlaveConfigurationNameBuilder newSlaveConfigurationNameBuilder() { 194 return new BasicSlaveConfigurationNameBuilder(); 195 } 196 197 protected void installMasterConfiguration(ConfigurationData configurationData, Artifact slaveConfigId) 198 throws IOException, InvalidConfigException { 199 ConfigurationData masterConfigurationData = buildMasterConfigurationData(configurationData, slaveConfigId); 200 try { 201 delegate.install(masterConfigurationData); 202 } catch (Exception e) { 203 storeDelegate.uninstall(clusterInfo, slaveConfigId); 204 try { 205 delegate.uninstall(slaveConfigId); 206 } catch (NoSuchConfigException nestedE) { 207 } 208 if (e instanceof IOException) { 209 throw (IOException) e; 210 } else if (e instanceof InvalidConfigException) { 211 throw (InvalidConfigException) e; 212 } 213 throw (IOException) new IOException("See nested").initCause(e); 214 } 215 } 216 217 protected void installSlaveConfiguration(ConfigurationData configurationData) 218 throws IOException, InvalidConfigException { 219 try { 220 delegate.install(configurationData); 221 } catch (Exception e) { 222 storeDelegate.uninstall(clusterInfo, configurationData.getId()); 223 if (e instanceof IOException) { 224 throw (IOException) e; 225 } else if (e instanceof InvalidConfigException) { 226 throw (InvalidConfigException) e; 227 } 228 throw (IOException) new IOException("See nested").initCause(e); 229 } 230 } 231 232 protected ConfigurationData buildMasterConfigurationData(ConfigurationData configurationData, 233 Artifact slaveConfigId) { 234 Environment environment = buildEnvironment(configurationData); 235 236 Artifact configId = environment.getConfigId(); 237 238 List<GBeanData> gbeans = buildControllerGBeans(configId, slaveConfigId); 239 240 File configurationDir = delegate.createNewConfigurationDir(configId); 241 242 return new ConfigurationData(ConfigurationModuleType.CAR, 243 new LinkedHashSet(), 244 gbeans, 245 Collections.EMPTY_MAP, 246 environment, 247 configurationDir, 248 null, 249 configurationData.getNaming()); 250 } 251 252 protected Environment buildEnvironment(ConfigurationData configurationData) { 253 Environment environment = new Environment(defaultEnvironment); 254 environment.setConfigId(configurationData.getId()); 255 return environment; 256 } 257 258 protected List<GBeanData> buildControllerGBeans(Artifact configId, Artifact slaveConfigId) { 259 List<GBeanData> gbeans = new ArrayList<GBeanData>(); 260 for (NodeInfo nodeInfo : clusterInfo.getNodeInfos()) { 261 GBeanData gbean = buildControllerGBean(configId, nodeInfo, slaveConfigId); 262 gbeans.add(gbean); 263 } 264 return gbeans; 265 } 266 267 protected GBeanData buildControllerGBean(Artifact configId, NodeInfo nodeInfo, Artifact slaveConfigId) { 268 AbstractName controllerName = buildControllerName(configId, nodeInfo); 269 270 GBeanData gbean = new GBeanData(controllerName, BasicClusterConfigurationController.GBEAN_INFO); 271 gbean.setAttribute(BasicClusterConfigurationController.GBEAN_ATTR_ARTIFACT, slaveConfigId); 272 gbean.setAttribute(BasicClusterConfigurationController.GBEAN_ATTR_IGNORE_START_CONF_FAIL_UPON_START, 273 Boolean.TRUE); 274 gbean.setAttribute(BasicClusterConfigurationController.GBEAN_ATTR_NODE_NAME, nodeInfo.getName()); 275 gbean.setAttribute(BasicClusterConfigurationController.GBEAN_ATTR_START_CONF_UPON_START, Boolean.TRUE); 276 gbean.setReferencePattern(BasicClusterConfigurationController.GBEAN_REF_CLUSTER_INFO, clusterInfoName); 277 return gbean; 278 } 279 280 protected AbstractName buildControllerName(Artifact configId, 281 NodeInfo nodeInfo) { 282 return new AbstractName(configId, Collections.singletonMap("nodeName", nodeInfo.getName())); 283 } 284 285 public static final GBeanInfo GBEAN_INFO; 286 287 public static final String GBEAN_J2EE_TYPE = "ConfigurationStore"; 288 public static final String GBEAN_ATTR_KERNEL = "kernel"; 289 public static final String GBEAN_ATTR_OBJECT_NAME = "objectName"; 290 public static final String GBEAN_ATTR_DEFAULT_ENV = "defaultEnvironment"; 291 public static final String GBEAN_REF_REPOSITORY = "Repository"; 292 public static final String GBEAN_REF_CLUSTER_INFO = "ClusterInfo"; 293 public static final String GBEAN_REF_CLUSTER_CONF_STORE_CLIENT = "ClusterConfigurationStoreClient"; 294 295 static { 296 GBeanInfoBuilder builder = GBeanInfoBuilder.createStatic(MasterConfigurationStore.class, GBEAN_J2EE_TYPE); 297 298 builder.addAttribute(GBEAN_ATTR_KERNEL, Kernel.class, false); 299 builder.addAttribute(GBEAN_ATTR_OBJECT_NAME, String.class, false); 300 builder.addAttribute("abstractName", AbstractName.class, false); 301 builder.addAttribute(GBEAN_ATTR_DEFAULT_ENV, Environment.class, true, true); 302 303 builder.addReference(GBEAN_REF_REPOSITORY, WritableListableRepository.class, "Repository"); 304 builder.addReference(GBEAN_REF_CLUSTER_INFO, ClusterInfo.class); 305 builder.addReference(GBEAN_REF_CLUSTER_CONF_STORE_CLIENT, ClusterConfigurationStoreClient.class); 306 307 builder.addInterface(ConfigurationStore.class); 308 309 builder.setConstructor(new String[]{GBEAN_ATTR_KERNEL, 310 GBEAN_ATTR_OBJECT_NAME, 311 "abstractName", 312 GBEAN_REF_REPOSITORY, 313 GBEAN_ATTR_DEFAULT_ENV, 314 GBEAN_REF_CLUSTER_INFO, 315 GBEAN_REF_CLUSTER_CONF_STORE_CLIENT}); 316 317 GBEAN_INFO = builder.getBeanInfo(); 318 } 319 320 public static GBeanInfo getGBeanInfo() { 321 return GBEAN_INFO; 322 } 323 324 }