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.deployment.plugin.jmx;
018
019 import java.io.File;
020 import java.io.IOException;
021 import java.io.InputStream;
022 import java.net.InetAddress;
023 import java.net.NetworkInterface;
024 import java.net.URL;
025 import java.util.ArrayList;
026 import java.util.Collection;
027 import java.util.Enumeration;
028 import java.util.List;
029 import java.util.Map;
030 import java.util.Set;
031
032 import javax.enterprise.deploy.shared.CommandType;
033 import javax.enterprise.deploy.shared.ModuleType;
034 import javax.enterprise.deploy.spi.Target;
035 import javax.enterprise.deploy.spi.TargetModuleID;
036 import javax.enterprise.deploy.spi.status.ProgressEvent;
037 import javax.enterprise.deploy.spi.status.ProgressListener;
038 import javax.management.MBeanServerConnection;
039 import javax.management.remote.JMXConnector;
040 import javax.security.auth.login.FailedLoginException;
041
042 import org.apache.commons.logging.Log;
043 import org.apache.commons.logging.LogFactory;
044 import org.apache.geronimo.deployment.ModuleConfigurer;
045 import org.apache.geronimo.deployment.plugin.GeronimoDeploymentManager;
046 import org.apache.geronimo.deployment.plugin.local.AbstractDeployCommand;
047 import org.apache.geronimo.deployment.plugin.local.DistributeCommand;
048 import org.apache.geronimo.deployment.plugin.local.RedeployCommand;
049 import org.apache.geronimo.deployment.plugin.remote.RemoteDeployUtil;
050 import org.apache.geronimo.gbean.AbstractName;
051 import org.apache.geronimo.gbean.AbstractNameQuery;
052 import org.apache.geronimo.gbean.GBeanInfo;
053 import org.apache.geronimo.gbean.GBeanInfoBuilder;
054 import org.apache.geronimo.kernel.config.NoSuchStoreException;
055 import org.apache.geronimo.kernel.repository.Artifact;
056 import org.apache.geronimo.kernel.repository.Dependency;
057 import org.apache.geronimo.kernel.repository.MissingDependencyException;
058 import org.apache.geronimo.kernel.InvalidGBeanException;
059 import org.apache.geronimo.system.jmx.KernelDelegate;
060 import org.apache.geronimo.system.plugin.DownloadPoller;
061 import org.apache.geronimo.system.plugin.DownloadResults;
062 import org.apache.geronimo.system.plugin.PluginInstaller;
063 import org.apache.geronimo.system.plugin.PluginRepositoryList;
064 import org.apache.geronimo.system.plugin.ServerArchiver;
065 import org.apache.geronimo.system.plugin.model.PluginListType;
066 import org.apache.geronimo.system.plugin.model.PluginType;
067 import org.apache.geronimo.system.plugin.model.AttributesType;
068 import org.codehaus.plexus.archiver.ArchiverException;
069
070 /**
071 * Connects to a Kernel in a remote VM (may or many not be on the same machine).
072 *
073 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
074 */
075 public class RemoteDeploymentManager extends JMXDeploymentManager implements GeronimoDeploymentManager, ServerArchiver {
076 private static final Log log = LogFactory.getLog(RemoteDeploymentManager.class);
077
078 private JMXConnector jmxConnector;
079 private boolean isSameMachine;
080
081 public RemoteDeploymentManager(Collection<ModuleConfigurer> moduleConfigurers) {
082 super(moduleConfigurers);
083 }
084
085 public void init(JMXConnector jmxConnector, String hostname) throws IOException {
086 this.jmxConnector = jmxConnector;
087 MBeanServerConnection mbServerConnection = jmxConnector.getMBeanServerConnection();
088 initialize(new KernelDelegate(mbServerConnection));
089 checkSameMachine(hostname);
090 }
091
092 public JMXConnector getJMXConnector() {
093 return this.jmxConnector;
094 }
095
096 public boolean isSameMachine() {
097 return isSameMachine;
098 }
099
100 private void checkSameMachine(String hostname) {
101 isSameMachine = false;
102 if (hostname.equals("localhost") || hostname.equals("127.0.0.1")) {
103 isSameMachine = true;
104 return;
105 }
106 try {
107 InetAddress dest = InetAddress.getByName(hostname);
108 Enumeration en = NetworkInterface.getNetworkInterfaces();
109 while (en.hasMoreElements()) {
110 NetworkInterface iface = (NetworkInterface) en.nextElement();
111 Enumeration ine = iface.getInetAddresses();
112 while (ine.hasMoreElements()) {
113 InetAddress address = (InetAddress) ine.nextElement();
114 if (address.equals(dest)) {
115 isSameMachine = true;
116 }
117 }
118 }
119 } catch (Exception e) {
120 log.error(
121 "Unable to look up host name '" + hostname + "'; assuming it is a different machine, but this may not get very far.",
122 e);
123 }
124 }
125
126 public void release() {
127 super.release();
128 try {
129 jmxConnector.close();
130 jmxConnector = null;
131 } catch (IOException e) {
132 throw (IllegalStateException) new IllegalStateException("Unable to close connection").initCause(e);
133 }
134 }
135
136 protected DistributeCommand createDistributeCommand(Target[] targetList, File moduleArchive, File deploymentPlan) {
137 if (isSameMachine) {
138 return super.createDistributeCommand(targetList, moduleArchive, deploymentPlan);
139 } else {
140 return new org.apache.geronimo.deployment.plugin.remote.DistributeCommand(kernel, targetList, moduleArchive,
141 deploymentPlan);
142 }
143 }
144
145 protected DistributeCommand createDistributeCommand(Target[] targetList, ModuleType moduleType, InputStream moduleArchive, InputStream deploymentPlan) {
146 if (isSameMachine) {
147 return super.createDistributeCommand(targetList, moduleType, moduleArchive, deploymentPlan);
148 } else {
149 return new org.apache.geronimo.deployment.plugin.remote.DistributeCommand(kernel, targetList, moduleType,
150 moduleArchive, deploymentPlan);
151 }
152 }
153
154 protected RedeployCommand createRedeployCommand(TargetModuleID[] moduleIDList, File moduleArchive, File deploymentPlan) {
155 if (isSameMachine) {
156 return super.createRedeployCommand(moduleIDList, moduleArchive, deploymentPlan);
157 } else {
158 return new org.apache.geronimo.deployment.plugin.remote.RedeployCommand(kernel, moduleIDList, moduleArchive,
159 deploymentPlan);
160 }
161 }
162
163 protected RedeployCommand createRedeployCommand(TargetModuleID[] moduleIDList, InputStream moduleArchive, InputStream deploymentPlan) {
164 if (isSameMachine) {
165 return super.createRedeployCommand(moduleIDList, moduleArchive, deploymentPlan);
166 } else {
167 return new org.apache.geronimo.deployment.plugin.remote.RedeployCommand(kernel, moduleIDList, moduleArchive,
168 deploymentPlan);
169 }
170 }
171
172 public PluginListType listPlugins(URL mavenRepository, String username, String password) throws FailedLoginException, IOException {
173 PluginInstaller installer = getPluginInstaller();
174 try {
175 return installer.listPlugins(mavenRepository, username, password);
176 } finally {
177 kernel.getProxyManager().destroyProxy(installer);
178 }
179 }
180
181 public void validatePlugin(PluginType plugin) throws MissingDependencyException {
182 PluginInstaller installer = getPluginInstaller();
183 try {
184 installer.validatePlugin(plugin);
185 } finally {
186 kernel.getProxyManager().destroyProxy(installer);
187 }
188 }
189
190 public Dependency[] checkPrerequisites(PluginType plugin) {
191 PluginInstaller installer = getPluginInstaller();
192 try {
193 return installer.checkPrerequisites(plugin);
194 } finally {
195 kernel.getProxyManager().destroyProxy(installer);
196 }
197 }
198
199
200 public DownloadResults install(PluginListType configsToInstall, String defaultRepository, boolean restrictToDefaultRepository, String username, String password) {
201 PluginInstaller installer = getPluginInstaller();
202 try {
203 return installer.install(configsToInstall, defaultRepository, restrictToDefaultRepository, username, password);
204 } finally {
205 kernel.getProxyManager().destroyProxy(installer);
206 }
207 }
208
209 public void install(PluginListType configsToInstall, String defaultRepository, boolean restrictToDefaultRepository, String username, String password, DownloadPoller poller) {
210 PluginInstaller installer = getPluginInstaller();
211 try {
212 installer.install(configsToInstall, defaultRepository, restrictToDefaultRepository, username, password, poller);
213 } finally {
214 kernel.getProxyManager().destroyProxy(installer);
215 }
216 }
217
218 public Object startInstall(PluginListType configsToInstall, String defaultRepository, boolean restrictToDefaultRepository, String username, String password) {
219 PluginInstaller installer = getPluginInstaller();
220 try {
221 return installer.startInstall(configsToInstall, defaultRepository, restrictToDefaultRepository, username, password);
222 } finally {
223 kernel.getProxyManager().destroyProxy(installer);
224 }
225 }
226
227 public Object startInstall(File carFile, String defaultRepository, boolean restrictToDefaultRepository, String username, String password) {
228 File[] args = new File[]{carFile};
229 if (!isSameMachine) {
230 AbstractDeployCommand progress = new AbstractDeployCommand(CommandType.DISTRIBUTE, kernel, null, null, null,
231 null, null, false) {
232 public void run() {
233 }
234 };
235 progress.addProgressListener(new ProgressListener() {
236 public void handleProgressEvent(ProgressEvent event) {
237 log.info(event.getDeploymentStatus().getMessage());
238 }
239 });
240 progress.setCommandContext(commandContext);
241 RemoteDeployUtil.uploadFilesToServer(args, progress);
242 }
243 PluginInstaller installer = getPluginInstaller();
244 try {
245 // make sure to pass args[0] as RemoteDeployUtil.uploadFilesToServer will update
246 // the args argument with the filenames returned from the server
247 return installer.startInstall(args[0], defaultRepository, restrictToDefaultRepository, username, password);
248 } finally {
249 kernel.getProxyManager().destroyProxy(installer);
250 }
251 }
252
253 public DownloadResults checkOnInstall(Object key) {
254 PluginInstaller installer = getPluginInstaller();
255 try {
256 return installer.checkOnInstall(key);
257 } finally {
258 kernel.getProxyManager().destroyProxy(installer);
259 }
260 }
261
262 public DownloadResults checkOnInstall(Object key, boolean remove) {
263 PluginInstaller installer = getPluginInstaller();
264 try {
265 return installer.checkOnInstall(key, remove);
266 } finally {
267 kernel.getProxyManager().destroyProxy(installer);
268 }
269 }
270
271 private PluginInstaller getPluginInstaller() {
272 Set<AbstractName> set = kernel.listGBeans(new AbstractNameQuery(PluginInstaller.class.getName()));
273 for (AbstractName name : set) {
274 return (PluginInstaller) kernel.getProxyManager().createProxy(name, PluginInstaller.class);
275 }
276 throw new IllegalStateException("No plugin installer found");
277 }
278 private ServerArchiver getServerArchiver() {
279 Set<AbstractName> set = kernel.listGBeans(new AbstractNameQuery(ServerArchiver.class.getName()));
280 for (AbstractName name : set) {
281 return (ServerArchiver) kernel.getProxyManager().createProxy(name, ServerArchiver.class);
282 }
283 throw new IllegalStateException("No plugin installer found");
284 }
285
286 //not likely to be useful remotely
287 public PluginListType createPluginListForRepositories(String repo) throws NoSuchStoreException {
288 PluginInstaller installer = getPluginInstaller();
289 try {
290 return installer.createPluginListForRepositories(repo);
291 } finally {
292 kernel.getProxyManager().destroyProxy(installer);
293 }
294 }
295
296 public Map getInstalledPlugins() {
297 PluginInstaller installer = getPluginInstaller();
298 try {
299 return installer.getInstalledPlugins();
300 } finally {
301 kernel.getProxyManager().destroyProxy(installer);
302 }
303 }
304
305 public PluginType getPluginMetadata(Artifact configId) {
306 PluginInstaller installer = getPluginInstaller();
307 try {
308 return installer.getPluginMetadata(configId);
309 } finally {
310 kernel.getProxyManager().destroyProxy(installer);
311 }
312 }
313
314 public void updatePluginMetadata(PluginType metadata) {
315 PluginInstaller installer = getPluginInstaller();
316 try {
317 installer.updatePluginMetadata(metadata);
318 } finally {
319 kernel.getProxyManager().destroyProxy(installer);
320 }
321 }
322
323 public URL[] getRepositories() {
324 List<URL> list = new ArrayList<URL>();
325 Set<AbstractName> set = kernel.listGBeans(new AbstractNameQuery(PluginRepositoryList.class.getName()));
326 for (AbstractName name : set) {
327 PluginRepositoryList repo = (PluginRepositoryList) kernel.getProxyManager().createProxy(name,
328 PluginRepositoryList.class);
329 list.addAll(repo.getRepositories());
330 kernel.getProxyManager().destroyProxy(repo);
331 }
332 return list.toArray(new URL[list.size()]);
333 }
334
335 public Artifact installLibrary(File libFile, String groupId) throws IOException {
336 File[] args = new File[]{libFile};
337 if(!isSameMachine) {
338 AbstractDeployCommand progress = new AbstractDeployCommand(CommandType.DISTRIBUTE, kernel, null, null, null, null, null, false) {
339 public void run() {
340 }
341 };
342 progress.addProgressListener(new ProgressListener() {
343 public void handleProgressEvent(ProgressEvent event) {
344 log.info(event.getDeploymentStatus().getMessage());
345 }
346 });
347 progress.setCommandContext(commandContext);
348 RemoteDeployUtil.uploadFilesToServer(args, progress);
349 }
350 Set<AbstractName> set = kernel.listGBeans(new AbstractNameQuery(PluginInstaller.class.getName()));
351 for (AbstractName name : set) {
352 PluginInstaller installer = (PluginInstaller) kernel.getProxyManager().createProxy(name, PluginInstaller.class);
353 // make sure to pass args[0] as RemoteDeployUtil.uploadFilesToServer will update
354 // the args argument with the filenames returned from the server
355 Artifact artifact = installer.installLibrary(args[0], groupId);
356 kernel.getProxyManager().destroyProxy(installer);
357 return artifact;
358 }
359 return null;
360 }
361
362 public DownloadResults installPluginList(String targetRepositoryPath, String relativeTargetServerPath, PluginListType pluginList) throws Exception {
363 PluginInstaller installer = getPluginInstaller();
364 try {
365 return installer.installPluginList(targetRepositoryPath, relativeTargetServerPath, pluginList);
366 } finally {
367 kernel.getProxyManager().destroyProxy(installer);
368 }
369 }
370
371 public void mergeOverrides(String server, AttributesType overrides) throws InvalidGBeanException, IOException {
372 PluginInstaller installer = getPluginInstaller();
373 try {
374 installer.mergeOverrides(server, overrides);
375 } finally {
376 kernel.getProxyManager().destroyProxy(installer);
377 }
378 }
379
380 public File archive(String sourcePath, String destPath, Artifact artifact) throws ArchiverException, IOException {
381 ServerArchiver archiver = getServerArchiver();
382 try {
383 return archiver.archive(sourcePath, destPath, artifact);
384 } finally {
385 kernel.getProxyManager().destroyProxy(archiver);
386 }
387 }
388
389 public static final GBeanInfo GBEAN_INFO;
390 public static final String GBEAN_REF_MODULE_CONFIGURERS = "ModuleConfigurers";
391
392 static {
393 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(RemoteDeploymentManager.class,
394 "RemoteDeploymentManager");
395 infoFactory.addInterface(GeronimoDeploymentManager.class);
396 infoFactory.addReference(GBEAN_REF_MODULE_CONFIGURERS, ModuleConfigurer.class);
397
398 infoFactory.setConstructor(new String[]{GBEAN_REF_MODULE_CONFIGURERS});
399
400 GBEAN_INFO = infoFactory.getBeanInfo();
401 }
402
403 public static GBeanInfo getGBeanInfo() {
404 return GBEAN_INFO;
405 }
406
407 }