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.net.URL;
025: import java.util.ArrayList;
026: import java.util.Collection;
027: import java.util.Set;
028:
029: import org.apache.commons.logging.Log;
030: import org.apache.commons.logging.LogFactory;
031: import org.apache.geronimo.farm.config.ClusterInfo;
032: import org.apache.geronimo.farm.config.ExtendedJMXConnectorInfo;
033: import org.apache.geronimo.farm.config.NodeInfo;
034: import org.apache.geronimo.deployment.plugin.remote.FileUploadClient;
035: import org.apache.geronimo.deployment.plugin.remote.FileUploadProgress;
036: import org.apache.geronimo.deployment.plugin.remote.FileUploadServletClient;
037: import org.apache.geronimo.gbean.AbstractName;
038: import org.apache.geronimo.gbean.AbstractNameQuery;
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.ConfigurationData;
043: import org.apache.geronimo.kernel.config.InvalidConfigException;
044: import org.apache.geronimo.kernel.repository.Artifact;
045:
046: /**
047: *
048: * @version $Rev:$ $Date:$
049: */
050: public class BasicClusterConfigurationStoreClient implements
051: ClusterConfigurationStoreClient {
052: private static final Log log = LogFactory
053: .getLog(BasicClusterConfigurationStoreClient.class);
054:
055: private static final String[] METHOD_SIGNATURE_INSTALL = new String[] {
056: ConfigurationData.class.getName(), File.class.getName() };
057: private static final String[] METHOD_SIGNATURE_UNINSTALL = new String[] { Artifact.class
058: .getName() };
059:
060: private final AbstractNameQuery clusterConfigurationStoreNameQuery;
061: private final DirectoryPackager packager;
062: private final FileUploadClient fileUploadClient;
063:
064: public BasicClusterConfigurationStoreClient(
065: AbstractNameQuery clusterConfigurationStoreNameQuery) {
066: if (null == clusterConfigurationStoreNameQuery) {
067: throw new IllegalArgumentException(
068: "clusterConfigurationStoreNameQuery is required");
069: }
070: this .clusterConfigurationStoreNameQuery = clusterConfigurationStoreNameQuery;
071:
072: packager = newDirectoryPackager();
073: fileUploadClient = newFileUploadClient();
074: }
075:
076: public void install(ClusterInfo clusterInfo,
077: ConfigurationData configurationData) throws IOException,
078: InvalidConfigException {
079: Collection<NodeInfo> nodeInfos = clusterInfo.getNodeInfos();
080:
081: Collection<NodeInfo> installedToNodeInfos = new ArrayList<NodeInfo>();
082: for (NodeInfo nodeInfo : nodeInfos) {
083: try {
084: install(nodeInfo, configurationData);
085: installedToNodeInfos.add(nodeInfo);
086: } catch (Exception e) {
087: uninstall(clusterInfo, configurationData.getId(),
088: installedToNodeInfos);
089: if (e instanceof IOException) {
090: throw (IOException) e;
091: } else if (e instanceof InvalidConfigException) {
092: throw (InvalidConfigException) e;
093: }
094: throw (IOException) new IOException("See nested")
095: .initCause(e);
096: }
097: }
098: }
099:
100: public void uninstall(ClusterInfo clusterInfo, Artifact configId) {
101: uninstall(clusterInfo, configId, clusterInfo.getNodeInfos());
102: }
103:
104: protected void uninstall(ClusterInfo clusterInfo,
105: Artifact configId, Collection<NodeInfo> installedToNodeInfos) {
106: for (NodeInfo nodeInfo : installedToNodeInfos) {
107: try {
108: uninstall(nodeInfo, configId);
109: } catch (Exception e) {
110: log.info("Ignoring error while uninstalling ["
111: + configId + "]from [" + nodeInfo + "]", e);
112: }
113: }
114: }
115:
116: protected void install(NodeInfo nodeInfo,
117: ConfigurationData configurationData) throws IOException {
118: Kernel kernel = nodeInfo.newKernel();
119:
120: AbstractName clusterConfigurationStoreName = searchClusterConfigurationStore(kernel);
121:
122: File configurationDataFile = uploadConfiguration(kernel,
123: nodeInfo, configurationData);
124:
125: boolean inVMCall = nodeInfo.getConnectorInfo().isLocal();
126: File oldConfigurationDir = null;
127: if (inVMCall) {
128: oldConfigurationDir = configurationData
129: .getConfigurationDir();
130: }
131: Object[] params = new Object[] { configurationData,
132: configurationDataFile };
133: try {
134: kernel.invoke(clusterConfigurationStoreName, "install",
135: params, METHOD_SIGNATURE_INSTALL);
136: } catch (Exception e) {
137: throw (IOException) new IOException("See nested")
138: .initCause(e);
139: } finally {
140: if (inVMCall) {
141: configurationData
142: .setConfigurationDir(oldConfigurationDir);
143: }
144: }
145: }
146:
147: protected void uninstall(NodeInfo nodeInfo, Artifact configId)
148: throws IOException {
149: Kernel kernel = nodeInfo.newKernel();
150:
151: AbstractName clusterConfigurationStoreName = searchClusterConfigurationStore(kernel);
152:
153: Object[] params = new Object[] { configId };
154: try {
155: kernel.invoke(clusterConfigurationStoreName, "uninstall",
156: params, METHOD_SIGNATURE_UNINSTALL);
157: } catch (Exception e) {
158: throw (IOException) new IOException("See nested")
159: .initCause(e);
160: }
161: }
162:
163: protected File uploadConfiguration(Kernel kernel,
164: NodeInfo nodeInfo, ConfigurationData configurationData)
165: throws IOException {
166: File packedConfigurationDir = packager.pack(configurationData
167: .getConfigurationDir());
168:
169: if (nodeInfo.getConnectorInfo().isLocal()) {
170: return packedConfigurationDir;
171: }
172:
173: URL remoteDeployUploadURL = fileUploadClient
174: .getRemoteDeployUploadURL(kernel);
175:
176: ConfigurationUploadProgress configurationUploadProgress = new ConfigurationUploadProgress(
177: configurationData);
178: File[] configurationDataFiles = new File[] { packedConfigurationDir };
179: ExtendedJMXConnectorInfo connectorInfo = nodeInfo
180: .getConnectorInfo();
181: fileUploadClient.uploadFilesToServer(remoteDeployUploadURL,
182: connectorInfo.getUsername(), connectorInfo
183: .getPassword(), configurationDataFiles,
184: configurationUploadProgress);
185:
186: if (configurationUploadProgress.failure) {
187: if (null != configurationUploadProgress.exception) {
188: throw (IOException) new IOException("See nested")
189: .initCause(configurationUploadProgress.exception);
190: }
191: throw new IOException(
192: configurationUploadProgress.failureMessage);
193: }
194:
195: return configurationDataFiles[0];
196: }
197:
198: protected DirectoryPackager newDirectoryPackager() {
199: return new ZipDirectoryPackager();
200: }
201:
202: protected FileUploadClient newFileUploadClient() {
203: return new FileUploadServletClient();
204: }
205:
206: protected AbstractName searchClusterConfigurationStore(Kernel kernel)
207: throws IOException {
208: Set<AbstractName> clusterConfigurationStoreNames = kernel
209: .listGBeans(clusterConfigurationStoreNameQuery);
210: if (1 != clusterConfigurationStoreNames.size()) {
211: throw new IOException("Cannot locate remote store. Found ["
212: + clusterConfigurationStoreNames + "]");
213: }
214: return clusterConfigurationStoreNames.iterator().next();
215: }
216:
217: protected class ConfigurationUploadProgress implements
218: FileUploadProgress {
219: private final ConfigurationData configurationData;
220: private boolean failure;
221: private Exception exception;
222: private String failureMessage;
223:
224: public ConfigurationUploadProgress(
225: ConfigurationData configurationData) {
226: this .configurationData = configurationData;
227: }
228:
229: public void fail(String message) {
230: failure = true;
231: failureMessage = "Upload of configuration ["
232: + configurationData.getId() + "] - [" + message
233: + "]";
234: log.error("Upload of configuration ["
235: + configurationData.getId() + "] - [" + message
236: + "]");
237: }
238:
239: public void fail(Exception exception) {
240: failure = true;
241: this .exception = exception;
242: log.error("Upload of configuration ["
243: + configurationData.getId() + "]", exception);
244: }
245:
246: public void updateStatus(String message) {
247: log.info("Upload of configuration ["
248: + configurationData.getId() + "] - [" + message
249: + "]");
250: }
251: }
252:
253: public static final GBeanInfo GBEAN_INFO;
254:
255: public static final String GBEAN_J2EE_TYPE = "ClusterConfigurationStoreClient";
256: public static final String GBEAN_ATTR_CLUSTER_CONF_STORE_NAME_QUERY = "clusterConfigurationStoreNameQuery";
257:
258: static {
259: GBeanInfoBuilder builder = GBeanInfoBuilder.createStatic(
260: BasicClusterConfigurationStoreClient.class,
261: GBEAN_J2EE_TYPE);
262:
263: builder.addAttribute(GBEAN_ATTR_CLUSTER_CONF_STORE_NAME_QUERY,
264: AbstractNameQuery.class, true);
265:
266: builder.addInterface(ClusterConfigurationStoreClient.class);
267:
268: builder
269: .setConstructor(new String[] { GBEAN_ATTR_CLUSTER_CONF_STORE_NAME_QUERY });
270:
271: GBEAN_INFO = builder.getBeanInfo();
272: }
273:
274: public static GBeanInfo getGBeanInfo() {
275: return GBEAN_INFO;
276: }
277:
278: }
|