blob: c2b103dc1ab183d522b0347d91a0b2d011652227 [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.stanbol.enhancer.nlp.json.writer;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import javax.servlet.ServletContext;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import org.apache.felix.scr.annotations.Reference;
import org.apache.stanbol.enhancer.nlp.json.AnalyzedTextSerializer;
import org.apache.stanbol.enhancer.nlp.json.valuetype.ValueTypeSerializer;
import org.apache.stanbol.enhancer.nlp.model.AnalysedText;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* JAX-RS {@link MessageBodyWriter} for {@link AnalysedText} that works
* within Apache Stanbol <code>commons.web.base</code> as well as outside
* of an OSGI environment.<p>
* This implementation depends on the {@link AnalyzedTextSerializer} service.
* This dependency is initialised as follows:<ul>
* <li> via a {@link Reference} annotation on the member
* <li> via the {@link ServletContext} by using the {@link AnalyzedTextSerializer}
* class name as attribute name
* <li> via a OSGI {@link BundleContext} by obtaining the {@link BundleContext}
* from the {@link ServletContext} by using the {@link BundleContext} class name
* as attribute name. This is the way Stanbol currently uses)
* <li> via the {@link AnalyzedTextSerializer#getDefaultInstance()}. This is
* the expected way to initialize outside an OSGI environment.
* </ul>
* Users can also directly set the {@link #serializer} instance in sub-classes.
* To access the {@link #serializer} the {@link #getSerializer()} method should
* be used.
* @author Rupert Westenthaler
*
*/
@Provider
@Produces(value=MediaType.APPLICATION_JSON)
public class AnalyzedTextWriter implements MessageBodyWriter<AnalysedText> {
Logger log = LoggerFactory.getLogger(AnalyzedTextWriter.class);
@Context
protected ServletContext servletContext;
/**
* The serializer (might be lazy initialised in case injection via
* {@link Reference} does not work
*/
@Reference
protected AnalyzedTextSerializer serializer;
/**
* Getter for the {@link AnalyzedTextSerializer}. If {@link #serializer} is
* not yet initialised (meaning that the {@link Reference} annotation has
* no effect) this tries to (1) get the service via the {@link #servletContext}
* (2) get a {@link BundleContext} via the {@link #servletContext} and than the
* service from the {@link BundleContext} and (3) obtain the default instance
* using {@link AnalyzedTextSerializer#getDefaultInstance()}. <p>
* When running within OSGI (3) could be problematic as some
* {@link ValueTypeSerializer} might not get registered through to
* classpath issues.
* @return the {@link AnalyzedTextSerializer} instance
*/
protected final AnalyzedTextSerializer getSerializer(){
if(serializer == null){
synchronized (this) {
if(serializer != null){ //check again because of concurrency
return serializer;
}
//(1) try to init directly get the service via the servlet context
Object s = servletContext.getAttribute(AnalyzedTextSerializer.class.getName());
if(s != null && s instanceof AnalyzedTextSerializer){
serializer = (AnalyzedTextSerializer)s;
return serializer;
}
//(2) try to init via BundleContext available in the servlet context
Object bc = servletContext.getAttribute(BundleContext.class.getName());
if(bc != null && bc instanceof BundleContext){
ServiceReference reference = ((BundleContext)bc).getServiceReference(
AnalyzedTextSerializer.class.getName());
if(reference != null){
serializer = (AnalyzedTextSerializer)((BundleContext)bc).getService(reference);
return serializer;
}
}
//(3) get the default instance
serializer = AnalyzedTextSerializer.getDefaultInstance();
}
}
return serializer;
}
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return AnalysedText.class.isAssignableFrom(type);
}
@Override
public long getSize(AnalysedText t, Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
return -1;
}
@Override
public void writeTo(AnalysedText at, Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String,Object> httpHeaders, OutputStream entityStream)
throws IOException, WebApplicationException {
String charsetName = mediaType.getParameters().get("charset");
Charset charset = null;
if(charsetName != null){
try {
charset = Charset.forName(charsetName);
} catch (IllegalCharsetNameException e) {
log.warn("Unable to use charset defined by the parsed MediaType '"
+ mediaType+"! Fallback to default (UTF-8).",e);
} catch (UnsupportedCharsetException e){
log.warn("Charset defined by the parsed MediaType '"+mediaType
+" is not supported! Fallback to default (UTF-8).",e);
}
}
getSerializer().serialize(at, entityStream, charset);
}
}