Java tutorial
package com.conwet.xjsp.session; /* * #%L * eXtensible JSON Streaming Protocol * %% * Copyright (C) 2011 - 2014 CoNWeT Lab., Universidad Politcnica de Madrid * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ import com.conwet.xjsp.features.MessageChannel; import com.conwet.xjsp.features.SessionListener; import com.conwet.xjsp.textstream.ConnectionHandler; import com.conwet.xjsp.errors.ConnectionException; import java.io.IOException; import java.nio.channels.WritableByteChannel; import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import org.json.simple.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Maintains an incoming buffer for a given connection. The buffer is offered to * the active connection state whenever new data arrive or the connection * timeout is triggered. * * The initial state is provided in the constructor. * * @author sortega * @apiviz.owns com.conwet.silbops.xjsp.session.ConnectionState * @apiviz.stereotype StatePattern */ public class ConnectionContext implements ConnectionHandler { private static final Logger logger = LoggerFactory.getLogger(ConnectionContext.class); private final ConnectionState initialState; private ConnectionState state; private MessageChannel channel; private final StringBuilder buffer; private final List<SessionListener> sessionListeners; private AtomicBoolean isOpen; public ConnectionContext(ConnectionState initialState) { this(initialState, new LinkedList<SessionListener>()); } public ConnectionContext(ConnectionState initialState, List<SessionListener> sessionListeners) { this.initialState = initialState; this.sessionListeners = sessionListeners; this.state = null; this.buffer = new StringBuilder(); this.isOpen = new AtomicBoolean(Boolean.TRUE); } @Override public void start() { this.setState(this.initialState); } /** * Transit to a new state which will be activated by calling its start method. * * @param state the {@linkplain ConnectionState} to use */ public void setState(ConnectionState state) { this.state = state; try { this.state.start(this); } catch (ConnectionException ex) { handleConnectionException(ex); } } @Override public void newData(String data) { this.buffer.append(data); try { state.newData(this); } catch (ConnectionException ex) { handleConnectionException(ex); } } @Override public void setChannel(WritableByteChannel channel) { this.channel = new MessageChannel(channel); } public StringBuilder getBuffer() { return this.buffer; } public MessageChannel getChannel() { return this.channel; } public List<SessionListener> getSessionListeners() { return this.sessionListeners; } @Override public void dispose() { if (isOpen.getAndSet(Boolean.FALSE)) { channel.close(); state.abort(this); } } @Override public void timeout() { try { this.state.timeout(this); } catch (ConnectionException ex) { handleConnectionException(ex); } } @Override public long getTimeoutPeriod() { return this.state.getTimeoutPeriod(this); } @SuppressWarnings("unchecked") private void handleConnectionException(ConnectionException ex) { switch (ex.getError()) { case ProtocolSyntaxError: case NegotiationError: case NegotiationFieldError: case NegotiationTimeout: case ApplicationError: logger.error("Closing connection on error: {}", ex.getError()); this.dispose(); break; default: JSONObject payload = new JSONObject(); payload.put("code", ex.getErrorCode()); payload.put("message", ex.getMessage()); if (ex.getMessageId() != null) { payload.put("id", ex.getMessageId()); } try { this.channel.sendErrorMessage(payload); } catch (IOException ex1) { logger.error("Unexpected exception", ex1); } } } }