working on fixes for mail test server

This commit is contained in:
Jörg Prante 2024-07-31 18:37:32 +02:00
parent d803fab767
commit 0849a6decf
15 changed files with 340 additions and 376 deletions

View file

@ -24,6 +24,7 @@ import org.junit.jupiter.api.Test;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@ -80,7 +81,7 @@ public final class IMAPAlertTest {
store.close();
}
} catch (final Exception e) {
e.printStackTrace();
//e.printStackTrace();
fail(e.getMessage());
} finally {
if (server != null) {
@ -94,9 +95,9 @@ public final class IMAPAlertTest {
*/
private static final class IMAPHandlerAlert extends IMAPHandler {
@Override
public void login() throws IOException {
untagged("OK [ALERT] account is over quota");
super.login();
public void login(OutputStream outputStream) throws IOException {
untagged(outputStream, "OK [ALERT] account is over quota");
super.login(outputStream);
}
}
}

View file

@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
import static org.junit.jupiter.api.Assertions.fail;
@ -37,11 +38,11 @@ public final class IMAPCloseFailureTest {
static boolean first = true;
@Override
public void examine(String line) throws IOException {
public void examine(OutputStream outputStream, String line) throws IOException {
if (first)
no("mailbox gone");
no(outputStream, "mailbox gone");
else
super.examine(line);
super.examine(outputStream, line);
first = false;
}
}
@ -50,11 +51,11 @@ public final class IMAPCloseFailureTest {
static boolean first = true;
@Override
public void examine(String line) throws IOException {
public void examine(OutputStream outputStream, String line) throws IOException {
if (first)
bad("mailbox gone");
bad(outputStream, "mailbox gone");
else
super.examine(line);
super.examine(outputStream, line);
first = false;
}
}

View file

@ -25,6 +25,7 @@ import org.xbib.net.mail.test.test.TestServer;
import org.xbib.net.mail.util.MailConnectException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.util.Properties;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -89,12 +90,12 @@ public final class IMAPConnectFailureTest {
try {
final IMAPHandler handler = new IMAPHandler() {
@Override
public void sendGreetings() throws IOException {
untagged("OK IMAPHandler");
public void sendGreetings(OutputStream outputStream) throws IOException {
untagged(outputStream, "OK IMAPHandler");
}
@Override
public void capability() throws IOException {
public void capability(OutputStream outputStream) throws IOException {
exit();
}
};

View file

@ -28,6 +28,7 @@ import org.xbib.net.mail.imap.IMAPFolder;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
@ -75,11 +76,12 @@ public final class IMAPFetchProfileTest {
},
new IMAPHandlerFetch() {
@Override
public void fetch(String line) throws IOException {
if (line.contains("INTERNALDATE"))
public void fetch(OutputStream outputStream, String line) throws IOException {
if (line.contains("INTERNALDATE")) {
saw.add("INTERNALDATE");
untagged("1 FETCH (INTERNALDATE \"" + RDATE + "\")");
ok();
}
untagged(outputStream, "1 FETCH (INTERNALDATE \"" + RDATE + "\")");
ok(outputStream);
}
});
}
@ -103,11 +105,12 @@ public final class IMAPFetchProfileTest {
},
new IMAPHandlerFetch() {
@Override
public void fetch(String line) throws IOException {
if (line.contains("INTERNALDATE"))
public void fetch(OutputStream outputStream, String line) throws IOException {
if (line.contains("INTERNALDATE")) {
saw.add("INTERNALDATE");
untagged("1 FETCH (INTERNALDATE \"" + RDATE + "\")");
ok();
}
untagged(outputStream, "1 FETCH (INTERNALDATE \"" + RDATE + "\")");
ok(outputStream);
}
});
}
@ -126,12 +129,13 @@ public final class IMAPFetchProfileTest {
},
new IMAPHandlerFetch() {
@Override
public void fetch(String line) throws IOException {
if (line.contains("INTERNALDATE"))
public void fetch(OutputStream outputStream, String line) throws IOException {
if (line.contains("INTERNALDATE")) {
saw.add("INTERNALDATE");
untagged("1 FETCH (ENVELOPE " + ENVELOPE +
}
untagged(outputStream, "1 FETCH (ENVELOPE " + ENVELOPE +
" INTERNALDATE \"" + RDATE + "\" RFC822.SIZE 0)");
ok();
ok(outputStream);
}
});
}
@ -182,9 +186,9 @@ public final class IMAPFetchProfileTest {
protected static Set<String> saw = new HashSet<>();
@Override
public void select(String line) throws IOException {
public void select(OutputStream outputStream, String line) throws IOException {
numberOfMessages = 1;
super.select(line);
super.select(outputStream, line);
}
public boolean saw(String item) {

View file

@ -27,6 +27,7 @@ import org.xbib.net.mail.imap.IMAPFolder;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.logging.Level;
@ -75,21 +76,21 @@ class IMAPFolderTest {
},
new IMAPHandler() {
@Override
public void create(String line) throws IOException {
public void create(OutputStream outputStream,String line) throws IOException {
StringTokenizer st = new StringTokenizer(line);
st.nextToken(); // skip tag
st.nextToken(); // skip "CREATE"
String name = st.nextToken();
if (name.equals(utf7Folder))
ok();
ok(outputStream);
else
no("wrong name");
no(outputStream, "wrong name");
}
@Override
public void list(String line) throws IOException {
untagged("LIST (\\HasNoChildren) \"/\" " + utf7Folder);
ok();
public void list(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "LIST (\\HasNoChildren) \"/\" " + utf7Folder);
ok(outputStream);
}
});
}
@ -111,22 +112,21 @@ class IMAPFolderTest {
},
new IMAPUtf8Handler() {
@Override
public void create(String line) throws IOException {
public void create(OutputStream outputStream, String line) throws IOException {
StringTokenizer st = new StringTokenizer(line);
st.nextToken(); // skip tag
st.nextToken(); // skip "CREATE"
String name = unquote(st.nextToken());
if (name.equals(utf8Folder))
ok();
ok(outputStream);
else
no("wrong name");
no(outputStream, "wrong name");
}
@Override
public void list(String line) throws IOException {
untagged("LIST (\\HasNoChildren) \"/\" \"" +
utf8Folder + "\"");
ok();
public void list(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "LIST (\\HasNoChildren) \"/\" \"" + utf8Folder + "\"");
ok(outputStream);
}
});
}
@ -148,15 +148,15 @@ class IMAPFolderTest {
},
new IMAPHandler() {
@Override
public void delete(String line) throws IOException {
public void delete(OutputStream outputStream, String line) throws IOException {
StringTokenizer st = new StringTokenizer(line);
st.nextToken(); // skip tag
st.nextToken(); // skip "DELETE"
String name = st.nextToken();
if (name.equals(utf7Folder))
ok();
ok(outputStream);
else
no("wrong name");
no(outputStream, "wrong name");
}
});
}
@ -178,15 +178,16 @@ class IMAPFolderTest {
},
new IMAPUtf8Handler() {
@Override
public void delete(String line) throws IOException {
public void delete(OutputStream outputStream, String line) throws IOException {
StringTokenizer st = new StringTokenizer(line);
st.nextToken(); // skip tag
st.nextToken(); // skip "DELETE"
String name = unquote(st.nextToken());
if (name.equals(utf8Folder))
ok();
else
no("wrong name");
if (name.equals(utf8Folder)) {
ok(outputStream);
} else {
no(outputStream, "wrong name");
}
}
});
}
@ -210,15 +211,15 @@ class IMAPFolderTest {
},
new IMAPHandler() {
@Override
public void select(String line) throws IOException {
public void select(OutputStream outputStream, String line) throws IOException {
StringTokenizer st = new StringTokenizer(line);
st.nextToken(); // skip tag
st.nextToken(); // skip "SELECT"
String name = st.nextToken();
if (name.equals(utf7Folder))
ok();
ok(outputStream);
else
no("wrong name");
no(outputStream, "wrong name");
}
});
}
@ -242,15 +243,15 @@ class IMAPFolderTest {
},
new IMAPUtf8Handler() {
@Override
public void select(String line) throws IOException {
public void select(OutputStream outputStream, String line) throws IOException {
StringTokenizer st = new StringTokenizer(line);
st.nextToken(); // skip tag
st.nextToken(); // skip "SELECT"
String name = unquote(st.nextToken());
if (name.equals(utf8Folder))
ok();
ok(outputStream);
else
no("wrong name");
no(outputStream, "wrong name");
}
});
}
@ -274,15 +275,15 @@ class IMAPFolderTest {
},
new IMAPHandler() {
@Override
public void examine(String line) throws IOException {
public void examine(OutputStream outputStream, String line) throws IOException {
StringTokenizer st = new StringTokenizer(line);
st.nextToken(); // skip tag
st.nextToken(); // skip "EXAMINE"
String name = st.nextToken();
if (name.equals(utf7Folder))
ok();
ok(outputStream);
else
no("wrong name");
no(outputStream, "wrong name");
}
});
}
@ -306,15 +307,15 @@ class IMAPFolderTest {
},
new IMAPUtf8Handler() {
@Override
public void examine(String line) throws IOException {
public void examine(OutputStream outputStream, String line) throws IOException {
StringTokenizer st = new StringTokenizer(line);
st.nextToken(); // skip tag
st.nextToken(); // skip "EXAMINE"
String name = unquote(st.nextToken());
if (name.equals(utf8Folder))
ok();
ok(outputStream);
else
no("wrong name");
no(outputStream, "wrong name");
}
});
}
@ -336,17 +337,17 @@ class IMAPFolderTest {
},
new IMAPHandler() {
@Override
public void status(String line) throws IOException {
public void status(OutputStream outputStream, String line) throws IOException {
StringTokenizer st = new StringTokenizer(line);
st.nextToken(); // skip tag
st.nextToken(); // skip "STATUS"
String name = st.nextToken();
if (name.equals(utf7Folder)) {
untagged("STATUS " + utf7Folder +
untagged(outputStream, "STATUS " + utf7Folder +
" (UIDVALIDITY 123)");
ok();
ok(outputStream);
} else
no("wrong name");
no(outputStream, "wrong name");
}
});
}
@ -368,17 +369,17 @@ class IMAPFolderTest {
},
new IMAPUtf8Handler() {
@Override
public void status(String line) throws IOException {
public void status(OutputStream outputStream, String line) throws IOException {
StringTokenizer st = new StringTokenizer(line);
st.nextToken(); // skip tag
st.nextToken(); // skip "STATUS"
String name = unquote(st.nextToken());
if (name.equals(utf8Folder)) {
untagged("STATUS \"" + utf8Folder +
untagged(outputStream, "STATUS \"" + utf8Folder +
"\" (UIDVALIDITY 123)");
ok();
ok(outputStream);
} else
no("wrong name");
no(outputStream, "wrong name");
}
});
}
@ -426,9 +427,9 @@ class IMAPFolderTest {
},
new IMAPHandler() {
@Override
public void select(String line) throws IOException {
untagged("NO [UIDNOTSTICKY]");
super.select(line);
public void select(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "NO [UIDNOTSTICKY]");
super.select(outputStream, line);
}
});
}
@ -457,10 +458,10 @@ class IMAPFolderTest {
},
new IMAPHandler() {
@Override
public void search(String line) throws IOException {
untagged("1 EXPUNGE");
untagged("0 EXISTS");
super.search(line);
public void search(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "1 EXPUNGE");
untagged(outputStream, "0 EXISTS");
super.search(outputStream, line);
}
});
}
@ -527,8 +528,8 @@ class IMAPFolderTest {
}
@Override
public void enable(String line) throws IOException {
ok();
public void enable(OutputStream outputStream, String line) throws IOException {
ok(outputStream);
}
}
}

