Server instance moved to FControl,

HomeUI buttons get enabled/disabled to indicate server status
Server - clientstates form a chain of responsibility for packets processing
packets for autorization (no checks performed, used to get player's name)
This commit is contained in:
Maxmtg
2013-04-14 10:51:04 +00:00
parent 7f50bb3515
commit 3eed2f993b
25 changed files with 359 additions and 107 deletions

11
.gitattributes vendored
View File

@@ -14292,19 +14292,24 @@ src/main/java/forge/net/NetServer.java -text
src/main/java/forge/net/client/INetClient.java -text src/main/java/forge/net/client/INetClient.java -text
src/main/java/forge/net/client/NetClient.java -text src/main/java/forge/net/client/NetClient.java -text
src/main/java/forge/net/client/package-info.java -text src/main/java/forge/net/client/package-info.java -text
src/main/java/forge/net/client/state/ClientState.java -text src/main/java/forge/net/client/state/ConnectedClientState.java -text
src/main/java/forge/net/client/state/ClientStateUnauthorized.java -text
src/main/java/forge/net/client/state/IClientState.java -text src/main/java/forge/net/client/state/IClientState.java -text
src/main/java/forge/net/client/state/InLobbyClientState.java -text
src/main/java/forge/net/client/state/UnauthorizedClientState.java -text
src/main/java/forge/net/client/state/package-info.java -text src/main/java/forge/net/client/state/package-info.java -text
src/main/java/forge/net/package-info.java -text src/main/java/forge/net/package-info.java -text
src/main/java/forge/net/protocol/incoming/AuthorizePacket.java -text
src/main/java/forge/net/protocol/incoming/ChatPacket.java -text src/main/java/forge/net/protocol/incoming/ChatPacket.java -text
src/main/java/forge/net/protocol/incoming/EchoPacket.java -text src/main/java/forge/net/protocol/incoming/EchoPacket.java -text
src/main/java/forge/net/protocol/incoming/IncorrectPacket.java -text
src/main/java/forge/net/protocol/incoming/Packet.java -text src/main/java/forge/net/protocol/incoming/Packet.java -text
src/main/java/forge/net/protocol/incoming/PacketOpcode.java -text src/main/java/forge/net/protocol/incoming/PacketOpcode.java -text
src/main/java/forge/net/protocol/incoming/UnknownPacket.java -text src/main/java/forge/net/protocol/incoming/UnknownPacket.java -text
src/main/java/forge/net/protocol/incoming/package-info.java -text src/main/java/forge/net/protocol/incoming/package-info.java -text
src/main/java/forge/net/protocol/outcoming/AuthorizationSuccessfulMessage.java -text
src/main/java/forge/net/protocol/outcoming/EchoMessage.java -text src/main/java/forge/net/protocol/outcoming/EchoMessage.java -text
src/main/java/forge/net/protocol/outcoming/Message.java -text src/main/java/forge/net/protocol/outcoming/IMessage.java -text
src/main/java/forge/net/protocol/outcoming/IncorrectPacketMessage.java -text
src/main/java/forge/net/protocol/outcoming/UnknownPacketMessage.java -text src/main/java/forge/net/protocol/outcoming/UnknownPacketMessage.java -text
src/main/java/forge/net/protocol/package-info.java -text src/main/java/forge/net/protocol/package-info.java -text
src/main/java/forge/package-info.java svneol=native#text/plain src/main/java/forge/package-info.java svneol=native#text/plain

View File

@@ -4,31 +4,30 @@ if (!window.WebSocket)
var server = new CWebSocket(); var server = new CWebSocket();
var listener = { var listener = {
onOpen : function() { onOpen : function() {
server.send('websockets are open for communications!'); $('#input').slideDown();
$('#input').fadeIn();
}, },
onMessage : function(m) { onMessage : function(m) {
if (m.data) { if (m.data) {
$('#messages').append(makeLi("incoming", m.data)); addLi("incoming", m.data);
var messageBox = $('#messages')[0];
messageBox.scrollTop = messageBox.scrollHeight - messageBox.clientHeight;
} }
}, },
onClose : function(m) { onClose : function(m) {
$('#messages').append(makeLi("error", "Connection was closed (" + m.code + "): " + m.reason)); addLi("error", "Connection was closed (" + m.code + "): " + m.reason);
onDisconnectClicked(); onDisconnectClicked();
$('#input').fadeOut(); $('#input').fadeOut();
} }
}; };
server.addListener(listener); server.addListener(listener);
function makeLi(className, text) { function addLi(className, text) {
var spanText = document.createElement('li'); var spanText = document.createElement('li');
spanText.className = className; spanText.className = className;
spanText.innerHTML = text; spanText.innerHTML = text;
return spanText; var messageBox = $('#messages')[0];
messageBox.appendChild(spanText);
messageBox.scrollTop = messageBox.scrollHeight - messageBox.clientHeight;
} }
function onConnectClicked() { function onConnectClicked() {
@@ -48,7 +47,7 @@ function onDisconnectClicked() {
function onSendClicked() { function onSendClicked() {
var toSend = $("#input input").val(); var toSend = $("#input input").val();
$("#input input").val(""); $("#input input").val("");
$('#messages').append(makeLi("outcoming", toSend)); addLi("outcoming", toSend);
server.send(toSend) server.send(toSend)
} }

View File

@@ -46,6 +46,7 @@ import forge.gui.match.VMatchUI;
import forge.gui.match.controllers.CDock; import forge.gui.match.controllers.CDock;
import forge.gui.toolbox.CardFaceSymbols; import forge.gui.toolbox.CardFaceSymbols;
import forge.gui.toolbox.FSkin; import forge.gui.toolbox.FSkin;
import forge.net.NetServer;
import forge.properties.NewConstants; import forge.properties.NewConstants;
import forge.quest.data.QuestPreferences.QPref; import forge.quest.data.QuestPreferences.QPref;
import forge.quest.io.QuestDataIO; import forge.quest.io.QuestDataIO;
@@ -316,4 +317,14 @@ public enum FControl {
public SoundSystem getSoundSystem() { public SoundSystem getSoundSystem() {
return soundSystem; return soundSystem;
} }
/**
* TODO: Write javadoc for this method.
* @return
*/
private final NetServer server = new NetServer();
public NetServer getServer() {
// TODO Auto-generated method stub
return server;
}
} }

View File

@@ -8,7 +8,6 @@ import forge.gui.deckeditor.controllers.CEditorConstructed;
import forge.gui.framework.EDocID; import forge.gui.framework.EDocID;
import forge.gui.framework.ICDoc; import forge.gui.framework.ICDoc;
import forge.gui.home.sanctioned.VSubmenuConstructed; import forge.gui.home.sanctioned.VSubmenuConstructed;
import forge.net.NetServer;
import forge.properties.ForgePreferences; import forge.properties.ForgePreferences;
import forge.properties.ForgePreferences.FPref; import forge.properties.ForgePreferences.FPref;
@@ -56,7 +55,6 @@ public enum CHomeUI implements ICDoc {
/* (non-Javadoc) /* (non-Javadoc)
* @see forge.view.home.ICDoc#intialize() * @see forge.view.home.ICDoc#intialize()
*/ */
private final NetServer server = new NetServer();
@SuppressWarnings("serial") @SuppressWarnings("serial")
@Override @Override
@@ -80,14 +78,18 @@ public enum CHomeUI implements ICDoc {
VHomeUI.SINGLETON_INSTANCE.getLblStartServer().setCommand(new Command() { VHomeUI.SINGLETON_INSTANCE.getLblStartServer().setCommand(new Command() {
@Override @Override
public void execute() { public void execute() {
server.listen(); FControl.SINGLETON_INSTANCE.getServer().listen();
VHomeUI.SINGLETON_INSTANCE.getLblStopServer().setEnabled(true);
VHomeUI.SINGLETON_INSTANCE.getLblStartServer().setEnabled(false);
} }
}); });
VHomeUI.SINGLETON_INSTANCE.getLblStopServer().setCommand(new Command() { VHomeUI.SINGLETON_INSTANCE.getLblStopServer().setCommand(new Command() {
@Override @Override
public void execute() { public void execute() {
server.stop(); FControl.SINGLETON_INSTANCE.getServer().stop();
VHomeUI.SINGLETON_INSTANCE.getLblStopServer().setEnabled(false);
VHomeUI.SINGLETON_INSTANCE.getLblStartServer().setEnabled(true);
} }
}); });
} }

View File

@@ -59,7 +59,6 @@ import forge.gui.home.variant.VSubmenuPlanechase;
import forge.gui.home.variant.VSubmenuVanguard; import forge.gui.home.variant.VSubmenuVanguard;
import forge.gui.toolbox.FLabel; import forge.gui.toolbox.FLabel;
import forge.gui.toolbox.FSkin; import forge.gui.toolbox.FSkin;
import forge.properties.ForgePreferences;
import forge.properties.ForgePreferences.FPref; import forge.properties.ForgePreferences.FPref;
import forge.view.FView; import forge.view.FView;
@@ -162,6 +161,7 @@ public enum VHomeUI implements IVTopLevelUI {
if ( Singletons.getModel().getPreferences().getPrefBoolean(FPref.DEV_MODE_ENABLED) ) { if ( Singletons.getModel().getPreferences().getPrefBoolean(FPref.DEV_MODE_ENABLED) ) {
pnlButtons.add(lblStartServer, "w 170px!, h 25px!, gap 0 10px 10px 0, sx 2 "); pnlButtons.add(lblStartServer, "w 170px!, h 25px!, gap 0 10px 10px 0, sx 2 ");
pnlButtons.add(lblStopServer, "w 50px!, h 25px!, gap 0 0 10px 0"); pnlButtons.add(lblStopServer, "w 50px!, h 25px!, gap 0 0 10px 0");
lblStopServer.setEnabled(false);
} }
pnlMenu.add(pnlButtons, "w 230px!, gap 10px 0 10px 10px"); pnlMenu.add(pnlButtons, "w 230px!, gap 10px 0 10px 10px");

View File

@@ -7,6 +7,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
@@ -27,6 +28,18 @@ public class NetServer {
private final Server srv = new Server(); private final Server srv = new Server();
private final Set<ClientSocket> _openSockets = new CopyOnWriteArraySet<ClientSocket>(); private final Set<ClientSocket> _openSockets = new CopyOnWriteArraySet<ClientSocket>();
public NetServer() {
SelectChannelConnector connector= new SelectChannelConnector();
connector.setPort(81);
srv.addConnector(connector);
ServletContextHandler context = new ServletContextHandler();
ServletHolder sh = new ServletHolder(new GameServlet());
context.addServlet(sh, "/*");
//context.setContextPath("/");
srv.setHandler(context);
}
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class GameServlet extends WebSocketServlet public class GameServlet extends WebSocketServlet
{ {
@@ -86,19 +99,10 @@ public class NetServer {
public void listen() { public void listen() {
if (!srv.isStarted()) if (!srv.isStarted())
{ {
SelectChannelConnector connector= new SelectChannelConnector();
connector.setPort(81);
srv.addConnector(connector);
ServletContextHandler context = new ServletContextHandler();
ServletHolder sh = new ServletHolder(new GameServlet());
context.addServlet(sh, "/*");
//context.setContextPath("/");
srv.setHandler(context);
URI serverUri = null; URI serverUri = null;
try { try {
srv.start(); srv.start();
Connector connector = srv.getConnectors()[0];
int port = connector.getLocalPort(); int port = connector.getLocalPort();
String host = connector.getHost(); String host = connector.getHost();
serverUri = new URI(String.format("ws://%s:%d/", host == null ? "localhost" : host ,port)); serverUri = new URI(String.format("ws://%s:%d/", host == null ? "localhost" : host ,port));

View File

@@ -1,6 +1,8 @@
package forge.net.client; package forge.net.client;
import forge.net.protocol.outcoming.Message; import forge.game.player.LobbyPlayer;
import forge.net.client.state.IClientState;
import forge.net.protocol.outcoming.IMessage;
/** /**
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
@@ -12,6 +14,12 @@ public interface INetClient {
* TODO: Write javadoc for this method. * TODO: Write javadoc for this method.
* @param echoMessage * @param echoMessage
*/ */
void send(Message echoMessage); void send(IMessage message);
void setPlayer(LobbyPlayer lobbyPlayer);
LobbyPlayer getPlayer();
void replaceState(IClientState old, IClientState newState);
} }

View File

@@ -1,27 +1,32 @@
package forge.net.client; package forge.net.client;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import forge.game.player.LobbyPlayer; import forge.game.player.LobbyPlayer;
import forge.game.player.PlayerType;
import forge.net.IClientSocket; import forge.net.IClientSocket;
import forge.net.IConnectionObserver; import forge.net.IConnectionObserver;
import forge.net.client.state.ClientStateUnauthorized; import forge.net.client.state.ConnectedClientState;
import forge.net.client.state.UnauthorizedClientState;
import forge.net.client.state.IClientState; import forge.net.client.state.IClientState;
import forge.net.protocol.incoming.Packet; import forge.net.protocol.incoming.Packet;
import forge.net.protocol.incoming.PacketOpcode; import forge.net.protocol.incoming.PacketOpcode;
import forge.net.protocol.outcoming.Message; import forge.net.protocol.outcoming.IMessage;
public class NetClient implements IConnectionObserver, INetClient{ public class NetClient implements IConnectionObserver, INetClient{
private final IClientSocket socket; private final IClientSocket socket;
private IClientState state = new ClientStateUnauthorized(this); private BlockingDeque<IClientState> state = new LinkedBlockingDeque<IClientState>();
private LobbyPlayer player = null; private LobbyPlayer player = null;
public NetClient(IClientSocket clientSocket) { public NetClient(IClientSocket clientSocket) {
socket = clientSocket; socket = clientSocket;
state.push(new ConnectedClientState(this));
state.push(new UnauthorizedClientState(this));
} }
public void autorized() { public void autorized() {
player = new LobbyPlayer(PlayerType.REMOTE, "Guest");
} }
/* (non-Javadoc) /* (non-Javadoc)
@@ -33,16 +38,42 @@ public class NetClient implements IConnectionObserver, INetClient{
} }
@Override
public final LobbyPlayer getPlayer() {
return player;
}
/** Receives input from network client */
@Override @Override
public void onMessage(String data) { public void onMessage(String data) {
Packet p = PacketOpcode.decode(data); Packet p = PacketOpcode.decode(data);
state.onPacket(p); for(IClientState s : state) {
if ( s.processPacket(p) )
break;
}
} }
@Override @Override
public void send(Message message) { public void send(IMessage message) {
socket.send(message.toNetString()); socket.send(message.toNetString());
} }
/* (non-Javadoc)
* @see forge.net.client.INetClient#setPlayer(forge.game.player.LobbyPlayer)
*/
@Override
public final void setPlayer(LobbyPlayer lobbyPlayer) {
player = lobbyPlayer;
}
/* (non-Javadoc)
* @see forge.net.client.INetClient#replaceState(forge.net.client.state.IClientState, forge.net.client.state.IClientState)
*/
@Override
public synchronized void replaceState(IClientState old, IClientState newState) {
state.removeFirstOccurrence(old);
state.push(newState);
}
} }

View File

@@ -1,37 +0,0 @@
package forge.net.client.state;
import forge.net.client.INetClient;
import forge.net.protocol.incoming.EchoPacket;
import forge.net.protocol.incoming.Packet;
import forge.net.protocol.outcoming.EchoMessage;
import forge.net.protocol.outcoming.UnknownPacketMessage;
/**
* TODO: Write javadoc for this type.
*
*/
public abstract class ClientState implements IClientState {
private final INetClient client;
protected ClientState(INetClient client)
{
this.client = client;
}
@Override
public void onPacket(Packet packet ) {
switch( packet.getOpCode() ) {
case Echo:
EchoPacket p = (EchoPacket)packet;
client.send(new EchoMessage(p.getMessage()));
break;
default:
client.send(new UnknownPacketMessage());
break;
}
}
}

View File

@@ -1,19 +0,0 @@
package forge.net.client.state;
import forge.net.client.INetClient;
/**
* TODO: Write javadoc for this type.
*
*/
public class ClientStateUnauthorized extends ClientState implements IClientState {
/**
* TODO: Write javadoc for Constructor.
* @param client
*/
public ClientStateUnauthorized(INetClient client) {
super(client);
}
}

View File

@@ -0,0 +1,40 @@
package forge.net.client.state;
import forge.net.client.INetClient;
import forge.net.protocol.incoming.EchoPacket;
import forge.net.protocol.incoming.IncorrectPacket;
import forge.net.protocol.incoming.Packet;
import forge.net.protocol.outcoming.EchoMessage;
import forge.net.protocol.outcoming.IncorrectPacketMessage;
import forge.net.protocol.outcoming.UnknownPacketMessage;
public class ConnectedClientState implements IClientState {
private final INetClient client;
public ConnectedClientState(INetClient client) {
this.client = client;
}
@Override
public boolean processPacket(Packet packet ) {
switch( packet.getOpCode() ) {
case Echo:
EchoPacket pe = (EchoPacket)packet;
client.send(new EchoMessage(pe.getMessage()));
return true;
case Incorrect:
IncorrectPacket pi = (IncorrectPacket)packet;
client.send(new IncorrectPacketMessage(pi));
return true;
default:
client.send(new UnknownPacketMessage());
return true;
}
}
}

View File

@@ -7,5 +7,5 @@ import forge.net.protocol.incoming.Packet;
* *
*/ */
public interface IClientState { public interface IClientState {
void onPacket(Packet data); boolean processPacket(Packet data);
} }

View File

@@ -0,0 +1,21 @@
package forge.net.client.state;
import forge.net.client.INetClient;
import forge.net.protocol.incoming.Packet;
/**
* TODO: Write javadoc for this type.
*
*/
public class InLobbyClientState implements IClientState {
private final INetClient client;
protected InLobbyClientState(INetClient client) {
this.client = client;
}
@Override
public boolean processPacket(Packet data) {
return false;
}
}

View File

@@ -0,0 +1,44 @@
package forge.net.client.state;
import forge.game.player.LobbyPlayer;
import forge.game.player.PlayerType;
import forge.net.client.INetClient;
import forge.net.protocol.incoming.AuthorizePacket;
import forge.net.protocol.incoming.Packet;
import forge.net.protocol.incoming.PacketOpcode;
import forge.net.protocol.outcoming.AuthorizationSuccessfulMessage;
/**
* TODO: Write javadoc for this type.
*
*/
public class UnauthorizedClientState implements IClientState {
/**
* TODO: Write javadoc for Constructor.
* @param client
*/
private final INetClient client;
public UnauthorizedClientState(INetClient client) {
this.client = client;
}
@Override
public boolean processPacket(Packet packet) {
if( packet.getOpCode() == PacketOpcode.Authorize ) {
AuthorizePacket p = (AuthorizePacket)packet;
if( true ) { // check credentials here!
client.send(new AuthorizationSuccessfulMessage(p.getUsername()));
client.setPlayer(new LobbyPlayer(PlayerType.REMOTE, p.getUsername()));
client.replaceState(this, new InLobbyClientState(client));
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,46 @@
package forge.net.protocol.incoming;
import org.apache.commons.lang3.StringUtils;
import forge.util.TextUtil;
/**
* TODO: Write javadoc for this type.
*
*/
public class AuthorizePacket extends Packet {
private final String username;
private final String password;
private AuthorizePacket(String name, String pass) {
super(PacketOpcode.Authorize);
username = name;
password = pass;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public static Packet parse(String data) {
String[] parts = TextUtil.splitWithParenthesis(data, ' ', '\"', '\"');
if(parts.length == 1 || parts.length == 2) {
if(!StringUtils.isAlphanumericSpace(parts[0]))
return new IncorrectPacket(PacketOpcode.Authorize, 0, parts[0]);
if( parts.length == 1)
return new AuthorizePacket(parts[0], null);
if(!StringUtils.isAsciiPrintable(parts[1]))
return new IncorrectPacket(PacketOpcode.Authorize, 1, parts[1]);
else
return new AuthorizePacket(parts[0], parts[1]);
}
return UnknownPacket.parse(data);
}
}

View File

@@ -8,10 +8,15 @@ package forge.net.protocol.incoming;
public class EchoPacket extends Packet { public class EchoPacket extends Packet {
private final String message; private final String message;
public EchoPacket(String data) { private EchoPacket(String data) {
super(PacketOpcode.Echo); super(PacketOpcode.Echo);
message = data; message = data;
} }
public static EchoPacket parse(String data) {
return new EchoPacket(data);
}
public String getMessage() { public String getMessage() {
return message; return message;
} }

View File

@@ -0,0 +1,32 @@
package forge.net.protocol.incoming;
/**
* TODO: Write javadoc for this type.
*
*/
public class IncorrectPacket extends Packet {
private final PacketOpcode intendedCode;
private final int index;
private final String sParam;
public IncorrectPacket(PacketOpcode code, int iParameter, String value) {
super(PacketOpcode.Incorrect);
intendedCode = code;
index = iParameter;
sParam = value;
}
public String getString() {
return sParam;
}
public int getIndex() {
return index;
}
public PacketOpcode getIntendedCode() {
return intendedCode;
}
}

View File

@@ -8,7 +8,10 @@ package forge.net.protocol.incoming;
public enum PacketOpcode { public enum PacketOpcode {
Echo("/echo"), Echo("/echo"),
Chat("/s"), Chat("/s"),
Unknown(""); Authorize("/auth"),
Incorrect(null),
Unknown(null);
@@ -18,6 +21,10 @@ public enum PacketOpcode {
opcode = code; opcode = code;
} }
public final String getOpcode() {
return opcode;
}
/** /**
* TODO: Write javadoc for this method. * TODO: Write javadoc for this method.
* @param data * @param data
@@ -25,11 +32,11 @@ public enum PacketOpcode {
*/ */
public static Packet decode(String data) { public static Packet decode(String data) {
for(PacketOpcode s : PacketOpcode.values()) { for(PacketOpcode s : PacketOpcode.values()) {
if ( data.startsWith(s.opcode) ) if ( s.opcode != null && data.startsWith(s.opcode) )
return decodePacket(s, data.substring(s.opcode.length()).trim()); return decodePacket(s, data.substring(s.opcode.length()).trim());
} }
if( data.startsWith("/") ) if( data.startsWith("/") )
return new UnknownPacket(data.substring(1)); return UnknownPacket.parse(data.substring(1));
else else
return new ChatPacket(data); return new ChatPacket(data);
} }
@@ -38,9 +45,11 @@ public enum PacketOpcode {
private static Packet decodePacket(PacketOpcode code, String data) { private static Packet decodePacket(PacketOpcode code, String data) {
switch(code) { switch(code) {
case Echo: case Echo:
return new EchoPacket(data); return EchoPacket.parse(data);
case Authorize:
return AuthorizePacket.parse(data);
default: default:
return new UnknownPacket(data); return UnknownPacket.parse(data);
} }
} }
} }

View File

@@ -8,12 +8,20 @@ package forge.net.protocol.incoming;
public class UnknownPacket extends Packet { public class UnknownPacket extends Packet {
private final String message; private final String message;
public UnknownPacket(String data) { private UnknownPacket(String data) {
super(PacketOpcode.Unknown); super(PacketOpcode.Unknown);
message = data; message = data;
} }
public String getMessage() { public String getMessage() {
return message; return message;
} }
/**
* TODO: Write javadoc for this method.
* @param substring
* @return
*/
public static Packet parse(String substring) {
return new UnknownPacket(substring);
}
} }

View File

@@ -0,0 +1,21 @@
package forge.net.protocol.outcoming;
/**
* TODO: Write javadoc for this type.
*
*/
public class AuthorizationSuccessfulMessage implements IMessage {
private final String username;
public AuthorizationSuccessfulMessage(String user) {
username = user;
}
@Override
public String toNetString() {
// TODO Auto-generated method stub
return "Authorization Successful. Welcome, " + username;
}
}

View File

@@ -4,7 +4,7 @@ package forge.net.protocol.outcoming;
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
* *
*/ */
public class EchoMessage extends Message { public class EchoMessage implements IMessage {
private final String message; private final String message;

View File

@@ -4,6 +4,6 @@ package forge.net.protocol.outcoming;
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
* *
*/ */
public abstract class Message { public interface IMessage {
public abstract String toNetString(); public String toNetString();
} }

View File

@@ -0,0 +1,18 @@
package forge.net.protocol.outcoming;
import forge.net.protocol.incoming.IncorrectPacket;
public class IncorrectPacketMessage implements IMessage {
IncorrectPacket badPacket;
public IncorrectPacketMessage(IncorrectPacket packet) {
badPacket = packet;
}
@Override
public String toNetString() {
return String.format("Wrong syntax for %s command: parameter #%d is %s", badPacket.getIntendedCode().getOpcode(), 1+badPacket.getIndex(), badPacket.getString());
}
}

View File

@@ -4,7 +4,7 @@ package forge.net.protocol.outcoming;
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
* *
*/ */
public class UnknownPacketMessage extends Message { public class UnknownPacketMessage implements IMessage {
/* (non-Javadoc) /* (non-Javadoc)
* @see forge.net.protocol.outcoming.Message#toNetString() * @see forge.net.protocol.outcoming.Message#toNetString()

View File

@@ -7,6 +7,7 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
/** /**
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
@@ -58,14 +59,16 @@ public class TextUtil {
*/ */
public static String[] splitWithParenthesis(CharSequence input, char delimiter, int maxEntries, char openPar, char closePar, boolean skipEmpty) { public static String[] splitWithParenthesis(CharSequence input, char delimiter, int maxEntries, char openPar, char closePar, boolean skipEmpty) {
List<String> result = new ArrayList<String>(); List<String> result = new ArrayList<String>();
// Assume that when equal non-zero parenthesis are passed, they need to be discarded
boolean trimParenthesis = openPar == closePar && openPar > 0;
int nPar = 0; int nPar = 0;
int len = input.length(); int len = input.length();
int start = 0; int start = 0;
int idx = 1; int idx = 1;
for (int iC = 0; iC < len; iC++ ) { for (int iC = 0; iC < len; iC++ ) {
char c = input.charAt(iC); char c = input.charAt(iC);
if( openPar > 0 && c == openPar ) nPar++; if( closePar > 0 && c == closePar && nPar > 0 ) { nPar--; }
if( closePar > 0 && c == closePar ) { nPar = nPar > 0 ? nPar - 1 : 0; } else if( openPar > 0 && c == openPar ) nPar++;
if( c == delimiter && nPar == 0 && idx < maxEntries) { if( c == delimiter && nPar == 0 && idx < maxEntries) {
if( iC > start || !skipEmpty ) { if( iC > start || !skipEmpty ) {
@@ -79,7 +82,8 @@ public class TextUtil {
if( len > start || !skipEmpty ) if( len > start || !skipEmpty )
result.add(input.subSequence(start, len).toString()); result.add(input.subSequence(start, len).toString());
return result.toArray(ArrayUtils.EMPTY_STRING_ARRAY); String[] toReturn = result.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
return trimParenthesis ? StringUtils.stripAll(toReturn, String.valueOf(openPar)) : toReturn;
} }
/** /**