/**
* 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.mainagent.builder;
import java.util.HashSet;
import java.util.Set;
import org.aim.api.exceptions.InstrumentationException;
import org.aim.api.instrumentation.AbstractEnclosingProbe;
import org.lpe.common.util.LpeNumericUtils;
import org.lpe.common.util.LpeSupportedTypes;
/**
* Builder for creating a combined probe snippet.
*
* @author Alexander Wert
*
*/
public class ProbeBuilder {
private static final String GRANULARITY_INIT_PART = "\n_GenericProbe_threadId=java.lang.Thread.currentThread().getId();";
private final String GRANULARITY_BEFORE_PART;
private static final String GRANULARITY_AFTER_PART = "}\n";
private final boolean useGranularity;
private String methodSignature;
Snippet currentSnippet = new Snippet();
private final Set<Class<? extends AbstractEnclosingProbe>> injectedProbeTypes;
/**
* Constructor.
*
* @param methodSignature
* target method to instrument
*/
public ProbeBuilder(String methodSignature, double granularity) {
this.methodSignature = methodSignature;
injectedProbeTypes = new HashSet<>();
int[] granNumDenom = LpeNumericUtils.getFractionFromDouble(granularity);
GRANULARITY_BEFORE_PART = "\nif(_GenericProbe_threadId % " + granNumDenom[1] + " < " + granNumDenom[0] + ") {";
if (granNumDenom[0] < granNumDenom[1]) {
useGranularity = true;
} else {
useGranularity = false;
}
}
/**
* Adds a probe for injection.
*
* @param probeType
* class of the probe to inject
* @return builder instance
* @throws InstrumentationException
* if injection fails
*/
public ProbeBuilder inject(Class<? extends AbstractEnclosingProbe> probeType) throws InstrumentationException {
if (!injectedProbeTypes.contains(probeType)) {
MultiSnippet mSnippet = SnippetProvider.getInstance().getSnippet(probeType);
String beforePart = mSnippet.getBeforePart(methodSignature) + currentSnippet.getBeforePart();
currentSnippet.setBeforePart(beforePart);
String afterPart = currentSnippet.getAfterPart() + mSnippet.getAfterPart(methodSignature);
currentSnippet.setAfterPart(afterPart);
String incPart = currentSnippet.getIncrementalPart() + mSnippet.getIncrementalPart();
currentSnippet.setIncrementalPart(incPart);
currentSnippet.getVariables().putAll(mSnippet.getVariables());
injectedProbeTypes.add(probeType);
}
return this;
}
/**
* Builds a combined probe snippet surrounded by common probe code.
*
* @return combined probe snippet.
* @throws InstrumentationException
* if snippet cannot be built
*/
public Snippet build() throws InstrumentationException {
MultiSnippet mSnippet = SnippetProvider.getInstance().getGenericSnippet();
Snippet resultSnippet = new Snippet();
String beforePart = mSnippet.getBeforePart(methodSignature) + currentSnippet.getBeforePart();
String afterPart = currentSnippet.getAfterPart() + mSnippet.getAfterPart(methodSignature);
if (useGranularity) {
StringBuilder initPartBuilder = new StringBuilder();
for (String var : mSnippet.getVariables().keySet()) {
initPartBuilder.append("\n");
initPartBuilder.append(var);
initPartBuilder.append("=");
LpeSupportedTypes lst = LpeSupportedTypes.get(mSnippet.getVariables().get(var));
if (lst == null || lst == LpeSupportedTypes.String) {
initPartBuilder.append("null");
} else {
initPartBuilder.append(LpeSupportedTypes.getValueOfType("0", lst));
}
initPartBuilder.append(";");
}
for (String var : currentSnippet.getVariables().keySet()) {
initPartBuilder.append("\n");
initPartBuilder.append(var);
initPartBuilder.append("=");
LpeSupportedTypes lst = LpeSupportedTypes.get(currentSnippet.getVariables().get(var));
if (lst == null || lst == LpeSupportedTypes.String) {
initPartBuilder.append("null");
} else {
initPartBuilder.append(LpeSupportedTypes.getValueOfType("0", lst));
}
initPartBuilder.append(";");
}
beforePart = initPartBuilder.toString() + GRANULARITY_INIT_PART + GRANULARITY_BEFORE_PART + beforePart
+ GRANULARITY_AFTER_PART;
afterPart = GRANULARITY_BEFORE_PART + afterPart + GRANULARITY_AFTER_PART;
}
beforePart = beforePart.replace(AbstractEnclosingProbe.METHOD_SIGNATURE_PLACE_HOLDER, "\"" + methodSignature
+ "\"");
beforePart = beforePart.replace("((java.util.Hashtable<K, Object>) System.getProperties())", "System.getProperties()");
afterPart = afterPart.replace(AbstractEnclosingProbe.METHOD_SIGNATURE_PLACE_HOLDER, "\"" + methodSignature
+ "\"");
afterPart = afterPart.replace("((java.util.Hashtable<K, Object>) System.getProperties())", "System.getProperties()");
resultSnippet.setBeforePart(beforePart);
resultSnippet.setAfterPart(afterPart);
resultSnippet.setIncrementalPart(currentSnippet.getIncrementalPart());
resultSnippet.getVariables().putAll(currentSnippet.getVariables());
resultSnippet.getVariables().putAll(mSnippet.getVariables());
return resultSnippet;
}
}