blob: e78620e8f86a59b13c7f30bf1ccaac70b9d472f7 [file] [log] [blame]
//
// ========================================================================
// Copyright (c) 1995-2015 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.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Map;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import org.eclipse.jetty.websocket.api.InvalidWebSocketException;
import org.eclipse.jetty.websocket.common.events.annotated.CallableMethod;
import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException;
import org.eclipse.jetty.websocket.common.util.ReflectUtils;
import org.eclipse.jetty.websocket.jsr356.JsrSession;
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
public abstract class JsrCallable extends CallableMethod
{
protected final Param[] params;
protected final Object[] args;
protected int idxSession = -1;
protected int idxConfig = -1;
public JsrCallable(Class<?> pojo, Method method)
{
super(pojo,method);
Class<?> ptypes[] = method.getParameterTypes();
Annotation pannos[][] = method.getParameterAnnotations();
int len = ptypes.length;
params = new Param[len];
for (int i = 0; i < len; i++)
{
params[i] = new Param(i,ptypes[i],pannos[i]);
}
args = new Object[len];
}
/**
* Copy Constructor
* @param copy the JsrCallable to copy from
*/
public JsrCallable(JsrCallable copy)
{
this(copy.getPojo(),copy.getMethod());
this.idxSession = copy.idxSession;
this.idxConfig = copy.idxConfig;
System.arraycopy(copy.params,0,this.params,0,params.length);
System.arraycopy(copy.args,0,this.args,0,args.length);
}
protected void assertRoleRequired(int index, String description)
{
if (index < 0)
{
StringBuilder err = new StringBuilder();
err.append("Unable to find parameter with role [");
err.append(description).append("] in method: ");
err.append(ReflectUtils.toString(pojo,method));
throw new InvalidSignatureException(err.toString());
}
}
/**
* Search the list of parameters for first one matching the role specified.
*
* @param role
* the role to look for
* @return the index for the role specified (or -1 if not found)
*/
protected int findIndexForRole(Role role)
{
Param param = findParamForRole(role);
if (param != null)
{
return param.index;
}
return -1;
}
/**
* Find first param for specified role.
*
* @param role
* the role specified
* @return the param (or null if not found)
*/
protected Param findParamForRole(Role role)
{
for (Param param : params)
{
if (param.role == role)
{
return param;
}
}
return null;
}
public Param[] getParams()
{
return params;
}
public void init(JsrSession session)
{
// Default for the session.
// Session is an optional parameter (always)
idxSession = findIndexForRole(Param.Role.SESSION);
if (idxSession >= 0)
{
args[idxSession] = session;
}
// Optional EndpointConfig
idxConfig = findIndexForRole(Param.Role.ENDPOINT_CONFIG);
if (idxConfig >= 0)
{
args[idxConfig] = session.getEndpointConfig();
}
// Default for the path parameters
// PathParam's are optional parameters (always)
Map<String, String> pathParams = session.getPathParameters();
if ((pathParams != null) && (pathParams.size() > 0))
{
for (Param param : params)
{
if (param.role == Role.PATH_PARAM)
{
int idx = param.index;
String rawvalue = pathParams.get(param.getPathParamName());
Decoder decoder = session.getDecoderFactory().getDecoderFor(param.type);
if (decoder instanceof Decoder.Text<?>)
{
Decoder.Text<?> textDecoder = (Decoder.Text<?>)decoder;
try
{
args[idx] = textDecoder.decode(rawvalue);
}
catch (DecodeException e)
{
session.notifyError(e);
}
}
else
{
throw new InvalidWebSocketException("PathParam decoders must use Decoder.Text");
}
}
}
}
}
public abstract void setDecoderClass(Class<? extends Decoder> decoderClass);
}