blob: 7c1a171534df3e792eee078a09ea8f90d1259bf5 [file] [log] [blame]
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356.annotations;
import java.lang.reflect.Method;
import javax.websocket.Decoder;
import javax.websocket.Encoder;
import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException;
import org.eclipse.jetty.websocket.common.util.ReflectUtils;
import org.eclipse.jetty.websocket.jsr356.EncoderFactory;
import org.eclipse.jetty.websocket.jsr356.InitException;
import org.eclipse.jetty.websocket.jsr356.JsrSession;
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
public class OnMessageCallable extends JsrCallable
{
protected final Class<?> returnType;
protected Encoder returnEncoder;
protected Class<? extends Decoder> decoderClass;
protected Decoder decoder;
protected int idxPartialMessageFlag = -1;
protected int idxMessageObject = -1;
protected boolean messageRoleAssigned = false;
public OnMessageCallable(Class<?> pojo, Method method)
{
super(pojo,method);
this.returnType = method.getReturnType();
}
public OnMessageCallable(OnMessageCallable copy)
{
super(copy);
this.returnType = copy.returnType;
this.decoderClass = copy.decoderClass;
this.decoder = copy.decoder;
this.idxPartialMessageFlag = copy.idxPartialMessageFlag;
this.idxMessageObject = copy.idxMessageObject;
}
protected void assertDecoderRequired()
{
if (getDecoder() == null)
{
StringBuilder err = new StringBuilder();
err.append("Unable to find a valid ");
err.append(Decoder.class.getName());
err.append(" for parameter #");
Param param = params[idxMessageObject];
err.append(param.index);
err.append(" [").append(param.type).append("] in method: ");
err.append(ReflectUtils.toString(pojo,method));
throw new InvalidSignatureException(err.toString());
}
}
private int findMessageObjectIndex()
{
int index = -1;
for (Param.Role role : Param.Role.getMessageRoles())
{
index = findIndexForRole(role);
if (index >= 0)
{
return index;
}
}
return -1;
}
public Decoder getDecoder()
{
return decoder;
}
public Class<? extends Decoder> getDecoderClass()
{
return decoderClass;
}
public Param getMessageObjectParam()
{
if (idxMessageObject < 0)
{
idxMessageObject = findMessageObjectIndex();
if (idxMessageObject < 0)
{
StringBuilder err = new StringBuilder();
err.append("A message type must be specified [TEXT, BINARY, DECODER, or PONG] : ");
err.append(ReflectUtils.toString(pojo,method));
throw new InvalidSignatureException(err.toString());
}
}
return super.params[idxMessageObject];
}
public Encoder getReturnEncoder()
{
return returnEncoder;
}
public Class<?> getReturnType()
{
return returnType;
}
@Override
public void init(JsrSession session)
{
super.init(session);
idxPartialMessageFlag = findIndexForRole(Role.MESSAGE_PARTIAL_FLAG);
EncoderFactory.Wrapper encoderWrapper = session.getEncoderFactory().getWrapperFor(returnType);
if (encoderWrapper != null)
{
this.returnEncoder = encoderWrapper.getEncoder();
}
if (decoderClass != null)
{
try
{
this.decoder = decoderClass.newInstance();
}
catch (InstantiationException | IllegalAccessException e)
{
throw new InitException("Unable to create decoder: " + decoderClass.getName(),e);
}
}
}
public boolean isMessageRoleAssigned()
{
return messageRoleAssigned;
}
public boolean isPartialMessageSupported()
{
return (idxPartialMessageFlag >= 0);
}
@Override
public void setDecoderClass(Class<? extends Decoder> decoderClass)
{
this.decoderClass = decoderClass;
messageRoleAssigned = true;
}
public void setPartialMessageFlag(Param param)
{
idxPartialMessageFlag = param.index;
}
}