package rocks.inspectit.shared.all.instrumentation.config.impl; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.ArrayUtils; import rocks.inspectit.shared.all.instrumentation.config.IMethodInstrumentationPoint; import rocks.inspectit.shared.all.instrumentation.config.PriorityEnum; /** * Registered sensor config used with the server-side instrumentation. * * @author Ivan Senic * */ public class SensorInstrumentationPoint implements IMethodInstrumentationPoint { /** * The method id. */ private long id; /** * List of sensor ids to run on the method. */ private long[] sensorIds = new long[0]; /** * Backing array for figuring the priority order of the sensor ids. Bytes are enough to store * values till 128 so we are safe here. * * @see #addSensorId(long, PriorityEnum) */ private transient byte[] sensorPriorities = new byte[0]; /** * If it's constructor to be instrumented. */ private boolean constructor; /** * If the invocation should be started. */ private boolean startsInvocation; /** * Additional settings are stored in this map. */ private Map<String, Object> settings; /** * If <code>propertyAccess</code> is set to true, then this list contains at least one element. * The contents is of type {@link PropertyPathStart}. */ private List<PropertyPathStart> propertyAccessorList; /** * {@inheritDoc} */ public long getId() { return id; } /** * Sets {@link #id}. * * @param id * New value for {@link #id} */ public void setId(long id) { this.id = id; } /** * {@inheritDoc} */ public long[] getSensorIds() { return sensorIds; } /** * Adds sensor Id if one does not exists already and properly sorts the id in the * {@link #sensorIds} array based on the priority. * * @param sensorId * id to add * @param priorityEnum * {@link PriorityEnum} of the sensor. * @return true if sensor id has been added, false otherwise */ public boolean addSensorId(long sensorId, PriorityEnum priorityEnum) { // don't add existing ones if (containsSensorId(sensorId)) { return false; } // check insert index by priority // we want sensor with highest priority to be first, thus we need to negate the ordinal // add in addition -1 to avoid having negative zero byte priority = (byte) (-1 - priorityEnum.ordinal()); int index = Math.abs(Arrays.binarySearch(sensorPriorities, priority) + 1); // update both arrays int length = sensorIds.length; long[] updateIds = new long[length + 1]; System.arraycopy(sensorIds, 0, updateIds, 0, index); System.arraycopy(sensorIds, index, updateIds, index + 1, length - index); updateIds[index] = sensorId; byte[] updatePriority = new byte[length + 1]; System.arraycopy(sensorPriorities, 0, updatePriority, 0, index); System.arraycopy(sensorPriorities, index, updatePriority, index + 1, length - index); updatePriority[index] = priority; sensorIds = updateIds; sensorPriorities = updatePriority; return true; } /** * If sensor if is contained in this {@link SensorInstrumentationPoint}. * * @param sensorId * sensor id to check * @return <code>true</code> if given sensor id is contained in the * {@link SensorInstrumentationPoint} */ public boolean containsSensorId(long sensorId) { return ArrayUtils.contains(sensorIds, sensorId); } /** * {@inheritDoc} */ public boolean isStartsInvocation() { return startsInvocation; } /** * Sets {@link #startsInvocation}. * * @param startsInvocation * New value for {@link #startsInvocation} */ public void setStartsInvocation(boolean startsInvocation) { this.startsInvocation = startsInvocation; } /** * Gets {@link #constructor}. * * @return {@link #constructor} */ public boolean isConstructor() { return constructor; } /** * Sets {@link #constructor}. * * @param constructor * New value for {@link #constructor} */ public void setConstructor(boolean constructor) { this.constructor = constructor; } /** * {@inheritDoc} */ public Map<String, Object> getSettings() { return settings; } /** * Sets {@link #settings}. * * @param settings * New value for {@link #settings} */ public void setSettings(Map<String, Object> settings) { this.settings = settings; } /** * Adds all given settings to the settings map. * * @param settings * Map of settings to add. */ public void addSettings(Map<String, Object> settings) { if (null == this.settings) { this.settings = new HashMap<String, Object>(settings.size()); } this.settings.putAll(settings); } /** * {@inheritDoc} */ public List<PropertyPathStart> getPropertyAccessorList() { return propertyAccessorList; } /** * Sets {@link #propertyAccessorList}. * * @param propertyAccessorList * New value for {@link #propertyAccessorList} */ public void setPropertyAccessorList(List<PropertyPathStart> propertyAccessorList) { this.propertyAccessorList = propertyAccessorList; } /** * Adds one {@link PropertyPathStart} to the list of the property acc list. * * @param propertyPathStart * {@link PropertyPathStart} to add. */ public void addPropertyAccessor(PropertyPathStart propertyPathStart) { if (null == this.propertyAccessorList) { this.propertyAccessorList = new ArrayList<PropertyPathStart>(1); } this.propertyAccessorList.add(propertyPathStart); } /** * {@inheritDoc} */ public boolean isPropertyAccess() { return CollectionUtils.isNotEmpty(propertyAccessorList); } }