View file

@ -21,10 +21,12 @@ import org.xbib.net.mail.test.test.ProtocolHandler;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.Channels;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Handle IMAP connection.
@ -33,6 +35,8 @@ import java.util.logging.Level;
*/
public class IMAPHandler extends ProtocolHandler {
private static final Logger logger = Logger.getLogger(IMAPHandler.class.getName());
/**
* Current line.
*/
@ -58,19 +62,14 @@ public class IMAPHandler extends ProtocolHandler {
*/
protected int numberOfRecentMessages = 0;
public IMAPHandler(InputStream inputStream,
OutputStream outputStream) {
super(inputStream, outputStream);
}
/**
* Send greetings.
*
* @throws IOException unable to write to socket
*/
@Override
public void sendGreetings() throws IOException {
untagged("OK [CAPABILITY " + capabilities + "] IMAPHandler");
public void sendGreetings(OutputStream outputStream) throws IOException {
untagged(outputStream, "OK [CAPABILITY " + capabilities + "] IMAPHandler");
}
/**
@ -79,10 +78,9 @@ public class IMAPHandler extends ProtocolHandler {
* @param str String to send
* @throws IOException unable to write to socket
*/
public void println(final String str) throws IOException {
writer.print(str);
writer.print("\r\n");
writer.flush();
public void println(OutputStream outputStream, final String str) throws IOException {
Channels.newChannel(outputStream).write(StandardCharsets.UTF_8.encode(str + "\r\n"));
outputStream.flush();
}
/**
@ -91,8 +89,8 @@ public class IMAPHandler extends ProtocolHandler {
* @param resp the response to send
* @throws IOException unable to read/write to socket
*/
public void tagged(final String resp) throws IOException {
println(tag + " " + resp);
public void tagged(OutputStream outputStream, final String resp) throws IOException {
println(outputStream, tag + " " + resp);
}
/**
@ -101,8 +99,8 @@ public class IMAPHandler extends ProtocolHandler {
* @param resp the response to send
* @throws IOException unable to read/write to socket
*/
public void untagged(final String resp) throws IOException {
println("* " + resp);
public void untagged(OutputStream outputStream, final String resp) throws IOException {
println(outputStream, "* " + resp);
}
/**
@ -110,8 +108,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void ok() throws IOException {
tagged("OK");
public void ok(OutputStream outputStream) throws IOException {
tagged(outputStream, "OK");
}
/**
@ -120,8 +118,8 @@ public class IMAPHandler extends ProtocolHandler {
* @param msg the message to send
* @throws IOException unable to read/write to socket
*/
public void ok(final String msg) throws IOException {
tagged("OK " + (msg != null ? msg : ""));
public void ok(OutputStream outputStream, final String msg) throws IOException {
tagged(outputStream, "OK " + (msg != null ? msg : ""));
}
/**
@ -130,8 +128,8 @@ public class IMAPHandler extends ProtocolHandler {
* @param msg the message to send
* @throws IOException unable to read/write to socket
*/
public void no(final String msg) throws IOException {
tagged("NO " + (msg != null ? msg : ""));
public void no(OutputStream outputStream, final String msg) throws IOException {
tagged(outputStream, "NO " + (msg != null ? msg : ""));
}
/**
@ -140,8 +138,8 @@ public class IMAPHandler extends ProtocolHandler {
* @param msg the message to send
* @throws IOException unable to read/write to socket
*/
public void bad(final String msg) throws IOException {
tagged("BAD " + (msg != null ? msg : ""));
public void bad(OutputStream outputStream, final String msg) throws IOException {
tagged(outputStream, "BAD " + (msg != null ? msg : ""));
}
/**
@ -150,8 +148,8 @@ public class IMAPHandler extends ProtocolHandler {
* @param msg the message to send
* @throws IOException unable to read/write to socket
*/
public void bye(final String msg) throws IOException {
untagged("BYE " + (msg != null ? msg : ""));
public void bye(OutputStream outputStream, final String msg) throws IOException {
untagged(outputStream, "BYE " + (msg != null ? msg : ""));
exit();
}
@ -160,8 +158,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void cont() throws IOException {
println("+ please continue");
public void cont(OutputStream outputStream) throws IOException {
println(outputStream, "+ please continue");
}
/**
@ -169,8 +167,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void cont(String msg) throws IOException {
println("+ " + (msg != null ? msg : ""));
public void cont(OutputStream outputStream, String msg) throws IOException {
println(outputStream, "+ " + (msg != null ? msg : ""));
}
/**
@ -179,96 +177,92 @@ public class IMAPHandler extends ProtocolHandler {
* @throws IOException unable to read/write to socket
*/
@Override
public void handleCommand() throws IOException {
currentLine = super.readLine();
public void handleCommand(InputStream inputStream, OutputStream outputStream) throws IOException {
currentLine = super.readLine(inputStream);
if (currentLine == null) {
// probably just EOF because the socket was closed
//LOGGER.severe("Current line is null!");
exit();
return;
}
StringTokenizer ct = new StringTokenizer(currentLine, " ");
if (!ct.hasMoreTokens()) {
LOGGER.log(Level.SEVERE, "ERROR no command tag: {0}",
escape(currentLine));
bad("no command tag");
logger.log(Level.SEVERE, "ERROR no command tag: {0}", escape(currentLine));
bad(outputStream, "no command tag");
return;
}
tag = ct.nextToken();
if (!ct.hasMoreTokens()) {
LOGGER.log(Level.SEVERE, "ERROR no command: {0}",
logger.log(Level.SEVERE, "ERROR no command: {0}",
escape(currentLine));
bad("no command");
bad(outputStream, "no command");
return;
}
final String commandName = ct.nextToken().toUpperCase();
if (commandName == null) {
LOGGER.severe("Command name is empty!");
if (commandName.isEmpty()) {
logger.severe("Command name is empty!");
exit();
return;
}
if (commandName.equals("LOGIN")) {
login();
login(outputStream);
} else if (commandName.equals("AUTHENTICATE")) {
String mech = ct.nextToken().toUpperCase();
String ir = null;
if (ct.hasMoreTokens())
if (ct.hasMoreTokens()) {
ir = ct.nextToken();
authenticate(mech, ir);
}
authenticate(inputStream, outputStream, mech, ir);
} else if (commandName.equals("CAPABILITY")) {
capability();
capability(outputStream);
} else if (commandName.equals("NOOP")) {
noop();
noop(outputStream);
} else if (commandName.equals("SELECT")) {
select(currentLine);
select(outputStream, currentLine);
} else if (commandName.equals("EXAMINE")) {
examine(currentLine);
examine(outputStream, currentLine);
} else if (commandName.equals("LIST")) {
list(currentLine);
list(outputStream, currentLine);
} else if (commandName.equals("IDLE")) {
idle();
idle(inputStream, outputStream);
} else if (commandName.equals("FETCH")) {
fetch(currentLine);
fetch(outputStream, currentLine);
} else if (commandName.equals("STORE")) {
store(currentLine);
store(outputStream, currentLine);
} else if (commandName.equals("SEARCH")) {
search(currentLine);
search(outputStream, currentLine);
} else if (commandName.equals("APPEND")) {
append(currentLine);
append(inputStream, outputStream, currentLine);
} else if (commandName.equals("CLOSE")) {
close();
close(outputStream);
} else if (commandName.equals("LOGOUT")) {
logout();
logout(outputStream);
} else if (commandName.equals("UID")) {
String subcommandName = ct.nextToken().toUpperCase();
if (subcommandName.equals("FETCH")) {
uidfetch(currentLine);
uidfetch(outputStream, currentLine);
} else if (subcommandName.equals("STORE")) {
uidstore(currentLine);
uidstore(outputStream, currentLine);
} else {
LOGGER.log(Level.SEVERE, "ERROR UID command unknown: {0}",
subcommandName);
bad("unknown UID command");
logger.log(Level.SEVERE, "ERROR UID command unknown: {0}", subcommandName);
bad(outputStream, "unknown UID command");
}
} else if (commandName.equals("ID")) {
id(currentLine);
id(outputStream, currentLine);
} else if (commandName.equals("ENABLE")) {
enable(currentLine);
enable(outputStream, currentLine);
} else if (commandName.equals("CREATE")) {
create(currentLine);
create(outputStream, currentLine);
} else if (commandName.equals("DELETE")) {
delete(currentLine);
delete(outputStream, currentLine);
} else if (commandName.equals("STATUS")) {
status(currentLine);
status(outputStream, currentLine);
} else if (commandName.equals("NAMESPACE")) {
namespace();
namespace(outputStream);
} else {
LOGGER.log(Level.SEVERE, "ERROR command unknown: {0}",
logger.log(Level.SEVERE, "ERROR command unknown: {0}",
escape(currentLine));
bad("unknown command");
bad(outputStream, "unknown command");
}
}
@ -277,8 +271,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void login() throws IOException {
ok("[CAPABILITY " + capabilities + "]");
public void login(OutputStream outputStream) throws IOException {
ok(outputStream, "[CAPABILITY " + capabilities + "]");
}
/**
@ -286,13 +280,13 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void authenticate(String mech, String ir) throws IOException {
public void authenticate(InputStream inputStream, OutputStream outputStream, String mech, String ir) throws IOException {
if (mech.equals("LOGIN"))
authlogin(ir);
authlogin(inputStream, outputStream, ir);
else if (mech.equals("PLAIN"))
authplain(ir);
authplain(inputStream, outputStream, ir);
else
bad("AUTHENTICATE not supported");
bad(outputStream, "AUTHENTICATE not supported");
}
/**
@ -300,14 +294,14 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void authlogin(String ir) throws IOException {
public void authlogin(InputStream inputStream, OutputStream outputStream, String ir) throws IOException {
if (ir != null)
bad("AUTHENTICATE LOGIN does not support initial response");
cont(base64encode("Username"));
String username = readLine();
cont(base64encode("Password"));
String password = readLine();
ok("[CAPABILITY " + capabilities + "]");
bad(outputStream, "AUTHENTICATE LOGIN does not support initial response");
cont(outputStream, base64encode("Username"));
String username = readLine(inputStream);
cont(outputStream, base64encode("Password"));
String password = readLine(inputStream);
ok(outputStream, "[CAPABILITY " + capabilities + "]");
}
/**
@ -315,12 +309,12 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void authplain(String ir) throws IOException {
public void authplain(InputStream inputStream, OutputStream outputStream, String ir) throws IOException {
if (ir == null) {
cont("");
String resp = readLine();
cont(outputStream, "");
String resp = readLine(inputStream);
}
ok("[CAPABILITY " + capabilities + "]");
ok(outputStream, "[CAPABILITY " + capabilities + "]");
}
/**
@ -328,9 +322,9 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void capability() throws IOException {
untagged("CAPABILITY " + capabilities);
ok();
public void capability(OutputStream outputStream) throws IOException {
untagged(outputStream, "CAPABILITY " + capabilities);
ok(outputStream);
}
/**
@ -338,10 +332,10 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void select(String line) throws IOException {
untagged(numberOfMessages + " EXISTS");
untagged(numberOfRecentMessages + " RECENT");
ok();
public void select(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, numberOfMessages + " EXISTS");
untagged(outputStream, numberOfRecentMessages + " RECENT");
ok(outputStream);
}
/**
@ -349,10 +343,10 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void examine(String line) throws IOException {
untagged(numberOfMessages + " EXISTS");
untagged(numberOfRecentMessages + " RECENT");
ok();
public void examine(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, numberOfMessages + " EXISTS");
untagged(outputStream, numberOfRecentMessages + " RECENT");
ok(outputStream);
}
/**
@ -360,8 +354,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void list(String line) throws IOException {
ok();
public void list(OutputStream outputStream, String line) throws IOException {
ok(outputStream);
}
/**
@ -369,29 +363,27 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void idle() throws IOException {
cont();
idleWait();
ok();
public void idle(InputStream inputStream, OutputStream outputStream) throws IOException {
cont(outputStream);
idleWait(inputStream, outputStream);
ok(outputStream);
}
@Override
protected String readLine() throws IOException {
currentLine = super.readLine();
protected String readLine(InputStream inputStream) throws IOException {
currentLine = super.readLine(inputStream);
if (currentLine == null) {
LOGGER.severe("Current line is null!");
logger.severe("Current line is null!");
exit();
}
return currentLine;
}
protected void idleWait() throws IOException {
String line = readLine();
protected void idleWait(InputStream inputStream, OutputStream outputStream) throws IOException {
String line = readLine(inputStream);
if (line != null && !line.equalsIgnoreCase("DONE")) {
LOGGER.severe("Didn't get DONE response to IDLE");
logger.severe("Didn't get DONE response to IDLE");
exit();
return;
}
}
@ -400,8 +392,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void fetch(String line) throws IOException {
ok(); // XXX
public void fetch(OutputStream outputStream, String line) throws IOException {
ok(outputStream);
}
/**
@ -409,8 +401,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void store(String line) throws IOException {
ok(); // XXX
public void store(OutputStream outputStream, String line) throws IOException {
ok(outputStream);
}
/**
@ -418,9 +410,9 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void search(String line) throws IOException {
untagged("SEARCH");
ok(); // XXX
public void search(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "SEARCH");
ok(outputStream);
}
/**
@ -428,8 +420,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void uidfetch(String line) throws IOException {
ok(); // XXX
public void uidfetch(OutputStream outputStream, String line) throws IOException {
ok(outputStream);
}
/**
@ -437,8 +429,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void uidstore(String line) throws IOException {
ok(); // XXX
public void uidstore(OutputStream outputStream, String line) throws IOException {
ok(outputStream);
}
/**
@ -446,13 +438,13 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void append(String line) throws IOException {
public void append(InputStream inputStream, OutputStream outputStream, String line) throws IOException {
int left = line.lastIndexOf('{');
int right = line.indexOf('}', left);
int bytes = Integer.parseInt(line.substring(left + 1, right));
cont("waiting for message");
collectMessage(bytes);
ok(); // XXX
cont(outputStream, "waiting for message");
collectMessage(inputStream, outputStream, bytes);
ok(outputStream);
}
/**
@ -460,9 +452,9 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void id(String line) throws IOException {
untagged("ID NIL");
ok();
public void id(OutputStream outputStream, String line) throws IOException {
untagged(outputStream, "ID NIL");
ok(outputStream);
}
/**
@ -470,8 +462,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void enable(String line) throws IOException {
no("can't enable");
public void enable(OutputStream outputStream, String line) throws IOException {
no(outputStream, "can't enable");
}
/**
@ -479,8 +471,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void create(String line) throws IOException {
no("can't create");
public void create(OutputStream outputStream, String line) throws IOException {
no(outputStream, "can't create");
}
/**
@ -488,8 +480,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void delete(String line) throws IOException {
no("can't delete");
public void delete(OutputStream outputStream, String line) throws IOException {
no(outputStream, "can't delete");
}
/**
@ -497,8 +489,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void status(String line) throws IOException {
no("can't get status");
public void status(OutputStream outputStream, String line) throws IOException {
no(outputStream, "can't get status");
}
/**
@ -506,23 +498,23 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void namespace() throws IOException {
no("no namespaces");
public void namespace(OutputStream outputStream) throws IOException {
no(outputStream, "no namespaces");
}
/**
* Collect "bytes" worth of data for the message being appended.
*/
protected void collectMessage(int bytes) throws IOException {
readLiteral(bytes); // read the data and throw it away
super.readLine(); // data followed by a newline
protected void collectMessage(InputStream inputStream, OutputStream outputStream, int bytes) throws IOException {
readLiteral(inputStream, outputStream, bytes); // read the data and throw it away
super.readLine(inputStream); // data followed by a newline
}
/**
* Read a literal of "bytes" bytes and return it as a UTF-8 string.
*/
protected String readLiteral(int bytes) throws IOException {
println("+");
protected String readLiteral(InputStream inputStream, OutputStream outputStream, int bytes) throws IOException {
println(outputStream, "+");
byte[] data = new byte[bytes];
int len = data.length;
int off = 0;
@ -539,8 +531,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void close() throws IOException {
ok();
public void close(OutputStream outputStream) throws IOException {
ok(outputStream);
}
/**
@ -548,8 +540,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void noop() throws IOException {
ok();
public void noop(OutputStream outputStream) throws IOException {
ok(outputStream);
}
/**
@ -557,8 +549,8 @@ public class IMAPHandler extends ProtocolHandler {
*
* @throws IOException unable to read/write to socket
*/
public void logout() throws IOException {
ok();
public void logout(OutputStream outputStream) throws IOException {
ok(outputStream);
exit();
}

View file

@ -23,6 +23,7 @@ import org.xbib.net.mail.imap.IMAPStore;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
@ -79,13 +80,13 @@ public final class IMAPIDTest {
private static final class IMAPHandlerID extends IMAPHandler {
@Override
public void id(String line) throws IOException {
public void id(OutputStream outputStream, String line) throws IOException {
StringTokenizer st = new StringTokenizer(line);
String tag = st.nextToken();
String cmd = st.nextToken();
String arg = st.nextToken();
untagged("ID (\"test\" \"" + arg.equals("NIL") + "\")");
ok();
untagged(outputStream, "ID (\"test\" \"" + arg.equals("NIL") + "\")");
ok(outputStream);
}
}
}

View file

@ -26,6 +26,7 @@ import org.xbib.net.mail.imap.IMAPStore;
import org.xbib.net.mail.imap.IdleManager;
import org.xbib.net.mail.test.test.TestServer;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
@ -347,9 +348,9 @@ public final class IMAPIdleManagerTest {
*/
private static abstract class IMAPHandlerIdle extends IMAPHandler {
@Override
public void select(String line) throws IOException {
public void select(OutputStream outputStream, String line) throws IOException {
numberOfMessages = 1;
super.select(line);
super.select(outputStream, line);
}
public abstract void waitForIdle() throws InterruptedException;

View file

@ -57,11 +57,11 @@ public class IMAPSaslHandler extends IMAPHandler {
CallbackHandler cbh = new CallbackHandler() {
@Override
public void handle(Callback[] callbacks) {
if (LOGGER.isLoggable(Level.FINE))
LOGGER.fine("SASL callback length: " + callbacks.length);
if (logger.isLoggable(Level.FINE))
logger.fine("SASL callback length: " + callbacks.length);
for (int i = 0; i < callbacks.length; i++) {
if (LOGGER.isLoggable(Level.FINE))
LOGGER.fine("SASL callback " + i + ": " + callbacks[i]);
if (logger.isLoggable(Level.FINE))
logger.fine("SASL callback " + i + ": " + callbacks[i]);
if (callbacks[i] instanceof NameCallback) {
NameCallback ncb = (NameCallback) callbacks[i];
ncb.setName(u);
@ -70,8 +70,8 @@ public class IMAPSaslHandler extends IMAPHandler {
pcb.setPassword(p.toCharArray());
} else if (callbacks[i] instanceof AuthorizeCallback) {
AuthorizeCallback ac = (AuthorizeCallback) callbacks[i];
if (LOGGER.isLoggable(Level.FINE))
LOGGER.fine("SASL authorize: " +
if (logger.isLoggable(Level.FINE))
logger.fine("SASL authorize: " +
"authn: " + ac.getAuthenticationID() + ", " +
"authz: " + ac.getAuthorizationID() + ", " +
"authorized: " + ac.getAuthorizedID());
@ -104,17 +104,17 @@ public class IMAPSaslHandler extends IMAPHandler {
try {
ss = Sasl.createSaslServer(mech, "imap", "localhost", null, cbh);
} catch (SaslException sex) {
LOGGER.log(Level.FINE, "Failed to create SASL server", sex);
logger.log(Level.FINE, "Failed to create SASL server", sex);
no("Failed to create SASL server");
return;
}
if (ss == null) {
LOGGER.fine("No SASL support");
logger.fine("No SASL support");
no("No SASL support");
return;
}
if (LOGGER.isLoggable(Level.FINE))
LOGGER.fine("SASL server " + ss.getMechanismName());
if (logger.isLoggable(Level.FINE))
logger.fine("SASL server " + ss.getMechanismName());
byte[] response = new byte[0];
while (!ss.isComplete()) {
@ -124,8 +124,8 @@ public class IMAPSaslHandler extends IMAPHandler {
break;
} else {
// send challenge
if (LOGGER.isLoggable(Level.FINE))
LOGGER.fine("SASL challenge: " +
if (logger.isLoggable(Level.FINE))
logger.fine("SASL challenge: " +
ASCIIUtility.toString(chal, 0, chal.length));
byte[] ba = Base64.getEncoder().encode(chal);
if (ba.length > 0)
@ -148,7 +148,7 @@ public class IMAPSaslHandler extends IMAPHandler {
if (qop != null && (qop.equalsIgnoreCase("auth-int") ||
qop.equalsIgnoreCase("auth-conf"))) {
// XXX - NOT SUPPORTED!!!
LOGGER.fine(
logger.fine(
"SASL Mechanism requires integrity or confidentiality");
no("SASL Mechanism requires integrity or confidentiality");
return;

View file

@ -118,7 +118,7 @@ public class POP3Handler extends ProtocolHandler {
final String commandName = st.nextToken().toUpperCase();
final String arg = st.hasMoreTokens() ? st.nextToken() : null;
if (commandName == null) {
LOGGER.severe("Command name is empty!");
logger.severe("Command name is empty!");
this.exit();
return;
}
@ -150,7 +150,7 @@ public class POP3Handler extends ProtocolHandler {
} else if (commandName.equals("AUTH")) {
this.auth();
} else {
LOGGER.log(Level.SEVERE, "ERROR command unknown: {0}", commandName);
logger.log(Level.SEVERE, "ERROR command unknown: {0}", commandName);
this.println("-ERR unknown command");
}
}

View file

@ -94,7 +94,7 @@ public class SMTPHandler extends ProtocolHandler {
final StringTokenizer st = new StringTokenizer(currentLine, " ");
final String commandName = st.nextToken().toUpperCase();
if (commandName == null) {
LOGGER.severe("Command name is empty!");
logger.severe("Command name is empty!");
exit();
return;
}
@ -120,7 +120,7 @@ public class SMTPHandler extends ProtocolHandler {
} else if (commandName.equals("AUTH")) {
auth(currentLine);
} else {
LOGGER.log(Level.SEVERE, "ERROR command unknown: {0}", commandName);
logger.log(Level.SEVERE, "ERROR command unknown: {0}", commandName);
println("-ERR unknown command");
}
}

View file

@ -58,8 +58,8 @@ public class SMTPLoginHandler extends SMTPHandler {
if (ct.hasMoreTokens())
ir = ct.nextToken();
if (LOGGER.isLoggable(Level.FINE))
LOGGER.fine(line);
if (logger.isLoggable(Level.FINE))
logger.fine(line);
if (mech.equalsIgnoreCase("PLAIN"))
plain(ir);
else if (mech.equalsIgnoreCase("LOGIN"))
@ -82,8 +82,8 @@ public class SMTPLoginHandler extends SMTPHandler {
byte[] response = resp.getBytes(StandardCharsets.US_ASCII);
response = Base64.getDecoder().decode(response);
String u = new String(response, StandardCharsets.UTF_8);
if (LOGGER.isLoggable(Level.FINE))
LOGGER.fine("USER: " + u);
if (logger.isLoggable(Level.FINE))
logger.fine("USER: " + u);
println("334");
// read password
@ -95,8 +95,8 @@ public class SMTPLoginHandler extends SMTPHandler {
response = resp.getBytes(StandardCharsets.US_ASCII);
response = Base64.getDecoder().decode(response);
String p = new String(response, StandardCharsets.UTF_8);
if (LOGGER.isLoggable(Level.FINE))
LOGGER.fine("PASSWORD: " + p);
if (logger.isLoggable(Level.FINE))
logger.fine("PASSWORD: " + p);
//System.out.printf("USER: %s, PASSWORD: %s%n", u, p);
if (!u.equals(username) || !p.equals(password)) {

View file

@ -72,11 +72,11 @@ public class SMTPSaslHandler extends SMTPHandler {
CallbackHandler cbh = new CallbackHandler() {
@Override
public void handle(Callback[] callbacks) {
if (LOGGER.isLoggable(Level.FINE))
LOGGER.fine("SASL callback length: " + callbacks.length);
if (logger.isLoggable(Level.FINE))
logger.fine("SASL callback length: " + callbacks.length);
for (int i = 0; i < callbacks.length; i++) {
if (LOGGER.isLoggable(Level.FINE))
LOGGER.fine("SASL callback " + i + ": " + callbacks[i]);
if (logger.isLoggable(Level.FINE))
logger.fine("SASL callback " + i + ": " + callbacks[i]);
if (callbacks[i] instanceof NameCallback) {
NameCallback ncb = (NameCallback) callbacks[i];
ncb.setName(u);
@ -85,8 +85,8 @@ public class SMTPSaslHandler extends SMTPHandler {
pcb.setPassword(p.toCharArray());
} else if (callbacks[i] instanceof AuthorizeCallback) {
AuthorizeCallback ac = (AuthorizeCallback) callbacks[i];
if (LOGGER.isLoggable(Level.FINE))
LOGGER.fine("SASL authorize: " +
if (logger.isLoggable(Level.FINE))
logger.fine("SASL authorize: " +
"authn: " + ac.getAuthenticationID() + ", " +
"authz: " + ac.getAuthorizationID() + ", " +
"authorized: " + ac.getAuthorizedID());
@ -119,25 +119,25 @@ public class SMTPSaslHandler extends SMTPHandler {
try {
ss = Sasl.createSaslServer(mech, "smtp", "localhost", null, cbh);
} catch (SaslException sex) {
LOGGER.log(Level.FINE, "Failed to create SASL server", sex);
logger.log(Level.FINE, "Failed to create SASL server", sex);
println("501 Failed to create SASL server");
return;
}
if (ss == null) {
LOGGER.fine("No SASL support");
logger.fine("No SASL support");
println("501 No SASL support");
return;
}
if (LOGGER.isLoggable(Level.FINE))
LOGGER.fine("SASL server " + ss.getMechanismName());
if (logger.isLoggable(Level.FINE))
logger.fine("SASL server " + ss.getMechanismName());
byte[] response = ir.getBytes();
while (!ss.isComplete()) {
try {
byte[] chal = ss.evaluateResponse(response);
// send challenge
if (LOGGER.isLoggable(Level.FINE))
LOGGER.fine("SASL challenge: " +
if (logger.isLoggable(Level.FINE))
logger.fine("SASL challenge: " +
ASCIIUtility.toString(chal, 0, chal.length));
byte[] ba = Base64.getEncoder().encode(chal);
if (ba.length > 0)
@ -164,7 +164,7 @@ public class SMTPSaslHandler extends SMTPHandler {
if (qop != null && (qop.equalsIgnoreCase("auth-int") ||
qop.equalsIgnoreCase("auth-conf"))) {
// XXX - NOT SUPPORTED!!!
LOGGER.fine(
logger.fine(
"SASL Mechanism requires integrity or confidentiality");
println("501 " +
"SASL Mechanism requires integrity or confidentiality");

View file

@ -16,12 +16,9 @@
package org.xbib.net.mail.test.test;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.PushbackInputStream;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
@ -35,64 +32,82 @@ import java.util.logging.Logger;
* @author sbo
* @author Bill Shannon
*/
public abstract class ProtocolHandler implements Runnable {
public abstract class ProtocolHandler {
/**
* Logger for this class.
*/
protected final Logger LOGGER = Logger.getLogger(this.getClass().getName());
private static final Logger logger = Logger.getLogger(ProtocolHandler.class.getName());
/**
* Quit?
*/
protected boolean quit;
/**
* Writer to socket.
*/
protected PrintWriter writer;
/**
* Input from socket.
*/
protected InputStream inputStream;
public ProtocolHandler(InputStream inputStream, OutputStream outputStream) {
this.inputStream = new BufferedInputStream(inputStream);
this.writer = new PrintWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
public void handle(InputStream inputStream, OutputStream outputStream) {
try {
sendGreetings(outputStream);
while (!quit) {
handleCommand(inputStream, outputStream);
}
if (quit) {
try {
if (inputStream != null)
inputStream.close();
if (outputStream != null) {
outputStream.close();
}
} catch (final IOException e) {
logger.log(Level.SEVERE, "Error", e);
}
}
} catch (IOException sex) {
// ignore it, often get "connection reset" when client closes
} catch (Exception e) {
logger.log(Level.SEVERE, "Error", e);
} finally {
try {
if (inputStream != null)
inputStream.close();
if (outputStream != null) {
outputStream.close();
}
} catch (final IOException ioe) {
logger.log(Level.SEVERE, "Error", ioe);
}
}
}
/**
* Optionally send a greeting when first connected.
*/
public void sendGreetings() throws IOException {
public void sendGreetings(OutputStream outputStream) throws IOException {
}
/**
* Read and process a single command.
*/
public abstract void handleCommand() throws IOException;
public abstract void handleCommand(InputStream inputStream, OutputStream outputStream) throws IOException;
/**
* Read a single line terminated by newline or CRLF.
* Convert the UTF-8 bytes in the line (minus the line terminator)
* to a String.
*/
protected String readLine() throws IOException {
protected String readLine(InputStream inputStream) throws IOException {
byte[] buf = new byte[128];
int room = buf.length;
int offset = 0;
int c;
while ((c = inputStream.read()) != -1) {
if (c == '\n') {
break;
} else if (c == '\r') {
int c2 = inputStream.read();
if ((c2 != '\n') && (c2 != -1)) {
if (!(inputStream instanceof PushbackInputStream))
this.inputStream = new PushbackInputStream(inputStream);
if (!(inputStream instanceof PushbackInputStream)) {
inputStream = new PushbackInputStream(inputStream);
}
((PushbackInputStream) inputStream).unread(c2);
}
break;
@ -106,51 +121,13 @@ public abstract class ProtocolHandler implements Runnable {
buf[offset++] = (byte) c;
}
}
if ((c == -1) && (offset == 0))
if ((c == -1) && (offset == 0)) {
return null;
}
return new String(buf, 0, offset, StandardCharsets.UTF_8);
}
/**
* {@inheritDoc}
*/
@Override
public final void run() {
try {
sendGreetings();
while (!quit) {
handleCommand();
}
} catch (IOException sex) {
// ignore it, often get "connection reset" when client closes
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Error", e);
} finally {
try {
if (inputStream != null)
inputStream.close();
if (writer != null) {
writer.close();
}
} catch (final IOException ioe) {
LOGGER.log(Level.SEVERE, "Error", ioe);
}
}
}
/**
* Quit.
*/
public void exit() {
quit = true;
try {
if (inputStream != null)
inputStream.close();
if (writer != null) {
writer.close();
}
} catch (final IOException e) {
LOGGER.log(Level.SEVERE, "Error", e);
}
}
}

View file

@ -16,6 +16,9 @@
package org.xbib.net.mail.test.test;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
@ -32,8 +35,11 @@ import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A simple server for testing.
@ -46,13 +52,17 @@ import java.util.List;
* @author sbo
* @author Bill Shannon
*/
public final class TestServer extends Thread {
public final class TestServer {
private static final Logger logger = Logger.getLogger(TestServer.class.getName());
/**
* Server socket.
*/
private ServerSocket serverSocket;
private final ExecutorService executorService = Executors.newCachedThreadPool();
/**
* Keep on?
*/
@ -63,7 +73,6 @@ public final class TestServer extends Thread {
*/
private final ProtocolHandler handler;
private List<Thread> clients = new ArrayList<Thread>();
/**
* Test server.
@ -83,7 +92,6 @@ public final class TestServer extends Thread {
public TestServer(final ProtocolHandler handler, final boolean isSSL)
throws IOException {
this.handler = handler;
/*
* Allowing the JDK to pick a port number sometimes results in it
* picking a number that's already in use by another process, but
@ -96,10 +104,6 @@ public final class TestServer extends Thread {
* already in use.
*/
for (int port = 49152; port < 50000 /*65535*/; port++) {
/*
if (isListening(port))
continue;
*/
try {
serverSocket = createServerSocket(port, isSSL);
return;
@ -170,12 +174,7 @@ public final class TestServer extends Thread {
}
}
/**
* {@inheritDoc}
*/
@Override
public void start() {
super.start();
// don't return until server is really listening
// XXX - this might not be necessary
for (int tries = 0; tries < 10; tries++) {
@ -193,25 +192,23 @@ public final class TestServer extends Thread {
/**
* {@inheritDoc}
*/
@Override
public void run() {
try {
keepOn = true;
while (keepOn) {
try {
final Socket clientSocket = serverSocket.accept();
final ProtocolHandler pHandler = handler;
pHandler.setClientSocket(clientSocket);
Thread t = new Thread(pHandler);
synchronized (clients) {
clients.add(t);
}
t.start();
} catch (final IOException e) {
//e.printStackTrace();
} catch (NullPointerException nex) {
// serverSocket can be set to null before we could check
executorService.submit(new Callable<Object>() {
final InputStream inputStream = new BufferedInputStream(clientSocket.getInputStream());
final OutputStream outputStream = clientSocket.getOutputStream();
@Override
public Object call() {
handler.handle(inputStream, outputStream);
return null;
}
});
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
}
} finally {
@ -219,20 +216,14 @@ public final class TestServer extends Thread {
}
}
/**
* Return number of clients ever created.
*/
public int clientCount() {
/*public int clientCount() {
synchronized (clients) {
// isListening creates a client that we don't count
return clients.size() - 1;
}
}
}*/
/**
* Wait for at least n clients to terminate.
*/
public void waitForClients(int n) {
/*public void waitForClients(int n) {
if (n > clientCount())
throw new RuntimeException("not that many clients");
for (; ; ) {
@ -250,7 +241,7 @@ public final class TestServer extends Thread {
} catch (InterruptedException ex) {
}
}
}
}*/
private boolean isListening(int port) {
try {
@ -265,10 +256,4 @@ public final class TestServer extends Thread {
return false;
}
class WrappedProtocolHandler {
Socket clientSocket;
ProtocolHandler handler;
}
}