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 018 package org.apache.geronimo.deployment.cli; 019 020 import java.io.BufferedInputStream; 021 import java.io.File; 022 import java.io.FileInputStream; 023 import java.io.FileNotFoundException; 024 import java.io.IOException; 025 import java.io.InputStream; 026 import java.io.PrintWriter; 027 import java.io.Serializable; 028 import java.io.Writer; 029 import java.util.Properties; 030 import java.util.jar.JarFile; 031 032 import javax.enterprise.deploy.shared.factories.DeploymentFactoryManager; 033 import javax.enterprise.deploy.spi.DeploymentManager; 034 import javax.enterprise.deploy.spi.exceptions.DeploymentManagerCreationException; 035 import javax.enterprise.deploy.spi.factories.DeploymentFactory; 036 037 import org.apache.geronimo.cli.deployer.ConnectionParams; 038 import org.apache.geronimo.common.DeploymentException; 039 import org.apache.geronimo.deployment.plugin.factories.AuthenticationFailedException; 040 import org.apache.geronimo.deployment.plugin.jmx.JMXDeploymentManager; 041 import org.apache.geronimo.deployment.plugin.jmx.LocalDeploymentManager; 042 import org.apache.geronimo.kernel.Kernel; 043 import org.apache.geronimo.crypto.EncryptionManager; 044 045 /** 046 * Supports online connections to the server, via JSR-88, valid only 047 * when the server is online. 048 * 049 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 050 */ 051 public class ServerConnection { 052 053 private final static String DEFAULT_URI = "deployer:geronimo:jmx"; 054 private final static String DEFAULT_SECURE_URI = "deployer:geronimo:jmxs"; 055 056 private final DeploymentFactory geronimoDeploymentFactory; 057 058 private DeploymentManager manager; 059 private Writer out; 060 private InputStream in; 061 private SavedAuthentication auth; 062 private boolean logToSysErr; 063 private boolean verboseMessages; 064 065 public ServerConnection(ConnectionParams params, PrintWriter out, InputStream in, Kernel kernel, DeploymentFactory geronimoDeploymentFactory) throws DeploymentException { 066 if (null == kernel) { 067 throw new IllegalArgumentException("kernel is required"); 068 } 069 this.geronimoDeploymentFactory = geronimoDeploymentFactory; 070 071 this.out = out; 072 this.in = in; 073 074 String uri = params.getURI(); 075 String driver = params.getDriver(); 076 String user = params.getUser(); 077 String password = params.getPassword(); 078 String host = params.getHost(); 079 Integer port = params.getPort(); 080 verboseMessages = params.isVerbose(); 081 logToSysErr = params.isSyserr(); 082 boolean offline = params.isOffline(); 083 boolean secure = params.isSecure(); 084 085 if ((driver != null) && uri == null) { 086 throw new DeploymentSyntaxException("A custom driver requires a custom URI"); 087 } 088 if (host != null || port != null) { 089 uri = getDefaultURI(secure) + "://" + (host == null ? "" : host) + (port == null ? "" : ":" + port); 090 } 091 if (offline) { 092 startOfflineDeployer(kernel); 093 manager = new LocalDeploymentManager(kernel); 094 } else { 095 tryToConnect(uri, driver, user, password, secure); 096 } 097 if (manager == null) { 098 throw new DeploymentException("Unexpected error; connection failed."); 099 } 100 } 101 102 protected void startOfflineDeployer(Kernel kernel) throws DeploymentException { 103 OfflineDeployerStarter offlineDeployerStarter = new OfflineDeployerStarter(kernel); 104 offlineDeployerStarter.start(); 105 } 106 107 private static String getDefaultURI(boolean secure) { 108 return (secure) ? DEFAULT_SECURE_URI : DEFAULT_URI; 109 } 110 111 public void close() throws DeploymentException { 112 if (manager != null) { 113 manager.release(); 114 } 115 } 116 117 Serializable getAuthentication() { 118 return auth; 119 } 120 121 String getServerURI() { 122 return auth.uri; 123 } 124 125 private void tryToConnect(String argURI, String driver, String user, String password, boolean secure) throws DeploymentException { 126 DeploymentFactoryManager mgr = DeploymentFactoryManager.getInstance(); 127 if (driver != null) { 128 loadDriver(driver, mgr); 129 } else { 130 mgr.registerDeploymentFactory(geronimoDeploymentFactory); 131 } 132 String useURI = argURI == null ? getDefaultURI(secure) : argURI; 133 134 if (user == null && password == null) { 135 InputStream in; 136 // First check for .geronimo-deployer on class path (e.g. packaged in deployer.jar) 137 in = ServerConnection.class.getResourceAsStream("/.geronimo-deployer"); 138 // If not there, check in home directory 139 if (in == null) { 140 File authFile = new File(System.getProperty("user.home"), ".geronimo-deployer"); 141 if (authFile.exists() && authFile.canRead()) { 142 try { 143 in = new BufferedInputStream(new FileInputStream(authFile)); 144 } catch (FileNotFoundException e) { 145 // ignore 146 } 147 } 148 } 149 if (in != null) { 150 try { 151 Properties props = new Properties(); 152 props.load(in); 153 String encrypted = props.getProperty("login." + useURI); 154 if (encrypted != null) { 155 156 if (encrypted.startsWith("{Plain}")) { 157 int pos = encrypted.indexOf("/"); 158 user = encrypted.substring(7, pos); 159 password = encrypted.substring(pos + 1); 160 } else { 161 Object o = EncryptionManager.decrypt(encrypted); 162 if (o == encrypted) { 163 System.out.print(DeployUtils.reformat("Unknown encryption used in saved login file", 4, 72)); 164 } else { 165 SavedAuthentication auth = (SavedAuthentication) o; 166 if (auth.uri.equals(useURI)) { 167 user = auth.user; 168 password = new String(auth.password); 169 } 170 } 171 } 172 } 173 } catch (IOException e) { 174 System.out.print(DeployUtils.reformat("Unable to read authentication from saved login file: " + e.getMessage(), 4, 72)); 175 } finally { 176 try { 177 in.close(); 178 } catch (IOException e) { 179 // ingore 180 } 181 } 182 } 183 } 184 185 if (user == null || password == null) { 186 try { 187 InputPrompt prompt = new InputPrompt(in, out); 188 if (user == null) { 189 user = prompt.getInput("Username: "); 190 } 191 if (password == null) { 192 password = prompt.getPassword("Password: "); 193 } 194 } catch (IOException e) { 195 throw new DeploymentException("Unable to prompt for login", e); 196 } 197 } 198 try { 199 manager = mgr.getDeploymentManager(useURI, user, password); 200 auth = new SavedAuthentication(useURI, user, password == null ? null : password.toCharArray()); 201 } catch (AuthenticationFailedException e) { 202 // server's there, you just can't talk to it 203 throw new DeploymentException("Login Failed"); 204 } catch (DeploymentManagerCreationException e) { 205 throw new DeploymentException("Unable to connect to server at " + useURI + " -- " + e.getMessage(), e); 206 } 207 208 if (manager instanceof JMXDeploymentManager) { 209 JMXDeploymentManager deploymentManager = (JMXDeploymentManager) manager; 210 deploymentManager.setLogConfiguration(logToSysErr, verboseMessages); 211 } 212 } 213 214 private void loadDriver(String driver, DeploymentFactoryManager mgr) throws DeploymentException { 215 File file = new File(driver); 216 if (!file.exists() || !file.canRead() || !DeployUtils.isJarFile(file)) { 217 throw new DeploymentSyntaxException("Driver '" + file.getAbsolutePath() + "' is not a readable JAR file"); 218 } 219 String className = null; 220 try { 221 JarFile jar = new JarFile(file); 222 className = jar.getManifest().getMainAttributes().getValue("J2EE-DeploymentFactory-Implementation-Class"); 223 if (className == null) { 224 throw new DeploymentException("The driver JAR " + file.getAbsolutePath() + " does not specify a J2EE-DeploymentFactory-Implementation-Class; cannot load driver."); 225 } 226 jar.close(); 227 DeploymentFactory factory = (DeploymentFactory) Class.forName(className).newInstance(); 228 mgr.registerDeploymentFactory(factory); 229 } catch (DeploymentException e) { 230 throw e; 231 } catch (Exception e) { 232 throw new DeploymentSyntaxException("Unable to load driver class " + className + " from JAR " + file.getAbsolutePath(), e); 233 } 234 } 235 236 public DeploymentManager getDeploymentManager() { 237 return manager; 238 } 239 240 public boolean isGeronimo() { 241 return manager.getClass().getName().startsWith("org.apache.geronimo."); 242 } 243 244 private final static class SavedAuthentication implements Serializable { 245 private String uri; 246 private String user; 247 private char[] password; 248 249 public SavedAuthentication(String uri, String user, char[] password) { 250 this.uri = uri; 251 this.user = user; 252 this.password = password; 253 } 254 } 255 }