View Javadoc
1   /*
2    * Licensed to The Apereo Foundation under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional
4    * information regarding copyright ownership.
5    *
6    *
7    * The Apereo Foundation licenses this file to you under the Educational
8    * Community License, Version 2.0 (the "License"); you may not use this file
9    * except in compliance with the License. You may obtain a copy of the License
10   * at:
11   *
12   *   http://opensource.org/licenses/ecl2.txt
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   *
20   */
21  
22  package org.opencastproject.adopter.registration;
23  
24  import org.apache.http.HttpResponse;
25  import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
26  import org.apache.http.client.methods.HttpPost;
27  import org.apache.http.entity.StringEntity;
28  import org.apache.http.impl.client.CloseableHttpClient;
29  import org.apache.http.impl.client.HttpClientBuilder;
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  
33  import java.io.BufferedReader;
34  import java.io.IOException;
35  import java.io.InputStream;
36  import java.io.InputStreamReader;
37  import java.net.URI;
38  import java.net.URL;
39  import java.nio.charset.StandardCharsets;
40  
41  /**
42   * Contains methods for sending statistic data via rest.
43   */
44  public class AdopterRegistrationSender {
45  
46    /** The logger */
47    private static final Logger logger = LoggerFactory.getLogger(AdopterRegistrationSender.class);
48  
49    /** The base URL for the external server where the data will be send to */
50    private String baseUrl;
51  
52    // The suffixes for the base statistic server URL
53    // they determine to which REST endpoint the data will be sent
54    private static final String GENERAL_DATA_URL_SUFFIX = "api/1.0/adopter";
55    private static final String STATISTIC_URL_SUFFIX = "api/1.0/statistic";
56  
57    private static final String EXTRA_URL_INFIX = "api/1.0";
58  
59    //================================================================================
60    // Constructor
61    //================================================================================
62  
63    /**
64     * Simple Constructor that requires the URL of the statistic server.
65     * @param statisticServerBaseUrl The URL prefix of the statistic server.
66     */
67    public AdopterRegistrationSender(String statisticServerBaseUrl) {
68      if (!statisticServerBaseUrl.endsWith("/")) {
69        statisticServerBaseUrl += "/";
70      }
71      this.baseUrl = statisticServerBaseUrl;
72    }
73  
74    //================================================================================
75    // Methods
76    //================================================================================
77  
78    /**
79     * Executes the 'send' method with the proper REST URL suffix.
80     * @param json The data which shall be sent.
81     * @throws IOException General exception that can occur while sending the data.
82     */
83    public void sendGeneralData(String json) throws IOException  {
84      send(json, GENERAL_DATA_URL_SUFFIX);
85    }
86  
87    /**
88     * Deletes the adopter data
89     * @param json The data which shall be sent.
90     * @throws IOException General exception that can occur while sending the data.
91     */
92    public void deleteGeneralData(String json) throws IOException  {
93      send(json, GENERAL_DATA_URL_SUFFIX, "DELETE");
94    }
95  
96    /**
97     * Executes the 'send' method with the proper REST URL suffix.
98     * @param json The data which shall be sent.
99     * @throws IOException General exception that can occur while sending the data.
100    */
101   public void sendStatistics(String json) throws IOException {
102     send(json, STATISTIC_URL_SUFFIX);
103   }
104 
105   /**
106    * Executes the 'send' method with the proper REST URL suffix.
107    * @param key The key for the extra data.
108    * @param json The data which shall be sent.
109    * @throws IOException General exception that can occur while sending the data.
110    */
111   public void sendExtraData(String key, String json) throws IOException {
112     send(json, EXTRA_URL_INFIX + "/" + key);
113   }
114 
115   /**
116    * Deletes the statistics data
117    * @param json The data which shall be sent.
118    * @throws IOException General exception that can occur while sending the data.
119    */
120   public void deleteStatistics(String json) throws IOException {
121     send(json, STATISTIC_URL_SUFFIX, "DELETE");
122   }
123 
124 
125   /**
126    * Sends the JSON string via post request.
127    * @param json The JSON string that has to be send.
128    * @param urlSuffix The url suffix determines to which rest endpoint the data will be send.
129    * @throws IOException General exception that can occur while processing the POST request.
130    */
131   private void send(String json, String urlSuffix) throws IOException {
132     send(json, urlSuffix, "GET");
133   }
134 
135   /**
136    * Sends the JSON string via post request.
137    * @param json The JSON string that has to be send.
138    * @param urlSuffix The url suffix determines to which rest endpoint the data will be send.
139    * @param method The HTTP method to send to the server with.  Hint: Try DELETE
140    * @throws IOException General exception that can occur while processing the POST request.
141    */
142   private void send(String json, String urlSuffix, String method) throws IOException {
143     try (CloseableHttpClient client = HttpClientBuilder.create().useSystemProperties().build()) {
144       String url = new URL(baseUrl + urlSuffix).toString();
145       HttpEntityEnclosingRequestBase request = null;
146       if ("DELETE".equals(method)) {
147         request = new HttpDeleteWithEntity(url);
148       } else {
149         request = new HttpPost(url);
150       }
151       request.addHeader("Content-Type", "application/json; utf-8");
152       request.addHeader("Accept", "application/json");
153       request.setEntity(new StringEntity(json, StandardCharsets.UTF_8));
154 
155       HttpResponse resp = client.execute(request);
156       int httpStatus = resp.getStatusLine().getStatusCode();
157       boolean errorOccurred = httpStatus < 200 || httpStatus > 299;
158       InputStream responseStream = resp.getEntity().getContent();
159 
160       try (BufferedReader br = new BufferedReader(new InputStreamReader(responseStream, StandardCharsets.UTF_8))) {
161         StringBuilder response = new StringBuilder();
162         String responseLine;
163         while ((responseLine = br.readLine()) != null) {
164           response.append(responseLine.trim());
165         }
166         if (errorOccurred) {
167           String errorMessage = String.format("HttpStatus: %s, HttpResponse: %s", httpStatus, response);
168           throw new RuntimeException(errorMessage);
169         }
170       }
171     }
172   }
173 
174   //This custom class is here because HttpDelete doesn't accept entities, which is needed by the server
175   static class HttpDeleteWithEntity extends HttpEntityEnclosingRequestBase {
176 
177     public static final String METHOD_NAME = "DELETE";
178 
179     HttpDeleteWithEntity(final String uri) {
180       super();
181       setURI(URI.create(uri));
182     }
183 
184     @Override
185     public String getMethod() {
186       return METHOD_NAME;
187     }
188   }
189 
190 }