All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.mail.iap.Protocol Maven / Gradle / Ivy

There is a newer version: 1.5.0-b01
Show newest version
/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (the "License").  You may not use this file except 
 * in compliance with the License.
 * 
 * You can obtain a copy of the license at 
 * glassfish/bootstrap/legal/CDDLv1.0.txt or 
 * https://glassfish.dev.java.net/public/CDDLv1.0.html. 
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * HEADER in each file and include the License file at 
 * glassfish/bootstrap/legal/CDDLv1.0.txt.  If applicable, 
 * add the following below this CDDL HEADER, with the 
 * fields enclosed by brackets "[]" replaced with your 
 * own identifying information: Portions Copyright [yyyy] 
 * [name of copyright owner]
 */

/*
 * @(#)Protocol.java	1.28 05/08/29
 *
 * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
 */

package com.sun.mail.iap;

import java.util.Vector;
import java.util.Properties;
import java.io.*;
import java.net.*;
import com.sun.mail.util.*;

/**
 *
 * @version 1.28, 05/08/29
 * @author  John Mani
 * @author  Max Spivak
 */

public class Protocol {
    protected String host;
    private Socket socket;
    // in case we turn on TLS, we'll need these later
    protected boolean debug;
    protected boolean quote;
    protected PrintStream out;

    private TraceInputStream traceInput; // the Tracer
    private ResponseInputStream input;

    private TraceOutputStream traceOutput; // the Tracer
    private DataOutputStream output;

    private int tagCounter = 0;

    private Vector handlers = null; // response handlers

    private long timestamp;

    protected static final byte[] CRLF = { (byte)'\r', (byte)'\n'};
 
    /**
     * Constructor. 

* * Opens a connection to the given host at given port. * * @param host host to connect to * @param port portnumber to connect to * @param debug debug mode * @param out debug output stream * @param props Properties object used by this protocol * @param prefix Prefix to prepend to property keys */ public Protocol(String host, int port, boolean debug, PrintStream out, Properties props, String prefix, boolean isSSL) throws IOException, ProtocolException { this.host = host; this.debug = debug; this.out = out; socket = SocketFetcher.getSocket(host, port, props, prefix, isSSL); String s = props.getProperty("mail.debug.quote"); quote = s != null && s.equalsIgnoreCase("true"); initStreams(out); // Read server greeting processGreeting(readResponse()); timestamp = System.currentTimeMillis(); } private void initStreams(PrintStream out) throws IOException { traceInput = new TraceInputStream(socket.getInputStream(), out); traceInput.setTrace(debug); traceInput.setQuote(quote); input = new ResponseInputStream(traceInput); traceOutput = new TraceOutputStream(socket.getOutputStream(), out); traceOutput.setTrace(debug); traceOutput.setQuote(quote); output = new DataOutputStream(new BufferedOutputStream(traceOutput)); } /** * Constructor for debugging. */ public Protocol(InputStream in, OutputStream out, boolean debug) throws IOException { this.host = "localhost"; this.debug = debug; this.quote = false; this.out = System.out; // XXX - inlined initStreams, won't allow later startTLS traceInput = new TraceInputStream(in, System.out); traceInput.setTrace(debug); traceInput.setQuote(quote); input = new ResponseInputStream(traceInput); traceOutput = new TraceOutputStream(out, System.out); traceOutput.setTrace(debug); traceOutput.setQuote(quote); output = new DataOutputStream(new BufferedOutputStream(traceOutput)); timestamp = System.currentTimeMillis(); } /** * Returns the timestamp. */ public long getTimestamp() { return timestamp; } /** * Adds a response handler. */ public synchronized void addResponseHandler(ResponseHandler h) { if (handlers == null) handlers = new Vector(); handlers.addElement(h); } /** * Removed the specified response handler. */ public synchronized void removeResponseHandler(ResponseHandler h) { if (handlers != null) handlers.removeElement(h); } /** * Notify response handlers */ public void notifyResponseHandlers(Response[] responses) { if (handlers == null) return; for (int i = 0; i < responses.length; i++) { // go thru responses Response r = responses[i]; // skip responses that have already been handled if (r == null) continue; int size = handlers.size(); if (size == 0) return; // Need to copy handlers list because handlers can be removed // when handling a response. Object[] h = new Object[size]; handlers.copyInto(h); // dispatch 'em for (int j = 0; j < size; j++) ((ResponseHandler)h[j]).handleResponse(r); } } protected void processGreeting(Response r) throws ProtocolException { if (r.isBYE()) throw new ConnectionException(this, r); } /** * Return the Protocol's InputStream. */ protected ResponseInputStream getInputStream() { return input; } /** * Return the Protocol's OutputStream */ protected OutputStream getOutputStream() { return output; } /** * Returns whether this Protocol supports non-synchronizing literals * Default is false. Subclasses should override this if required */ protected boolean supportsNonSyncLiterals() { return false; } public Response readResponse() throws IOException, ProtocolException { return new Response(this); } public String writeCommand(String command, Argument args) throws IOException, ProtocolException { String tag = "A" + Integer.toString(tagCounter++, 10); // unique tag output.writeBytes(tag + " " + command); if (args != null) { output.write(' '); args.write(this); } output.write(CRLF); output.flush(); return tag; } /** * Send a command to the server. Collect all responses until either * the corresponding command completion response or a BYE response * (indicating server failure). Return all the collected responses. * * @param command the command * @param args the arguments * @return array of Response objects returned by the server */ public synchronized Response[] command(String command, Argument args) { Vector v = new Vector(); boolean done = false; String tag = null; Response r = null; // write the command try { tag = writeCommand(command, args); } catch (LiteralException lex) { v.addElement(lex.getResponse()); done = true; } catch (Exception ex) { // Convert this into a BYE response v.addElement(Response.byeResponse(ex)); done = true; } while (!done) { try { r = readResponse(); } catch (IOException ioex) { // convert this into a BYE response r = Response.byeResponse(ioex); } catch (ProtocolException pex) { continue; // skip this response } v.addElement(r); if (r.isBYE()) // shouldn't wait for command completion response done = true; // If this is a matching command completion response, we are done if (r.isTagged() && r.getTag().equals(tag)) done = true; } Response[] responses = new Response[v.size()]; v.copyInto(responses); timestamp = System.currentTimeMillis(); return responses; } /** * Convenience routine to handle OK, NO, BAD and BYE responses. */ public void handleResult(Response response) throws ProtocolException { if (response.isOK()) return; else if (response.isNO()) throw new CommandFailedException(response); else if (response.isBAD()) throw new BadCommandException(response); else if (response.isBYE()) { disconnect(); throw new ConnectionException(this, response); } } /** * Convenience routine to handle simple IAP commands * that do not have responses specific to that command. */ public void simpleCommand(String cmd, Argument args) throws ProtocolException { // Issue command Response[] r = command(cmd, args); // dispatch untagged responses notifyResponseHandlers(r); // Handle result of this command handleResult(r[r.length-1]); } /** * Start TLS on the current connection. * cmd is the command to issue to start TLS negotiation. * If the command succeeds, we begin TLS negotiation. */ public void startTLS(String cmd) throws IOException, ProtocolException { simpleCommand(cmd, null); socket = SocketFetcher.startTLS(socket); initStreams(out); } /** * Disconnect. */ protected synchronized void disconnect() { if (socket != null) { try { socket.close(); } catch (IOException e) { } socket = null; } } /** * Finalizer. */ protected void finalize() throws Throwable { super.finalize(); disconnect(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy