package org.odata4j.producer.resources;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
@Provider
@Consumes(ODataBatchProvider.MULTIPART_MIXED)
public class ODataBatchProvider implements MessageBodyReader<List<BatchBodyPart>> {
@Context
HttpHeaders httpHeaders;
@Context
UriInfo uriInfo;
public enum HTTP_METHOD {
GET,
PUT,
POST,
MERGE,
DELETE
};
public static final String MULTIPART_MIXED = "multipart/mixed";
public static String createResponseBodyPart(BatchBodyPart bodyPart, Response response) {
final String CONTENT_ID = "Content-ID";
StringBuilder body = new StringBuilder("\nHTTP/1.1 ");
Status status = Response.Status.fromStatusCode(response.getStatus());
body.append(status.getStatusCode());
body.append(' ');
body.append(status.getReasonPhrase());
body.append('\n');
if (bodyPart.getHeaders().containsKey(CONTENT_ID)) {
body.append(CONTENT_ID);
body.append(": ");
body.append(bodyPart.getHeaders().getFirst(CONTENT_ID));
body.append('\n');
}
for (String key : response.getMetadata().keySet()) {
body.append(key).append(": ");
for (Object value : response.getMetadata().get(key)) {
body.append(value).append(";");
}
body.append('\n');
}
body.append('\n');
if (response.getEntity() != null) {
body.append(response.getEntity().toString());
}
body.append('\n');
return body.toString();
}
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] antns, MediaType mt) {
if (genericType instanceof ParameterizedType) {
for (Type gType : ((ParameterizedType) genericType).getActualTypeArguments()) {
if (gType == BatchBodyPart.class && type == List.class) {
return true;
}
}
}
return false;
}
@Override
public List<BatchBodyPart> readFrom(
Class<List<BatchBodyPart>> type,
Type genericType,
Annotation[] antns,
MediaType mt,
MultivaluedMap<String, String> mm,
InputStream inputStream) throws IOException, WebApplicationException {
List<BatchBodyPart> parts = new ArrayList<BatchBodyPart>();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
final String ContentType = "content-type:";
String currentLine = "";
while ((currentLine = br.readLine()) != null) {
if (currentLine.toLowerCase().startsWith(ContentType)) {
String ctype = currentLine.substring(ContentType.length()).trim();
if (ctype.toLowerCase().startsWith("application/http")) {
parts.add(parseBodyPart(br));
}
}
}
br.close();
return parts;
}
private BatchBodyPart parseBodyPart(BufferedReader br) throws IOException {
BatchBodyPart block = new BatchBodyPart(httpHeaders, uriInfo);
final int SKIP_CONTENT_BEGIN = 2;
String line = "";
while ((line = br.readLine()) != null) {
if (line.equals("")) {
continue;
}
if (line.startsWith("--")) {
return validateBodyPart(block);
}
if (block.getHttpMethod() == null) {
for (HTTP_METHOD method : HTTP_METHOD.values()) {
if (line.startsWith(method.name())) {
String uri = line.substring(method.name().length() + 1);
int lastIdx = uri.lastIndexOf(" ");
if (lastIdx != -1) {
uri = uri.substring(0, lastIdx);
}
block.setHttpMethod(method);
block.setUri(uri);
break;
}
}
} else {
Integer idx = line.indexOf(':');
String key = line.substring(0, idx);
String value = line.substring(idx + 1).trim();
block.getHeaders().putSingle(key, value);
if (key.toLowerCase().equals("content-length")) {
int capacity = Integer.parseInt(value) - SKIP_CONTENT_BEGIN;
char[] buf = new char[capacity];
int offset = 0;
br.skip(SKIP_CONTENT_BEGIN);
while (offset != capacity) {
offset += br.read(buf, offset, capacity - offset);
}
block.setEntity(new String(buf));
return validateBodyPart(block);
}
}
}
throw new IllegalArgumentException("Cann't parse block");
}
private static BatchBodyPart validateBodyPart(BatchBodyPart block) {
if (block.getHttpMethod() == null ? "" == null : block.getHttpMethod().toString().equals("")) {
throw new IllegalArgumentException("Block HTTP METHOD is empty.");
}
if (block.getUri() == null ? "" == null : block.getUri().equals("")) {
throw new IllegalArgumentException("Block URI is empty.");
}
return block;
}
}