blob: 7d6d1adbec7596587871170da5e98f7cbc18e7ad [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.tuscany.sca.binding.rest.provider;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.activation.DataSource;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;
import javax.xml.namespace.QName;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.core.UtilityExtensionPoint;
import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint;
import org.apache.tuscany.sca.databinding.Mediator;
import org.apache.tuscany.sca.interfacedef.DataType;
import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
import org.apache.tuscany.sca.interfacedef.util.XMLType;
/**
* A JAX-RS provider that leverages Tuscany's databinding framework to handle read/write
* for JAX-RS runtime
*/
@Provider
public abstract class DataBindingJAXRSProvider {
protected DataBindingExtensionPoint dataBindingExtensionPoint;
protected Mediator mediator;
public DataBindingJAXRSProvider(ExtensionPointRegistry registry) {
this.dataBindingExtensionPoint = registry.getExtensionPoint(DataBindingExtensionPoint.class);
UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
this.mediator = utilities.getUtility(Mediator.class);
}
protected <A extends Annotation> A getAnnotation(Annotation[] annotations, Class<A> type) {
if(annotations == null) {
return null;
}
for (Annotation a : annotations) {
if (a.annotationType() == type) {
return type.cast(a);
}
}
return null;
}
protected void introspectAnnotations(Annotation[] annotations, DataType targetDataType) {
WebResult result = getAnnotation(annotations, WebResult.class);
if (result != null) {
QName name = new QName(result.targetNamespace(), result.name());
targetDataType.setLogical(new XMLType(name, null));
}
WebParam param = getAnnotation(annotations, WebParam.class);
if (param != null) {
QName name = new QName(param.targetNamespace(), param.name());
targetDataType.setLogical(new XMLType(name, null));
}
}
protected DataType createDataType(Class<?> type, Type genericType) {
DataType dataType = new DataTypeImpl(null, type, genericType, genericType);
dataBindingExtensionPoint.introspectType(dataType, null);
return dataType;
}
protected boolean supports(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
// Some media types have parameters
mediaType = new MediaType(mediaType.getType(), mediaType.getSubtype());
return MediaType.APPLICATION_JSON_TYPE.isCompatible(mediaType) || MediaType.APPLICATION_XML_TYPE.isCompatible(mediaType)
|| MediaType.TEXT_XML_TYPE.isCompatible(mediaType);
}
protected Object convert(InputStream content, String contentType, Class<?> type) throws IOException {
if (type == DataSource.class) {
return type.cast(new InputStreamDataSource(content, contentType));
} else if (type == InputStream.class) {
return type.cast(content);
} else if (type == Reader.class) {
return type.cast(new InputStreamReader(content, "UTF-8"));
} else if (type == String.class) {
try {
StringWriter sw = new StringWriter();
InputStreamReader reader = new InputStreamReader(content, "UTF-8");
char[] buf = new char[8192];
while (true) {
int size = reader.read(buf);
if (size < 0) {
break;
}
sw.write(buf, 0, size);
}
return type.cast(sw.toString());
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
} else if (type == byte[].class) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[8192];
while (true) {
int size = content.read(buf);
if (size < 0) {
break;
}
bos.write(buf, 0, size);
}
return type.cast(bos.toByteArray());
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
} else {
return content;
}
}
protected void write(OutputStream out, Object content, Class<?> type) throws IOException {
if (content == null) {
return;
}
InputStream in = null;
if (DataSource.class.isAssignableFrom(type)) {
in = ((DataSource)content).getInputStream();
} else if (InputStream.class.isAssignableFrom(type)) {
in = (InputStream)content;
} else if (type == String.class) {
in = new ByteArrayInputStream(((String)content).getBytes("UTF-8"));
} else if (type == byte[].class) {
in = new ByteArrayInputStream((byte[])content);
}
if (in == null) {
throw new IllegalArgumentException("Type is not supported: " + type);
}
byte[] buf = new byte[8192];
while (true) {
int len = in.read(buf);
if (len < 0) {
in.close();
break;
}
out.write(buf, 0, len);
}
}
public static final class InputStreamDataSource implements DataSource {
public static final String DEFAULT_TYPE = "application/octet-stream";
private final InputStream in;
private final String ctype;
public InputStreamDataSource(InputStream in) {
this(in, null);
}
public InputStreamDataSource(InputStream in, String ctype) {
this.in = in;
this.ctype = (ctype != null) ? ctype : DEFAULT_TYPE;
}
public String getContentType() {
return ctype;
}
public String getName() {
return null;
}
public InputStream getInputStream() throws IOException {
return in;
}
public OutputStream getOutputStream() throws IOException {
return null;
}
}
}