/**
* Copyright 2014 SAP AG
*
* 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.aim.artifacts.instrumentation;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import javax.ws.rs.core.MediaType;
import org.aim.api.exceptions.InstrumentationException;
import org.aim.api.exceptions.MeasurementException;
import org.aim.api.instrumentation.AbstractEnclosingProbe;
import org.aim.api.instrumentation.entities.FlatInstrumentationState;
import org.aim.api.instrumentation.entities.OverheadData;
import org.aim.api.instrumentation.entities.SupportedExtensions;
import org.aim.api.measurement.MeasurementData;
import org.aim.artifacts.measurement.collector.StreamReader;
import org.aim.description.InstrumentationDescription;
import org.lpe.common.util.web.LpeWebUtils;
import com.sun.jersey.api.client.WebResource;
/**
* Service client for instrumentation.
*
* @author Alexander Wert
*
*/
public class InstrumentationClient {
public static final String URL_PATH_INSTRUMENTATION = "instrumentation";
public static final String URL_PATH_MEASUREMENT = "measurement";
public static final String PATH_PREFIX = "agent";
private static final String TEST_CONNECTION = PATH_PREFIX + "/"
+ "testConnection";
private static final String INSTRUMENT = PATH_PREFIX + "/"
+ URL_PATH_INSTRUMENTATION + "/" + "instrument";
private static final String UNINSTRUMENT = PATH_PREFIX + "/"
+ URL_PATH_INSTRUMENTATION + "/" + "uninstrument";
private static final String GET_STATE = PATH_PREFIX + "/"
+ URL_PATH_INSTRUMENTATION + "/" + "getState";
private static final String GET_SUPPORTED_EXTENSIONS = PATH_PREFIX + "/"
+ URL_PATH_INSTRUMENTATION + "/" + "getSupportedExtensions";
private static final String ENABLE = PATH_PREFIX + "/"
+ URL_PATH_MEASUREMENT + "/" + "enable";
private static final String DISABLE = PATH_PREFIX + "/"
+ URL_PATH_MEASUREMENT + "/" + "disable";
private static final String GET_DATA = PATH_PREFIX + "/"
+ URL_PATH_MEASUREMENT + "/" + "getdata";
private static final String CURRENT_TIME = PATH_PREFIX + "/"
+ URL_PATH_MEASUREMENT + "/" + "currentTime";
private static final String MEASURE_OVERHEAD = PATH_PREFIX + "/"
+ URL_PATH_MEASUREMENT + "/" + "measureOverhead";
private static final String MONITORING_STATE = PATH_PREFIX + "/"
+ URL_PATH_MEASUREMENT + "/" + "monitoringState";
private final String baseUrl;
private String host;
private String port;
private WebResource webResource;
/**
* Constructor.
*
* @param host
* host of the service
* @param port
* port where to reach service
*/
public InstrumentationClient(String host, String port) {
this.host = host;
this.port = port;
this.baseUrl = "http://" + host + ":" + port;
webResource = LpeWebUtils.getWebClient().resource(baseUrl);
}
/**
* Instruments the code according to the passed
* {@link InstrumentationDescription}.
*
* @param description
* describes where and how to instrument the application code
* @throws InstrumentationException
* thrown if exception occur during instrumentation
*/
public void instrument(InstrumentationDescription description)
throws InstrumentationException {
webResource.path(INSTRUMENT).type(MediaType.APPLICATION_JSON)
.post(description);
}
/**
* Reverts all previous instrumentation steps and resets the application
* code to the original state.
*
* false
*
* @throws InstrumentationException
* thrown if exception occur during uninstrumentation
*/
public void uninstrument() throws InstrumentationException {
webResource.path(UNINSTRUMENT).post();
}
/**
* Enables monitoring or measurement data collection.
*
* @throws MeasurementException
* thrown if monitoring fails
*/
public void enableMonitoring() throws MeasurementException {
webResource.path(ENABLE).post();
}
/**
* Disables monitoring or measurement data collection.
*
* @throws MeasurementException
* thrown if monitoring fails
*/
public void disableMonitoring() throws MeasurementException {
webResource.path(DISABLE).post();
}
/**
* Retrieves the state whether monitoring is enabled.
*
* @return boolean whether monitoring is enabled
*/
public boolean isMonitoringEnabled() {
return webResource.path(MONITORING_STATE)
.accept(MediaType.APPLICATION_JSON).get(Boolean.class);
}
/**
* Retrieves the current instrumentation state.
*
* @return a flat representation of the internal instrumentation state.
*/
public FlatInstrumentationState getInstrumentationState() {
return webResource.path(GET_STATE).accept(MediaType.APPLICATION_JSON)
.get(FlatInstrumentationState.class);
}
/**
* Retrieves all supported extensions for the extension points of the
* instrumentation description.
*
* @return an object wrapping all supported extensions
*/
public SupportedExtensions getSupportedExtensions() {
return webResource.path(GET_SUPPORTED_EXTENSIONS)
.accept(MediaType.APPLICATION_JSON)
.get(SupportedExtensions.class);
}
/**
*
* @return collected measurement data
* @throws MeasurementException
* thrown if data cannot be retrieved
*/
public MeasurementData getMeasurementData() throws MeasurementException {
HttpURLConnection connection = null;
try {
connection = LpeWebUtils.get(baseUrl + "/" + GET_DATA);
StreamReader reader = new StreamReader();
reader.setSource(connection.getInputStream());
return reader.read();
} catch (IOException e) {
throw new MeasurementException(e);
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
/**
* Measures the overhead of the given probe type.
*
* @param probeType
* type of the probe
* @return overhead information.
*/
public OverheadData measureProbeOverhead(
Class<? extends AbstractEnclosingProbe> probeType) {
String probeClassName = probeType.getName();
return webResource.path(MEASURE_OVERHEAD)
.accept(MediaType.APPLICATION_JSON)
.type(MediaType.APPLICATION_JSON)
.post(OverheadData.class, probeClassName);
}
/**
*
* @param oStream
* output stream where to pipe the input to
* @throws MeasurementException
* thrown if data cannot be retrieved
*/
public void pipeToOutputStream(OutputStream oStream)
throws MeasurementException {
HttpURLConnection connection = null;
try {
connection = LpeWebUtils.get(baseUrl + "/" + GET_DATA);
StreamReader reader = new StreamReader();
reader.setSource(connection.getInputStream());
reader.pipeToOutputStream(oStream);
} catch (IOException e) {
throw new MeasurementException(e);
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
/**
*
* @return the current local timestamp of the specific controller
*/
public long getCurrentTime() {
return webResource.path(CURRENT_TIME)
.accept(MediaType.APPLICATION_JSON).get(Long.class);
}
/**
*
* @return true if connecting to service possible
*/
public boolean testConnection() {
return testConnection(host, port);
}
/**
* tests connection to the agent.
*
* @param host
* instrumentation host
* @param port
* instrumentation port
* @return true if connection could have been established
*/
public static boolean testConnection(String host, String port) {
String path = TEST_CONNECTION;
return LpeWebUtils.testConnection(host, port, path);
}
}