this.next = next;
}
public Message invoke(Message msg) {
try {
HTTPContext bindingContext = (HTTPContext)msg.getBindingContext();
if(! "get".equalsIgnoreCase(bindingContext.getHttpRequest().getMethod())) {
throw new RuntimeException("RPC Invocation only allowed over HTTP GET operations");
}
String path = URLDecoder.decode(HTTPUtils.getRequestPath(bindingContext.getHttpRequest()), "UTF-8");
if (path.startsWith("/")) {
path = path.substring(1);
}
String operationName = bindingContext.getHttpRequest().getParameter("method");
Operation operation = findOperation( operationName );
if (operation == null) {
throw new RuntimeException("Invalid Operation '" + operationName + "'" );
}
final JavaOperation javaOperation = (JavaOperation)operation;
final Method method = javaOperation.getJavaMethod();
List<Object> messageParameters = new ArrayList<Object>();
for(int i=0; i<method.getParameterTypes().length; i++) {
for(Annotation annotation : method.getParameterAnnotations()[i]) {
if (annotation instanceof QueryParam) {
QueryParam queryParam = (QueryParam) annotation;
String name = queryParam.value();
String[] values = bindingContext.getHttpRequest().getParameterValues(name);
if(values.length == 1) {
//process value, making necessary map from string to expected value
Class<?> clazz = method.getParameterTypes()[i];
TypeInfo typeInfo = simpleTypeMapper.getXMLType(clazz);
Object v = simpleTypeMapper.toJavaObject(typeInfo.getQName(), values[0], null);
messageParameters.add(v);
} else {
//process value, making necessary map from string to expected value
Class<?> clazz = (method.getParameterTypes()[i]).getComponentType();
TypeInfo typeInfo = simpleTypeMapper.getXMLType(clazz);
Object objectArray = Array.newInstance(clazz, values.length);
for (int count = 0; count < values.length; ++count) {
Object v = simpleTypeMapper.toJavaObject(typeInfo.getQName(), values[count], null);
Array.set(objectArray, count, v);
}
messageParameters.add(objectArray);
}
}
}
}
Object[] body = new Object[messageParameters.size()];
messageParameters.toArray(body);
msg.setBody(body);
msg.setOperation(operation);
Message responseMessage = getNext().invoke(msg);
//set Cache-Control to no-cache to avoid intermediary
//proxy/reverse-proxy caches and always hit the server
//that would identify if the value was current or not
bindingContext.getHttpResponse().setHeader("Cache-Control", "no-cache");
bindingContext.getHttpResponse().setHeader("Expires", new Date(0).toGMTString());
String eTag = HTTPUtils.calculateHashETag(responseMessage.getBody().toString().getBytes("UTF-8"));
// Test request for predicates.
String predicate = bindingContext.getHttpRequest().getHeader( "If-Match" );
if (( predicate != null ) && ( !predicate.equals(eTag) )) {
// No match, should short circuit
bindingContext.getHttpResponse().sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
}
predicate = bindingContext.getHttpRequest().getHeader( "If-None-Match" );
if (( predicate != null ) && ( predicate.equals(eTag) )) {
// Match, should short circuit
bindingContext.getHttpResponse().sendError(HttpServletResponse.SC_NOT_MODIFIED);
}
bindingContext.getHttpResponse().addHeader("ETag", eTag);
return responseMessage;
} catch (Exception e) {
throw new RuntimeException(e);
}