00001
00002
00003 #include "YosokumoRequest.h"
00004 #include "StringUtil.h"
00005
00006 using namespace Yosokumo;
00007
00008
00009 std::vector<uint8_t> YosokumoRequest::emptyEntity;
00010
00011 YosokumoRequest::YosokumoRequest(
00012 const Credentials &credentials,
00013 const std::string &hostName,
00014 int port,
00015 const std::string &contentType)
00016 {
00017 this->trace = false;
00018
00019 this->credentials = credentials;
00020 this->hostName = hostName;
00021 this->port = port;
00022 this->contentType = contentType;
00023
00024 initForOperation();
00025
00026 emptyEntity.clear();
00027 }
00028
00029 void YosokumoRequest::initForOperation()
00030 {
00031 auxHeaderName = "";
00032 auxHeaderValue = "";
00033 statusCode = 0;
00034 entity.clear();
00035 exception = ServiceException();
00036 }
00037
00038 void YosokumoRequest::setCredentials(Credentials credentials)
00039 {
00040 this->credentials = credentials;
00041 }
00042
00043 void YosokumoRequest::setAuxHeader(
00044 const std::string &name,
00045 const std::string &value)
00046 {
00047 auxHeaderName = name;
00048 auxHeaderValue = value;
00049 }
00050
00051 void YosokumoRequest::setTrace(bool traceOn)
00052 {
00053 this->trace = traceOn;
00054 }
00055
00056 bool YosokumoRequest::getTrace()
00057 {
00058 return trace;
00059 }
00060
00061 int YosokumoRequest::getStatusCode()
00062 {
00063 return statusCode;
00064 }
00065
00066 void YosokumoRequest::getEntity(std::vector<uint8_t> &putEntityHere)
00067 {
00068 putEntityHere = entity;
00069 }
00070
00071 bool YosokumoRequest::isException()
00072 {
00073 return YosokumoDIF::isException(exception);
00074 }
00075
00076 ServiceException YosokumoRequest::getException()
00077 {
00078 return exception;
00079 }
00080
00081
00082
00083 bool YosokumoRequest::getFromServer(const std::string &resourceUri)
00084 {
00085 std::string uri = normalizeResourceUri(resourceUri, hostName, port);
00086
00087 return makeRequest(1, "getFromServer");
00088
00089 }
00090
00091 bool YosokumoRequest::postToServer(
00092 const std::string &resourceUri,
00093 const std::vector<uint8_t> &entityToPost)
00094 {
00095 std::string uri = normalizeResourceUri(resourceUri, hostName, port);
00096 return makeRequest(2, "postToServer", entityToPost);
00097
00098 }
00099
00100 bool YosokumoRequest::deleteFromServer(const std::string &resourceUri)
00101 {
00102 std::string uri = normalizeResourceUri(resourceUri, hostName, port);
00103
00104 return makeRequest(3, "deleteFromServer");
00105
00106 }
00107
00108 bool YosokumoRequest::putToServer(
00109 const std::string &resourceUri,
00110 const std::vector<uint8_t> &entityToPost)
00111 {
00112 std::string uri = normalizeResourceUri(resourceUri, hostName, port);
00113
00114 return makeRequest(4, "putToServer", entityToPost);
00115
00116 }
00117
00118
00119
00120 bool YosokumoRequest::makeRequest(
00121 HttpRequestBase httpRequest,
00122 const std::string &traceName,
00123 const std::vector<uint8_t> &entityToSend)
00124 {
00125 #if 0 //??? patch out
00126 if (trace)
00127 {
00128 System.out.println(traceName+":");
00129 System.out.println(credentials.toString());
00130 }
00131
00132 statusCode = 0;
00133 entity = null;
00134 exception = null;
00135
00136
00137
00138 httpRequest.addHeader("Host", hostName);
00139 httpRequest.addHeader("Date", DateUtils.formatDate(new Date()));
00140 httpRequest.addHeader("Accept", contentType);
00141
00142 if (auxHeaderName != null && !auxHeaderName.isEmpty())
00143 {
00144 httpRequest.addHeader(auxHeaderName, auxHeaderValue);
00145 auxHeaderName = null;
00146 auxHeaderValue = null;
00147 }
00148
00149 if (entityToSend != null)
00150 {
00151 httpRequest.addHeader("Content-Type", contentType);
00152 httpRequest.addHeader("Content-Length",
00153 Integer.toString(entityToSend.length));
00154 }
00155
00156 std::string requestDigest = makeDigest(httpRequest);
00157 if (requestDigest == null)
00158 return false;
00159
00160 httpRequest.addHeader("Authorization", "yosokumo " +
00161 credentials.getUserId() + ":" + requestDigest);
00162
00163 if (entityToSend != null)
00164 {
00165
00166
00167
00168
00169
00170
00171 httpRequest.removeHeaders("Content-Length");
00172 ByteArrayEntity baEntity = new ByteArrayEntity(entityToSend);
00173 ((HttpEntityEnclosingRequestBase)httpRequest).setEntity(baEntity);
00174 }
00175
00176 if (trace)
00177 {
00178 System.out.println(" Request:");
00179 System.out.println(" Request line: " +
00180 httpRequest.getRequestLine());
00181 HeaderIterator it = httpRequest.headerIterator(null);
00182 while (it.hasNext())
00183 System.out.println(" " + it.next());
00184 }
00185
00186
00187
00188 return getResponse(httpRequest, traceName);
00189 #endif
00190 return false;
00191
00192 }
00193
00194 bool YosokumoRequest::getResponse(HttpRequestBase httpRequest, const std::string &traceName)
00195 {
00196 #if 0 //???
00197 HttpClient httpclient = new DefaultHttpClient();
00198
00199 try
00200 {
00201 HttpResponse response = httpclient.execute(httpRequest);
00202
00203 statusCode = response.getStatusLine().getStatusCode();
00204
00205 HttpEntity theEntity = response.getEntity();
00206
00207 if (theEntity != null)
00208 {
00209 int contentLen = (int)theEntity.getContentLength();
00210
00211 if (contentLen < 0)
00212 {
00213
00214 final int BUFF_SIZE = 16384;
00215 byte [] buffer = new byte[BUFF_SIZE];
00216 int totalBytesRead = 0;
00217 InputStream is = theEntity.getContent();
00218 while (true)
00219 {
00220 if (totalBytesRead == buffer.length)
00221 {
00222 byte [] tempArray = new byte[4*buffer.length];
00223 System.arraycopy(buffer, 0, tempArray, 0,
00224 totalBytesRead);
00225 buffer = tempArray;
00226 }
00227
00228 int numRead = is.read(buffer, totalBytesRead,
00229 buffer.length-totalBytesRead);
00230 if (numRead == -1)
00231 break;
00232 totalBytesRead += numRead;
00233 }
00234 if (totalBytesRead > 0)
00235 {
00236 entity = new byte[totalBytesRead];
00237 System.arraycopy(buffer, 0, entity, 0, totalBytesRead);
00238 }
00239 }
00240
00241 if (contentLen >= 0)
00242 {
00243
00244 entity = new byte[contentLen];
00245 InputStream is = theEntity.getContent();
00246 int offset = 0;
00247 while (contentLen > 0)
00248 {
00249 int numRead = is.read(entity, offset, contentLen);
00250 if (numRead == -1)
00251 break;
00252 offset += numRead;
00253 contentLen -= numRead;
00254 }
00255 if (contentLen > 0)
00256 {
00257 exception = new ServiceException("Attempt to read " +
00258 "last " + contentLen + " bytes of entity failed");
00259 return false;
00260 }
00261 }
00262 }
00263 if (trace)
00264 {
00265 System.out.println(" Response:");
00266 System.out.println(" Status line: " +
00267 response.getStatusLine());
00268 HeaderIterator it = response.headerIterator(null);
00269 while (it.hasNext())
00270 System.out.println(" " + it.next());
00271 }
00272
00273 }
00274 catch (IOException e)
00275 {
00276 exception = new ServiceException("Fatal transport error in " +
00277 traceName, e);
00278 return false;
00279 }
00280 finally
00281 {
00282
00283
00284
00285
00286 httpclient.getConnectionManager().shutdown();
00287 }
00288
00289 return true;
00290 #endif
00291 return false;
00292
00293 }
00294
00295 std::string YosokumoRequest::normalizeResourceUri(
00296 const std::string &resourceUri,
00297 const std::string &hostName,
00298 int port)
00299 {
00300 std::stringstream s;
00301 s << port;
00302 std::string portAsString = s.str();
00303
00304 std::string scheme = "http://";
00305
00306 if (startsWith(resourceUri, scheme))
00307 {
00308 std::string schemeHostName = scheme + hostName;
00309 if (!startsWith(resourceUri, schemeHostName))
00310 return resourceUri;
00311 int len = schemeHostName.length();
00312 return (resourceUri.substr(0, len) + ":" + portAsString +
00313 resourceUri.substr(len));
00314 }
00315
00316 std::string newUri = "http://";
00317
00318 if (!startsWith(resourceUri, hostName))
00319 newUri.append(hostName + ":" + portAsString);
00320
00321 newUri.append(resourceUri);
00322
00323 return newUri;
00324 }
00325
00326 std::string YosokumoRequest::makeDigest(HttpRequestBase request)
00327 {
00328 #if 0 //???
00329 std::string requestString = makeRequestString(request);
00330
00331 if (trace)
00332 System.out.println(" requestString: " + requestString);
00333
00334 std::string requestDigest;
00335
00336 try
00337 {
00338 requestDigest = DigestRequest.makeDigest(requestString,
00339 credentials.getKey());
00340 }
00341 catch (ServiceException e)
00342 {
00343 exception = e;
00344 requestDigest = null;
00345 }
00346
00347 return requestDigest;
00348 #endif
00349 return "";
00350
00351 }
00352
00353 std::string YosokumoRequest::makeRequestString(HttpRequestBase r)
00354 {
00355 #if 0
00356 StringBuilder s = new StringBuilder();
00357 Header h;
00358
00359 s.append(r.getRequestLine().getMethod());
00360 appendHeaderValue(r, "Host", s);
00361 s.append("+" + r.getURI().getPath());
00362 appendHeaderValue(r, "Date", s);
00363 appendHeaderValue(r, "Content-Type", s);
00364 appendHeaderValue(r, "Content-Length", s);
00365 appendHeaderValue(r, "Content-Encoding", s);
00366 appendHeaderValue(r, "Content-MD5", s);
00367 return s.toString();
00368 #endif
00369 return "";
00370
00371 }
00372
00373 void YosokumoRequest::appendHeaderValue(
00374 HttpRequest r,
00375 const std::string &headerName,
00376 std::string &s)
00377 {
00378 #if 0 //??
00379 Header h;
00380
00381 s.append("+");
00382 h = r.getFirstHeader(headerName);
00383 if (h != null)
00384 s.append(h.getValue());
00385 #endif
00386 }
00387
00388
00389