001 package org.apache.jcs.auxiliary.remote.http.client;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 import java.io.IOException;
023 import java.io.Serializable;
024 import java.io.UnsupportedEncodingException;
025 import java.net.URLEncoder;
026
027 import org.apache.commons.httpclient.HttpException;
028 import org.apache.commons.httpclient.HttpMethod;
029 import org.apache.commons.httpclient.HttpState;
030 import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
031 import org.apache.commons.httpclient.methods.PostMethod;
032 import org.apache.commons.httpclient.methods.RequestEntity;
033 import org.apache.commons.logging.Log;
034 import org.apache.commons.logging.LogFactory;
035 import org.apache.jcs.auxiliary.remote.behavior.IRemoteCacheDispatcher;
036 import org.apache.jcs.auxiliary.remote.value.RemoteCacheRequest;
037 import org.apache.jcs.auxiliary.remote.value.RemoteCacheResponse;
038 import org.apache.jcs.utils.serialization.StandardSerializer;
039
040 /** Calls the service. */
041 public class RemoteHttpCacheDispatcher
042 extends AbstractHttpClient
043 implements IRemoteCacheDispatcher
044 {
045 /** Named of the parameter */
046 private static final String PARAMETER_REQUEST_TYPE = "RequestType";
047
048 /** Named of the parameter */
049 private static final String PARAMETER_KEY = "Key";
050
051 /** Named of the parameter */
052 private static final String PARAMETER_CACHE_NAME = "CacheName";
053
054 /** The Logger. */
055 private final static Log log = LogFactory.getLog( RemoteHttpCacheDispatcher.class );
056
057 /** This needs to be standard, since the other side is standard */
058 private StandardSerializer serializer = new StandardSerializer();
059
060 /**
061 * @param remoteHttpCacheAttributes
062 */
063 public RemoteHttpCacheDispatcher( RemoteHttpCacheAttributes remoteHttpCacheAttributes )
064 {
065 super( remoteHttpCacheAttributes );
066 }
067
068 /**
069 * All requests will go through this method.
070 * <p>
071 * TODO consider taking in a URL instead of using the one in the configuration.
072 * <p>
073 * @param remoteCacheRequest
074 * @return RemoteCacheResponse
075 * @throws IOException
076 */
077 public <K extends Serializable, V extends Serializable, T>
078 RemoteCacheResponse<T> dispatchRequest( RemoteCacheRequest<K, V> remoteCacheRequest )
079 throws IOException
080 {
081 try
082 {
083 byte[] requestAsByteArray = serializer.serialize( remoteCacheRequest );
084
085 String url = addParameters( remoteCacheRequest, getRemoteHttpCacheAttributes().getUrl() );
086
087 byte[] responseAsByteArray = processRequest( requestAsByteArray, url );
088
089 RemoteCacheResponse<T> remoteCacheResponse = null;
090 try
091 {
092 remoteCacheResponse = serializer.deSerialize( responseAsByteArray );
093 }
094 catch ( ClassNotFoundException e )
095 {
096 log.error( "Couldn't deserialize the response.", e );
097 }
098 return remoteCacheResponse;
099 }
100 catch ( Exception e )
101 {
102 log.error( "Problem dispatching request.", e );
103 throw new IOException( e.getMessage() );
104 }
105 }
106
107 /**
108 * @param requestAsByteArray
109 * @param url
110 * @return byte[] - the response
111 * @throws IOException
112 * @throws HttpException
113 */
114 protected byte[] processRequest( byte[] requestAsByteArray, String url )
115 throws IOException, HttpException
116 {
117 PostMethod post = new PostMethod( url );
118 RequestEntity requestEntity = new ByteArrayRequestEntity( requestAsByteArray );
119 post.setRequestEntity( requestEntity );
120 doWebserviceCall( post );
121 byte[] response = post.getResponseBody();
122 return response;
123 }
124
125 /**
126 * @param remoteCacheRequest
127 * @param baseUrl
128 * @return String
129 */
130 protected <K extends Serializable, V extends Serializable> String addParameters( RemoteCacheRequest<K, V> remoteCacheRequest, String baseUrl )
131 {
132 StringBuffer url = new StringBuffer( baseUrl );
133
134 try
135 {
136 if ( baseUrl != null && ( baseUrl.indexOf( "?" ) == -1 ) )
137 {
138 url.append( "?" );
139 }
140 else
141 {
142 url.append( "&" );
143 }
144
145 if ( getRemoteHttpCacheAttributes().isIncludeCacheNameAsParameter() )
146 {
147 if ( remoteCacheRequest.getCacheName() != null )
148 {
149 url.append( PARAMETER_CACHE_NAME + "="
150 + URLEncoder.encode( remoteCacheRequest.getCacheName(), "UTF-8" ) );
151 }
152 }
153 if ( getRemoteHttpCacheAttributes().isIncludeKeysAndPatternsAsParameter() )
154 {
155 String keyValue = "";
156 switch ( remoteCacheRequest.getRequestType() )
157 {
158 case GET:
159 keyValue = remoteCacheRequest.getKey() + "";
160 break;
161 case REMOVE:
162 keyValue = remoteCacheRequest.getKey() + "";
163 break;
164 case GET_MATCHING:
165 keyValue = remoteCacheRequest.getPattern();
166 break;
167 case GET_MULTIPLE:
168 keyValue = remoteCacheRequest.getKeySet() + "";
169 break;
170 case GET_GROUP_KEYS:
171 keyValue = remoteCacheRequest.getKey() + "";
172 break;
173 case GET_GROUP_NAMES:
174 keyValue = remoteCacheRequest.getKey() + "";
175 break;
176 case UPDATE:
177 keyValue = remoteCacheRequest.getCacheElement().getKey() + "";
178 break;
179 default:
180 break;
181 }
182 String encodedKeyValue = URLEncoder.encode( keyValue, "UTF-8" );
183 url.append( "&" + PARAMETER_KEY + "=" + encodedKeyValue );
184 }
185 if ( getRemoteHttpCacheAttributes().isIncludeRequestTypeasAsParameter() )
186 {
187 url.append( "&"
188 + PARAMETER_REQUEST_TYPE
189 + "="
190 + URLEncoder.encode( remoteCacheRequest.getRequestType().toString(), "UTF-8" ) );
191 }
192 }
193 catch ( UnsupportedEncodingException e )
194 {
195 log.error( "Couldn't encode URL.", e );
196 }
197
198 if ( log.isDebugEnabled() )
199 {
200 log.debug( "Url: " + url.toString() );
201 }
202
203 return url.toString();
204 }
205
206 /**
207 * Called before the executeMethod on the client.
208 * <p>
209 * @param post http method
210 * @return HttpState
211 * @throws IOException
212 */
213 @Override
214 public HttpState preProcessWebserviceCall( HttpMethod post )
215 throws IOException
216 {
217 // do nothing. Child can override.
218 return null;
219 }
220
221 /**
222 * Called after the executeMethod on the client.
223 * <p>
224 * @param post http method
225 * @param httpState state
226 * @throws IOException
227 */
228 @Override
229 public void postProcessWebserviceCall( HttpMethod post, HttpState httpState )
230 throws IOException
231 {
232 // do nothing. Child can override.
233 }
234 }