bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford/*
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * The contents of this file are subject to the terms of the Common Development and
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Distribution License (the License). You may not use this file except in compliance with the
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * License.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford *
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * specific language governing permission and limitations under the License.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford *
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * When distributing Covered Software, include this CDDL Header Notice in each file and include
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Header, with the fields enclosed by brackets [] replaced by your own identifying
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * information: "Portions copyright [year] [name of copyright owner]".
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford *
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Copyright 2016 ForgeRock AS.
6b642033251d6306c85cd6a38ea40f5a9907d278Tony Bamford *
6b642033251d6306c85cd6a38ea40f5a9907d278Tony Bamford * Portions Copyright 2008 Sun Microsystems Inc.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordpackage com.sun.identity.install.tools.util;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamfordimport org.forgerock.openam.utils.StringUtils;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordimport java.io.BufferedReader;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordimport java.io.DataOutputStream;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordimport java.io.FileNotFoundException;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordimport java.io.IOException;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordimport java.io.InputStream;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordimport java.io.InputStreamReader;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordimport java.net.ConnectException;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordimport java.net.HttpURLConnection;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordimport java.net.URL;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordimport java.net.UnknownHostException;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordimport java.util.ArrayList;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordimport java.util.LinkedHashMap;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordimport java.util.List;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordimport java.util.Map;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford/**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Construct REST endpoints and call them.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamfordpublic final class RESTEndpoint {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford public static final String AUTHENTICATION_URI = "/json/{REALM}authenticate";
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public static final String AUTHENTICATION_URI_API_VERSION = "1.0";
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford public static final String CREATE_PROFILE_URI = "/json/{REALM}agents";
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public static final String CREATE_PROFILE_URI_ACTION_VALUE = "create";
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public static final String CREATE_PROFILE_URI_API_VERSION = "1.0";
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public static final String SERVER_INFO_URI = "/json/serverinfo/*";
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public static final String SERVER_INFO_URI_API_VERSION = "1.0";
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private static final String AUTH_INDEX_TYPE_NAME = "authIndexType";
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private static final String AUTH_INDEX_TYPE_VALUE = "module";
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private static final String AUTH_INDEX_VALUE_NAME = "authIndexValue";
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private static final String AUTH_INDEX_VALUE_VALUE = "Application";
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private enum HTTPMethod {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford GET, POST;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private final String path;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private final Map<String, String> parameters;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private final String postData;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private final HTTPMethod httpMethod;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private final Map<String, String> headers;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private RESTEndpoint(RESTEndpointBuilder builder) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford this.path = builder.getPath();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford this.parameters = builder.parameters;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford this.postData = builder.postData;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford this.httpMethod = builder.httpMethod;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford this.headers = builder.headers;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Call a REST endpoint, returning its response.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return RESTResponse object containing status and text of returned value.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @throws IOException
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public RESTResponse call() throws IOException {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford HttpURLConnection urlConnect = null;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford RESTResponse response = new RESTResponse();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford List<String> returnList = new ArrayList<>();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford try {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford URL serviceURL = new URL(path + paramsToString());
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford urlConnect = (HttpURLConnection) serviceURL.openConnection();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford if (httpMethod == HTTPMethod.GET) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford urlConnect.setRequestMethod("GET");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford } else {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford urlConnect.setRequestMethod("POST");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford urlConnect.setDoOutput(true);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford urlConnect.setUseCaches(false);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford if (!headers.isEmpty()) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford for (Map.Entry<String, String> entry : headers.entrySet()) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford urlConnect.setRequestProperty(entry.getKey(), entry.getValue());
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford if (httpMethod == HTTPMethod.POST) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford // post data
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford try (DataOutputStream output = new DataOutputStream(urlConnect.getOutputStream())){
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford output.writeBytes(postData);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford output.flush();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford // read response
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford response.setResponseCode(urlConnect.getResponseCode());
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford try (BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnect.getInputStream()))) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford String line;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford while ((line = reader.readLine()) != null) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford returnList.add(line);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford } catch (FileNotFoundException | UnknownHostException | ConnectException ex) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford throw ex;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford } catch (IOException ex) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford if (urlConnect != null) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford InputStream is = urlConnect.getErrorStream();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford String line;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford while((line = br.readLine()) != null) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford returnList.add(line);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford response.setContent(returnList);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return response;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Convert the parameters into a string of ?name=value&othername=othervalue
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return the parameters as a string
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private String paramsToString() {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford StringBuilder result = new StringBuilder();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford if (!parameters.isEmpty()) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford for (Map.Entry<String, String> entry : parameters.entrySet()) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford if (result.length() == 0) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append("?");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford } else {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append("&");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append(entry.getKey());
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append("=");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append(entry.getValue());
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return result.toString();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * ONLY EVER USE THIS FUNCTION FOR DEBUGGING PURPOSES. IT HIDES PASSWORDS. This obviously won't be what you
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * want in real life.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford *
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return A string representing the headers of this endpoint, with a clumsy attempt to knock out clear text
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * passwords
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private String headersToString() {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford StringBuilder result = new StringBuilder();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford for (Map.Entry<String, String> entry : headers.entrySet()) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append(entry.getKey());
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append(": ");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford if (entry.getKey().toLowerCase().contains("password")) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append("***************");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford } else {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append(entry.getValue());
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append("\n");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return result.toString();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Turn this RESTEndpoint into a string - ONLY for debugging purposes.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return a representation of this endpoint.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford @Override
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public String toString() {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford StringBuilder result = new StringBuilder();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append("path+params=");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append(path);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append(paramsToString());
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append(" method: ");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append(httpMethod.toString());
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford if (postData.length() > 0) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append(" post data ");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford if (postData.toLowerCase().contains("password")) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append(postData.length() + " bytes of POST data (hidden as it appears to contain a password)");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford } else {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append(postData);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford if (!headers.isEmpty()) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append(" headers:");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append("\n");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford result.append(headersToString());
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return result.toString();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * For a little less than total debugging, try this:
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return The path of the endpoint
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public String getPath() {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return path + paramsToString();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Build a RESTEndpoint
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public static class RESTEndpointBuilder {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private StringBuilder path;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private Map<String, String> parameters;
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford private String realm;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private String postData;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private HTTPMethod httpMethod;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private Map<String, String> headers;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public RESTEndpointBuilder() {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford path = new StringBuilder();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford parameters = new LinkedHashMap<>();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford headers = new LinkedHashMap<>();
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford realm = null;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford httpMethod = HTTPMethod.POST;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford postData = "";
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * This is where we assemble the path (straightforward in itself) but substitute the realm. For a number of
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * URLs we use, the realm is not involved (none of the OIDC calls use it) but for others (like the identity
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * endpoint) it is very important. Unfortunately substituting it is painful as we can accidentally change
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * <p/>
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * path1/{REALM}/path2
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * <p/>
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * to
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * <p/>
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * path1//path2
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * <p/>
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * when the realm is undefined (i.e. it is the root realm), or even worse:
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * <p/>
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * path1///path2
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * <p/>
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * when the realm is set to "/".
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford *
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * @return the carefully assembled path
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public String getPath() {
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford String result = path.toString();
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford // Trim the realm. Note that in this way if the caller set the realm to "/" (root realm), we trim it
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford // such that it becomes zero length.
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford //
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford if (realm != null) {
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford if (realm.startsWith("/")) {
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford realm = realm.substring(1);
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford }
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford if (realm.endsWith("/")) {
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford realm = realm.substring(0, realm.length() - 1);
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford }
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford }
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford if (result.contains("{REALM}/")) {
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford result = result.replace("{REALM}/", "{REALM}");
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford }
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford if (result.contains("{REALM}")) {
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford if (StringUtils.isBlank(realm)) {
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford result = result.replace("{REALM}", "");
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford } else {
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford result = result.replace("{REALM}", realm + "/");
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford }
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford }
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford return result;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Add the specified value to the path carefully. We must never end up gluing together two "/" characters
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * (one from the end of the previous path and another from the start of the next path).
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * @param incoming the value to append to the path.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return the rest call builder object for fluency.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford public RESTEndpointBuilder path(String incoming) {
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford if (StringUtils.isBlank(incoming)) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return this;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford if (incoming.startsWith("/")) {
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford incoming = incoming.substring(1);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford if (incoming.endsWith("/")) {
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford incoming = incoming.substring(0, incoming.length() - 1);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford if (this.path.length() > 0) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford this.path.append("/");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford this.path.append(incoming);
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford return this;
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford /**
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * Add the specified realm.
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * @param s The realm.
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford * @return the rest call builder object for fluency.
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford */
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford public RESTEndpointBuilder realm(String s) {
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford realm = s;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return this;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Add the specified name/value pair to the list of parameters. The list of parameters is preserved in order,
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * even though this technically may not be necessary.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford *
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @param name the name of the parameter
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @param value the value of the parameter
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return the rest call builder object for added fluency
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public RESTEndpointBuilder parameter(String name, String value) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford if (name.startsWith("&") || name.startsWith("?")) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford name = name.substring(1);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford parameters.put(name, value);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return this;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Add the auth index name and auth index value to the list of parameters.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return the current rest call builder object
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public RESTEndpointBuilder addModuleParameters() {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford parameters.put(AUTH_INDEX_TYPE_NAME, AUTH_INDEX_TYPE_VALUE);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford parameters.put(AUTH_INDEX_VALUE_NAME, AUTH_INDEX_VALUE_VALUE);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return this;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Add HTTP POST data. No checking is done in the case where we're actually building a GET and the post
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * data will still be written.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return the current rest call builder object
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public RESTEndpointBuilder postData(String s) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford this.postData = s;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return this;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Set the HTTP method to GET.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return the current rest call builder object
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public RESTEndpointBuilder get() {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford this.httpMethod = HTTPMethod.GET;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return this;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Set the HTTP method to POST
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return the current rest call builder object
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public RESTEndpointBuilder post() {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford this.httpMethod = HTTPMethod.POST;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return this;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Add the name/value pair to the outgoing headers.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @param header The header name
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @param value The header value
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return the current rest call builder object
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
e80c6451e400ef4956af170a3efaa0423aede68cTony Bamford public RESTEndpointBuilder header(String header, String value) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford headers.put(header, value);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return this;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Set the API version for this endpoint.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @param apiVersion The specified API version
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return the current rest call builder object
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public RESTEndpointBuilder apiVersion(String apiVersion) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford headers.put("Accept-API-Version", "protocol=1.0,resource=" + apiVersion);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return this;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Build the rest endpoint object
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return the built rest endpoint
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public RESTEndpoint build() {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return new RESTEndpoint(this);
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Class to encapsulate the response from REST API.
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public static class RESTResponse {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private int responseCode = -1;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford private List<String> content = null;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return All the text returned by the endpoint, as a list of lines
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public List<String> getContent() {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return content;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * Set the content, as a list of lines, returned by the endpoint
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @param content The content, as a list of lines
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public void setContent(List<String> content) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford this.content = content;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return the response code of the endpoint
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public int getResponseCode() {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return responseCode;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * set the response code of the endpoint
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @param responseCode the response code to set
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public void setResponseCode(int responseCode) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford this.responseCode = responseCode;
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford /**
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford * @return A string representation of the endpoint's response
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford */
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford public String toString() {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford StringBuilder buffer = new StringBuilder();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford if (content != null) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford for (int i = 0; i < content.size(); i++) {
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford buffer.append(content.get(i) + "\n");
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford return buffer.toString();
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford }
bbe59b9e7b19daeef0e63ffa77aaefb67aceb85eTony Bamford}