| /***************************************************************************** |
| * Sun Public License Notice |
| * |
| * The contents of this file are subject to the Sun Public License Version |
| * 1.0 (the "License"). You may not use this file except in compliance with |
| * the License. A copy of the License is available at http://www.sun.com/ |
| |
| * The Original Code is the CVS Client Library. |
| * The Initial Developer of the Original Code is Robert Greig. |
| * Portions created by Robert Greig are Copyright (C) 2000. |
| * All Rights Reserved. |
| |
| * Contributor(s): Robert Greig. |
| *****************************************************************************/ |
| package org.netbeans.lib.cvsclient.connection; |
| |
| import org.jetbrains.annotations.NonNls; |
| import org.netbeans.lib.cvsclient.JavaCvsSrcBundle; |
| import org.netbeans.lib.cvsclient.io.IStreamLogger; |
| import org.netbeans.lib.cvsclient.io.StreamUtilities; |
| import org.netbeans.lib.cvsclient.util.BugLog; |
| |
| import java.io.*; |
| import java.net.*; |
| |
| /** |
| * Implements a connection to a pserver. See the cvs documents for more |
| * information about different connection methods. PServer is popular where |
| * security is not an issue. For secure connections, consider using a |
| * kserver (Kerberos) or the GSSAPI. |
| * |
| * @author Robert Greig |
| */ |
| public final class PServerConnection |
| implements IConnection { |
| |
| // Fields ================================================================= |
| |
| private final String userName; |
| private final String encodedPassword; |
| private final String repository; |
| private final ConnectionSettings connectionSettings; |
| |
| private Socket socket; |
| private InputStream socketInputStream; |
| private OutputStream socketOutputStream; |
| @NonNls private static final String ENCODED_PASSWORD_OUTPUT_MESSAGE = "@encodedPassword@"; |
| @NonNls private static final String SUCCESS_MESSAGE = "I LOVE YOU"; |
| @NonNls private static final String FAILED_MESSAGE = "I HATE YOU"; |
| // Setup ================================================================== |
| |
| public PServerConnection(ConnectionSettings connectionSettings, |
| String userName, |
| String encodedPassword, |
| String repository) { |
| BugLog.getInstance().assertNotNull(userName); |
| BugLog.getInstance().assertNotNull(repository); |
| BugLog.getInstance().assertTrue(connectionSettings.getConnectionTimeout() >= 0, "Timeout must be >= 0"); |
| |
| this.userName = userName; |
| this.encodedPassword = (encodedPassword != null) ? encodedPassword : ""; |
| this.repository = repository; |
| this.connectionSettings = connectionSettings; |
| } |
| |
| // Implemented ============================================================) |
| |
| public InputStream getInputStream() { |
| return socketInputStream; |
| } |
| |
| public OutputStream getOutputStream() { |
| return socketOutputStream; |
| } |
| |
| public String getRepository() { |
| return repository; |
| } |
| |
| public void verify(IStreamLogger streamLogger) throws AuthenticationException { |
| try { |
| open(streamLogger); |
| } |
| finally { |
| close(); |
| } |
| } |
| |
| public void open(IStreamLogger streamLogger) throws AuthenticationException { |
| openConnection("BEGIN AUTH REQUEST", "END AUTH REQUEST", streamLogger); |
| } |
| |
| public void close() { |
| if (socketInputStream != null) { |
| try { |
| socketInputStream.close(); |
| } |
| catch (IOException ex) { |
| BugLog.getInstance().showException(ex); |
| } |
| finally { |
| socketInputStream = null; |
| } |
| } |
| |
| if (socketOutputStream != null) { |
| try { |
| socketOutputStream.close(); |
| } |
| catch (IOException ex) { |
| BugLog.getInstance().showException(ex); |
| } |
| finally { |
| socketOutputStream = null; |
| } |
| } |
| |
| if (socket != null) { |
| try { |
| socket.close(); |
| } |
| catch (IOException ex) { |
| // ignore |
| } |
| finally { |
| socket = null; |
| } |
| } |
| } |
| |
| // Utils ================================================================== |
| |
| /** |
| * Authenticate a connection with the server, using the specified |
| * postamble and preamble. |
| * |
| * @param preamble the preamble to use |
| * @param postamble the postamble to use |
| * @throws AuthenticationException if an error occurred |
| * Return the socket used to make the connection. The socket is |
| * guaranteed to be open if an exception has not been thrown |
| */ |
| private void openConnection(@NonNls String preamble, @NonNls String postamble, IStreamLogger streamLogger) throws AuthenticationException { |
| boolean error = true; |
| |
| try { |
| createSocket(); |
| |
| this.socketOutputStream = new BufferedOutputStream(socket.getOutputStream()); |
| this.socketInputStream = new BufferedInputStream(socket.getInputStream()); |
| |
| final OutputStream loggingOutputStream = streamLogger.createLoggingOutputStream(this.socketOutputStream); |
| final InputStream loggingInputStream = streamLogger.createLoggingInputStream(this.socketInputStream); |
| |
| writeLn(loggingOutputStream, preamble, "US-ASCII"); |
| writeLn(loggingOutputStream, repository); |
| writeLn(loggingOutputStream, userName); |
| |
| writeLn(socketOutputStream, encodedPassword, "US-ASCII"); |
| writeLn(streamLogger.getOutputLogStream(), ENCODED_PASSWORD_OUTPUT_MESSAGE); |
| |
| writeLn(loggingOutputStream, postamble, "US-ASCII"); |
| loggingOutputStream.flush(); |
| |
| String response = new StreamUtilities(null).readLine(loggingInputStream); |
| if (response.equals(SUCCESS_MESSAGE)) { |
| error = false; |
| return; |
| } |
| |
| if (response.length() == 0) { |
| throw new AuthenticationException(JavaCvsSrcBundle.message("no.response.from.server.error.message")); |
| } |
| |
| if (response.equals(FAILED_MESSAGE)) { |
| throw new UnknownUserException(JavaCvsSrcBundle.message("wrong.password.or.unknown.user.error.message")); |
| } |
| |
| response = removePrefix(response, "error "); |
| response = removePrefix(response, "E "); |
| throw new AuthenticationException(JavaCvsSrcBundle.message("authentication.failed.error.message", response)); |
| } |
| catch (ConnectException ex) { |
| throw new AuthenticationException(JavaCvsSrcBundle.message("cannot.connect.to.host.error.message", |
| connectionSettings.getHostName()), ex); |
| } |
| catch (NoRouteToHostException ex) { |
| throw new AuthenticationException(JavaCvsSrcBundle.message("no.route.to.host.error.message", |
| connectionSettings.getHostName()), ex); |
| } |
| catch (UnknownHostException ex) { |
| throw new AuthenticationException(JavaCvsSrcBundle.message("unknown.host.error.message", |
| connectionSettings.getHostName()), ex); |
| } |
| catch (SocketTimeoutException ex) { |
| throw new AuthenticationException(JavaCvsSrcBundle.message("timeout.error.message", |
| connectionSettings.getHostName()), ex); |
| } |
| catch (IOException ex) { |
| throw new AuthenticationException(JavaCvsSrcBundle.message("i.o.error.while.connecting.to.host.error.message", |
| connectionSettings.getHostName()), ex); |
| } |
| finally { |
| if (error) { |
| close(); |
| } |
| } |
| } |
| |
| private static void writeLn(final OutputStream outputStream, final String line, @NonNls final String encoding) throws IOException { |
| final String line1 = line + "\n"; |
| outputStream.write(line1.getBytes(encoding)); |
| } |
| |
| private static void writeLn(final OutputStream outputStream, final String line) throws IOException { |
| final String line1 = line + "\n"; |
| outputStream.write(line1.getBytes()); |
| } |
| |
| private void createSocket() throws IOException { |
| if (connectionSettings.isUseProxy()) { |
| this.socket = connectionSettings.createProxyTransport(); |
| } |
| else { |
| this.socket = new Socket(); |
| final InetSocketAddress address = |
| new InetSocketAddress(connectionSettings.getHostName(), connectionSettings.getPort()); |
| this.socket.connect(address, connectionSettings.getConnectionTimeout()); |
| this.socket.setSoTimeout(connectionSettings.getConnectionTimeout()); |
| } |
| } |
| |
| // Utils ================================================================== |
| |
| private static String removePrefix(String response, @NonNls String prefix) { |
| if (response.length() > prefix.length() |
| && response.startsWith(prefix)) { |
| return response.substring(prefix.length()); |
| } |
| return response; |
| } |
| } |