| // Licensed to the Apache Software Foundation (ASF) under one | |
| // or more contributor license agreements. See the NOTICE file | |
| // distributed with this work for additional information | |
| // regarding copyright ownership. The ASF licenses this file | |
| // to you under the Apache License, Version 2.0 (the | |
| // "License"); you may not use this file except in compliance | |
| // the License. You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, | |
| // software distributed under the License is distributed on an | |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| // KIND, either express or implied. See the License for the | |
| // specific language governing permissions and limitations | |
| // under the License. | |
| package com.cloud.api; | |
| import com.cloud.utils.exception.CloudRuntimeException; | |
| import com.google.gson.Gson; | |
| import org.apache.cloudstack.api.response.SuccessResponse; | |
| import java.io.BufferedReader; | |
| import java.io.EOFException; | |
| import java.io.InputStreamReader; | |
| import java.math.BigInteger; | |
| import java.net.HttpURLConnection; | |
| import java.net.URL; | |
| import java.net.URLEncoder; | |
| import java.security.MessageDigest; | |
| import java.security.NoSuchAlgorithmException; | |
| import java.util.HashMap; | |
| import java.util.Iterator; | |
| /** | |
| * Base class for API Test | |
| * | |
| */ | |
| public abstract class APITest { | |
| protected String rootUrl = "http://localhost:8080/client/api"; | |
| protected String sessionKey = null; | |
| protected String cookieToSent = null; | |
| /** | |
| * Sending an api request through Http GET | |
| * @param command command name | |
| * @param params command query parameters in a HashMap | |
| * @return http request response string | |
| */ | |
| protected String sendRequest(String command, HashMap<String, String> params) { | |
| try { | |
| // Construct query string | |
| StringBuilder sBuilder = new StringBuilder(); | |
| sBuilder.append("command="); | |
| sBuilder.append(command); | |
| if (params != null && params.size() > 0) { | |
| Iterator<String> keys = params.keySet().iterator(); | |
| while (keys.hasNext()) { | |
| String key = keys.next(); | |
| sBuilder.append("&"); | |
| sBuilder.append(key); | |
| sBuilder.append("="); | |
| sBuilder.append(URLEncoder.encode(params.get(key), "UTF-8")); | |
| } | |
| } | |
| // Construct request url | |
| String reqUrl = rootUrl + "?" + sBuilder.toString(); | |
| // Send Http GET request | |
| URL url = new URL(reqUrl); | |
| HttpURLConnection conn = (HttpURLConnection)url.openConnection(); | |
| conn.setRequestMethod("GET"); | |
| if (!command.equals("login") && cookieToSent != null) { | |
| // add the cookie to a request | |
| conn.setRequestProperty("Cookie", cookieToSent); | |
| } | |
| conn.connect(); | |
| if (command.equals("login")) { | |
| // if it is login call, store cookie | |
| String headerName = null; | |
| for (int i = 1; (headerName = conn.getHeaderFieldKey(i)) != null; i++) { | |
| if (headerName.equals("Set-Cookie")) { | |
| String cookie = conn.getHeaderField(i); | |
| cookie = cookie.substring(0, cookie.indexOf(";")); | |
| String cookieName = cookie.substring(0, cookie.indexOf("=")); | |
| String cookieValue = cookie.substring(cookie.indexOf("=") + 1, cookie.length()); | |
| cookieToSent = cookieName + "=" + cookieValue; | |
| } | |
| } | |
| } | |
| // Get the response | |
| StringBuilder response = new StringBuilder(); | |
| BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); | |
| String line; | |
| try { | |
| while ((line = rd.readLine()) != null) { | |
| response.append(line); | |
| } | |
| } catch (EOFException ex) { | |
| // ignore this exception | |
| System.out.println("EOF exception due to java bug"); | |
| } | |
| rd.close(); | |
| return response.toString(); | |
| } catch (Exception e) { | |
| throw new CloudRuntimeException("Problem with sending api request", e); | |
| } | |
| } | |
| protected String createMD5String(String password) { | |
| MessageDigest md5; | |
| try { | |
| md5 = MessageDigest.getInstance("MD5"); | |
| } catch (NoSuchAlgorithmException e) { | |
| throw new CloudRuntimeException("Error", e); | |
| } | |
| md5.reset(); | |
| BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes())); | |
| // make sure our MD5 hash value is 32 digits long... | |
| StringBuffer sb = new StringBuffer(); | |
| String pwStr = pwInt.toString(16); | |
| int padding = 32 - pwStr.length(); | |
| for (int i = 0; i < padding; i++) { | |
| sb.append('0'); | |
| } | |
| sb.append(pwStr); | |
| return sb.toString(); | |
| } | |
| protected Object fromSerializedString(String result, Class<?> repCls) { | |
| try { | |
| if (result != null && !result.isEmpty()) { | |
| // get real content | |
| int start; | |
| int end; | |
| if (repCls == LoginResponse.class || repCls == SuccessResponse.class) { | |
| start = result.indexOf('{', result.indexOf('{') + 1); // find | |
| // the | |
| // second | |
| // { | |
| end = result.lastIndexOf('}', result.lastIndexOf('}') - 1); // find | |
| // the | |
| // second | |
| // } | |
| // backwards | |
| } else { | |
| // get real content | |
| start = result.indexOf('{', result.indexOf('{', result.indexOf('{') + 1) + 1); // find | |
| // the | |
| // third | |
| // { | |
| end = result.lastIndexOf('}', result.lastIndexOf('}', result.lastIndexOf('}') - 1) - 1); // find | |
| // the | |
| // third | |
| // } | |
| // backwards | |
| } | |
| if (start < 0 || end < 0) { | |
| throw new CloudRuntimeException("Response format is wrong: " + result); | |
| } | |
| String content = result.substring(start, end + 1); | |
| Gson gson = ApiGsonHelper.getBuilder().create(); | |
| return gson.fromJson(content, repCls); | |
| } | |
| return null; | |
| } catch (RuntimeException e) { | |
| throw new CloudRuntimeException("Caught runtime exception when doing GSON deserialization on: " + result, e); | |
| } | |
| } | |
| /** | |
| * Login call | |
| * @param username user name | |
| * @param password password (plain password, we will do MD5 hash here for you) | |
| * @return login response string | |
| */ | |
| protected void login(String username, String password) { | |
| //String md5Psw = createMD5String(password); | |
| // send login request | |
| HashMap<String, String> params = new HashMap<String, String>(); | |
| params.put("response", "json"); | |
| params.put("username", username); | |
| params.put("password", password); | |
| String result = this.sendRequest("login", params); | |
| LoginResponse loginResp = (LoginResponse)fromSerializedString(result, LoginResponse.class); | |
| sessionKey = loginResp.getSessionkey(); | |
| } | |
| } |