package org.jolokia.request;
/*
* Copyright 2009-2013 Roland Huss
*
* 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.
*/
import java.util.*;
import org.jolokia.config.*;
import org.jolokia.converter.json.ValueFaultHandler;
import org.jolokia.util.*;
import org.json.simple.JSONObject;
/**
* Abstract base class for a JMX request. This is the server side
* representation of a Jolokia request.
*
*
* @author roland
* @since 15.03.11
*/
public abstract class JmxRequest {
// Type of request
private RequestType type;
// An optional target configuration
private ProxyTargetConfig targetConfig = null;
// Processing configuration for tis request object
private ProcessingParameters processingConfig;
// A value fault handler for dealing with exception when extracting values
private ValueFaultHandler valueFaultHandler;
// HTTP method which lead to this request. The method is selected dependent on the
// constructor used.
private HttpMethod method;
// Path parts, which are used for selecting parts of the return value
private List<String> pathParts;
/**
* Constructor used for representing {@link HttpMethod#GET} requests.
*
* @param pType request type
* @param pPathParts an optional path, splitted up in parts. Not all requests do handle a path.
* @param pProcessingParams init parameters provided as query params for a GET request. They are used to
* to influence the processing.
*/
protected JmxRequest(RequestType pType, List<String> pPathParts, ProcessingParameters pProcessingParams) {
this(pType, HttpMethod.GET, pPathParts, pProcessingParams);
}
/**
* Constructor used for {@link HttpMethod#POST} requests, which receive a JSON payload.
*
* @param pMap map containing requests parameters
* @param pInitParams optional processing parameters (obtained as query parameters or from within the
* JSON request)
*/
public JmxRequest(Map<String, ?> pMap, ProcessingParameters pInitParams) {
this(RequestType.getTypeByName((String) pMap.get("type")),
HttpMethod.POST,
EscapeUtil.parsePath((String) pMap.get("path")),
pInitParams);
Map target = (Map) pMap.get("target");
if (target != null) {
targetConfig = new ProxyTargetConfig(target);
}
}
// Common parts of both constructors
private JmxRequest(RequestType pType, HttpMethod pMethod, List<String> pPathParts, ProcessingParameters pProcessingParams) {
method = pMethod;
type = pType;
verifyPath(pPathParts);
pathParts = pPathParts;
initParameters(pProcessingParams);
}
/**
* Get request type
*
* @return request type of this request.
*/
public RequestType getType() {
return type;
}
/**
* Get a processing configuration or null if not set
* @param pConfigKey configuration key to fetch
* @return string value or <code>null</code> if not set
*/
public String getParameter(ConfigKey pConfigKey) {
return processingConfig.get(pConfigKey);
}
/**
* Get a processing configuration as integer or null
* if not set
*
* @param pConfigKey configuration to lookup
* @return integer value of configuration or 0 if not set.
*/
public int getParameterAsInt(ConfigKey pConfigKey) {
String intValueS = processingConfig.get(pConfigKey);
if (intValueS != null) {
return Integer.parseInt(intValueS);
} else {
return 0;
}
}
/**
* Get a processing configuration as a boolean value
*
* @param pConfigKey configuration to lookup
* @return boolean value of the configuration, the default value or false if the default value is null
*/
public Boolean getParameterAsBool(ConfigKey pConfigKey) {
String booleanS = getParameter(pConfigKey);
return Boolean.parseBoolean(booleanS != null ? booleanS : pConfigKey.getDefaultValue());
}
/**
* Get the proxy target configuration provided with the request
*
* @return the proxy target configuration or null if the the request
* is not a proxy based request.
*/
public ProxyTargetConfig getTargetConfig() {
return targetConfig;
}
/**
* HTTP method used for creating this request
*
* @return HTTP method which lead to this request
*/
public HttpMethod getHttpMethod() {
return method;
}
/**
* Get tha value fault handler, which can be passwed around.
* @return the value fault handler
*/
public ValueFaultHandler getValueFaultHandler() {
return valueFaultHandler;
}
/**
* Textual description of this request containing base information. Can be used in toString() methods
* of subclasses
*
* @return description of this base request
*/
protected String getInfo() {
StringBuffer ret = new StringBuffer();
if (pathParts != null) {
ret.append(", path=").append(pathParts);
}
if (targetConfig != null) {
ret.append(", target=").append(targetConfig);
}
return ret.length() > 0 ? ret.toString() : null;
}
/**
* Get the parts of a path
*
* @return the parts of an path or null if no path was used
*/
public List<String> getPathParts() {
return pathParts;
}
/**
* Get the path combined with proper escaping
*
* @return path as string or null if no path is given.
*/
public String getPath() {
return EscapeUtil.combineToPath(pathParts);
}
/**
* Convert this request to a JSON object, which can be used as a part of a return value.
*
* @return JSON object representing this base request object
*/
public JSONObject toJSON() {
JSONObject ret = new JSONObject();
ret.put("type",type.getName());
if (targetConfig != null) {
ret.put("target", targetConfig.toJSON());
}
if (pathParts != null) {
try {
ret.put("path",getPath());
} catch (UnsupportedOperationException exp) {
// Happens when request doesnt support paths
}
}
return ret;
}
// Init parameters and value fault handler
private void initParameters(ProcessingParameters pParams) {
processingConfig = pParams;
String ignoreErrors = processingConfig.get(ConfigKey.IGNORE_ERRORS);
if (ignoreErrors != null && ignoreErrors.matches("^(true|yes|on|1)$")) {
valueFaultHandler = ValueFaultHandler.IGNORING_VALUE_FAULT_HANDLER;
} else {
valueFaultHandler = ValueFaultHandler.THROWING_VALUE_FAULT_HANDLER;
}
}
private void verifyPath(List<String> pPathParts) {
if (pPathParts != null && !pPathParts.isEmpty() && pPathParts.get(pPathParts.size() - 1) == null) {
String path = EscapeUtil.combineToPath(pPathParts);
throw new IllegalArgumentException("Path '" + path + "' must not end with a wildcard");
}
}
}