package org.jolokia.history;
import java.io.Serializable;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import 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.
*/
/**
* Key used in the {@link HistoryStore} for indexing historical values. The key has
* a type reflecting the kind of JMX operataion (<code>attribute</code> or <code>operation</code>)
* and can be used in proxy mode for different targets.
*
* @author roland
* @since Jun 12, 2009
*/
public class HistoryKey implements Serializable {
private static final long serialVersionUID = 42L;
private String type;
private ObjectName mBean;
private String secondary;
private String path;
private String target;
/**
* Create a key from a read request from which all necessary information is extracted
*
* @param pJmxRequest read request
*/
HistoryKey(JmxReadRequest pJmxRequest) {
init(pJmxRequest);
if (pJmxRequest.getAttributeNames() != null && pJmxRequest.getAttributeNames().size() > 1) {
throw new IllegalArgumentException("A key cannot contain more than one attribute");
}
type = "attribute";
secondary = pJmxRequest.isMultiAttributeMode() ? pJmxRequest.getAttributeNames().get(0) : pJmxRequest.getAttributeName();
if (secondary == null) {
secondary = "(all)";
}
path = pJmxRequest.getPath();
}
/**
* Create a key from a write request from which all necessary information is extracted
*
* @param pJmxReq write request
*/
HistoryKey(JmxWriteRequest pJmxReq) {
init(pJmxReq);
type = "attribute";
secondary = pJmxReq.getAttributeName();
path = pJmxReq.getPath();
if (secondary == null) {
throw new IllegalArgumentException(type + " name must not be null");
}
}
/**
* Create a key from an exec request from which all necessary information is extracted
*
* @param pJmxReq read request
*/
HistoryKey(JmxExecRequest pJmxReq) {
init(pJmxReq);
type = "operation";
secondary = pJmxReq.getOperation();
path = null;
if (secondary == null) {
throw new IllegalArgumentException(type + " name must not be null");
}
}
private void init(JmxObjectNameRequest pJmxReq) {
if (pJmxReq.getObjectNameAsString() == null) {
throw new IllegalArgumentException("MBean name must not be null");
}
if (pJmxReq.getObjectName().isPattern()) {
throw new IllegalArgumentException("MBean name must not be a pattern");
}
if (pJmxReq.getTargetConfig() != null) {
target = pJmxReq.getTargetConfig().getUrl();
}
mBean = pJmxReq.getObjectName();
}
/**
* Constructor for type <code>operation</code>
*
* @param pMBean MBean name
* @param pOperation operation name
* @param pTarget optional target if used in proxy mode
* @throws MalformedObjectNameException if the mbean name is invalid
*/
public HistoryKey(String pMBean, String pOperation, String pTarget) throws MalformedObjectNameException {
type = "operation";
mBean = new ObjectName(pMBean);
secondary = pOperation;
path = null;
target = sanitize(pTarget);
}
// Return null for an empty string
private String sanitize(String pValue) {
return "".equals(pValue) ? null : pValue;
}
/**
* Constructor for type <code>attribute</code>
*
* @param pMBean MBean name
* @param pAttribute attribute
* @param pPath optional path
* @param pTarget optional proxy target
* @throws MalformedObjectNameException if the mbean name is invalid
*/
public HistoryKey(String pMBean, String pAttribute, String pPath, String pTarget)
throws MalformedObjectNameException {
type = "attribute";
mBean = new ObjectName(pMBean);
secondary = pAttribute;
path = sanitize(pPath);
target = pTarget;
}
/**
* Whether this key embraces a MBean pattern
*
* @return true if the the included MBean is a pattern
*/
public boolean isMBeanPattern() {
return mBean.isPattern();
}
/**
* Whether the key matches the given MBean name
*
* @param pKey to match
* @return true if the given mbean matches the Mbean encapsulated by this key
*/
public boolean matches(HistoryKey pKey) {
return mBean.apply(pKey.mBean);
}
// CHECKSTYLE:OFF
/** {@inheritDoc} */
@Override
@SuppressWarnings("PMD.IfStmtsMustUseBraces")
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
HistoryKey that = (HistoryKey) o;
if (!mBean.equals(that.mBean)) return false;
if (path != null ? !path.equals(that.path) : that.path != null) return false;
if (!secondary.equals(that.secondary)) return false;
if (target != null ? !target.equals(that.target) : that.target != null)
return false;
if (!type.equals(that.type)) return false;
return true;
}
// CHECKSTYLE:ON
/** {@inheritDoc} */
@Override
public int hashCode() {
int result = type.hashCode();
result = 31 * result + mBean.hashCode();
result = 31 * result + secondary.hashCode();
result = 31 * result + (path != null ? path.hashCode() : 0);
result = 31 * result + (target != null ? target.hashCode() : 0);
return result;
}
/** {@inheritDoc} */
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("HistoryKey");
sb.append("{type='").append(type).append('\'');
sb.append(", mBean=").append(mBean);
sb.append(", secondary='").append(secondary).append('\'');
sb.append(", path='").append(path).append('\'');
sb.append(", target='").append(target).append('\'');
sb.append('}');
return sb.toString();
}
}