Java tutorial
/* * Copyright 2013 John Ahlroos * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package fi.jasoft.remoteconnection; import java.util.LinkedList; import java.util.List; import java.util.logging.Logger; import com.vaadin.annotations.JavaScript; import com.vaadin.server.AbstractExtension; import com.vaadin.ui.UI; import fi.jasoft.remoteconnection.client.RemoteConnectionClientRPC; import fi.jasoft.remoteconnection.client.RemoteConnectionServerRPC; import fi.jasoft.remoteconnection.shared.ConnectedListener; import fi.jasoft.remoteconnection.shared.ConnectionError; import fi.jasoft.remoteconnection.shared.IncomingChannelConnectionListener; import fi.jasoft.remoteconnection.shared.RemoteChannel; import fi.jasoft.remoteconnection.shared.RemoteConnection; import fi.jasoft.remoteconnection.shared.RemoteConnectionConfiguration; import fi.jasoft.remoteconnection.shared.RemoteConnectionDataListener; import fi.jasoft.remoteconnection.shared.RemoteConnectionErrorHandler; import fi.jasoft.remoteconnection.shared.RemoteConnectionState; /** * Server implementation for {@link RemoteConnection} * * @author John Ahlroos */ @SuppressWarnings("serial") @JavaScript("peer.min.js") public class ServerRemoteConnection extends AbstractExtension implements RemoteConnection { /** * A channel between two remote connections * */ public class ServerRemoteChannel implements RemoteChannel { private final String id; private boolean connected = false; private List<ConnectedListener> connectedListeners = new LinkedList<ConnectedListener>(); @Override public void send(String message) { getRpcProxy(RemoteConnectionClientRPC.class).sendMessage(id, message); } @Override public String getId() { return id; } @Override public boolean isConnected() { return connected; } @Override public void addConnectedListener(ConnectedListener listener) { connectedListeners.add(listener); } private ServerRemoteChannel(String id) { this.id = id; } private void messageRecieved(String message) { for (RemoteConnectionDataListener listener : listeners) { listener.dataRecieved(this, message); } } private void setConnected(boolean connected, String channelId) { this.connected = connected; if (connected) { for (ConnectedListener listener : connectedListeners) { listener.connected(channelId); } } } } /* * RPC for making communication from client -> server */ private RemoteConnectionServerRPC rpc = new RemoteConnectionServerRPC() { @Override public void recievedMessage(String id, String message) { getChannelById(id).messageRecieved(message); } @Override public void recievedConnection(String id) { ServerRemoteChannel channel = new ServerRemoteChannel(id); channels.add(channel); for (IncomingChannelConnectionListener listener : incomingListeners) { listener.connected(channel); } } @Override public void peerConnected(String id) { connected = true; getState(false).configuration.setId(id); for (ConnectedListener listener : connetedListeners) { listener.connected(id); } } @Override public void error(String reason) { if (errorHandler != null) { errorHandler.onConnectionError(ConnectionError.get(reason), reason); } else { System.err.println("An error occurred when connecting (" + reason + ")"); } } @Override public void channelConnected(String id) { getChannelById(id).setConnected(true, id); } }; // Currently open channels private final List<ServerRemoteChannel> channels = new LinkedList<ServerRemoteChannel>(); // Currently attached data listeners private final List<RemoteConnectionDataListener> listeners = new LinkedList<RemoteConnectionDataListener>(); private final List<IncomingChannelConnectionListener> incomingListeners = new LinkedList<IncomingChannelConnectionListener>(); private final List<ConnectedListener> connetedListeners = new LinkedList<ConnectedListener>(); private boolean connected = false; private RemoteConnectionErrorHandler errorHandler; /** * Attaches a remote connection to an UI * * @param ui * The UI to attach to * @return * Returns the connection to communicate with remote channels with */ public static ServerRemoteConnection register(UI ui) { return new ServerRemoteConnection(ui); } /** * Attaches a remote connection to an UI * * @param ui * The UI to attach to * @param peerId * The id of this remote connection * @return * Returns the connection to communicate with remote channels with */ public static RemoteConnection register(UI ui, RemoteConnectionConfiguration configuration) { ServerRemoteConnection peer = register(ui); peer.getState().configuration = configuration; return peer; } @Override public RemoteChannel openChannel(String endpointPeerId) { RemoteChannel channel = getChannel(endpointPeerId); if (channel != null) { return channel; } // Open the channel on the client side getRpcProxy(RemoteConnectionClientRPC.class).openChannel(endpointPeerId); // Create channel instance channel = new ServerRemoteChannel(endpointPeerId); channels.add((ServerRemoteChannel) channel); return channel; } @Override protected RemoteConnectionState getState() { return (RemoteConnectionState) super.getState(); } @Override protected RemoteConnectionState getState(boolean markAsDirty) { return (RemoteConnectionState) super.getState(markAsDirty); } @Override public void addDataListener(RemoteConnectionDataListener listener) { listeners.add(listener); } @Override public void addIncomingConnectionListener(IncomingChannelConnectionListener listener) { incomingListeners.add(listener); } @Override public void broadcast(String message) { for (RemoteChannel channel : channels) { channel.send(message); } } @Override public RemoteChannel getChannel(String endpointPeerId) { for (ServerRemoteChannel channel : channels) { if (channel.getId().equals(endpointPeerId)) { return channel; } } return null; } @Override public void terminate() { getRpcProxy(RemoteConnectionClientRPC.class).terminate(); } @Override public void connect() { if (getState(false).configuration.getKey().equals(RemoteConnectionConfiguration.DEVELOPMENT_PEER_JS_KEY)) { getLogger().warning("You are using the development key of RemoteConnection " + "with a very limited amount of connections shared among all " + "RemoteConnection users. You are strongly encoraged to apply " + "for your own developer key at http://peerjs.com/peerserver or " + "run your own server which can be downloaded from https://github.com/peers/peerjs-server. " + "You can supply your own peer server details through the RemoteConnection.getConfiguration() " + "option. Thank you."); } getRpcProxy(RemoteConnectionClientRPC.class).connect(); } @Override public boolean isConnected() { return connected; } @Override public void setErrorHandler(RemoteConnectionErrorHandler handler) { errorHandler = handler; } @Override public void addConnectedListener(ConnectedListener listener) { connetedListeners.add(listener); } /** * Default construction * * @param ui * The UI the connection should be attached to */ private ServerRemoteConnection(UI ui) { super.extend(ui); registerRpc(rpc); // Use Vaadin's script injection getState().configuration.setScriptInjected(false); } /** * Returns, or creates a new, channel by using its remote peer id * * @param id * The peer id of the channel endpoint * @return */ private ServerRemoteChannel getChannelById(String id) { for (ServerRemoteChannel channel : channels) { if (channel.getId().equals(id)) { return channel; } } return null; } private Logger getLogger() { return Logger.getLogger(ServerRemoteConnection.class.getCanonicalName()); } @Override public RemoteConnectionConfiguration getConfiguration() { return getState().configuration; } }