com.cloudbees.eclipse.core.util.Utils.java Source code

Java tutorial

Introduction

Here is the source code for com.cloudbees.eclipse.core.util.Utils.java

Source

/*******************************************************************************
 * Copyright (c) 2013 Cloud Bees, Inc.
 * All rights reserved. 
 * This program is made available under the terms of the 
 * Eclipse Public License v1.0 which accompanies this distribution, 
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Cloud Bees, Inc. - initial API and implementation 
 *******************************************************************************/
package com.cloudbees.eclipse.core.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.AuthPolicy;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.eclipse.core.net.proxy.IProxyData;
import org.eclipse.core.net.proxy.IProxyService;

import com.cloudbees.eclipse.core.CloudBeesCorePlugin;
import com.cloudbees.eclipse.core.CloudBeesException;
import com.cloudbees.eclipse.core.XMLReplace;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Utils {

    public static Gson createGson() {
        final GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.serializeSpecialFloatingPointValues();
        gsonBuilder.serializeNulls();
        // gsonBuilder.setPrettyPrinting(); // temporary
        // gsonBuilder.excludeFieldsWithoutExposeAnnotation();
        Gson g = gsonBuilder.create();
        return g;
    }

    /**
     * Converts string to US-ASCII base64 string.
     * 
     * @param str
     * @return
     */
    public static String toB64(final String str) {
        try {
            if (str == null || str.length() == 0) {
                return new String(new byte[0], "US-ASCII");
            }
            return new String(Base64.encodeBase64(str.getBytes("UTF-8")), "US-ASCII");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Converts string from base64 string.
     * 
     * @param str
     * @return
     */
    public static String fromB64(final String str) {
        try {
            if (str == null || str.length() == 0) {
                return new String(new byte[0], "UTF-8");
            }
            return new String(Base64.decodeBase64(str.getBytes("US-ASCII")));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public final static String readString(final InputStream is) throws CloudBeesException {
        if (is == null) {
            return null;
        }
        try {
            Writer writer = new StringWriter();
            char[] buffer = new char[1024];
            try {
                Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                int n;
                while ((n = reader.read(buffer)) != -1) {
                    writer.write(buffer, 0, n);
                }
            } finally {
                is.close();
            }
            return writer.toString();
        } catch (Exception e) {
            throw new CloudBeesException("Failed to read inputstream", e);
        }
    }

    /**
     * @param url
     *          url to connec. Required to determine proxy settings if available. If <code>null</code> then proxy is not
     *          configured for the client returned.
     * @return
     * @throws CloudBeesException
     */
    public final static DefaultHttpClient getAPIClient(String url) throws CloudBeesException {
        DefaultHttpClient httpclient = new DefaultHttpClient();
        try {
            HttpClientParams.setCookiePolicy(httpclient.getParams(), CookiePolicy.BROWSER_COMPATIBILITY);

            String version = null;
            if (CloudBeesCorePlugin.getDefault() != null) {
                version = CloudBeesCorePlugin.getDefault().getBundle().getVersion().toString();
            } else {
                version = "n/a";
            }
            HttpProtocolParams.setUserAgent(httpclient.getParams(), "CBEclipseToolkit/" + version);

            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());

            CloudBeesCorePlugin plugin = CloudBeesCorePlugin.getDefault();

            URL truststore;

            if (plugin == null) {
                //Outside the OSGI environment, try to open the stream from the current dir.
                truststore = new File("truststore").toURI().toURL();
            } else {
                truststore = plugin.getBundle().getResource("truststore");
            }

            InputStream instream = truststore.openStream();

            try {
                trustStore.load(instream, "123456".toCharArray());
            } finally {
                instream.close();
            }

            TrustStrategy trustAllStrategy = new TrustStrategy() {
                @Override
                public boolean isTrusted(final X509Certificate[] chain, final String authType)
                        throws CertificateException {
                    return true;
                }
            };

            SSLSocketFactory socketFactory = new SSLSocketFactory(SSLSocketFactory.TLS, null, null, trustStore,
                    null, trustAllStrategy, SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            // Override https handling to use provided truststore
            @SuppressWarnings("deprecation")
            Scheme sch = new Scheme("https", socketFactory, 443);
            httpclient.getConnectionManager().getSchemeRegistry().register(sch);

            HttpParams params = httpclient.getParams();

            //TODO Make configurable from the UI?
            HttpConnectionParams.setConnectionTimeout(params, 10000);
            HttpConnectionParams.setSoTimeout(params, 10000);

            if (CloudBeesCorePlugin.getDefault() != null) { // exclude proxy support when running outside eclipse
                IProxyService ps = CloudBeesCorePlugin.getDefault().getProxyService();
                if (ps.isProxiesEnabled()) {

                    IProxyData[] pr = ps.select(new URI(url));

                    //NOTE! For now we use just the first proxy settings with type HTTP or HTTPS to try out the connection. If configuration has more than 1 conf then for now this likely won't work!
                    if (pr != null) {
                        for (int i = 0; i < pr.length; i++) {

                            IProxyData prd = pr[i];

                            if (IProxyData.HTTP_PROXY_TYPE.equals(prd.getType())
                                    || IProxyData.HTTPS_PROXY_TYPE.equals(prd.getType())) {

                                String proxyHost = prd.getHost();
                                int proxyPort = prd.getPort();
                                String proxyUser = prd.getUserId();
                                String proxyPass = prd.getPassword();

                                HttpHost proxy = new HttpHost(proxyHost, proxyPort);
                                httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);

                                if (prd.isRequiresAuthentication()) {
                                    List authpref = new ArrayList();
                                    authpref.add(AuthPolicy.BASIC);
                                    AuthScope authScope = new AuthScope(proxyHost, proxyPort);
                                    httpclient.getCredentialsProvider().setCredentials(authScope,
                                            new UsernamePasswordCredentials(proxyUser, proxyPass));
                                }

                                break;

                            }

                        }
                    }
                }
            }

            /*      httpclient.getHostConfiguration().setProxy(proxyHost,proxyPort);      
                  //if there are proxy credentials available, set those too
                  Credentials proxyCredentials = null;
                  String proxyUser = beesClientConfiguration.getProxyUser();
                  String proxyPassword = beesClientConfiguration.getProxyPassword();
                  if(proxyUser != null || proxyPassword != null)
            proxyCredentials = new UsernamePasswordCredentials(proxyUser, proxyPassword);
                  if(proxyCredentials != null)
            client.getState().setProxyCredentials(AuthScope.ANY, proxyCredentials);
                
            */

            return httpclient;

        } catch (Exception e) {
            throw new CloudBeesException("Error while initiating access to JSON APIs!", e);
        }
    }

    public static HttpPost jsonRequest(final String url, final Object req) throws UnsupportedEncodingException {
        HttpPost post = new HttpPost(url);
        Gson g = Utils.createGson();
        String json = g.toJson(req);
        post.setHeader("Accept", "application/json");
        post.setHeader("Content-type", "application/json");

        //System.out.println("JSON REQUEST STRING " + json);
        StringEntity se = new StringEntity(json);
        post.setEntity(se);
        return post;
    }

    public final static String getResponseBody(final HttpResponse resp) throws CloudBeesException {
        try {
            return Utils.readString(resp.getEntity().getContent());
        } catch (IllegalStateException e) {
            throw new CloudBeesException("Failed to read response", e);
        } catch (IOException e) {
            throw new CloudBeesException("Failed to read response", e);
        }
    }

    public final static void checkResponseCode(final HttpResponse resp) throws CloudBeesException {
        checkResponseCode(resp, false);
    }

    public final static void checkResponseCode(final HttpResponse resp, final boolean expectCIRedirect,
            final boolean jenkinsAtCloud) throws CloudBeesException {
        int responseStatus = resp.getStatusLine().getStatusCode();

        Header firstHeader = resp.getFirstHeader("Location");

        if (expectCIRedirect && (responseStatus == 302 || responseStatus == 301) && firstHeader != null
                && firstHeader.getValue() != null) {
            //FIXME ugly way to detect a normal redirect within the site that does not redirect to signon but no good idea for better implementation
            if (!jenkinsAtCloud || firstHeader.getValue().indexOf(".ci.") > 0) {
                return;
            }
        }

        if (responseStatus == 302 || responseStatus == 301) {
            throw new CloudBeesException(
                    "Authentication required! Either wrong or no credentials were provided! Reason:"
                            + resp.getStatusLine().getReasonPhrase());
        }
        if (responseStatus != 200) {
            throw new CloudBeesException("Unexpected response code:" + responseStatus + ". Message:"
                    + resp.getStatusLine().getReasonPhrase());
        }
    }

    public final static void checkResponseCode(final HttpResponse resp, final boolean expectCIRedirect)
            throws CloudBeesException {
        int responseStatus = resp.getStatusLine().getStatusCode();

        Header firstHeader = resp.getFirstHeader("Location");

        if (expectCIRedirect && (responseStatus == 302 || responseStatus == 301) && firstHeader != null
                && firstHeader.getValue() != null) {
            //FIXME ugly way to detect a normal redirect within the site that does not redirect to signon but no good idea for better implementation
            if (firstHeader.getValue().indexOf(".ci.") > 0) {
                return;
            }
        }

        if (responseStatus == 302 || responseStatus == 301) {
            throw new CloudBeesException(
                    "Authentication required! Either wrong or no credentials were provided! Reason:"
                            + resp.getStatusLine().getReasonPhrase());
        }
        if (responseStatus != 200) {
            throw new CloudBeesException("Unexpected response code:" + responseStatus + ". Message:"
                    + resp.getStatusLine().getReasonPhrase());
        }
    }

    public static String humanReadableTime(final long duration) {
        String unit = "";
        long mins = duration / (60L * 1000);
        long hr = mins / 60;
        long yrs = hr / 24 / 365;

        if (mins <= 0) {
            long secs = duration / 1000;
            unit = secs + " sec";
            if (secs > 1) {
                unit = unit + "s";
            }
        } else if (mins < 60) {
            unit = mins + " min";
            if (mins > 1) {
                unit = unit + "s";
            }
        } else if (mins < 60 * 24) {
            //long newmins = mins - (hr * 60);
            unit = hr + " hr" + (hr > 1 ? "s" : "");/* + " " + newmins + " min" + (newmins > 1 ? "s" : "");*/
        } else if (yrs < 1) {
            long days = hr / 24L;
            unit = days + " day" + (days > 1 ? "s" : "")/* + ", " + hr + " hr" + (hr > 1 ? "s" : "")*/;
        } else {
            unit = yrs + " year" + (yrs > 1 ? "s" : "");
        }

        return unit;
    }

    public static <T> T createInstance(final Class<T> clazz, final Class<?>[] types, final Object[] params) {
        try {
            Constructor<T> cnst;
            cnst = clazz.getConstructor(types);
            return cnst.newInstance(params);
        } catch (SecurityException e) {
        } catch (NoSuchMethodException e) {
        } catch (IllegalArgumentException e) {
        } catch (InstantiationException e) {
        } catch (IllegalAccessException e) {
        } catch (InvocationTargetException e) {
        }
        return null;
    }

    public static String createEmptyConfig(String description) throws Exception {
        XMLReplace xmlReplace = XMLReplace.getInstance(CloudBeesCorePlugin.getEmptyConfigXML());
        return xmlReplace.addReplacement("description", description).replaceToString();
    }

    public static String createSCMConfig(String description, String url) throws Exception {
        XMLReplace xmlReplace = XMLReplace.getInstance(CloudBeesCorePlugin.getSCMConfigXML());
        return xmlReplace.addReplacement("description", description).addReplacement("remote", url)
                .replaceToString();
    }

    public static HttpGet jsonGetRequest(String url) {
        HttpGet get = new HttpGet(url);
        get.setHeader("Accept", "application/json");
        get.setHeader("Content-type", "application/json");
        return get;
    }
}