001package org.apache.commons.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 022import java.io.IOException; 023import java.io.UnsupportedEncodingException; 024import java.net.URLEncoder; 025 026import org.apache.commons.httpclient.HttpException; 027import org.apache.commons.httpclient.HttpMethod; 028import org.apache.commons.httpclient.HttpState; 029import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; 030import org.apache.commons.httpclient.methods.PostMethod; 031import org.apache.commons.httpclient.methods.RequestEntity; 032import org.apache.commons.jcs.auxiliary.remote.behavior.IRemoteCacheDispatcher; 033import org.apache.commons.jcs.auxiliary.remote.value.RemoteCacheRequest; 034import org.apache.commons.jcs.auxiliary.remote.value.RemoteCacheResponse; 035import org.apache.commons.jcs.utils.serialization.StandardSerializer; 036import org.apache.commons.logging.Log; 037import org.apache.commons.logging.LogFactory; 038 039/** Calls the service. */ 040public class RemoteHttpCacheDispatcher 041 extends AbstractHttpClient 042 implements IRemoteCacheDispatcher 043{ 044 /** Parameter encoding */ 045 private static final String DEFAULT_ENCODING = "UTF-8"; 046 047 /** Named of the parameter */ 048 private static final String PARAMETER_REQUEST_TYPE = "RequestType"; 049 050 /** Named of the parameter */ 051 private static final String PARAMETER_KEY = "Key"; 052 053 /** Named of the parameter */ 054 private static final String PARAMETER_CACHE_NAME = "CacheName"; 055 056 /** The Logger. */ 057 private static final Log log = LogFactory.getLog( RemoteHttpCacheDispatcher.class ); 058 059 /** This needs to be standard, since the other side is standard */ 060 private StandardSerializer serializer = new StandardSerializer(); 061 062 /** 063 * @param remoteHttpCacheAttributes 064 */ 065 public RemoteHttpCacheDispatcher( RemoteHttpCacheAttributes remoteHttpCacheAttributes ) 066 { 067 super( remoteHttpCacheAttributes ); 068 } 069 070 /** 071 * All requests will go through this method. 072 * <p> 073 * TODO consider taking in a URL instead of using the one in the configuration. 074 * <p> 075 * @param remoteCacheRequest 076 * @return RemoteCacheResponse 077 * @throws IOException 078 */ 079 @Override 080 public <K, V, T> 081 RemoteCacheResponse<T> dispatchRequest( RemoteCacheRequest<K, V> remoteCacheRequest ) 082 throws IOException 083 { 084 try 085 { 086 byte[] requestAsByteArray = serializer.serialize( remoteCacheRequest ); 087 088 String url = addParameters( remoteCacheRequest, getRemoteHttpCacheAttributes().getUrl() ); 089 090 byte[] responseAsByteArray = processRequest( requestAsByteArray, url ); 091 092 RemoteCacheResponse<T> remoteCacheResponse = null; 093 try 094 { 095 remoteCacheResponse = serializer.deSerialize( responseAsByteArray, null ); 096 } 097 catch ( ClassNotFoundException e ) 098 { 099 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}