/*
* 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.bayeux;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.directwebremoting.ScriptBuffer;
import org.directwebremoting.dwrp.CallBatch;
import org.directwebremoting.dwrp.PlainCallHandler;
import org.directwebremoting.extend.Call;
import org.directwebremoting.extend.Calls;
import org.directwebremoting.extend.ConverterManager;
import org.directwebremoting.extend.EnginePrivate;
import org.directwebremoting.extend.FormField;
import org.directwebremoting.extend.Remoter;
import org.directwebremoting.extend.Replies;
import org.directwebremoting.extend.Reply;
import org.directwebremoting.extend.ScriptConduit;
import dojox.cometd.Bayeux;
import dojox.cometd.Channel;
import dojox.cometd.Client;
import dojox.cometd.Listener;
import dojox.cometd.Message;
/**
* @author Greg Wilkins [gregw at webtide dot com]
* @author Joe Walker [joe at getahead dot ltd dot uk]
*/
public class BayeuxClient implements Listener
{
public BayeuxClient(Bayeux bayeux)
{
this.bayeux = bayeux;
// At this point BayeuxClient is fully initialized so it is safe to
// allow other classes to see and use us.
Channel channel = bayeux.getChannel("/dwr", true);
channel.subscribe(client);
}
/* (non-Javadoc)
* @see dojox.cometd.MessageListener#deliver(dojox.cometd.Client, dojox.cometd.Client, dojox.cometd.Message)
*/
public void deliver(Client fromClient, Client toClient, Message message)
{
try
{
Map<String, FormField> fileParams = new HashMap<String, FormField>(message.size());
for (Map.Entry<String, Object> entry : message.entrySet())
{
String param = (String) entry.getValue();
FormField formField = new FormField(param);
fileParams.put(entry.getKey(), formField);
}
CallBatch batch = new CallBatch(fileParams, false);
Calls calls = plainCallHandler.marshallInbound(batch);
log.debug("Calls="+calls);
for (int i = 0; i < calls.getCallCount(); i++)
{
Call call = calls.getCall(i);
Object[] params = call.getParameters();
log.debug("Call[" + i + "]=" + call.getScriptName() + "." + call.getMethodName() + (params == null ? "[]" : Arrays.asList(params)));
}
Replies replies = remoter.execute(calls);
ScriptConduit conduit = new BayeuxScriptConduit(converterManager, JSON_OUTPUT);
for (Reply reply : replies)
{
String batchId = calls.getBatchId();
log.debug("Reply="+reply+" BatchId="+batchId);
if (reply.getThrowable() != null)
{
Throwable ex = reply.getThrowable();
ScriptBuffer script = EnginePrivate.getRemoteHandleExceptionScript(batchId, reply.getCallId(), ex);
conduit.addScript(script);
log.warn("--Erroring: batchId[" + batchId + "] message[" + ex.toString() + ']');
}
else
{
Object data = reply.getReply();
log.debug("data="+data);
ScriptBuffer script = EnginePrivate.getRemoteHandleCallbackScript(batchId, reply.getCallId(), data);
conduit.addScript(script);
}
}
String output = conduit.toString();
log.debug("<< "+output);
Channel channel = bayeux.getChannel("/dwr" + fromClient.getId(), true);
channel.publish(client, output, calls.getBatchId());
}
catch (Exception ex)
{
log.warn("Protocol Error", ex);
}
}
/* (non-Javadoc)
* @see dojox.cometd.Listener#removed(java.lang.String, boolean)
*/
public void removed(String clientId, boolean timeout)
{
}
/**
* We're note constraining our output to JSON at the moment
*/
private static final boolean JSON_OUTPUT = false;
private final Bayeux bayeux;
private Client client;
/**
* @param remoter
*/
public void setRemoter(Remoter remoter)
{
this.remoter = remoter;
}
private Remoter remoter;
/**
* @param converterManager
*/
public void setConverterManager(ConverterManager converterManager)
{
this.converterManager = converterManager;
}
private ConverterManager converterManager;
/**
* @param plainCallHandler
*/
public void setPlainCallHandler(PlainCallHandler plainCallHandler)
{
this.plainCallHandler = plainCallHandler;
}
private PlainCallHandler plainCallHandler;
/**
* The log stream
*/
private static final Log log = LogFactory.getLog(BayeuxClient.class);
}