All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.cloudbees.api.BeesClientBase Maven / Gradle / Ivy

There is a newer version: 1.5.9
Show newest version
/*
 * Copyright 2010-2011, CloudBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with 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.cloudbees.api;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Logger;


import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.params.HttpParams;

public class BeesClientBase {
    Logger logger = Logger.getLogger(getClass().getSimpleName());
    protected String format = "xml";

    private String serverApiUrl = "http://localhost:8080/api";

    private String api_key;

    private String secret;

    private String version = "1.0";
    
    private String sigVersion = "1";

    private boolean verbose = true;

    private BeesClientConfiguration beesClientConfiguration;

    public BeesClientBase(BeesClientConfiguration beesClientConfiguration ) {
        if (beesClientConfiguration==null) {
            throw new IllegalArgumentException("BeesClientConfiguration cannot be null");
        }
        this.beesClientConfiguration = beesClientConfiguration;
        if (beesClientConfiguration.getServerApiUrl() != null) {
            this.serverApiUrl = beesClientConfiguration.getServerApiUrl();
        }
        if (beesClientConfiguration.getApiKey() != null) {
            this.api_key = beesClientConfiguration.getApiKey();
        }
        if (beesClientConfiguration.getSecret() != null) {
            this.secret = beesClientConfiguration.getSecret();
        }
        if (beesClientConfiguration.getFormat() != null) {
            this.format = beesClientConfiguration.getFormat();
        }
        if (beesClientConfiguration.getVersion() != null) {
            this.version = beesClientConfiguration.getVersion();
        }
    }

    public BeesClientBase(String serverApiUrl, String apiKey, String secret,
                          String format, String version) {
        this(new BeesClientConfiguration( serverApiUrl, apiKey, secret, format, version ));
    }

    public boolean isVerbose() {
        return verbose;
    }

    public void setVerbose(boolean verbose) {
        this.verbose = verbose;
    }

    public String getRequestURL(String method, Map methodParams)
    throws Exception {
        return getRequestURL(method, methodParams, true);
    }

    public String getRequestURL(String method, Map methodParams, boolean asActionParam)
            throws Exception {
        HashMap urlParams = getDefaultParameters();

        StringBuilder requestURL = getApiUrl(asActionParam ? null : method);
        requestURL.append("?");

        for (Map.Entry entry : methodParams.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            urlParams.put(key, value);
        }
        
        if(asActionParam)
            urlParams.put("action", method);

        String signature = calculateSignature(urlParams);        
        Iterator> it = urlParams.entrySet().iterator();
        for (int i=0; it.hasNext(); i++) {
            Map.Entry entry = it.next();
            String key = entry.getKey();
            String value = entry.getValue();
            if (i > 0)
                requestURL.append("&");
            requestURL.append(URLEncoder.encode(key, "UTF-8"));
            requestURL.append("=");
            requestURL.append(URLEncoder.encode(value, "UTF-8"));
        }
        
        requestURL.append("&");
        requestURL.append("sig");
        requestURL.append("=");
        requestURL.append(signature);

        return requestURL.toString();
    }
    
    private String calculateSignature(Map entries) throws Exception
    {
        StringBuilder sigData = new StringBuilder();
        ArrayList> sortedParams = new ArrayList>(entries.entrySet());
        Collections.sort(sortedParams, new Comparator>(){
            public int compare(Entry e1,
                    Entry e2) {
                return e1.getKey().compareTo(e2.getKey());
            }
        });
        for (Map.Entry entry : sortedParams) {
            String key = entry.getKey();
            String value = entry.getValue();
            sigData.append(key);
            sigData.append(value);
        }

        // append the signature
        String signature = getSignature(sigData.toString(), secret);
        return signature;
    }

    protected StringBuilder getApiUrl(String method) {
        StringBuilder requestURL = new StringBuilder();        
        requestURL.append(serverApiUrl);
        if(method != null)
        {
            requestURL.append("/");
            requestURL.append(method);
        }
        return requestURL;
    }

    private HashMap getDefaultParameters() {
        HashMap urlParams = new HashMap();
        urlParams.put("format", format);
        urlParams.put("v", version);
        urlParams.put("api_key", api_key);
        urlParams.put("timestamp", new Long(System.currentTimeMillis() / 1000)
                .toString());
        urlParams.put("sig_version", sigVersion);
        return urlParams;
    }

    public static String getSignature(String data, String secret)
            throws Exception {
        String s = data + secret;
        String sig = md5(s);
        return sig;
    }

    public static String md5(String message) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] md5Bytes = md5.digest(message.getBytes("CP1252"));
            StringBuffer hex = new StringBuffer();
            for (int i = 0; i < md5Bytes.length; ++i) {
                hex.append(Integer.toHexString((md5Bytes[i] & 0xFF) | 0x100)
                        .substring(1, 3));
            }

            return hex.toString();
        } catch (NoSuchAlgorithmException e) {
        } catch (UnsupportedEncodingException e) {
        }
        return null;
    }

    public String executeRequest(String url) throws Exception {
        HttpClient httpClient = HttpClientHelper.createClient(this.beesClientConfiguration);
        GetMethod getMethod = new GetMethod(url);
        int code = httpClient.executeMethod(getMethod);
        String response = getResponseString(getMethod.getResponseBodyAsStream());
        if (code >= 300) {
            processError(response, code);
        }

        return response;
    }

    private String getResponseString(InputStream ins) throws IOException {
        StringBuffer response = new StringBuffer();
        try {
            InputStreamReader isr = new InputStreamReader(ins);
            char[] chars = new char[1024];
            int numRead = isr.read(chars, 0, chars.length);
            while (numRead != -1) {
                response.append(new String(chars, 0, numRead));
                numRead = isr.read(chars, 0, chars.length);
            }
        } finally {
            ins.close();
        }
        return response.toString();
    }

    public InputStream executeCometRequest(String url) throws Exception {
        HttpClient httpClient = HttpClientHelper.createClient(this.beesClientConfiguration);
        HttpParams params = httpClient.getParams();
        params.setIntParameter(HttpConnectionParams.SO_TIMEOUT, 0);
        GetMethod getMethod = new GetMethod(url);
        int code = httpClient.executeMethod(getMethod);
        if (code >= 300) {
            processError(getResponseString(getMethod.getResponseBodyAsStream()), code);
        }
        return getMethod.getResponseBodyAsStream();
    }

    protected void processError(String response, int code) throws BeesClientException {
        ErrorResponse er = new ErrorResponse();
        er.errorCode = "" + code;
        if (isVerbose())
            er.message = response;
        else
            er.message = HttpStatus.getStatusText(code);
        throw new BeesClientException(er);
    }

    protected void trace(String message)
    {
        if (verbose) {
            System.out.println(message);
        }
    }

    protected void traceResponse(String message)
    {
        if (verbose) System.out.println("xml response: " + message);
    }

    protected String executeUpload(String uploadURL, Map params,
            Map files, UploadProgress writeListener)
            throws Exception {
        HashMap clientParams = getDefaultParameters();
        clientParams.putAll(params);

        PostMethod filePost = new PostMethod(uploadURL);
        try {
            ArrayList parts = new ArrayList();

            int fileUploadSize = 0;
            for (Map.Entry fileEntry : files.entrySet()) {
                FilePart filePart = new FilePart(fileEntry.getKey(), fileEntry
                        .getValue());
                parts.add(filePart);
                fileUploadSize += filePart.length();
                //TODO: file params are not currently included in the signature,
                //      we should hash the file contents so we can verify them
            }

            for (Map.Entry entry : clientParams.entrySet()) {
                parts.add(new StringPart(entry.getKey(), entry.getValue()));
            }

            // add the signature
            String signature = calculateSignature(clientParams);
            parts.add(new StringPart("sig", signature));

            ProgressUploadEntity uploadEntity = new ProgressUploadEntity(parts
                    .toArray(new Part[parts.size()]), filePost.getParams(),
                    writeListener, fileUploadSize);
            filePost.setRequestEntity(uploadEntity);
            HttpClient client = HttpClientHelper.createClient(this.beesClientConfiguration);
            client.getHttpConnectionManager().getParams().setConnectionTimeout(
                    10000);
            
            int status = client.executeMethod(filePost);
            String response = getResponseString(filePost.getResponseBodyAsStream());
            if (status == HttpStatus.SC_OK) {
                trace("upload complete, response=" + response);
            } else {
                trace("upload failed, response=" + HttpStatus.getStatusText(status));
                processError(response, status);
            }
            return response;
        } finally {
            filePost.releaseConnection();
        }
    }

    class ProgressUploadEntity extends MultipartRequestEntity {
        private UploadProgress listener;
        long length;

        public ProgressUploadEntity(Part[] parts, HttpMethodParams params,
                UploadProgress listener, long length) {
            super(parts, params);
            this.listener = listener;
            this.length = length;
        }

        @Override
        public void writeRequest(OutputStream out) throws IOException {
            WriteListenerOutputStream listenStream = new WriteListenerOutputStream(
                    out, listener, length);
            super.writeRequest(listenStream);
        }
    }

    class WriteListenerOutputStream extends OutputStream {
        private OutputStream targetStream;
        private long bytesWritten;
        private boolean isClosed;
        private long bytesToSend;
        private UploadProgress writeListener;

        public WriteListenerOutputStream(OutputStream targetStream,
                UploadProgress writeListener, long length) {
            super();
            this.targetStream = targetStream;
            this.writeListener = writeListener;
            this.bytesToSend = length;
        }

        public void close() throws IOException {
            isClosed = true;
            targetStream.close();
        }

        public void flush() throws IOException {
            targetStream.flush();
        }

        public void write(byte[] b, int off, int len) throws IOException {
            targetStream.write(b, off, len);
            trackBytesWritten(len);
        }

        public void write(byte[] b) throws IOException {
            targetStream.write(b);
            trackBytesWritten(b.length);
        }

        public void write(int b) throws IOException {
            targetStream.write(b);
            trackBytesWritten(1);
        }

        public boolean isClosed() {
            return isClosed;
        }

        public long getBytesWritten() {
            return bytesWritten;
        }

        private void trackBytesWritten(long count) {
            bytesWritten += count;
            if (writeListener != null) {
                writeListener.handleBytesWritten(count, bytesWritten,
                        bytesToSend);
            }
        }
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy