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 }