package NetworkAdapter.Implementation; import EnvironmentPluginAPI.CustomNetworkMessages.NetworkMessage; import ZeroTypes.Exceptions.TypeIsNotSerializableException; import NetworkAdapter.Interface.Exceptions.ConnectionLostException; import NetworkAdapter.Messages.ConnectionEndMessage; import java.io.IOException; import java.io.NotSerializableException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.InetAddress; import java.net.Socket; import java.util.logging.Level; import java.util.logging.Logger; /** * This object offers read and write access to the network in the form of CustomNetworkMessages. */ class NetworkAccessProtocol { private Socket socket; private ObjectOutputStream objectOutputStream; private ObjectInputStream objectInputStream; private int clientId = -1; /** * Creates the NetworkAccessProtocol object. * * @param socket an open socket != null */ NetworkAccessProtocol(Socket socket) throws IOException { this.socket = socket; objectOutputStream = new ObjectOutputStream(socket.getOutputStream()); objectInputStream = new ContextAwareObjectInputStream(socket.getInputStream()); } /** * Writes a network message to the stream. * * @param message the message to send * @throws ConnectionLostException if socket not writable. */ public void writeMessage(NetworkMessage message) throws ConnectionLostException { try { objectOutputStream.writeObject(message); objectOutputStream.flush(); } catch (NotSerializableException ne) { throw new TypeIsNotSerializableException(ne); } catch (IOException e) { throw new ConnectionLostException(message.getClientId()); } catch (Throwable t) { t.printStackTrace(); } } /** * reads raw byte stream from network and creates a NetworkMessage from it. * * @return the message, that was read * @throws ConnectionLostException if unable to read from socket. */ public NetworkMessage readMessage() throws ConnectionLostException { NetworkMessage message = null; String messageType = null; // try to read the raw data from the network and construct a message object from it try { message = (NetworkMessage) objectInputStream.readObject(); } catch (IOException ex) { ex.printStackTrace(); throw new ConnectionLostException(clientId); } catch (ClassNotFoundException ex) { System.err.println("Unable to find class. Make sure the same version of all types are known on both server and client ends."); ex.printStackTrace(); } catch (Exception ex) { ex.printStackTrace(); Logger.getLogger(NetworkAccessProtocol.class.getName()).log(Level.SEVERE, "An exception occurred while invoking the contract constructor of '" + message.getClass() + "'.\nReason:", ex); } return message; } public InetAddress getClientAddress() { return socket.getInetAddress(); } public void setClientId(int clientId) { this.clientId = clientId; } /** * informs the remote end about the connection closing und closes the socket. * * @param message * @throws ConnectionLostException */ public void closeConnection(ConnectionEndMessage message) throws ConnectionLostException { writeMessage(message); } public void forceClose() { try { objectInputStream.close(); objectOutputStream.close(); } catch (IOException e) { } } public boolean isSocketOpen() { return !socket.isClosed(); } }