org.jboss.arquillian.container.was.wlp_remote_8_5.WLPRestClient.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.arquillian.container.was.wlp_remote_8_5.WLPRestClient.java

Source

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the @authors tag. All rights reserved.
 * See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * 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 org.jboss.arquillian.container.was.wlp_remote_8_5;

import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.fluent.Executor;
import org.apache.http.client.fluent.Request;
import org.apache.http.entity.ContentType;
import org.jboss.arquillian.container.spi.client.container.DeploymentException;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 
 * This is a wrapper around the WebSphere Liberty JMX Rest API.
 * 
 * @author <a href="mailto:tayres@gmail.com">Tony Ayres</a>
 *
 */
public class WLPRestClient {

    private static final String className = WLPRestClient.class.getName();

    private static Logger log = Logger.getLogger(className);

    private WLPRemoteContainerConfiguration configuration;

    private static final String IBMJMX_CONNECTOR_REST = "/IBMJMXConnectorREST";
    private static final String FILE_ENDPOINT = IBMJMX_CONNECTOR_REST + "/file/";
    private static final String MBEANS_ENDPOINT = IBMJMX_CONNECTOR_REST + "/mbeans/";
    private static final String UTF_8 = "UTF-8";
    private static final String STARTED = "STARTED";

    private final Executor executor;

    public WLPRestClient(WLPRemoteContainerConfiguration configuration) {
        this.configuration = configuration;
        executor = Executor.newInstance().auth(new HttpHost(configuration.getHostName()),
                configuration.getUsername(), configuration.getPassword());
    }

    /**
     * Uses the rest api to upload an application binary to the dropins folder
     * of WLP to allow the server automatically deploy it.
     * 
     * @param archive
     * @throws ClientProtocolException
     * @throws IOException
     */
    public void deploy(File archive) throws ClientProtocolException, IOException {

        if (log.isLoggable(Level.FINER)) {
            log.entering(className, "deploy");
        }

        String deployPath = String.format("${wlp.user.dir}/servers/%s/dropins/%s", configuration.getServerName(),
                archive.getName());

        String serverRestEndpoint = String.format("https://%s:%d%s%s", configuration.getHostName(),
                configuration.getHttpsPort(), FILE_ENDPOINT, URLEncoder.encode(deployPath, UTF_8));

        HttpResponse result = executor.execute(Request.Post(serverRestEndpoint).useExpectContinue()
                .version(HttpVersion.HTTP_1_1).bodyFile(archive, ContentType.DEFAULT_BINARY)).returnResponse();

        if (log.isLoggable(Level.FINE)) {
            log.fine("While deploying file " + archive.getName() + ", server returned response: "
                    + result.getStatusLine().getStatusCode());
        }

        if (!isSuccessful(result)) {
            throw new ClientProtocolException(
                    "Could not deploy application to server, server returned response: " + result);
        }

        if (log.isLoggable(Level.FINER)) {
            log.exiting(className, "deploy");
        }

    }

    /**
     * Deletes the specified application from the servers dropins directory. WLP
     * will detect this and then undeploy it.
     * 
     * @param String
     *            - applicationName
     * @throws ClientProtocolException
     * @throws IOException
     */
    public void undeploy(String applicationName) throws ClientProtocolException, IOException {

        if (log.isLoggable(Level.FINER)) {
            log.entering(className, "undeploy");
        }

        String deployPath = String.format("${wlp.user.dir}/servers/%s/dropins/%s", configuration.getServerName(),
                applicationName);

        String serverRestEndpoint = String.format("https://%s:%d%s%s", configuration.getHostName(),
                configuration.getHttpsPort(), FILE_ENDPOINT, URLEncoder.encode(deployPath, UTF_8));

        HttpResponse result = executor
                .execute(Request.Delete(serverRestEndpoint).useExpectContinue().version(HttpVersion.HTTP_1_1))
                .returnResponse();

        if (isSuccessful(result)) {
            log.fine("File " + applicationName + " was deleted");
        } else {
            throw new ClientProtocolException("Unable to undeploy application " + applicationName
                    + ", server returned response: " + result.getStatusLine());
        }

        if (log.isLoggable(Level.FINER)) {
            log.exiting(className, "undeploy", result);
        }
    }

