/** * Copyright (c) 2013-2014 Angelo ZERR. * All rights reserved. This program and the accompanying materials * are 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: * Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation */ package tern.server.nodejs; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.StatusLine; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import com.eclipsesource.json.Json; import com.eclipsesource.json.JsonObject; import com.eclipsesource.json.ParseException; import tern.TernException; import tern.server.IInterceptor; import tern.server.ITernServer; import tern.server.TernExceptionFactory; import tern.server.protocol.TernDoc; import tern.server.protocol.TernQuery; import tern.utils.IOUtils; import tern.utils.StringUtils; /** * Nodejs Tern helper. * */ public class NodejsTernHelper { // properties for remote access public static final boolean DEFAULT_REMOTE_ACCESS = false; public static final int DEFAULT_REMOTE_PORT = 1234; // properties for direct access public static final long DEFAULT_TIMEOUT = 200L; // 200ms public static final int DEFAULT_TEST_NUMBER = 50; // try to retrieve the // node.js port 50 // each time on timeout // (max=50*200ms=10000ms). public static final boolean DEFAULT_PERSISTENT = false; // tern uses UTF-8 encoding private static final String UTF_8 = "UTF-8"; public NodejsTernHelper() { } public static JsonObject makeRequest(String baseURL, TernDoc doc, boolean silent, List<IInterceptor> interceptors, ITernServer server) throws IOException, TernException { TernQuery query = doc.getQuery(); String methodName = query != null ? query.getLabel() : ""; long startTime = 0; if (interceptors != null) { startTime = System.nanoTime(); for (IInterceptor interceptor : interceptors) { interceptor.handleRequest(doc, server, methodName); } } HttpClient httpClient = new DefaultHttpClient(); try { // Post JSON Tern doc HttpPost httpPost = createHttpPost(baseURL, doc); HttpResponse httpResponse = httpClient.execute(httpPost); HttpEntity entity = httpResponse.getEntity(); InputStream in = entity.getContent(); // Check the status StatusLine statusLine = httpResponse.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode != HttpStatus.SC_OK) { // node.js server throws error String message = IOUtils.toString(in); if (StringUtils.isEmpty(message)) { throw new TernException(statusLine.toString()); } throw TernExceptionFactory.create(message); } try { JsonObject response = (JsonObject) Json.parse(new InputStreamReader(in, UTF_8)); if (interceptors != null) { for (IInterceptor interceptor : interceptors) { interceptor.handleResponse(response, server, methodName, getElapsedTimeInMs(startTime)); } } return response; } catch (ParseException e) { throw new IOException(e); } } catch (Exception e) { if (interceptors != null) { for (IInterceptor interceptor : interceptors) { interceptor.handleError(e, server, methodName, getElapsedTimeInMs(startTime)); } } if (e instanceof IOException) { throw (IOException) e; } if (e instanceof TernException) { throw (TernException) e; } throw new TernException(e); } finally { httpClient.getConnectionManager().shutdown(); } } private static HttpPost createHttpPost(String baseURL, JsonObject doc) throws UnsupportedEncodingException { HttpPost httpPost = new HttpPost(baseURL); httpPost.setEntity(new StringEntity(doc.toString(), UTF_8)); return httpPost; } public static long getElapsedTimeInMs(long startTime) { return ((System.nanoTime() - startTime) / 1000000L); } }