View Javadoc

1   /*
2    * SymmetricDS is an open source database synchronization solution.
3    *   
4    * Copyright (C) Chris Henson <chenson42@users.sourceforge.net>
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 3 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, see
18   * <http://www.gnu.org/licenses/>.
19   */
20  
21  package org.jumpmind.symmetric.transport.http;
22  
23  import java.io.BufferedReader;
24  import java.io.BufferedWriter;
25  import java.io.IOException;
26  import java.io.OutputStream;
27  import java.io.OutputStreamWriter;
28  import java.net.HttpURLConnection;
29  import java.net.URL;
30  import java.util.zip.GZIPOutputStream;
31  
32  import javax.servlet.http.HttpServletResponse;
33  
34  import org.apache.commons.io.IOUtils;
35  import org.jumpmind.symmetric.common.Constants;
36  import org.jumpmind.symmetric.transport.AuthenticationException;
37  import org.jumpmind.symmetric.transport.ConnectionRejectedException;
38  import org.jumpmind.symmetric.transport.IOutgoingWithResponseTransport;
39  
40  public class HttpOutgoingTransport implements IOutgoingWithResponseTransport {
41  
42      private URL url;
43  
44      private BufferedWriter writer;
45  
46      private BufferedReader reader;
47  
48      private HttpURLConnection connection;
49  
50      private int httpTimeout;
51  
52      private boolean useCompression;
53  
54      public HttpOutgoingTransport(URL url, int httpTimeout, boolean useCompression) {
55          this.url = url;
56          this.httpTimeout = httpTimeout;
57          this.useCompression = useCompression;
58      }
59  
60      public void close() throws IOException {
61          closeWriter();
62          closeReader();
63          if (connection != null) {
64              connection.disconnect();
65              connection = null;
66          }
67      }
68  
69      private void closeReader() throws IOException {
70          if (reader != null) {
71              IOUtils.closeQuietly(reader);
72              reader = null;
73          }
74      }
75  
76      private void closeWriter() throws IOException {
77          if (writer != null) {
78              writer.flush();
79              IOUtils.closeQuietly(writer);
80              writer = null;
81          }
82      }
83  
84      /***
85       * Before streaming data to the remote node, make sure it is ok to. We have
86       * found that we can be more efficient on a push by relying on HTTP
87       * keep-alive.
88       * 
89       * @throws IOException
90       * @throws {@link ConnectionRejectedException}
91       * @throws {@link AuthenticationException}
92       */
93      private void requestReservation() throws IOException {
94          HttpURLConnection c = (HttpURLConnection) url.openConnection();
95          c.setUseCaches(false);
96          c.setConnectTimeout(httpTimeout);
97          c.setReadTimeout(httpTimeout);
98          c.setRequestMethod("HEAD");
99          analyzeResponseCode(c.getResponseCode());
100     }
101 
102     public BufferedWriter open() throws IOException {
103         requestReservation();
104         connection = (HttpURLConnection) url.openConnection();
105         connection.setDoInput(true);
106         connection.setDoOutput(true);
107         connection.setUseCaches(false);
108         connection.setConnectTimeout(httpTimeout);
109         connection.setReadTimeout(httpTimeout);
110         connection.setRequestMethod("PUT");
111         connection.setRequestProperty("accept-encoding", "gzip");
112         if (useCompression) {
113             connection.addRequestProperty("Content-Type", "gzip"); // application/x-gzip?
114         }
115         OutputStream out = connection.getOutputStream();
116         if (useCompression) {
117             out = new GZIPOutputStream(out);
118         }
119         OutputStreamWriter wout = new OutputStreamWriter(out, Constants.ENCODING);
120         writer = new BufferedWriter(wout);
121         return writer;
122     }
123 
124     /***
125      * @throws {@link ConnectionRejectedException}
126      * @throws {@link AuthenticationException}
127      */
128     private void analyzeResponseCode(int code) throws IOException {
129         if (HttpServletResponse.SC_SERVICE_UNAVAILABLE == code) {
130             throw new ConnectionRejectedException();
131         } else if (HttpServletResponse.SC_FORBIDDEN == code) {
132             throw new AuthenticationException();
133         }
134     }
135 
136     public BufferedReader readResponse() throws IOException {
137         closeWriter();
138         analyzeResponseCode(connection.getResponseCode());
139         this.reader = HttpTransportManager.getReaderFrom(connection);
140         return this.reader;
141     }
142 
143     public boolean isOpen() {
144         return connection != null;
145     }
146 
147 }