    /**
     * Calls the rest api to determine if the application server is up and
     * running.
     * 
     * @return boolean - true if the server is running
     */
    public boolean isServerUp() throws ClientProtocolException, IOException {
        if (log.isLoggable(Level.FINER)) {
            log.entering(className, "isServerUp");
        }

        String hostName = String.format("https://%s:%d%s", configuration.getHostName(),
                configuration.getHttpsPort(), IBMJMX_CONNECTOR_REST);

        HttpResponse result = executor.execute(Request.Get(hostName)).returnResponse();

        if (!isSuccessful(result)) {
            throw new ClientProtocolException(
                    "Could not successfully connect to REST endpoint, server returned response: " + result);
        }

        if (log.isLoggable(Level.FINER)) {
            log.exiting(className, "isServerUp");
        }
        return isSuccessful(result);
    }

    /**
     * Queries the rest api for the servers name.
     * 
     * @return the name of the running server e.g. defaultServer
     * @throws IOException
     * @throws ClientProtocolException
     */
    public String getServerName() throws ClientProtocolException, IOException {
        if (log.isLoggable(Level.FINER)) {
            log.entering(className, "getServerName");
        }

        String restEndpoint = String.format(
                "https://%s:%d%sWebSphere:feature=kernel,name=ServerInfo/attributes/Name",
                configuration.getHostName(), configuration.getHttpsPort(), MBEANS_ENDPOINT);

        String jsonResponse = executor.execute(Request.Get(restEndpoint)).returnContent().asString();
        String serverName = parseJsonResponse(jsonResponse);

        if (log.isLoggable(Level.FINER)) {
            log.exiting(className, "isServerUp");
        }
        return serverName;
    }

    /**
     * Checks the application State using the WLP rest api.
     * 
     * @param applicationName
     * @return true if the application is in STARTED state
     * @throws DeploymentException
     */
    public boolean isApplicationStarted(String applicationName) {

        if (log.isLoggable(Level.FINER)) {
            log.entering(className, "isApplicationStarted");
        }

        String restEndpoint = String.format(
                "https://%s:%d%sWebSphere:service=com.ibm.websphere.application.ApplicationMBean,name=%s/attributes/State",
                configuration.getHostName(), configuration.getHttpsPort(), MBEANS_ENDPOINT, applicationName);

        String status = "";
        try {
            String jsonResponse = executor.execute(Request.Get(restEndpoint)).returnContent().asString();
            status = parseJsonResponse(jsonResponse);
        } catch (ClientProtocolException e) {
            // This exception is expected if the application hasn't been
            // deployed yet as its MBean won't exist.
            // We expect this and can continue, set status to error.
            log.finest("Expected error occurred while checking if application " + applicationName
                    + " is already started, app may not have been deployed yet. Ok to continue. " + e);
            status = "error";
        } catch (IOException e) {
            log.severe("IOException occurred while checking if application " + applicationName
                    + " is already started " + e);
            status = "error";
        }

        boolean applicationState;

        if (STARTED.equals(status)) {
            applicationState = true;
        } else {
            applicationState = false;
        }

        if (log.isLoggable(Level.FINER)) {
            log.exiting(className, "isApplicationStarted", applicationState);
        }

        return applicationState;
    }

    /*
     * Get a value from a json response.
     */
    private String parseJsonResponse(String jsonString) {
        ObjectMapper mapper = new ObjectMapper();
        String value = "";
        try {
            Map result = mapper.readValue(jsonString.getBytes(), Map.class);
            value = (String) result.get("value");
        } catch (JsonParseException e) {
            log.severe("Error parsing Json response " + e);
        } catch (JsonMappingException e) {
            log.severe("Error mapping Json response " + e);
        } catch (IOException e) {
            log.severe("IOException while parsing Json response " + e);
        }
        return value;
    }

    /**
     * Tests if a HttpResponse contains a 2xx response code
     * 
     * @param response
     * @return true if the response code is a 2xx code.
     */
    private boolean isSuccessful(HttpResponse response) {
        if (response.getStatusLine().getStatusCode() >= HttpStatus.SC_OK
                && response.getStatusLine().getStatusCode() <= HttpStatus.SC_NO_CONTENT) {
            return true;
        }
        return false;
    }

}