org.atmosphere.gwt.server.AtmosphereGwtHandler Maven / Gradle / Ivy
/*
* Copyright 2012 Jeanfrancois Arcand
*
* 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 org.atmosphere.gwt.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.AtmosphereServletProcessor;
import org.atmosphere.cpr.Broadcaster;
import org.atmosphere.cpr.BroadcasterFactory;
import org.atmosphere.cpr.DefaultBroadcaster;
import org.atmosphere.cpr.FrameworkConfig;
import org.atmosphere.gwt.server.impl.GwtAtmosphereResourceImpl;
import org.atmosphere.gwt.server.impl.GwtRpcDeserializer;
import org.atmosphere.gwt.server.spi.JSONSerializerProvider;
import org.atmosphere.gwt.shared.Constants;
import org.atmosphere.gwt.shared.SerialMode;
import org.atmosphere.handler.AbstractReflectorAtmosphereHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author p.havelaar
*/
public class AtmosphereGwtHandler extends AbstractReflectorAtmosphereHandler
implements Executor, AtmosphereServletProcessor {
public static final int NO_TIMEOUT = -1;
public static final String GWT_BROADCASTER_ID = "GWT_BROADCASTER";
private static final int DEFAULT_HEARTBEAT = 15 * 1000; // 15 seconds by default
private ExecutorService executorService;
private int heartbeat = DEFAULT_HEARTBEAT;
private boolean escapeText = true;
protected final Logger logger = LoggerFactory.getLogger(getClass());
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
private GwtRpcDeserializer gwtRpc;
private JSONDeserializer jsonSerializer;
/**
* This is the main entrypoint on the server that you will want to hook into and override.
* This method is called when a client has request a new connection. Best practice is to do all your
* required setup here and tie the AtmosphereResource to a Broadcaster, but do not send anything to
* the client yet. If you wish to do so it is best to let the client send a notification to the server
* using the {@link AtmosphereClient#post} method in the onConnected event.
*
* @param resource
* @return
* @throws ServletException
* @throws IOException
*/
public int doComet(GwtAtmosphereResource resource) throws ServletException, IOException {
Broadcaster broadcaster = BroadcasterFactory.getDefault().lookup(Broadcaster.class, GWT_BROADCASTER_ID);
if (broadcaster == null) {
broadcaster = BroadcasterFactory.getDefault().get(DefaultBroadcaster.class, GWT_BROADCASTER_ID);
}
resource.getAtmosphereResource().setBroadcaster(broadcaster);
return NO_TIMEOUT;
}
/**
* When the connection has died this method will be called to let you know about it.
*
*
* @param cometResponse
* @param serverInitiated
*/
public void cometTerminated(GwtAtmosphereResource cometResponse, boolean serverInitiated) {
}
/**
* Called when a message is sent from the client using the post method.
*
* Default implementation echo's the message back to the client
*
* @param messages
* @param cometResource
*/
public void doPost(HttpServletRequest postRequest, HttpServletResponse postResponse,
List> messages, GwtAtmosphereResource cometResource) {
if (cometResource != null) {
if (messages.size() == 1) {
cometResource.post(messages.get(0));
} else {
cometResource.post(messages);
}
}
}
/**
* This can be used to lookup a resource for instance if you are implementing a remote service call
* You will need to pass the connectionID, which you can pass as an url parameter {getConnectionID()} or
* directly in your remote call
*
* @param connectionId
* @return
*/
protected GwtAtmosphereResource lookupResource(int connectionId) {
if (resources == null) {
return null;
}
GwtAtmosphereResource r = resources.get(connectionId);
if (r != null) {
return r;
} else {
logger.info("Failed to find resource for [" + connectionId + "]");
}
return null;
}
// -------------- you most likely don't need to override the functions below -----------------
private Map resources;
private ServletContext context;
@Override
public void init(ServletConfig servletConfig) throws ServletException {
executorService = Executors.newCachedThreadPool();
String heartbeat = servletConfig.getInitParameter("heartbeat");
context = servletConfig.getServletContext();
if (heartbeat != null) {
this.heartbeat = Integer.parseInt(heartbeat);
}
String escText = servletConfig.getInitParameter("escapeText");
if (escText != null) {
this.escapeText = Boolean.valueOf(escText);
}
}
@Override
public void destroy() {
if (executorService != null) {
executorService.shutdown();
}
if (scheduler != null) {
scheduler.shutdown();
}
}
public boolean isEscapeText() {
return escapeText;
}
public void setEscapeText(boolean escapeText) {
this.escapeText = escapeText;
}
public int getHeartbeat() {
return heartbeat;
}
public void setHeartbeat(int heartbeat) {
this.heartbeat = heartbeat;
}
public ServletContext getServletContext() {
return context;
}
protected void reapResources() {
if (resources != null) {
for (GwtAtmosphereResource resource : resources.values()) {
if (!resource.isAlive()) {
resources.remove(resource.getConnectionID());
}
}
}
}
@Override
public void onRequest(AtmosphereResource resource) throws IOException {
HttpServletRequest request = resource.getRequest();
String servertransport = request.getParameter("servertransport");
Object webSocketSubProtocol = resource.getRequest().getAttribute(FrameworkConfig.WEBSOCKET_SUBPROTOCOL);
if ("rpcprotocol".equals(servertransport)) {
Integer connectionID = Integer.parseInt(request.getParameter("connectionID"));
doServerMessage(request, resource.getResponse(), connectionID);
return;
} else if (webSocketSubProtocol != null
&& webSocketSubProtocol.equals(FrameworkConfig.SIMPLE_HTTP_OVER_WEBSOCKET)) {
Integer connectionID = (Integer) request.getAttribute(AtmosphereGwtHandler.class.getName()
+ ".connectionID");
doServerMessage(request, resource.getResponse(), connectionID);
return;
}
try {
int requestHeartbeat = getRequestedHeartbeat(request);
boolean requestEscapeText = getRequestedEscapeOfText(request);
GwtAtmosphereResourceImpl resourceWrapper =
new GwtAtmosphereResourceImpl(resource, this, requestHeartbeat, requestEscapeText);
request.setAttribute(AtmosphereGwtHandler.class.getName() + ".connectionID",
(Integer) resourceWrapper.getConnectionID());
doCometImpl(resourceWrapper);
} catch (IOException e) {
// GwtAtmosphereResourceImpl resource = new GwtAtmosphereResourceImpl(atm, this, -1);
logger.error("Unable to initiated comet" + e.getMessage(), e);
// resource.getResponseWriter().sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
}
}
private boolean getRequestedEscapeOfText(HttpServletRequest request) throws IOException {
boolean requestEscapeText = this.escapeText;
String requestedEscapeText = request.getParameter("escapeText");
if (requestedEscapeText != null) {
requestEscapeText = Boolean.valueOf(requestedEscapeText);
}
return requestEscapeText;
}
private int getRequestedHeartbeat(HttpServletRequest request) throws IOException {
int requestHeartbeat = heartbeat;
String requestedHeartbeat = request.getParameter("heartbeat");
if (requestedHeartbeat != null) {
try {
requestHeartbeat = Integer.parseInt(requestedHeartbeat);
if (requestHeartbeat <= 0) {
throw new IOException("invalid heartbeat parameter");
}
requestHeartbeat = computeHeartbeat(requestHeartbeat);
} catch (NumberFormatException e) {
throw new IOException("invalid heartbeat parameter");
}
}
return requestHeartbeat;
}
/// --- server message handlers
protected void doServerMessage(HttpServletRequest request, HttpServletResponse response, int connectionID)
throws IOException{
BufferedReader data = request.getReader();
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy