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 }