root/trunk/src/java/org/jcoderz/commons/connector/http/transport/HttpClientConnectionImpl.java

Revision 1011, 24.2 kB (checked in by amandel, 4 years ago)

Aligned svn keyword settings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 *
4 * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 *    * Redistributions of source code must retain the above copyright
11 *      notice, this list of conditions and the following disclaimer.
12 *    * Redistributions in binary form must reproduce the above
13 *      copyright notice, this list of conditions and the following
14 *      disclaimer in the documentation and/or other materials
15 *      provided with the distribution.
16 *    * Neither the name of the jCoderZ.org Project nor the names of
17 *      its contributors may be used to endorse or promote products
18 *      derived from this software without specific prior written
19 *      permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33package org.jcoderz.commons.connector.http.transport;
34
35import java.io.IOException;
36import java.io.InputStream;
37import java.net.ConnectException;
38import java.security.KeyStore;
39import java.util.HashMap;
40import java.util.Iterator;
41import java.util.Map;
42import java.util.logging.Level;
43import java.util.logging.Logger;
44
45import org.apache.commons.httpclient.Header;
46import org.apache.commons.httpclient.HostConfiguration;
47import org.apache.commons.httpclient.HttpClient;
48import org.apache.commons.httpclient.HttpConnection;
49import org.apache.commons.httpclient.HttpConnectionManager;
50import org.apache.commons.httpclient.HttpException;
51import org.apache.commons.httpclient.SimpleHttpConnectionManager;
52import org.apache.commons.httpclient.URI;
53import org.apache.commons.httpclient.URIException;
54import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
55import org.apache.commons.httpclient.methods.PostMethod;
56import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
57import org.apache.commons.httpclient.protocol.Protocol;
58import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
59import org.jcoderz.commons.ArgumentMalformedException;
60import org.jcoderz.commons.util.Assert;
61import org.jcoderz.commons.util.Constants;
62import org.jcoderz.commons.util.HexUtil;
63import org.jcoderz.commons.util.StringUtil;
64
65
66
67/**
68 * This class implements the HttpConnectionInterface using the Jakarta
69 * commons-httpclient library.
70 *
71 */
72public class HttpClientConnectionImpl
73      implements HttpClientConnection
74{
75   /** The class name used for logging */
76   private static final String CLASSNAME
77         = HttpClientConnectionImpl.class.getName();
78   /** The logger in use */
79   private static final Logger logger
80         = Logger.getLogger(CLASSNAME);
81   /** The default port used for SSL connections */
82   private static final int DEFAULT_SSL_PORT = 443;
83   /** Constant for line feed. */
84   private static final String LINE_FEED = "\n";
85   /** Constant for the HTTP result code 200 */
86   private static final int HTTP_RESULT_OK = 200;
87   /** Contant for the HTTP result code 300 */
88   private static final int HTTP_REDIRECT = 300;
89   /** Constant for the HTTP result code 400 */
90   private static final int HTTP_BAD_REQUEST = 400;
91   /** Constant for the HTTP result code 500 */
92   private static final int HTTP_INTERNAL_SERVER_ERROR = 500;
93   /** The HttpClient defined in the 3rd party library. */
94   private HttpClient mHttpClient;
95   /** The HostConfiguration defined in the 3rd party library. */
96   private HostConfiguration mHostConfiguration;
97   /** The PostMethod defined in the 3rd party library. */
98   private PostMethod mPostMethod;
99   /** The state identifying the current step of the HTTP send/receive
100      process. */
101   /** Input stream for the request message used for the httpclient */
102   private InputStream mRequestBodyInputStream = null;
103   /** Content length of the request message */
104   private int mRequestContentLength = 0;
105   /** Flag indicating if the content length has been set via interface method.
106       If false the content length will be calculated by the httpclient. */
107   private boolean mIsRequestContentLengthSet = false;
108   /** Content type of the request message */
109   private String mRequestContentType = null;
110   /** Current state of the httpclient. Used to check the correct usage of the
111       interface methods defined within HttpClientConnection interface. */
112   private HttpConnectionState mState
113         = HttpConnectionState.CONNECTION_NOT_ESTABLISHED;
114   /** Keystore filename used for SSL connections. Used to load the keystore
115       from the filesystem if not given within interface method. */
116   private String mKeyStoreFilename = null;
117   /** Keystore password used for SSL connection. */
118   private String mKeyStorePassword = null;
119   /** Truststore filename used for SSL connections. Used to load the truststore
120       from the filesystem if not given within interface method. */
121   private String mTrustStoreFilename = null;
122   /** Truststore password used for SSL connection. */
123   private String mTrustStorePassword = null;
124   /** Keystore used for SSL connections obtained via interface method. */
125   private KeyStore mKeyStore = null;
126   private KeyStore mTrustStore = null;
127   /** Key alias of the sending system used for SSL connections. */
128   private String mKeyAlias = null;
129   /** Key password of the used key. */
130   private String mKeyAliasPassword = null;
131   /** Path used to load the keystore from file system if not given within
132       interface method calls. */
133   private String mPath = null;
134
135   private HttpConnectorEventListener mHttpEventListener = null;
136   private ConnectorContext mConnectorContext = null;
137   private HttpRequestResponseHeader mRequestResponseHeader = null;
138
139   /** {@inheritDoc} */
140   public void establishConnection (
141      String uriAsString,
142      int connectTimeout,
143      int readTimeout)
144   {
145      Assert.notNull(uriAsString, "uriAsString");
146      mHostConfiguration = new HostConfiguration();
147      mPostMethod = new PostMethod();
148
149      URI uri;
150      try
151      {
152         uri = new URI(uriAsString, false);
153         mPath = uri.getPathQuery();
154         mPostMethod.setPath(mPath);
155
156         final String scheme = uri.getScheme();
157         if (scheme != null && scheme.toLowerCase(Constants.SYSTEM_LOCALE).
158               equals("https"))
159         {
160            SslSocketFactory sslFactory = null;
161            if (mKeyStore != null && mTrustStore != null)
162            {
163               // using the keystore given from signature service
164               sslFactory = new SslSocketFactory(
165                     mKeyStore, mTrustStore, mKeyAlias, mKeyAliasPassword);
166            }
167            else
168            {
169               // using a keystore loading from file system
170               sslFactory = new SslSocketFactory(
171                     mKeyStoreFilename, mKeyStorePassword,
172                     mTrustStoreFilename, mTrustStorePassword,
173                     mKeyAlias, mKeyAliasPassword);
174            }
175            final Protocol https
176                  = new Protocol(
177                        "https",
178                        (ProtocolSocketFactory) sslFactory,
179                        DEFAULT_SSL_PORT);
180            int port = uri.getPort();
181            if (port == -1)
182            {
183               port = DEFAULT_SSL_PORT;
184            }
185            final String host = uri.getHost();
186            mHostConfiguration.setHost(host, port, https);
187         }
188         else
189         {
190            mHostConfiguration.setHost(uri);
191         }
192      }
193      catch (URIException ue)
194      {
195         final ArgumentMalformedException ame = new ArgumentMalformedException(
196            "uriAsString", uriAsString, ue.getMessage(), ue);
197         throw ame;
198      }
199      catch (IllegalArgumentException iae)
200      {
201         final ArgumentMalformedException ame = new ArgumentMalformedException(
202            "uriAsString", uriAsString, iae.getMessage(), iae);
203         throw ame;
204      }
205      mHttpClient = new HttpClient();
206
207      final SimpleHttpConnectionManager connectionManager
208            = new SimpleHttpConnectionManager();
209      final HttpConnectionManagerParams httpParams
210            = new HttpConnectionManagerParams();
211      httpParams.setConnectionTimeout(connectTimeout);
212      httpParams.setSoTimeout(readTimeout);
213      connectionManager.setParams(httpParams);
214      mHttpClient.setHttpConnectionManager(connectionManager);
215      mState = HttpConnectionState.CONNECTION_ESTABLISHED;
216   }
217
218   /** {@inheritDoc} */
219   public void releaseConnection ()
220   {
221      if (mState == HttpConnectionState.CONNECTION_RELEASED)
222      {
223         return;
224      }
225      if (mState != HttpConnectionState.CONNECTION_ESTABLISHED
226            && mState != HttpConnectionState.CONNECTION_EXECUTED)
227      {
228         final IllegalStateException ile = new IllegalStateException(
229               "Connection must be established before");
230         throw ile;
231      }
232      mPostMethod.releaseConnection();
233
234      // depcrecated and will be removed in future releases
235      mPostMethod.recycle();
236      mState = HttpConnectionState.CONNECTION_RELEASED;
237   }
238
239   /** {@inheritDoc} */
240   public void closeConnection ()
241   {
242      if (mState != HttpConnectionState.CONNECTION_ESTABLISHED
243            && mState != HttpConnectionState.CONNECTION_EXECUTED
244            && mState != HttpConnectionState.CONNECTION_RELEASED)
245      {
246         final IllegalStateException ile = new IllegalStateException(
247               "Connection must be established before");
248         throw ile;
249      }
250      final HttpConnectionManager connManager
251         = mHttpClient.getHttpConnectionManager();
252      final HttpConnection connection
253         = connManager.getConnection(mHostConfiguration);
254      connection.close();
255      mState = HttpConnectionState.CONNECTION_CLOSED;
256   }
257
258   /** {@inheritDoc} */
259   public void execute ()
260         throws HttpConnectionException
261   {
262      assertStateForExecute();
263      setRequestHeader();
264      mPostMethod.setRequestEntity(getRequestEntity());
265
266      // reassign the path to the previously released post method
267      if (mState == HttpConnectionState.CONNECTION_RELEASED)
268      {
269         mPostMethod.setPath(mPath);
270      }
271      //  dump request
272      if (logger.isLoggable(Level.FINEST))
273      {
274         dumpRequestHeader();
275      }
276      int resultCode = 0;
277      try
278      {
279         doCallbackRequestSend();
280         resultCode = mHttpClient.executeMethod(
281               mHostConfiguration, mPostMethod);
282         doCallbackResponseReceived(resultCode, getResponseBody());
283      }
284      catch (HttpException he)
285      {
286         final HttpConnectionException hce = new HttpConnectionException(
287               he.getMessage(), he);
288         throw hce;
289      }
290      catch (ConnectException ce)
291      {
292         final HttpConnectConnectionException hce
293               = new HttpConnectConnectionException(ce.getMessage(), ce);
294         throw hce;
295      }
296      catch (IOException ioe)
297      {
298         handleIOExceptionWhilstExecute(ioe);
299      }
300      // dump response
301      if (logger.isLoggable(Level.FINEST))
302      {
303         dumpResponse();
304      }
305
306      assertResultCode(resultCode);
307      assertResponseHeader();
308      mState = HttpConnectionState.CONNECTION_EXECUTED;
309   }
310
311   private void assertStateForExecute ()
312   {
313      if (mState != HttpConnectionState.CONNECTION_ESTABLISHED
314            && mState != HttpConnectionState.CONNECTION_RELEASED)
315      {
316         final IllegalStateException ile = new IllegalStateException(
317               "Connection must be established before or released");
318         throw ile;
319      }
320   }
321
322   private void handleIOExceptionWhilstExecute (
323         IOException ioe)
324         throws HttpConnectionException
325   {
326      final String message = ioe.getMessage().toLowerCase(
327            Constants.SYSTEM_LOCALE);
328      HttpConnectionException hce;
329      if (message.equals("read timed out"))
330      {
331         hce = new HttpTimeoutConnectionException(ioe.getMessage(), ioe);
332      }
333      else
334      {
335         hce = new HttpConnectionException(ioe.getMessage(), ioe);
336      }
337      throw hce;
338   }
339
340   /** {@inheritDoc} */
341   public void setRequestBody (InputStream in)
342   {
343      mRequestBodyInputStream = in;
344   }
345
346   /** {@inheritDoc} */
347   public byte[] getResponseBody ()
348         throws HttpEmptyResponseException
349   {
350      final byte[] result;
351      try
352      {
353         result = mPostMethod.getResponseBody();
354      }
355      catch (IOException ioe)
356      {
357         final HttpEmptyResponseException ere
358               = new HttpEmptyResponseException(
359                     "IOException while obtaining response body", ioe);
360         throw ere;
361      }
362
363      if (result == null || result.length == 0)
364      {
365         final HttpEmptyResponseException ere
366            = new HttpEmptyResponseException(
367               "Received empty http body in response");
368         throw ere;
369      }
370      return result;
371   }
372
373   /** {@inheritDoc} */
374   public String getResponseHeader (String key)
375   {
376      String result = null;
377      final Header header = mPostMethod.getResponseHeader(key);
378
379      if (header != null)
380      {
381         result = (header.getElements())[0].getName();
382      }
383      return result;
384   }
385
386   /** {@inheritDoc} */
387   public void initSsl (
388         String keyAlias,
389         String keyAliasPassword)
390   {
391      Assert.notNull(keyAlias, "keyAlias");
392      Assert.notNull(keyAliasPassword, "keyAliasPassword");
393      mKeyStoreFilename = System.getProperty(
394            "javax.net.ssl.keyStore");
395      mKeyStorePassword = System.getProperty(
396            "javax.net.ssl.keyStorePassword");
397      mTrustStoreFilename = System.getProperty(
398            "javax.net.ssl.trustStore");
399      mTrustStorePassword = System.getProperty(
400            "javax.net.ssl.trustStorePassword");
401      mKeyStore = null;
402      mTrustStore = null;
403      mKeyAlias = keyAlias;
404      mKeyAliasPassword = keyAliasPassword;
405   }
406
407   /** {@inheritDoc} */
408   public void initSsl (
409         KeyStore keyStore,
410         KeyStore trustStore,
411         String keyAlias,
412         String keyAliasPassword)
413   {
414      Assert.notNull(keyStore, "keyStore");
415      Assert.notNull(trustStore, "trustStore");
416      Assert.notNull(keyAlias, "keyAlias");
417      Assert.notNull(keyAliasPassword, "keyAliasPassword");
418      mKeyStore = keyStore;
419      mTrustStore = trustStore;
420      mKeyAlias = keyAlias;
421      mKeyAliasPassword = keyAliasPassword;
422   }
423
424   /** {@inheritDoc} */
425   public void setEventListener (HttpConnectorEventListener listener,
426         ConnectorContext context)
427   {
428      mHttpEventListener = listener;
429      mConnectorContext = context;
430   }
431
432   /** {@inheritDoc} */
433   public void setRequestResponseHeader (HttpRequestResponseHeader header)
434   {
435      mRequestResponseHeader = header;
436   }
437
438   /**
439    * Prepares the InputStream including the http request for the
440    * httpclient.
441    *
442    * @return InputStreamRequestEntity the InputStream used by httpclient
443    */
444   private InputStreamRequestEntity getRequestEntity ()
445   {
446      InputStreamRequestEntity entity = null;
447      if (mIsRequestContentLengthSet && mRequestContentType != null)
448      {
449         entity = new InputStreamRequestEntity(mRequestBodyInputStream,
450            mRequestContentLength, mRequestContentType);
451      }
452      else if (mIsRequestContentLengthSet)
453      {
454         entity = new InputStreamRequestEntity(mRequestBodyInputStream,
455               mRequestContentLength);
456      }
457      else if (mRequestContentType != null)
458      {
459         entity = new InputStreamRequestEntity(mRequestBodyInputStream,
460               mRequestContentType);
461      }
462      else
463      {
464         entity = new InputStreamRequestEntity(mRequestBodyInputStream);
465      }
466      return entity;
467   }
468
469   /**
470    * Sets the request header included in the HttpRequestResponseHeader object.
471    */
472   private void setRequestHeader ()
473   {
474      if (mRequestResponseHeader != null)
475      {
476         final Map header
477               = new HashMap(mRequestResponseHeader.getRequestHeader());
478         if (!header.containsKey("Content-Type"))
479         {
480            // default Content-Type
481            header.put("Content-Type", "text/xml; charset=ISO-8859-1");
482         }
483         for (final Iterator it = header.keySet().iterator(); it.hasNext();)
484         {
485            final String key = (String) it.next();
486            final String value = (String) header.get(key);
487            mPostMethod.setRequestHeader(key, value);
488
489            if (key.equals("Content-Length"))
490            {
491               setRequestContentLength(Integer.parseInt(value));
492            }
493            else if (key.equals("Content-Type"))
494            {
495               mRequestContentType = value;
496            }
497         }
498      }
499   }
500
501   /**
502    * Sets the content lenght of the request.
503    * @param contentLength the length to set
504    */
505   private void setRequestContentLength (int contentLength)
506   {
507      mRequestContentLength = contentLength;
508      mIsRequestContentLengthSet = true;
509   }
510
511   /**
512    * Checks the http status code in the response message.
513    * Throws appropriate HttpConnectionException if result code is
514    * not 200 (OK).
515    *
516    * @param resultCode the http result code received in response
517    * @throws HttpConnectionException to indicate failure on http level
518    */
519   private void assertResultCode (int resultCode)
520         throws HttpConnectionException
521   {
522      if (resultCode != HTTP_RESULT_OK)
523      {
524         HttpConnectionException hce;
525         if (resultCode >= HTTP_BAD_REQUEST
526               && resultCode < HTTP_INTERNAL_SERVER_ERROR)
527         {  // HTTP 4xx
528            hce = new HttpClientConnectionException(
529                     "HTTP Result Code of range 4xx in response",
530                     null);
531         }
532         else if (resultCode >= HTTP_INTERNAL_SERVER_ERROR)
533         {  // HTTP 5xx
534            hce = new HttpServerConnectionException(
535                     "HTTP Result Code of range 5xx in response",
536                     null);
537         }
538         else if (resultCode >= HTTP_REDIRECT
539               && resultCode < HTTP_BAD_REQUEST)
540         {  // HTTP 3xx
541            hce = new HttpServerConnectionException(
542                     "HTTP redirect not supported",
543                     null);
544         }
545         else
546         {
547            hce = new HttpServerConnectionException(
548                     "Unsupported HTTP Result Code in response",
549                     null);
550         }
551         hce.setStatusCode(resultCode);
552         hce.setHttpMessage(StringUtil.asciiToString(getResponseBody()));
553
554         throw hce;
555      }
556   }
557
558   /**
559    * Checks if the received http header in response match the
560    * response header defined in the given HttpRequestResponseHeader object.
561    *
562    * @throws HttpInvalidResponseHeaderException if one or more header
563    *          values are not like expected
564    */
565   private void assertResponseHeader ()
566         throws HttpInvalidResponseHeaderException
567   {
568      if (mRequestResponseHeader != null)
569      {
570         logger.finest(mRequestResponseHeader.toString());
571         final Map expectedResponseHeader
572               = mRequestResponseHeader.getResponseHeader();
573         final StringBuffer message = new StringBuffer();
574         final Map invalidHeaders = new HashMap();
575         for (final Iterator it = expectedResponseHeader.keySet().iterator();
576               it.hasNext();)
577         {
578            final String key = (String) it.next();
579            final String value = (String) expectedResponseHeader.get(key);
580            final String responseValue = getResponseHeader(key);
581            if (responseValue == null)
582            {
583               if (message.length() == 0)
584               {
585                  message.append("One or more invalid header");
586                  message.append(" values detected in response:\n");
587               }
588               message.append("Expected response header <");
589               message.append(key);
590               message.append("> not received\n");
591               invalidHeaders.put(key, null);
592            }
593            else if (!responseValue.equalsIgnoreCase(value))
594            {
595               if (message.length() == 0)
596               {
597                  message.append("One or more invalid header");
598                  message.append(" values detected in response:\n");
599               }
600               message.append("Value for <");
601               message.append(key);
602               message.append("> is '");
603               message.append(responseValue);
604               message.append("' expected was '");
605               message.append(value);
606               message.append("'\n");
607               invalidHeaders.put(key, responseValue);
608            }
609         } // end for
610
611         if (message.length() != 0)
612         {
613            final HttpInvalidResponseHeaderException ihe
614                  = new HttpInvalidResponseHeaderException(
615                        message.toString(), invalidHeaders);
616
617            try
618            {
619               ihe.setHttpMessage(HexUtil.dump(mPostMethod.getResponseBody()));
620            }
621            catch (IOException ignore)
622            {
623               // ignore
624            }
625            throw ihe;
626         }
627      }
628      else
629      {
630         logger.finest("No response header for validating set");
631      }
632   }
633
634   private void doCallbackRequestSend ()
635   {
636      if (mHttpEventListener != null)
637      {
638         mHttpEventListener.requestSend(mConnectorContext);
639      }
640   }
641
642   private void doCallbackResponseReceived (int resultCode, byte[] responseData)
643   {
644      if (mHttpEventListener != null)
645      {
646         mHttpEventListener.responseReceived(
647               resultCode, responseData, mConnectorContext);
648      }
649   }
650
651   /**
652    * Dumps the request message.
653    */
654   private void dumpRequestHeader ()
655   {
656      final StringBuffer dumpBuffer = new StringBuffer();
657      dumpBuffer.append("\n-------------------------DUMP REQUEST HEADER---\n");
658      dumpBuffer.append("Host: ");
659      dumpBuffer.append(mHostConfiguration.getHost());
660      dumpBuffer.append(LINE_FEED);
661      dumpBuffer.append("Port: ");
662      dumpBuffer.append(mHostConfiguration.getPort());
663      dumpBuffer.append(LINE_FEED);
664      dumpBuffer.append("Path: ");
665      dumpBuffer.append(mPostMethod.getPath());
666      dumpBuffer.append(LINE_FEED);
667      dumpBuffer.append(LINE_FEED);
668      dumpBuffer.append("Header:\n");
669      final Header[] headers = mPostMethod.getRequestHeaders();
670      for (int i = 0; i < headers.length; i++)
671      {
672         final String header = headers[i].toString();
673         dumpBuffer.append(header);
674      }
675      dumpBuffer.append(LINE_FEED);
676      dumpBuffer.append("-----------------------------------------");
677      logger.finest(dumpBuffer.toString());
678   }
679
680   /**
681    * Dumps the response message.
682    */
683   private void dumpResponse ()
684   {
685      final StringBuffer dumpBuffer = new StringBuffer();
686      dumpBuffer.append("\n-------------------------DUMP RESPONSE---\n");
687      dumpBuffer.append("StatusLine: ");
688      dumpBuffer.append(mPostMethod.getStatusLine().toString());
689      dumpBuffer.append(LINE_FEED);
690      dumpBuffer.append(LINE_FEED);
691      dumpBuffer.append("Header:\n");
692      final Header[] headers = mPostMethod.getResponseHeaders();
693      for (int i = 0; i < headers.length; i++)
694      {
695         final String header = headers[i].toString();
696         dumpBuffer.append(header);
697      }
698      dumpBuffer.append(LINE_FEED);
699      dumpBuffer.append("Body: \n");
700      byte[] response = null;
701      try
702      {
703         response = mPostMethod.getResponseBody();
704      }
705      catch (IOException ignore)
706      {
707         // ignore
708      }
709      if (response != null)
710      {
711         dumpBuffer.append(HexUtil.dump(response));
712      }
713      else
714      {
715         dumpBuffer.append("no response body available");
716      }
717      dumpBuffer.append(LINE_FEED);
718      dumpBuffer.append("-----------------------------------------");
719      logger.finest(dumpBuffer.toString());
720   }
721}
Note: See TracBrowser for help on using the browser.