blob: 9f7391421827dc1ca868b4cadaea481936f2112e [file]
/***
* $Id: POP3.java,v 1.1 2002/04/03 01:04:33 brekke Exp $
*
* NetComponents Internet Protocol Library
* Copyright (C) 1997-2002 Daniel F. Savarese
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library in the LICENSE file; if not, write
* to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
***/
package com.oroinc.net.pop3;
import java.io.*;
import java.net.*;
import java.util.*;
import com.oroinc.net.*;
/***
* The POP3 class is not meant to be used by itself and is provided
* only so that you may easily implement your own POP3 client if
* you so desire. If you have no need to perform your own implementation,
* you should use <a href="com.oroinc.net.pop3.POP3Client.html">POP3Client</a>.
* <p>
* Rather than list it separately for each method, we mention here that
* every method communicating with the server and throwing an IOException
* can also throw a
* <a href="com.oroinc.net.MalformedServerReplyException.html">
* MalformedServerReplyException </a>, which is a subclass
* of IOException. A MalformedServerReplyException will be thrown when
* the reply received from the server deviates enough from the protocol
* specification that it cannot be interpreted in a useful manner despite
* attempts to be as lenient as possible.
* <p>
* <p>
* @author Daniel F. Savarese
* @see POP3Client
* @see com.oroinc.net.MalformedServerReplyException
***/
public class POP3 extends SocketClient {
/*** The default POP3 port. Set to 110 according to RFC 1288. ***/
public static final int DEFAULT_PORT = 110;
/***
* A constant representing the state where the client is not yet connected
* to a POP3 server.
***/
public static final int DISCONNECTED_STATE = -1;
/*** A constant representing the POP3 authorization state. ***/
public static final int AUTHORIZATION_STATE = 0;
/*** A constant representing the POP3 transaction state. ***/
public static final int TRANSACTION_STATE = 1;
/*** A constant representing the POP3 update state. ***/
public static final int UPDATE_STATE = 2;
static final String _OK = "+OK";
static final String _ERROR = "-ERR";
private int __popState;
private BufferedWriter __writer;
private StringBuffer __commandBuffer;
BufferedReader _reader;
int _replyCode;
String _lastReplyLine;
Vector _replyLines;
/***
* A ProtocolCommandSupport object used to manage the registering of
* ProtocolCommandListeners and te firing of ProtocolCommandEvents.
***/
protected ProtocolCommandSupport _commandSupport_;
/***
* The default POP3Client constructor. Initializes the state
* to <code>DISCONNECTED_STATE</code>.
***/
public POP3() {
setDefaultPort(DEFAULT_PORT);
__commandBuffer = new StringBuffer();
__popState = DISCONNECTED_STATE;
_reader = null;
__writer = null;
_replyLines = new Vector();
_commandSupport_ = new ProtocolCommandSupport(this);
}
private void __getReply() throws IOException {
String line;
_replyLines.setSize(0);
line = _reader.readLine();
if(line == null)
throw new EOFException("Connection closed without indication.");
if(line.startsWith(_OK))
_replyCode = POP3Reply.OK;
else if(line.startsWith(_ERROR))
_replyCode = POP3Reply.ERROR;
else
throw new
MalformedServerReplyException(
"Received invalid POP3 protocol response from server.");
if(_commandSupport_.getListenerCount() > 0)
_commandSupport_.fireReplyReceived(_replyCode, getReplyString());
_replyLines.addElement(line);
_lastReplyLine = line;
}
/***
* Performs connection initialization and sets state to
* <code> AUTHORIZATION_STATE </code>.
***/
protected void _connectAction_() throws IOException {
super._connectAction_();
_reader = new BufferedReader(new InputStreamReader(_input_));
__writer = new BufferedWriter(new OutputStreamWriter(_output_));
__getReply();
setState(AUTHORIZATION_STATE);
}
/***
* Adds a ProtocolCommandListener. Delegates this task to
* <a href="#_commandSupport_"> _commandSupport_ </a>.
* <p>
* @param listener The ProtocolCommandListener to add.
***/
public void addProtocolCommandListener(ProtocolCommandListener listener){
_commandSupport_.addProtocolCommandListener(listener);
}
/***
* Removes a ProtocolCommandListener. Delegates this task to
* <a href="#_commandSupport_"> _commandSupport_ </a>.
* <p>
* @param listener The ProtocolCommandListener to remove.
***/
public void removeProtocolCommandistener(ProtocolCommandListener listener){
_commandSupport_.removeProtocolCommandListener(listener);
}
/***
* Sets POP3 client state. This must be one of the
* <code>_STATE</code> constants.
* <p>
* @param state The new state.
***/
public void setState(int state) { __popState = state; }
/***
* Returns the current POP3 client state.
* <p>
* @return The current POP3 client state.
***/
public int getState() { return __popState; }
/***
* Retrieves the additional lines of a multi-line server reply.
***/
public void getAdditionalReply() throws IOException {
String line;
line = _reader.readLine();
while(line != null) {
_replyLines.addElement(line);
if(line.equals("."))
break;
line = _reader.readLine();
}
}
/***
* Disconnects the client from the server, and sets the state to
* <code> DISCONNECTED_STATE </code>. The reply text information
* from the last issued command is voided to allow garbage collection
* of the memory used to store that information.
* <p>
* @exception IOException If there is an error in disconnecting.
***/
public void disconnect() throws IOException {
super.disconnect();
_reader = null;
__writer = null;
_lastReplyLine = null;
_replyLines.setSize(0);
setState(DISCONNECTED_STATE);
}
/***
* Sends a command an arguments to the server and returns the reply code.
* <p>
* @param command The POP3 command to send.
* @param args The command arguments.
* @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
***/
public int sendCommand(String command, String args) throws IOException {
String message;
__commandBuffer.setLength(0);
__commandBuffer.append(command);
if(args != null) {
__commandBuffer.append(' ');
__commandBuffer.append(args);
}
__commandBuffer.append(SocketClient.NETASCII_EOL);
__writer.write(message = __commandBuffer.toString());
__writer.flush();
if(_commandSupport_.getListenerCount() > 0)
_commandSupport_.fireCommandSent(command, message);
__getReply();
return _replyCode;
}
/***
* Sends a command with no arguments to the server and returns the
* reply code.
* <p>
* @param command The POP3 command to send.
* @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
***/
public int sendCommand(String command) throws IOException {
return sendCommand(command, null);
}
/***
* Sends a command an arguments to the server and returns the reply code.
* <p>
* @param command The POP3 command to send
* (one of the POP3Command constants).
* @param args The command arguments.
* @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
***/
public int sendCommand(int command, String args) throws IOException {
return sendCommand(POP3Command._commands[command], args);
}
/***
* Sends a command with no arguments to the server and returns the
* reply code.
* <p>
* @param command The POP3 command to send
* (one of the POP3Command constants).
* @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
***/
public int sendCommand(int command) throws IOException {
return sendCommand(POP3Command._commands[command], null);
}
/***
* Returns an array of lines received as a reply to the last command
* sent to the server. The lines have end of lines truncated. If
* the reply is a single line, but its format ndicates it should be
* a multiline reply, then you must call
* <a href="#getAdditionalReply"> getAdditionalReply() </a> to
* fetch the rest of the reply, and then call <code>getReplyStrings</code>
* again. You only have to worry about this if you are implementing
* your own client using the <a href="#sendComand"> sendCommand </a> methods.
* <p>
* @return The last server response.
***/
public String[] getReplyStrings() {
String[] lines;
lines = new String[_replyLines.size()];
_replyLines.copyInto(lines);
return lines;
}
/***
* Returns the reply to the last command sent to the server.
* The value is a single string containing all the reply lines including
* newlines. If the reply is a single line, but its format ndicates it
* should be a multiline reply, then you must call
* <a href="#getAdditionalReply"> getAdditionalReply() </a> to
* fetch the rest of the reply, and then call <code>getReplyString</code>
* again. You only have to worry about this if you are implementing
* your own client using the <a href="#sendComand"> sendCommand </a> methods.
* <p>
* @return The last server response.
***/
public String getReplyString() {
Enumeration enum;
StringBuffer buffer = new StringBuffer(256);
enum = _replyLines.elements();
while(enum.hasMoreElements()) {
buffer.append((String)enum.nextElement());
buffer.append(SocketClient.NETASCII_EOL);
}
return buffer.toString();
}
}