View Javadoc
1   package org.apache.commons.jcs.auxiliary.remote.http.client;
2   
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,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.io.UnsupportedEncodingException;
24  import java.net.URLEncoder;
25  
26  import org.apache.commons.httpclient.HttpException;
27  import org.apache.commons.httpclient.HttpMethod;
28  import org.apache.commons.httpclient.HttpState;
29  import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
30  import org.apache.commons.httpclient.methods.PostMethod;
31  import org.apache.commons.httpclient.methods.RequestEntity;
32  import org.apache.commons.jcs.auxiliary.remote.behavior.IRemoteCacheDispatcher;
33  import org.apache.commons.jcs.auxiliary.remote.value.RemoteCacheRequest;
34  import org.apache.commons.jcs.auxiliary.remote.value.RemoteCacheResponse;
35  import org.apache.commons.jcs.utils.serialization.StandardSerializer;
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  
39  /** Calls the service. */
40  public class RemoteHttpCacheDispatcher
41      extends AbstractHttpClient
42      implements IRemoteCacheDispatcher
43  {
44      /** Parameter encoding */
45      private static final String DEFAULT_ENCODING = "UTF-8";
46  
47      /** Named of the parameter */
48      private static final String PARAMETER_REQUEST_TYPE = "RequestType";
49  
50      /** Named of the parameter */
51      private static final String PARAMETER_KEY = "Key";
52  
53      /** Named of the parameter */
54      private static final String PARAMETER_CACHE_NAME = "CacheName";
55  
56      /** The Logger. */
57      private static final Log log = LogFactory.getLog( RemoteHttpCacheDispatcher.class );
58  
59      /** This needs to be standard, since the other side is standard */
60      private StandardSerializer serializer = new StandardSerializer();
61  
62      /**
63       * @param remoteHttpCacheAttributes
64       */
65      public RemoteHttpCacheDispatcher( RemoteHttpCacheAttributes remoteHttpCacheAttributes )
66      {
67          super( remoteHttpCacheAttributes );
68      }
69  
70      /**
71       * All requests will go through this method.
72       * <p>
73       * TODO consider taking in a URL instead of using the one in the configuration.
74       * <p>
75       * @param remoteCacheRequest
76       * @return RemoteCacheResponse
77       * @throws IOException
78       */
79      @Override
80      public <K, V, T>
81          RemoteCacheResponse<T> dispatchRequest( RemoteCacheRequest<K, V> remoteCacheRequest )
82          throws IOException
83      {
84          try
85          {
86              byte[] requestAsByteArray = serializer.serialize( remoteCacheRequest );
87  
88              String url = addParameters( remoteCacheRequest, getRemoteHttpCacheAttributes().getUrl() );
89  
90              byte[] responseAsByteArray = processRequest( requestAsByteArray, url );
91  
92              RemoteCacheResponse<T> remoteCacheResponse = null;
93              try
94              {
95                  remoteCacheResponse = serializer.deSerialize( responseAsByteArray, null );
96              }
97              catch ( ClassNotFoundException e )
98              {
99                  log.error( "Couldn't deserialize the response.", e );
100             }
101             return remoteCacheResponse;
102         }
103         catch ( Exception e )
104         {
105             throw new IOException("Problem dispatching request.", e);
106         }
107     }
108 
109     /**
110      * @param requestAsByteArray
111      * @param url
112      * @return byte[] - the response
113      * @throws IOException
114      * @throws HttpException
115      */
116     protected byte[] processRequest( byte[] requestAsByteArray, String url )
117         throws IOException, HttpException
118     {
119         PostMethod post = new PostMethod( url );
120         RequestEntity requestEntity = new ByteArrayRequestEntity( requestAsByteArray );
121         post.setRequestEntity( requestEntity );
122         doWebserviceCall( post );
123         byte[] response = post.getResponseBody();
124         return response;
125     }
126 
127     /**
128      * @param remoteCacheRequest
129      * @param baseUrl
130      * @return String
131      */
132     protected <K, V> String addParameters( RemoteCacheRequest<K, V> remoteCacheRequest, String baseUrl )
133     {
134         StringBuilder url = new StringBuilder( baseUrl == null ? "" : baseUrl );
135 
136         try
137         {
138             if ( baseUrl != null && baseUrl.indexOf( "?" ) == -1 )
139             {
140                 url.append( "?" );
141             }
142             else
143             {
144                 url.append( "&" );
145             }
146 
147             if ( getRemoteHttpCacheAttributes().isIncludeCacheNameAsParameter() )
148             {
149                 if ( remoteCacheRequest.getCacheName() != null )
150                 {
151                     url.append( PARAMETER_CACHE_NAME + "="
152                         + URLEncoder.encode( remoteCacheRequest.getCacheName(), DEFAULT_ENCODING ) );
153                 }
154             }
155             if ( getRemoteHttpCacheAttributes().isIncludeKeysAndPatternsAsParameter() )
156             {
157                 String keyValue = "";
158                 switch ( remoteCacheRequest.getRequestType() )
159                 {
160                     case GET:
161                     case REMOVE:
162                     case GET_KEYSET:
163                         keyValue = remoteCacheRequest.getKey() + "";
164                         break;
165                     case GET_MATCHING:
166                         keyValue = remoteCacheRequest.getPattern();
167                         break;
168                     case GET_MULTIPLE:
169                         keyValue = remoteCacheRequest.getKeySet() + "";
170                         break;
171                     case UPDATE:
172                         keyValue = remoteCacheRequest.getCacheElement().getKey() + "";
173                         break;
174                     default:
175                         break;
176                 }
177                 String encodedKeyValue = URLEncoder.encode( keyValue, DEFAULT_ENCODING );
178                 url.append( "&" + PARAMETER_KEY + "=" + encodedKeyValue );
179             }
180             if ( getRemoteHttpCacheAttributes().isIncludeRequestTypeasAsParameter() )
181             {
182                 url.append( "&"
183                     + PARAMETER_REQUEST_TYPE
184                     + "="
185                     + URLEncoder.encode( remoteCacheRequest.getRequestType().toString(), DEFAULT_ENCODING ) );
186             }
187         }
188         catch ( UnsupportedEncodingException e )
189         {
190             log.error( "Couldn't encode URL.", e );
191         }
192 
193         if ( log.isDebugEnabled() )
194         {
195             log.debug( "Url: " + url.toString() );
196         }
197 
198         return url.toString();
199     }
200 
201     /**
202      * Called before the executeMethod on the client.
203      * <p>
204      * @param post http method
205      * @return HttpState
206      * @throws IOException
207      */
208     @Override
209     protected HttpState preProcessWebserviceCall( HttpMethod post )
210         throws IOException
211     {
212         // do nothing. Child can override.
213         return null;
214     }
215 
216     /**
217      * Called after the executeMethod on the client.
218      * <p>
219      * @param post http method
220      * @param httpState state
221      * @throws IOException
222      */
223     @Override
224     protected void postProcessWebserviceCall( HttpMethod post, HttpState httpState )
225         throws IOException
226     {
227         // do nothing. Child can override.
228     }
229 }