View Javadoc

1   /*
2    * Copyright 2003-2008 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * You are receiving this code free of charge, which represents many hours of
17   * effort from other individuals and corporations.  As a responsible member 
18   * of the community, you are asked (but not required) to donate any 
19   * enhancements or improvements back to the community under a similar open 
20   * source license.  Thank you. -TMN
21   */
22  package groovyx.net.http;
23  
24  import java.io.IOException;
25  
26  import org.apache.http.Header;
27  import org.apache.http.HeaderElement;
28  import org.apache.http.HttpEntity;
29  import org.apache.http.HttpException;
30  import org.apache.http.HttpRequest;
31  import org.apache.http.HttpRequestInterceptor;
32  import org.apache.http.HttpResponse;
33  import org.apache.http.HttpResponseInterceptor;
34  import org.apache.http.protocol.HttpContext;
35  
36  /**
37   * Base class for handing content-encoding.  
38   * @author <a href='mailto:tnichols@enernoc.com'>Tom Nichols</a>
39   */
40  public abstract class ContentEncoding {
41  
42  	public static final String ACCEPT_ENC_HDR = "Accept-Encoding";
43  	public static final String CONTENT_ENC_HDR = "Content-Encoding";
44  
45  	protected abstract String getContentEncoding();
46  	protected abstract HttpEntity wrapResponseEntity( HttpEntity raw );
47  
48  	public HttpRequestInterceptor getRequestInterceptor() {
49  		return new RequestInterceptor();
50  	}
51  	
52  	public HttpResponseInterceptor getResponseInterceptor() {
53  		return new ResponseInterceptor();
54  	}
55  	
56  	/**
57  	 * Enumeration of common content-encodings.
58  	 */
59  	public static enum Type {
60  		GZIP,
61  		COMPRESS,
62  		DEFLATE;
63  
64  		/** Prints the value as it should appear in an HTTP header */
65  		@Override public String toString() {
66  			return this.name().toLowerCase();
67  		}
68  	}
69  	
70  	/**
71  	 * Request interceptor that adds the correct <code>Accept</code> header
72  	 * to the outgoing request.
73  	 * @author <a href='mailto:tnichols@enernoc.com'>Tom Nichols</a>
74  	 */
75  	protected class RequestInterceptor implements HttpRequestInterceptor {
76  		public void process( final HttpRequest req,
77  				final HttpContext context ) throws HttpException, IOException {
78  			
79  			// set the Accept-Encoding header:
80  			String encoding = getContentEncoding();			
81  			if ( !req.containsHeader( ACCEPT_ENC_HDR ) )
82  				req.addHeader( ACCEPT_ENC_HDR, encoding );
83  
84  			else {
85  				StringBuilder values = new StringBuilder();
86  				for ( Header h : req.getHeaders( ACCEPT_ENC_HDR ) )
87  					values.append( h.getValue() ).append( "," );
88  
89  				String encList = (!values.toString().contains( encoding )) ? values
90  						.append( encoding ).toString()
91  						: values.toString().substring( 0, values.lastIndexOf( "," ) );
92  						
93  				req.setHeader( ACCEPT_ENC_HDR, encList );
94  			}
95  
96  			//TODO compress request and add content-encoding header.
97  		}
98  	}
99  
100 	/**
101 	 * Response interceptor that filters the response stream to decode the 
102 	 * compressed content before it is passed on to the parser.
103 	 * @author <a href='mailto:tnichols@enernoc.com'>Tom Nichols</a>
104 	 */
105 	protected class ResponseInterceptor implements HttpResponseInterceptor {
106 		public void process( final HttpResponse response, final HttpContext context ) 
107 				throws HttpException, IOException {
108 
109 			if ( hasEncoding( response, getContentEncoding() ) )
110 				response.setEntity( wrapResponseEntity( response.getEntity() ) );
111 		}
112 		
113 		protected boolean hasEncoding( final HttpResponse response, final String encoding ) {
114 			HttpEntity entity = response.getEntity();
115 			if ( entity == null ) return false;
116 			Header ceHeader = entity.getContentEncoding();
117 			if ( ceHeader == null ) return false;
118 
119 			HeaderElement[] codecs = ceHeader.getElements();
120 			for ( int i = 0; i < codecs.length; i++ )
121 				if ( encoding.equalsIgnoreCase( codecs[i].getName() ) )
122 					return true;
123 			
124 			return false;
125 		}
126 	}
127 }