/* * The contents of this file are subject to the terms of the Common Development and * Distribution License (the License). You may not use this file except in compliance with the * License. * * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the * specific language governing permission and limitations under the License. * * When distributing Covered Software, include this CDDL Header Notice in each file and include * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL * Header, with the fields enclosed by brackets [] replaced by your own identifying * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2016 ForgeRock AS. */ package org.opends.server.api; import static org.opends.server.core.DirectoryServer.*; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.UUID; import org.forgerock.opendj.ldap.ByteString; import org.forgerock.opendj.ldap.DN; import org.forgerock.opendj.ldap.GeneralizedTime; import org.forgerock.opendj.ldap.schema.AttributeType; import org.forgerock.opendj.ldap.schema.CoreSchema; import org.forgerock.opendj.ldap.schema.Syntax; import org.opends.server.types.Attribute; import org.opends.server.types.Attribute.RemoveOnceSwitchingAttributes; import org.opends.server.types.AttributeBuilder; import org.opends.server.types.Attributes; import org.opends.server.types.PublicAPI; import org.opends.server.types.StabilityLevel; /** * This class is used to hold monitoring data, i.e. a list of attributes. It provides convenient * methods to easily build such data. *

* Note:
* Creating monitor entries may become a lot easier once we've migrated to the SDK Entry class: * *

 * Entry entry = ...;
 * entry.addAttribute("stringStat", "aString")
 *       .addAttribute("integerStat", 12345)
 *       .addAttribute("dnStat", DN.valueOf("dc=aDN");
 * 
* * We could also envisage an annotation based approach where we determine the monitor content from * annotated fields/methods in an object. */ @PublicAPI(stability = StabilityLevel.PRIVATE) public final class MonitorData implements Iterable { private final List attrs; /** Constructor to use when the number of attributes to create is unknown. */ public MonitorData() { attrs = new ArrayList<>(); } /** * Constructor that accepts the number of attributes to create. * * @param expectedAttributesCount * number of attributes that will be added */ public MonitorData(int expectedAttributesCount) { attrs = new ArrayList<>(expectedAttributesCount); } /** * Adds an attribute with the provided name and value. * * @param attrName * the attribute name * @param attrValue * the attribute value */ public void add(String attrName, Object attrValue) { Syntax syntax; if (attrValue instanceof String || attrValue instanceof ByteString || attrValue instanceof Float || attrValue instanceof Double) { // coming first because they are the most common types syntax = CoreSchema.getDirectoryStringSyntax(); } else if (attrValue instanceof Number) { syntax = CoreSchema.getIntegerSyntax(); } else if (attrValue instanceof Boolean) { syntax = CoreSchema.getBooleanSyntax(); } else if (attrValue instanceof DN) { syntax = CoreSchema.getDNSyntax(); } else if (attrValue instanceof Date) { syntax = CoreSchema.getGeneralizedTimeSyntax(); attrValue = GeneralizedTime.valueOf((Date) attrValue); } else if (attrValue instanceof Calendar) { syntax = CoreSchema.getGeneralizedTimeSyntax(); attrValue = GeneralizedTime.valueOf((Calendar) attrValue); } else if (attrValue instanceof UUID) { syntax = CoreSchema.getUUIDSyntax(); } else { syntax = CoreSchema.getDirectoryStringSyntax(); } add(attrName, syntax, attrValue); } private void add(String attrName, Syntax syntax, Object attrValue) { AttributeType attrType = getInstance().getServerContext().getSchema().getAttributeType(attrName, syntax); attrs.add(Attributes.create(attrType, String.valueOf(attrValue))); } /** * Adds an attribute with the provided name and value if the value is not null. * * @param attrName * the attribute name * @param attrValue * the attribute value */ public void addIfNotNull(String attrName, Object attrValue) { if (attrValue != null) { add(attrName, attrValue); } } /** * Adds an attribute with the provided name and values. * * @param attrName * the attribute name * @param attrValues * the attribute values */ @RemoveOnceSwitchingAttributes(comment = "once using the non immutable SDK's Attribute class, " + "we can incrementally build an attribute by using the add(String attrName, Object attrValue) method") public void add(String attrName, Collection attrValues) { AttributeBuilder builder = new AttributeBuilder(attrName); builder.addAllStrings(attrValues); attrs.add(builder.toAttribute()); } /** * Adds all the properties from the provided bean as attributes, prepending the provided prefix. * * @param bean * the bean from which to read the properties * @param attributesPrefix * the prefix to prepend to the attributes read from the bean * @throws ReflectiveOperationException * if a problem occurs while reading the properties of the bean */ public void addBean(Object bean, String attributesPrefix) throws ReflectiveOperationException { for (Method method : bean.getClass().getMethods()) { if (method.getName().startsWith("get")) { Class returnType = method.getReturnType(); if (returnType.equals(int.class) || returnType.equals(long.class) || returnType.equals(String.class)) { addStatAttribute(attributesPrefix, bean, method, 3); } } else if (method.getName().startsWith("is") && method.getReturnType().equals(boolean.class)) { addStatAttribute(attributesPrefix, bean, method, 2); } } } private void addStatAttribute(String attrPrefix, Object stats, Method method, int skipNameLen) throws ReflectiveOperationException { String attrName = attrPrefix + method.getName().substring(skipNameLen); add(attrName, method.invoke(stats)); } @Override public Iterator iterator() { return attrs.iterator(); } /** * Returns the number of attributes. * * @return the number of attributes */ public int size() { return attrs.size(); } @Override public String toString() { return getClass().getSimpleName() + attrs; } }