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 }