brainleg.app.util.AppWeb.java Source code

Java tutorial

Introduction

Here is the source code for brainleg.app.util.AppWeb.java

Source

/*
 * Copyright 2011 Roman Stepanenko
 *
 * 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 brainleg.app.util;

import brainleg.app.api.SearchResults;
import brainleg.app.api.UserInfoResponse;
import brainleg.app.intellij.BLSettingsService;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.net.HttpConfigurable;
import brainleg.app.engine.EData;
import brainleg.app.engine.Generator;
import brainleg.app.exception.RequestRejectedException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * Responsible for working with the BrainLeg website.
 *
 * @author Roman Stepanenko
 */
public class AppWeb {
    /**
     * Returns null if there was a communication error.
     *
     * @param userAuthToken
     * @return
     */
    public static UserInfoResponse getUserInfo(String userAuthToken) {
        try {
            Gson gson = new Gson();
            String jsonText = get(
                    getUrl("api/getUserInfo?apiToken=" + (userAuthToken == null ? "" : userAuthToken.trim())));
            UserInfoResponse response = gson.fromJson(jsonText, UserInfoResponse.class);
            return response;
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * Returns true if success, false otherwise.
     * @param solution
     * @param snippet
     * @param exception
     * @return
     */
    public static boolean submitSolution(String solution, String snippet, EData exception) {
        String exceptionString = Generator.generateStringForWebSubmission(exception,
                BLSettingsService.getSettings().sendExceptionMessage,
                BLSettingsService.getSettings().sendFullTraces);

        try {
            post(getUrl("api/submitSolution"),
                    new NameValuePair[] { new NameValuePair("clientId", "intellij"),
                            new NameValuePair("clientVer", AppUtil.getPluginVersion()),
                            new NameValuePair("userAPIToken",
                                    BLSettingsService.getSettings().userAuthToken == null ? ""
                                            : BLSettingsService.getSettings().userAuthToken.trim()),
                            new NameValuePair("exception", exceptionString),
                            new NameValuePair("solution", solution), new NameValuePair("snippet", snippet) });
            return true;
        } catch (RequestRejectedException e) {
            if ("USER_NOT_FOUND".equals(e.getResponseCode())) {
                Messages.showMessageDialog(
                        "The user token does not match your website profile. Please open BrainLeg settings and update it",
                        "Incorrect user token", Messages.getInformationIcon());
            } else {
                Messages.showMessageDialog(
                        "Connected to server but request was rejected: " + e.getResponseCode() + ":"
                                + e.getResponseMessage(),
                        "Request rejected by the server", Messages.getInformationIcon());
            }
            return false;
        } catch (IOException e) {
            System.out.println("Can't connect to the server: " + e.getMessage());
            Messages.showMessageDialog("Can't connect to the server", "Connection Problem",
                    Messages.getInformationIcon());
            return false;
        }
    }

    public static void sendQueryAndOpenBrowser(EData exception) {
        String searchString = generateExceptionStringForSearchViaApi(exception);

        try {
            //stack trace can be too big to send via GET
            //so we first send the exception via POST, the server responds with a temp request token
            //and then we open browser with a short url containing this token
            String requestToken = post(getUrl("api/submitSearch"),
                    new NameValuePair[] { new NameValuePair("plugin", "intellij"),
                            new NameValuePair("version", AppUtil.getPluginVersion()),
                            new NameValuePair("exception", searchString) });

            BrowserUtil.launchBrowser(getUrl("api/search?token=" + requestToken));
        } catch (RequestRejectedException e) {
            Messages.showMessageDialog("Connected to server but request was rejected",
                    "Request rejected by the server", Messages.getInformationIcon());
        } catch (IOException e) {
            Messages.showMessageDialog("Can't connect to the server", "Connection Problem",
                    Messages.getInformationIcon());
        }
    }

    public static void openSearchResultsInBrowser(String requestToken) {
        BrowserUtil.launchBrowser(getUrl("api/searchInBrowser?token=" + requestToken));
    }

    public static SearchResults sendQuery(EData exception, boolean isAutomaticSearch) {
        String searchString = generateExceptionStringForSearchViaApi(exception);

        try {
            //stack trace can be too big to send via GET
            //so we first send the exception via POST,
            String jsonText = post(getUrl("api/intellijSearch"),
                    new NameValuePair[] { new NameValuePair("plugin", "intellij"),
                            new NameValuePair("version", AppUtil.getPluginVersion()),
                            new NameValuePair("exception", searchString),
                            new NameValuePair("automatic", "" + isAutomaticSearch) });

            Gson gson = new Gson();

            SearchResults response = gson.fromJson(jsonText, SearchResults.class);
            return response;
        } catch (RequestRejectedException e) {
            System.out.println("Connected to server but request was rejected");
            return null;
        } catch (IOException e) {
            System.out.println("Can't connect to the server: " + e.getMessage());
            return null;
        }
    }

    private static String generateExceptionStringForSearchViaApi(EData exception) {
        return Generator.generateStringForWebSubmission(exception,
                BLSettingsService.getSettings().sendExceptionMessage,
                BLSettingsService.getSettings().sendFullTraces);
    }

    public static String post(String url, NameValuePair[] postParameters)
            throws RequestRejectedException, IOException {
        HttpConfigurable.getInstance().prepareURL(getUrl("api/proxyTest"));

        HttpURLConnection connection = doPost(url, join(Arrays.asList(postParameters)));
        int responseCode = connection.getResponseCode();

        String responseText;

        InputStream is = new BufferedInputStream(connection.getInputStream());
        try {
            responseText = readFrom(is);
        } finally {
            is.close();
        }

        if (responseCode != HttpURLConnection.HTTP_OK) {
            // if this is 400 this is an application error (something is rejected by the app)
            if (responseCode == 400 && responseText != null) {
                //normally we return error messages like this: REQUIRED_PARAM_MISSING:Required parameters missing
                List<String> tokens = Lists
                        .newArrayList(Splitter.on(":").omitEmptyStrings().trimResults().split(responseText));
                if (tokens.isEmpty()) {
                    throw new RequestRejectedException();
                } else if (tokens.size() == 1) {
                    throw new RequestRejectedException(tokens.get(0), null);
                } else {
                    throw new RequestRejectedException(tokens.get(0), tokens.get(1));
                }
            } else {
                throw new IOException("response code from server: " + responseCode);
            }
        } else {
            return responseText;
        }
    }

    public static String get(String url) throws IOException {
        GetMethod get = null;
        try {
            HttpConfigurable.getInstance().prepareURL(getUrl("api/proxyTest"));
            HttpClient httpclient = new HttpClient();

            get = new GetMethod(url);
            httpclient.executeMethod(get);

            String responseBody = get.getResponseBodyAsString();
            return responseBody;
        } finally {
            if (get != null) {
                get.releaseConnection();
            }
        }
    }

    /**
     * Copied from ITNProxy
     * @param params
     * @return
     * @throws UnsupportedEncodingException
     */
    private static byte[] join(List<NameValuePair> params) throws UnsupportedEncodingException {
        StringBuilder builder = new StringBuilder();

        Iterator<NameValuePair> it = params.iterator();

        while (it.hasNext()) {
            NameValuePair param = it.next();

            if (StringUtil.isEmpty(param.getName()))
                throw new IllegalArgumentException(param.toString());

            if (StringUtil.isNotEmpty(param.getValue()))
                builder.append(param.getName()).append("=").append(URLEncoder.encode(param.getValue(), ENCODING));

            if (it.hasNext())
                builder.append(POST_DELIMITER);
        }

        return builder.toString().getBytes();
    }

    private static String readFrom(InputStream is) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int c;
        while ((c = is.read()) != -1) {
            out.write(c);
        }
        String s = out.toString();
        out.close();
        return s;
    }

    /**
     * Copied from ITNProxy
     */
    private static HttpURLConnection doPost(String url, byte[] bytes) throws IOException {
        HttpURLConnection connection = (HttpURLConnection) HttpConfigurable.getInstance().openConnection(url);

        connection.setReadTimeout(60 * 1000);
        connection.setConnectTimeout(10 * 1000);
        connection.setRequestMethod(HTTP_POST);
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setRequestProperty(HTTP_CONTENT_TYPE, String.format("%s; charset=%s", HTTP_WWW_FORM, ENCODING));
        connection.setRequestProperty(HTTP_CONTENT_LENGTH, Integer.toString(bytes.length));

        OutputStream out = new BufferedOutputStream(connection.getOutputStream());
        try {
            out.write(bytes);
            out.flush();
        } finally {
            out.close();
        }

        return connection;
    }

    private static String getUrl(String uri) {
        //        return "http://localhost:8080/app/" + uri;
        return "http://www.brainleg.com/" + uri;
    }

    public static final String ENCODING = "UTF8";
    public static final String POST_DELIMITER = "&";

    public static final String HTTP_CONTENT_LENGTH = "Content-Length";
    public static final String HTTP_CONTENT_TYPE = "Content-Type";
    public static final String HTTP_WWW_FORM = "application/x-www-form-urlencoded";
    public static final String HTTP_POST = "POST";

}