/*
* Copyright 2005 Joe Walker
*
* 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.directwebremoting.extend;
import org.directwebremoting.ScriptBuffer;
import org.directwebremoting.util.JavascriptUtil;
/**
* An abstraction of the dwr.engine Javascript class.
* @author Joe Walker [joe at getahead dot ltd dot uk]
*/
public class EnginePrivate
{
/**
* Call the dwr.engine.remote.handleResponse() in the browser
* @param batchId The identifier of the batch that we are handling a response for
* @param callId The identifier of the call that we are handling a response for
* @param data The data to pass to the callback function
* @return The script to send to the browser
*/
public static ScriptBuffer getRemoteHandleCallbackScript(String batchId, String callId, Object data)
{
ScriptBuffer script = new ScriptBuffer();
script.appendCall("dwr.engine.remote.handleCallback", batchId, callId, data);
return script;
}
/**
* Call dwr.engine.remote.handleException() in the browser
* @param batchId The identifier of the batch that we are handling a response for
* @param callId The id of the call we are replying to
* @param ex The exception to throw on the remote end
* @return The script to send to the browser
*/
public static ScriptBuffer getRemoteHandleExceptionScript(String batchId, String callId, Throwable ex)
{
ScriptBuffer script = new ScriptBuffer();
script.appendCall("dwr.engine.remote.handleException", batchId, callId, ex);
return script;
}
/**
* Call dwr.engine.remote.handleNewScriptSession() in the browser
* @param newSessionId The new script session id for the browser to reuse
* @return The script to send to the browser
*/
public static ScriptBuffer getRemoteHandleNewScriptSessionScript(String newSessionId)
{
ScriptBuffer script = new ScriptBuffer();
script.appendCall("dwr.engine.remote.handleNewScriptSession", newSessionId);
return script;
}
/**
* Call dwr.engine.remote.handleNewWindowName() in the browser
* @param windowName The new window name for the page
* @return The script to send to the browser
*/
public static ScriptBuffer getRemoteHandleNewWindowNameScript(String windowName)
{
ScriptBuffer script = new ScriptBuffer();
script.appendCall("dwr.engine.remote.handleNewWindowName", windowName);
return script;
}
/**
* Call dwr.engine.remote.handleServerException() in the browser
* @param batchId The identifier of the batch that we are handling a response for
* @param ex The exception from which we make a reply
* @return The script to send to the browser
*/
public static String getRemoteHandleBatchExceptionScript(String batchId, Exception ex)
{
StringBuffer reply = new StringBuffer();
String output = JavascriptUtil.escapeJavaScript(ex.getMessage());
String params = "{ name:'" + ex.getClass().getName() + "', message:'" + output + "' }";
if (batchId != null)
{
params += ", '" + batchId + "'";
}
reply.append(ProtocolConstants.SCRIPT_CALL_REPLY).append("\r\n");
reply.append("if (window.dwr) dwr.engine.remote.handleBatchException(").append(params).append(");\r\n");
reply.append("else if (window.parent.dwr) window.parent.dwr.engine.remote.handleBatchException(").append(params).append(");\r\n");
return reply.toString();
}
/**
* Call dwr.engine.remote.executeFunction() in the browser
* @param id The registered function name
* @param params The data to pass to the function
* @return The script to send to the browser
*/
public static ScriptBuffer getRemoteExecuteFunctionScript(String id, Object[] params)
{
ScriptBuffer script = new ScriptBuffer();
script.appendCall("dwr.engine.remote.handleFunctionCall", id, params);
return script;
}
/**
* Call dwr.engine.remote.executeFunction() in the browser
* @param id The registered function name
* @param params The data to pass to the function
* @return The script to send to the browser
*/
public static ScriptBuffer getRemoteExecuteObjectScript(String id, String methodName, Object[] params)
{
ScriptBuffer script = new ScriptBuffer();
script.appendCall("dwr.engine.remote.handleObjectCall", id, methodName, params);
return script;
}
/**
* Call dwr.engine.remote.executeFunction() in the browser
* @param id The registered function name
* @param propertyName The name of the property to alter on the client object
* @param data The new value for the client object property
* @return The script to send to the browser
*/
public static ScriptBuffer getRemoteSetObjectScript(String id, String propertyName, Object data)
{
ScriptBuffer script = new ScriptBuffer();
script.appendCall("dwr.engine.remote.handleSetCall", id, propertyName, data);
return script;
}
/**
* Call dwr.engine.remote.closeFunction() in the browser
* @param id The registered function name
* @return The script to send to the browser
*/
public static ScriptBuffer getRemoteCloseFunctionScript(String id)
{
ScriptBuffer script = new ScriptBuffer();
script.appendCall("dwr.engine.remote.handleFunctionClose", id);
return script;
}
/**
* Call dwr.engine.remote.pollCometDisabled() in the browser
* @param batchId The identifier of the batch that we are handling a response for
* @return The script to send to the browser
*/
public static String getRemotePollCometDisabledScript(String batchId)
{
StringBuffer reply = new StringBuffer();
String params = "{ name:'dwr.engine.pollAndCometDisabled', message:'Polling and Comet are disabled. See the server logs.' }";
if (batchId != null)
{
params += ", '" + batchId + "'";
}
reply.append(ProtocolConstants.SCRIPT_CALL_REPLY).append("\r\n");
reply.append("if (window.dwr) dwr.engine.remote.pollCometDisabled(").append(params).append(");\r\n");
reply.append("else if (window.parent.dwr) window.parent.dwr.engine.remote.pollCometDisabled(").append(params).append(");\r\n");
return reply.toString();
}
/**
* Take an XML string, and convert it into some Javascript that when
* executed will return a DOM object that represents the same XML object
* @param xml The XML string to convert
* @return The Javascript
*/
public static String xmlStringToJavascriptDomElement(String xml)
{
String xmlout = JavascriptUtil.escapeJavaScript(xml);
return "dwr.engine.serialize.toDomElement(\"" + xmlout + "\")";
}
/**
* Take an XML string, and convert it into some Javascript that when
* executed will return a DOM object that represents the same XML object
* @param xml The XML string to convert
* @return The Javascript
*/
public static String xmlStringToJavascriptDomDocument(String xml)
{
String xmlout = JavascriptUtil.escapeJavaScript(xml);
return "dwr.engine.serialize.toDomDocument(\"" + xmlout + "\")";
}
/**
* Get a string which will initialize a dwr.engine object
* @return A dwr.engine init script
*/
public static String getEngineInitScript()
{
return "// Provide a default path to dwr.engine\n" +
"if (typeof this['dwr'] == 'undefined') this.dwr = {};\n" +
"if (typeof dwr['engine'] == 'undefined') dwr.engine = {};\n" +
"if (typeof dwr.engine['_mappedClasses'] == 'undefined') dwr.engine._mappedClasses = {};\n" +
'\n';
}
/**
* The DefaultRemoter needs to know the name of the execute function
* @return The execute function name
*/
public static String getExecuteFunctionName()
{
return "dwr.engine._execute";
}
/**
* A script to send at the beginning of an iframe response
* @param batchId The id of the current batch
* @param useWindowParent Will the exec happen from a child iframe which is
* the case for normal iframe based calls, or from the main window, which is
* the case for iframe streamed polling.
* @return A script to init the environment
*/
public static String remoteBeginIFrameResponse(String batchId, boolean useWindowParent)
{
String script = "dwr.engine.transport.iframe.remote.beginIFrameResponse(this.frameElement"+(batchId == null?"":", '" + batchId+"'") + ");";
if (useWindowParent)
{
script = addWindowParent(script);
}
return script;
}
/**
* A script to send at the end of an iframe response
* @param batchId The id of the current batch
* @param useWindowParent Will the exec happen from a child iframe which is
* the case for normal iframe based calls, or from the main window, which is
* the case for iframe streamed polling.
* @return A script to tidy up the environment
*/
public static String remoteEndIFrameResponse(String batchId, boolean useWindowParent)
{
String script = "dwr.engine.transport.iframe.remote.endIFrameResponse("+(batchId == null?"":"'" + batchId+"'")+");";
if (useWindowParent)
{
script = addWindowParent(script);
}
return script;
}
/**
* Prepare a script for execution in an iframe environment
* @param script The script to modify
* @return The modified script
*/
public static String remoteEval(String script)
{
String script2 = "dwr.engine._eval(\"" + JavascriptUtil.escapeJavaScript(script) + "\");";
return addWindowParent(script2);
}
/**
* Evade the 2 connection limit by sending scripts to the wrong window and
* having that use window.name to push it to the right window
* @param original The script that we wish to be proxied
* @param windowName The window to which we wish the window to be proxied
* @return A script to send to a different window to cause proxying
*/
public static ScriptBuffer createForeignWindowProxy(String windowName, ScriptBuffer original)
{
String proxy = JavascriptUtil.escapeJavaScript(original.toString());
ScriptBuffer reply = new ScriptBuffer();
reply.appendCall("dwr.engine.remote.handleForeign", windowName, proxy);
reply.appendData(proxy);
return reply;
}
/**
* A Utility to add a try/catch block to get rid of the infamous IE
* "Can't execute code from a freed script" errors
* @param script The script to wrap in a try/catch
* @return The wrapped script
*/
private static String addWindowParent(String script)
{
return "try { window.parent." + script + " } catch(ex) { if (!(ex.number && ex.number == -2146823277)) { throw ex; }}";
}
}