KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > mail > iap > Protocol


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

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

27
28 package com.sun.mail.iap;
29
30 import java.util.Vector JavaDoc;
31 import java.util.Properties JavaDoc;
32 import java.io.*;
33 import java.net.*;
34 import com.sun.mail.util.*;
35
36 /**
37  *
38  * @version 1.28, 05/08/29
39  * @author John Mani
40  * @author Max Spivak
41  */

42
43 public class Protocol {
44     protected String JavaDoc host;
45     private Socket socket;
46     // in case we turn on TLS, we'll need these later
47
protected boolean debug;
48     protected boolean quote;
49     protected PrintStream out;
50
51     private TraceInputStream traceInput; // the Tracer
52
private ResponseInputStream input;
53
54     private TraceOutputStream traceOutput; // the Tracer
55
private DataOutputStream output;
56
57     private int tagCounter = 0;
58
59     private Vector JavaDoc handlers = null; // response handlers
60

61     private long timestamp;
62
63     protected static final byte[] CRLF = { (byte)'\r', (byte)'\n'};
64  
65     /**
66      * Constructor. <p>
67      *
68      * Opens a connection to the given host at given port.
69      *
70      * @param host host to connect to
71      * @param port portnumber to connect to
72      * @param debug debug mode
73      * @param out debug output stream
74      * @param props Properties object used by this protocol
75      * @param prefix Prefix to prepend to property keys
76      */

77     public Protocol(String JavaDoc host, int port, boolean debug,
78             PrintStream out, Properties JavaDoc props, String JavaDoc prefix,
79             boolean isSSL) throws IOException, ProtocolException {
80     this.host = host;
81     this.debug = debug;
82     this.out = out;
83
84     socket = SocketFetcher.getSocket(host, port, props, prefix, isSSL);
85     String JavaDoc s = props.getProperty("mail.debug.quote");
86     quote = s != null && s.equalsIgnoreCase("true");
87
88     initStreams(out);
89
90     // Read server greeting
91
processGreeting(readResponse());
92
93         timestamp = System.currentTimeMillis();
94  
95     }
96
97     private void initStreams(PrintStream out) throws IOException {
98     traceInput = new TraceInputStream(socket.getInputStream(), out);
99     traceInput.setTrace(debug);
100     traceInput.setQuote(quote);
101     input = new ResponseInputStream(traceInput);
102
103     traceOutput = new TraceOutputStream(socket.getOutputStream(), out);
104     traceOutput.setTrace(debug);
105     traceOutput.setQuote(quote);
106     output = new DataOutputStream(new BufferedOutputStream(traceOutput));
107     }
108
109     /**
110      * Constructor for debugging.
111      */

112     public Protocol(InputStream in, OutputStream out, boolean debug)
113                 throws IOException {
114     this.host = "localhost";
115     this.debug = debug;
116     this.quote = false;
117     this.out = System.out;
118
119     // XXX - inlined initStreams, won't allow later startTLS
120
traceInput = new TraceInputStream(in, System.out);
121     traceInput.setTrace(debug);
122     traceInput.setQuote(quote);
123     input = new ResponseInputStream(traceInput);
124
125     traceOutput = new TraceOutputStream(out, System.out);
126     traceOutput.setTrace(debug);
127     traceOutput.setQuote(quote);
128     output = new DataOutputStream(new BufferedOutputStream(traceOutput));
129
130         timestamp = System.currentTimeMillis();
131     }
132
133     /**
134      * Returns the timestamp.
135      */

136  
137     public long getTimestamp() {
138         return timestamp;
139     }
140  
141     /**
142      * Adds a response handler.
143      */

144     public synchronized void addResponseHandler(ResponseHandler h) {
145     if (handlers == null)
146         handlers = new Vector JavaDoc();
147     handlers.addElement(h);
148     }
149
150     /**
151      * Removed the specified response handler.
152      */

153     public synchronized void removeResponseHandler(ResponseHandler h) {
154     if (handlers != null)
155         handlers.removeElement(h);
156     }
157
158     /**
159      * Notify response handlers
160      */

161     public void notifyResponseHandlers(Response[] responses) {
162     if (handlers == null)
163         return;
164     
165     for (int i = 0; i < responses.length; i++) { // go thru responses
166
Response r = responses[i];
167
168         // skip responses that have already been handled
169
if (r == null)
170         continue;
171
172         int size = handlers.size();
173         if (size == 0)
174         return;
175         // Need to copy handlers list because handlers can be removed
176
// when handling a response.
177
Object JavaDoc[] h = new Object JavaDoc[size];
178         handlers.copyInto(h);
179
180         // dispatch 'em
181
for (int j = 0; j < size; j++)
182         ((ResponseHandler)h[j]).handleResponse(r);
183     }
184     }
185
186     protected void processGreeting(Response r) throws ProtocolException {
187     if (r.isBYE())
188         throw new ConnectionException(this, r);
189     }
190
191     /**
192      * Return the Protocol's InputStream.
193      */

194     protected ResponseInputStream getInputStream() {
195     return input;
196     }
197
198     /**
199      * Return the Protocol's OutputStream
200      */

201     protected OutputStream getOutputStream() {
202     return output;
203     }
204
205     /**
206      * Returns whether this Protocol supports non-synchronizing literals
207      * Default is false. Subclasses should override this if required
208      */

209     protected boolean supportsNonSyncLiterals() {
210     return false;
211     }
212
213     public Response readResponse()
214         throws IOException, ProtocolException {
215     return new Response(this);
216     }
217
218     public String JavaDoc writeCommand(String JavaDoc command, Argument args)
219         throws IOException, ProtocolException {
220     String JavaDoc tag = "A" + Integer.toString(tagCounter++, 10); // unique tag
221

222     output.writeBytes(tag + " " + command);
223     
224     if (args != null) {
225         output.write(' ');
226         args.write(this);
227     }
228
229     output.write(CRLF);
230     output.flush();
231     return tag;
232     }
233
234     /**
235      * Send a command to the server. Collect all responses until either
236      * the corresponding command completion response or a BYE response
237      * (indicating server failure). Return all the collected responses.
238      *
239      * @param command the command
240      * @param args the arguments
241      * @return array of Response objects returned by the server
242      */

243     public synchronized Response[] command(String JavaDoc command, Argument args) {
244     Vector JavaDoc v = new Vector JavaDoc();
245     boolean done = false;
246     String JavaDoc tag = null;
247     Response r = null;
248
249     // write the command
250
try {
251         tag = writeCommand(command, args);
252     } catch (LiteralException lex) {
253         v.addElement(lex.getResponse());
254         done = true;
255     } catch (Exception JavaDoc ex) {
256         // Convert this into a BYE response
257
v.addElement(Response.byeResponse(ex));
258         done = true;
259     }
260
261     while (!done) {
262         try {
263         r = readResponse();
264         } catch (IOException ioex) {
265         // convert this into a BYE response
266
r = Response.byeResponse(ioex);
267         } catch (ProtocolException pex) {
268         continue; // skip this response
269
}
270         
271         v.addElement(r);
272
273         if (r.isBYE()) // shouldn't wait for command completion response
274
done = true;
275
276         // If this is a matching command completion response, we are done
277
if (r.isTagged() && r.getTag().equals(tag))
278         done = true;
279     }
280
281     Response[] responses = new Response[v.size()];
282     v.copyInto(responses);
283         timestamp = System.currentTimeMillis();
284     return responses;
285     }
286
287     /**
288      * Convenience routine to handle OK, NO, BAD and BYE responses.
289      */

290     public void handleResult(Response response) throws ProtocolException {
291     if (response.isOK())
292         return;
293     else if (response.isNO())
294         throw new CommandFailedException(response);
295     else if (response.isBAD())
296         throw new BadCommandException(response);
297     else if (response.isBYE()) {
298         disconnect();
299         throw new ConnectionException(this, response);
300     }
301     }
302
303     /**
304      * Convenience routine to handle simple IAP commands
305      * that do not have responses specific to that command.
306      */

307     public void simpleCommand(String JavaDoc cmd, Argument args)
308             throws ProtocolException {
309     // Issue command
310
Response[] r = command(cmd, args);
311
312     // dispatch untagged responses
313
notifyResponseHandlers(r);
314
315     // Handle result of this command
316
handleResult(r[r.length-1]);
317     }
318
319     /**
320      * Start TLS on the current connection.
321      * <code>cmd</code> is the command to issue to start TLS negotiation.
322      * If the command succeeds, we begin TLS negotiation.
323      */

324     public void startTLS(String JavaDoc cmd) throws IOException, ProtocolException {
325     simpleCommand(cmd, null);
326     socket = SocketFetcher.startTLS(socket);
327     initStreams(out);
328     }
329
330     /**
331      * Disconnect.
332      */

333     protected synchronized void disconnect() {
334     if (socket != null) {
335         try {
336         socket.close();
337         } catch (IOException e) { }
338         socket = null;
339     }
340     }
341
342     /**
343      * Finalizer.
344      */

345     protected void finalize() throws Throwable JavaDoc {
346     super.finalize();
347     disconnect();
348     }
349 }
350
Popular Tags