View Javadoc

1   /*
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.hadoop.hbase.rest.provider.producer;
22  
23  import java.io.ByteArrayOutputStream;
24  import java.io.IOException;
25  import java.io.OutputStream;
26  import java.lang.annotation.Annotation;
27  import java.lang.reflect.Type;
28  
29  import javax.ws.rs.Produces;
30  import javax.ws.rs.WebApplicationException;
31  import javax.ws.rs.core.MediaType;
32  import javax.ws.rs.core.MultivaluedMap;
33  import javax.ws.rs.ext.MessageBodyWriter;
34  import javax.ws.rs.ext.Provider;
35  
36  import org.apache.hadoop.hbase.rest.Constants;
37  import org.apache.hadoop.hbase.rest.ProtobufMessageHandler;
38  
39  /**
40   * An adapter between Jersey and ProtobufMessageHandler implementors. Hooks up
41   * protobuf output producing methods to the Jersey content handling framework.
42   * Jersey will first call getSize() to learn the number of bytes that will be
43   * sent, then writeTo to perform the actual I/O.
44   */
45  @Provider
46  @Produces({Constants.MIMETYPE_PROTOBUF, Constants.MIMETYPE_PROTOBUF_IETF})
47  public class ProtobufMessageBodyProducer
48    implements MessageBodyWriter<ProtobufMessageHandler> {
49  
50    private ThreadLocal<byte[]> buffer = new ThreadLocal<byte[]>();
51  
52  	@Override
53  	public boolean isWriteable(Class<?> type, Type genericType, 
54  	  Annotation[] annotations, MediaType mediaType) {
55        return ProtobufMessageHandler.class.isAssignableFrom(type);
56    }
57  
58  	@Override
59  	public long getSize(ProtobufMessageHandler m, Class<?> type, Type genericType,
60  	    Annotation[] annotations, MediaType mediaType) {
61  	  ByteArrayOutputStream baos = new ByteArrayOutputStream();
62  	  try {
63  	    baos.write(m.createProtobufOutput());
64  	  } catch (IOException e) {
65  	    return -1;
66  	  }
67  	  byte[] bytes = baos.toByteArray();
68  	  buffer.set(bytes);
69  	  return bytes.length;
70  	}
71  
72  	public void writeTo(ProtobufMessageHandler m, Class<?> type, Type genericType,
73  	    Annotation[] annotations, MediaType mediaType, 
74  	    MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) 
75  	    throws IOException, WebApplicationException {
76      byte[] bytes = buffer.get();
77  	  entityStream.write(bytes);
78      buffer.remove();
79  	}
80  }