public JSONArray execute() throws QueryException {

        // Build request url using the query
        URL requestUrl = null;
        try {
            requestUrl = new URL(HOST + query);
        } catch (MalformedURLException e) {
            throw new QueryException(QueryExceptionType.MALFORMED_URL, this, HOST + query, e);
        }

        // Open connection to request url
        HttpURLConnection request = null;
        try {
            request = FileUtils.resolveRedirects((HttpURLConnection) requestUrl.openConnection());
        } catch (IOException e) {
            throw new QueryException(QueryExceptionType.CANNOT_OPEN_CONNECTION, this, requestUrl.toExternalForm(), e);
        }

        // Set connection timeout
        request.setConnectTimeout(CONNECTION_TIMEOUT);
        request.setReadTimeout(CONNECTION_TIMEOUT);

        // Set user agent
        request.addRequestProperty("User-Agent", USER_AGENT);

        // Set api key (if provided)
        String apiKey = QuarterBukkit.getPlugin().getConfig().getString("server-mods-api-key");
        if (apiKey != null && !apiKey.isEmpty()) {
            request.addRequestProperty("X-API-Key", apiKey);
        }

        // We want to read the results
        request.setDoOutput(true);

        // Read first line from the response
        BufferedReader reader = null;
        String response = null;
        try {
            reader = new BufferedReader(new InputStreamReader(request.getInputStream(), Charset.forName("UTF-8")));
            response = reader.readLine();
        } catch (IOException e) {
            if (e.getMessage().contains("HTTP response code: 403")) {
                throw new QueryException(QueryExceptionType.INVALID_API_KEY, this, requestUrl.toExternalForm(), e);
            } else {
                throw new QueryException(QueryExceptionType.CANNOT_READ_RESPONSE, this, requestUrl.toExternalForm(), e);
            }
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    // Ignore
                }
            }
        }

        // Parse the response
        Object jsonResponse = JSONValue.parse(response);

        if (jsonResponse instanceof JSONArray) {
            return (JSONArray) jsonResponse;
        } else {
            throw new QueryException(QueryExceptionType.INVALID_RESPONSE, this, requestUrl.toExternalForm());
        }
    }