/*******************************************************************************
* Copyright (c) 2007, 2010 Innoopract Informationssysteme GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Innoopract Informationssysteme GmbH - initial API and implementation
* EclipseSource - ongoing development
******************************************************************************/
package org.eclipse.rwt.internal.lifecycle;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.eclipse.rwt.RWT;
import org.eclipse.rwt.SessionSingletonBase;
import org.eclipse.rwt.internal.service.*;
import org.eclipse.rwt.internal.util.HTML;
import org.eclipse.rwt.service.IServiceHandler;
import org.eclipse.rwt.service.ISessionStore;
import org.eclipse.swt.SWT;
public class UICallBackServiceHandler implements IServiceHandler {
// keep in sync with function enableUICallBack() in Request.js
public final static String HANDLER_ID
= UICallBackServiceHandler.class.getName();
static final String JS_SEND_CALLBACK_REQUEST
= "org.eclipse.swt.Request.getInstance().enableUICallBack();";
private static final String JS_SEND_UI_REQUEST
= "org.eclipse.swt.Request.getInstance().send();";
private static final String BUFFERED_SEND_CALLBACK_REQUEST
= UICallBackServiceHandler.class.getName() + "#jsUICallback";
private static final String NEED_UI_CALLBACK_ACTIVATOR
= UICallBackServiceHandler.class.getName() + "#needUICallBackActivator";
////////////////
// inner classes
private static final class IdManager {
static IdManager getInstance() {
return ( IdManager )SessionSingletonBase.getInstance( IdManager.class );
}
private final Set ids;
private final Object lock;
private IdManager() {
ids = new HashSet();
lock = new Object();
}
int add( final String id ) {
synchronized( lock ) {
ids.add( id );
return ids.size();
}
}
int remove( final String id ) {
synchronized( lock ) {
ids.remove( id );
return ids.size();
}
}
boolean isEmpty() {
synchronized( lock ) {
return ids.isEmpty();
}
}
}
public void service() throws IOException, ServletException {
ISessionStore sessionStore = RWT.getSessionStore();
if( !UICallBackManager.getInstance().blockCallBackRequest()
&& ContextProvider.hasContext()
&& sessionStore.isBound() )
{
writeResponse();
}
}
public static void activateUICallBacksFor( final String id ) {
int size = IdManager.getInstance().add( id );
if( size == 1 ) {
registerUICallBackActivator();
}
}
private static void registerUICallBackActivator() {
ISessionStore session = ContextProvider.getSession();
session.setAttribute( NEED_UI_CALLBACK_ACTIVATOR, Boolean.TRUE );
}
public static void deactivateUICallBacksFor( final String id ) {
// release blocked callback handler request
int size = IdManager.getInstance().remove( id );
if( size == 0 ) {
UICallBackManager instance = UICallBackManager.getInstance();
instance.setActive( false );
instance.sendUICallBack();
}
}
public static void writeActivation() throws IOException {
if( needsActivation() ) {
ISessionStore session = ContextProvider.getSession();
session.setAttribute( NEED_UI_CALLBACK_ACTIVATOR, Boolean.FALSE );
UICallBackManager.getInstance().setActive( true );
IServiceStateInfo stateInfo = ContextProvider.getStateInfo();
HtmlResponseWriter writer = stateInfo.getResponseWriter();
writer.write( UICallBackServiceHandler.JS_SEND_CALLBACK_REQUEST );
}
}
private static boolean needsActivation() {
ISessionStore session = ContextProvider.getSession();
return UICallBackServiceHandler.isUICallBackActive()
&& Boolean.TRUE == session.getAttribute( NEED_UI_CALLBACK_ACTIVATOR )
&& !UICallBackManager.getInstance().isCallBackRequestBlocked();
}
//////////////////////////
// Service helping methods
static void writeResponse() throws IOException {
HttpServletResponse response = ContextProvider.getResponse();
response.setHeader( HTML.CONTENT_TYPE, HTML.CONTENT_TEXT_JAVASCRIPT_UTF_8 );
PrintWriter writer = response.getWriter();
writer.print( jsUICallBack() );
writer.flush();
}
private static String jsUICallBack() {
String result;
if( isUICallBackActive()
&& !UICallBackManager.getInstance().isCallBackRequestBlocked() )
{
ISessionStore session = ContextProvider.getSession();
String bufferedCode
= ( String )session.getAttribute( BUFFERED_SEND_CALLBACK_REQUEST );
if( bufferedCode == null ) {
StringBuffer code = new StringBuffer();
code.append( JS_SEND_UI_REQUEST );
code.append( JS_SEND_CALLBACK_REQUEST );
bufferedCode = code.toString();
session.setAttribute( BUFFERED_SEND_CALLBACK_REQUEST, bufferedCode );
}
result = bufferedCode;
} else {
result = JS_SEND_UI_REQUEST;
}
return result;
}
static boolean isUICallBackActive() {
boolean result = !IdManager.getInstance().isEmpty();
if( !result ) {
result = UICallBackManager.getInstance().hasRunnables();
}
return result;
}
}