| File was renamed from opends/src/server/org/opends/server/types/CompressedSchema.java |
| | |
| | | * |
| | | * Portions Copyright 2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.types; |
| | | import org.opends.messages.Message; |
| | | package org.opends.server.core; |
| | | |
| | | |
| | | |
| | |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.messages.Message; |
| | | import org.opends.server.api.CompressedSchema; |
| | | import org.opends.server.loggers.debug.DebugTracer; |
| | | import org.opends.server.protocols.asn1.ASN1Element; |
| | | import org.opends.server.protocols.asn1.ASN1Integer; |
| | |
| | | import org.opends.server.protocols.asn1.ASN1Reader; |
| | | import org.opends.server.protocols.asn1.ASN1Sequence; |
| | | import org.opends.server.protocols.asn1.ASN1Writer; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.ByteArray; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.ObjectClass; |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | |
| | | |
| | | |
| | | /** |
| | | * This class provides a utility for interacting with compressed |
| | | * representations of schema elements. |
| | | * This class provides a default implementation of a compressed schema manager |
| | | * that will store the schema definitions in a binary file |
| | | * (config/schematokens.dat). |
| | | */ |
| | | @org.opends.server.types.PublicAPI( |
| | | stability=org.opends.server.types.StabilityLevel.PRIVATE, |
| | | mayInstantiate=false, |
| | | mayExtend=false, |
| | | mayInvoke=false) |
| | | public final class CompressedSchema |
| | | public final class DefaultCompressedSchema |
| | | extends CompressedSchema |
| | | { |
| | | /** |
| | | * The tracer object for the debug logger. |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * The singleton instance that will be used to perform the mapping. |
| | | */ |
| | | private static CompressedSchema instance = new CompressedSchema(); |
| | | |
| | | |
| | | |
| | | // The counter used for attribute descriptions. |
| | | private AtomicInteger adCounter; |
| | | |
| | |
| | | private ConcurrentHashMap<ByteArray,AttributeType> atDecodeMap; |
| | | |
| | | // The map between encoded representations and attribute options. |
| | | private ConcurrentHashMap<ByteArray, |
| | | LinkedHashSet<String>> aoDecodeMap; |
| | | private ConcurrentHashMap<ByteArray,LinkedHashSet<String>> aoDecodeMap; |
| | | |
| | | // The map between encoded representations and object class sets. |
| | | private ConcurrentHashMap<ByteArray, |
| | | Map<ObjectClass,String>> ocDecodeMap; |
| | | private ConcurrentHashMap<ByteArray,Map<ObjectClass,String>> ocDecodeMap; |
| | | |
| | | // The map between attribute descriptions and their encoded |
| | | // representations. |
| | | private ConcurrentHashMap<AttributeType, |
| | | ConcurrentHashMap<LinkedHashSet<String>,ByteArray>> |
| | | adEncodeMap; |
| | | ConcurrentHashMap<LinkedHashSet<String>,ByteArray>> adEncodeMap; |
| | | |
| | | // The map between object class sets and encoded representations. |
| | | private ConcurrentHashMap<Map<ObjectClass,String>, |
| | | ByteArray> ocEncodeMap; |
| | | private ConcurrentHashMap<Map<ObjectClass,String>,ByteArray> ocEncodeMap; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new instance of this compressed schema manager. |
| | | */ |
| | | private CompressedSchema() |
| | | public DefaultCompressedSchema() |
| | | { |
| | | atDecodeMap = new ConcurrentHashMap<ByteArray,AttributeType>(); |
| | | aoDecodeMap = new ConcurrentHashMap<ByteArray, |
| | | LinkedHashSet<String>>(); |
| | | ocDecodeMap = new ConcurrentHashMap<ByteArray, |
| | | Map<ObjectClass,String>>(); |
| | | adEncodeMap = new ConcurrentHashMap<AttributeType, |
| | | ConcurrentHashMap<LinkedHashSet<String>, |
| | | ByteArray>>(); |
| | | ocEncodeMap = new ConcurrentHashMap<Map<ObjectClass,String>, |
| | | ByteArray>(); |
| | | aoDecodeMap = new ConcurrentHashMap<ByteArray,LinkedHashSet<String>>(); |
| | | ocDecodeMap = new ConcurrentHashMap<ByteArray,Map<ObjectClass,String>>(); |
| | | adEncodeMap = |
| | | new ConcurrentHashMap<AttributeType, |
| | | ConcurrentHashMap<LinkedHashSet<String>,ByteArray>>(); |
| | | ocEncodeMap = new ConcurrentHashMap<Map<ObjectClass,String>,ByteArray>(); |
| | | |
| | | adCounter = new AtomicInteger(1); |
| | | ocCounter = new AtomicInteger(1); |
| | |
| | | |
| | | try |
| | | { |
| | | // Determine the location of the compressed schema data file |
| | | // It should be in the config directory with a name of |
| | | // "schematokens.dat". If that file doesn't exist, then don't |
| | | // do anything. |
| | | // Determine the location of the compressed schema data file. It should |
| | | // be in the config directory with a name of "schematokens.dat". If that |
| | | // file doesn't exist, then don't do anything. |
| | | String path = DirectoryServer.getServerRoot() + File.separator + |
| | | CONFIG_DIR_NAME + File.separator + |
| | | COMPRESSED_SCHEMA_FILE_NAME; |
| | |
| | | reader = new ASN1Reader(inputStream); |
| | | |
| | | |
| | | // The first element in the file should be a sequence of object |
| | | // class sets. Each object class set will itself be a sequence |
| | | // of octet strings, where the first one is the token and the |
| | | // remaining elements are the names of the associated object |
| | | // classes. |
| | | ASN1Sequence ocSequence = |
| | | reader.readElement().decodeAsSequence(); |
| | | // The first element in the file should be a sequence of object class |
| | | // sets. Each object class set will itself be a sequence of octet |
| | | // strings, where the first one is the token and the remaining elements |
| | | // are the names of the associated object classes. |
| | | ASN1Sequence ocSequence = reader.readElement().decodeAsSequence(); |
| | | for (ASN1Element element : ocSequence.elements()) |
| | | { |
| | | ArrayList<ASN1Element> elements = |
| | | element.decodeAsSequence().elements(); |
| | | ArrayList<ASN1Element> elements = element.decodeAsSequence().elements(); |
| | | ASN1OctetString os = elements.get(0).decodeAsOctetString(); |
| | | ByteArray token = new ByteArray(os.value()); |
| | | |
| | |
| | | os = elements.get(i).decodeAsOctetString(); |
| | | String ocName = os.stringValue(); |
| | | String lowerName = toLowerCase(ocName); |
| | | ObjectClass oc = |
| | | DirectoryServer.getObjectClass(lowerName, true); |
| | | ObjectClass oc = DirectoryServer.getObjectClass(lowerName, true); |
| | | ocMap.put(oc, ocName); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | // The second element in the file should be an integer element |
| | | // that holds the value to use to initialize the object class |
| | | // counter. |
| | | // The second element in the file should be an integer element that holds |
| | | // the value to use to initialize the object class counter. |
| | | ASN1Element counterElement = reader.readElement(); |
| | | ocCounter.set(counterElement.decodeAsInteger().intValue()); |
| | | |
| | | |
| | | // The third element in the file should be a sequence of |
| | | // attribute description components. Each attribute description |
| | | // component will itself be a sequence of octet strings, where |
| | | // the first one is the token, the second is the attribute name, |
| | | // and all remaining elements are the attribute options. |
| | | ASN1Sequence adSequence = |
| | | reader.readElement().decodeAsSequence(); |
| | | // The third element in the file should be a sequence of attribute |
| | | // description components. Each attribute description component will |
| | | // itself be a sequence of octet strings, where the first one is the |
| | | // token, the second is the attribute name, and all remaining elements are |
| | | // the attribute options. |
| | | ASN1Sequence adSequence = reader.readElement().decodeAsSequence(); |
| | | for (ASN1Element element : adSequence.elements()) |
| | | { |
| | | ArrayList<ASN1Element> elements = |
| | | element.decodeAsSequence().elements(); |
| | | ArrayList<ASN1Element> elements = element.decodeAsSequence().elements(); |
| | | ASN1OctetString os = elements. get(0).decodeAsOctetString(); |
| | | ByteArray token = new ByteArray(os.value()); |
| | | |
| | |
| | | adEncodeMap.get(attrType); |
| | | if (map == null) |
| | | { |
| | | map = new ConcurrentHashMap<LinkedHashSet<String>, |
| | | ByteArray>(1); |
| | | map = new ConcurrentHashMap<LinkedHashSet<String>,ByteArray>(1); |
| | | map.put(options, token); |
| | | adEncodeMap.put(attrType, map); |
| | | } |
| | |
| | | } |
| | | |
| | | |
| | | // The fourth element in the file should be an integer element |
| | | // that holds the value to use to initialize the attribute |
| | | // description counter. |
| | | // The fourth element in the file should be an integer element that holds |
| | | // the value to use to initialize the attribute description counter. |
| | | counterElement = reader.readElement(); |
| | | adCounter.set(counterElement.decodeAsInteger().intValue()); |
| | | } |
| | |
| | | /** |
| | | * Writes the compressed schema information to disk. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while writing |
| | | * the updated information. |
| | | * @throws DirectoryException If a problem occurs while writing the updated |
| | | * information. |
| | | */ |
| | | private void save() |
| | | throws DirectoryException |
| | |
| | | ASN1Writer writer = null; |
| | | try |
| | | { |
| | | // Determine the location of the "live" compressed schema data |
| | | // file, and then append ".tmp" to get the name of the temporary |
| | | // file that we will use. |
| | | // Determine the location of the "live" compressed schema data file, and |
| | | // then append ".tmp" to get the name of the temporary file that we will |
| | | // use. |
| | | String path = DirectoryServer.getServerRoot() + File.separator + |
| | | CONFIG_DIR_NAME + File.separator + |
| | | COMPRESSED_SCHEMA_FILE_NAME; |
| | |
| | | writer = new ASN1Writer(outputStream); |
| | | |
| | | |
| | | // The first element in the file should be a sequence of object |
| | | // class sets. Each object class set will itself be a sequence |
| | | // of octet strings, where the first one is the token and the |
| | | // remaining elements are the names of the associated object |
| | | // classes. |
| | | // The first element in the file should be a sequence of object class |
| | | // sets. Each object class set will itself be a sequence of octet |
| | | // strings, where the first one is the token and the remaining elements |
| | | // are the names of the associated object classes. |
| | | ArrayList<ASN1Element> ocElements = |
| | | new ArrayList<ASN1Element>(ocDecodeMap.size()); |
| | | for (Map.Entry<ByteArray,Map<ObjectClass,String>> mapEntry : |
| | |
| | | writer.writeElement(new ASN1Sequence(ocElements)); |
| | | |
| | | |
| | | // The second element in the file should be an integer element |
| | | // that holds the value to use to initialize the object class |
| | | // counter. |
| | | // The second element in the file should be an integer element that holds |
| | | // the value to use to initialize the object class counter. |
| | | writer.writeElement(new ASN1Integer(ocCounter.get())); |
| | | |
| | | |
| | | // The third element in the file should be a sequence of |
| | | // attribute description components. Each attribute description |
| | | // component will itself be a sequence of octet strings, where |
| | | // the first one is the token, the second is the attribute name, |
| | | // and all remaining elements are the attribute options. |
| | | // The third element in the file should be a sequence of attribute |
| | | // description components. Each attribute description component will |
| | | // itself be a sequence of octet strings, where the first one is the |
| | | // token, the second is the attribute name, and all remaining elements are |
| | | // the attribute options. |
| | | ArrayList<ASN1Element> adElements = |
| | | new ArrayList<ASN1Element>(atDecodeMap.size()); |
| | | for (ByteArray token : atDecodeMap.keySet()) |
| | |
| | | writer.writeElement(new ASN1Sequence(adElements)); |
| | | |
| | | |
| | | // The fourth element in the file should be an integer element |
| | | // that holds the value to use to initialize the attribute |
| | | // description counter. |
| | | // The fourth element in the file should be an integer element that holds |
| | | // the value to use to initialize the attribute description counter. |
| | | writer.writeElement(new ASN1Integer(adCounter.get())); |
| | | |
| | | |
| | |
| | | |
| | | if (liveFile.exists()) |
| | | { |
| | | File saveFile = |
| | | new File(liveFile.getAbsolutePath() + ".save"); |
| | | File saveFile = new File(liveFile.getAbsolutePath() + ".save"); |
| | | if (saveFile.exists()) |
| | | { |
| | | saveFile.delete(); |
| | |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | Message message = |
| | | ERR_COMPRESSEDSCHEMA_CANNOT_WRITE_UPDATED_DATA. |
| | | get(stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException( |
| | | DirectoryServer.getServerErrorResultCode(), |
| | | message, e); |
| | | Message message = ERR_COMPRESSEDSCHEMA_CANNOT_WRITE_UPDATED_DATA.get( |
| | | stackTraceToSingleLineString(e)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message, e); |
| | | } |
| | | finally |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Encodes the provided set of object classes to a byte array. If |
| | | * the same set had been previously encoded, then the cached value |
| | | * will be used. Otherwise, a new value will be created. |
| | | * |
| | | * @param objectClasses The set of object classes for which to |
| | | * retrieve the corresponding byte array |
| | | * token. |
| | | * |
| | | * @return A byte array containing the identifier assigned to the |
| | | * object class set. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while attempting |
| | | * to determine the appropriate |
| | | * identifier. |
| | | * {@inheritDoc} |
| | | */ |
| | | public static byte[] |
| | | encodeObjectClasses(Map<ObjectClass,String> objectClasses) |
| | | @Override() |
| | | public byte[] encodeObjectClasses(Map<ObjectClass,String> objectClasses) |
| | | throws DirectoryException |
| | | { |
| | | ByteArray encodedClasses = |
| | | instance.ocEncodeMap.get(objectClasses); |
| | | ByteArray encodedClasses = ocEncodeMap.get(objectClasses); |
| | | if (encodedClasses == null) |
| | | { |
| | | synchronized (instance.ocEncodeMap) |
| | | synchronized (ocEncodeMap) |
| | | { |
| | | int setValue = instance.ocCounter.getAndIncrement(); |
| | | int setValue = ocCounter.getAndIncrement(); |
| | | byte[] array = encodeInt(setValue); |
| | | |
| | | encodedClasses = new ByteArray(array); |
| | | instance.ocEncodeMap.put(objectClasses, encodedClasses); |
| | | instance.ocDecodeMap.put(encodedClasses, objectClasses); |
| | | ocEncodeMap.put(objectClasses, encodedClasses); |
| | | ocDecodeMap.put(encodedClasses, objectClasses); |
| | | |
| | | instance.save(); |
| | | save(); |
| | | return array; |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * Decodes an object class set from the provided byte array. |
| | | * |
| | | * @param encodedObjectClasses The byte array containing the |
| | | * object class set identifier. |
| | | * |
| | | * @return The decoded object class set. |
| | | * |
| | | * @throws DirectoryException If the provided byte array cannot be |
| | | * decoded as an object class set. |
| | | * {@inheritDoc} |
| | | */ |
| | | public static Map<ObjectClass,String> |
| | | decodeObjectClasses(byte[] encodedObjectClasses) |
| | | @Override() |
| | | public Map<ObjectClass,String> decodeObjectClasses( |
| | | byte[] encodedObjectClasses) |
| | | throws DirectoryException |
| | | { |
| | | ByteArray byteArray = new ByteArray(encodedObjectClasses); |
| | | Map<ObjectClass,String> ocMap = |
| | | instance.ocDecodeMap.get(byteArray); |
| | | Map<ObjectClass,String> ocMap = ocDecodeMap.get(byteArray); |
| | | if (ocMap == null) |
| | | { |
| | | Message message = ERR_COMPRESSEDSCHEMA_UNKNOWN_OC_TOKEN.get( |
| | | bytesToHex(encodedObjectClasses)); |
| | | throw new DirectoryException( |
| | | DirectoryServer.getServerErrorResultCode(), |
| | | message); |
| | | bytesToHex(encodedObjectClasses)); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message); |
| | | } |
| | | else |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Encodes the information in the provided attribute to a byte |
| | | * array. |
| | | * |
| | | * @param attribute The attribute to be encoded. |
| | | * |
| | | * @return An encoded representation of the provided attribute. |
| | | * |
| | | * @throws DirectoryException If a problem occurs while attempting |
| | | * to determine the appropriate |
| | | * identifier. |
| | | * {@inheritDoc} |
| | | */ |
| | | public static byte[] encodeAttribute(Attribute attribute) |
| | | @Override() |
| | | public byte[] encodeAttribute(Attribute attribute) |
| | | throws DirectoryException |
| | | { |
| | | AttributeType type = attribute.getAttributeType(); |
| | | LinkedHashSet<String> options = attribute.getOptions(); |
| | | |
| | | ConcurrentHashMap<LinkedHashSet<String>,ByteArray> map = |
| | | instance.adEncodeMap.get(type); |
| | | adEncodeMap.get(type); |
| | | if (map == null) |
| | | { |
| | | byte[] array; |
| | | synchronized (instance.adEncodeMap) |
| | | synchronized (adEncodeMap) |
| | | { |
| | | map = new ConcurrentHashMap<LinkedHashSet<String>, |
| | | ByteArray>(1); |
| | | map = new ConcurrentHashMap<LinkedHashSet<String>,ByteArray>(1); |
| | | |
| | | int intValue = instance.adCounter.getAndIncrement(); |
| | | int intValue = adCounter.getAndIncrement(); |
| | | array = encodeInt(intValue); |
| | | ByteArray byteArray = new ByteArray(array); |
| | | map.put(options,byteArray); |
| | | |
| | | instance.adEncodeMap.put(type, map); |
| | | instance.atDecodeMap.put(byteArray, type); |
| | | instance.aoDecodeMap.put(byteArray, options); |
| | | instance.save(); |
| | | adEncodeMap.put(type, map); |
| | | atDecodeMap.put(byteArray, type); |
| | | aoDecodeMap.put(byteArray, options); |
| | | save(); |
| | | } |
| | | |
| | | return encodeAttribute(array, attribute); |
| | |
| | | byte[] array; |
| | | synchronized (map) |
| | | { |
| | | int intValue = instance.adCounter.getAndIncrement(); |
| | | int intValue = adCounter.getAndIncrement(); |
| | | array = encodeInt(intValue); |
| | | byteArray = new ByteArray(array); |
| | | map.put(options,byteArray); |
| | | |
| | | instance.atDecodeMap.put(byteArray, type); |
| | | instance.aoDecodeMap.put(byteArray, options); |
| | | instance.save(); |
| | | atDecodeMap.put(byteArray, type); |
| | | aoDecodeMap.put(byteArray, options); |
| | | save(); |
| | | } |
| | | |
| | | return encodeAttribute(array, attribute); |
| | |
| | | * |
| | | * @return An encoded representation of the provided attribute. |
| | | */ |
| | | private static byte[] encodeAttribute(byte[] adArray, |
| | | Attribute attribute) |
| | | private byte[] encodeAttribute(byte[] adArray, Attribute attribute) |
| | | { |
| | | LinkedHashSet<AttributeValue> values = attribute.getValues(); |
| | | int totalValuesLength = 0; |
| | |
| | | |
| | | |
| | | /** |
| | | * Decodes the contents of the provided array as an attribute. |
| | | * |
| | | * @param encodedEntry The byte array containing the encoded |
| | | * entry. |
| | | * @param startPos The position within the array of the first |
| | | * byte for the attribute to decode. |
| | | * @param length The number of bytes contained in the |
| | | * encoded attribute. |
| | | * |
| | | * @return The decoded attribute. |
| | | * |
| | | * @throws DirectoryException If the attribute could not be |
| | | * decoded properly for some reason. |
| | | * {@inheritDoc} |
| | | */ |
| | | public static Attribute decodeAttribute(byte[] encodedEntry, |
| | | int startPos, int length) |
| | | @Override() |
| | | public Attribute decodeAttribute(byte[] encodedEntry, int startPos, |
| | | int length) |
| | | throws DirectoryException |
| | | { |
| | | // Figure out how many bytes are in the token that is the |
| | | // placeholder for the attribute description. |
| | | // Figure out how many bytes are in the token that is the placeholder for |
| | | // the attribute description. |
| | | int pos = startPos; |
| | | int adArrayLength = encodedEntry[pos] & 0x7F; |
| | | if (adArrayLength != encodedEntry[pos++]) |
| | |
| | | adArrayLength = 0; |
| | | for (int i=0; i < numLengthBytes; i++, pos++) |
| | | { |
| | | adArrayLength = |
| | | (adArrayLength << 8) | (encodedEntry[pos] & 0xFF); |
| | | adArrayLength = (adArrayLength << 8) | (encodedEntry[pos] & 0xFF); |
| | | } |
| | | } |
| | | |
| | | |
| | | // Get the attribute description token and make sure it resolves |
| | | // to an attribute type and option set. |
| | | // Get the attribute description token and make sure it resolves to an |
| | | // attribute type and option set. |
| | | ByteArray adArray = new ByteArray(new byte[adArrayLength]); |
| | | System.arraycopy(encodedEntry, pos, adArray.array(), 0, |
| | | adArrayLength); |
| | | System.arraycopy(encodedEntry, pos, adArray.array(), 0, adArrayLength); |
| | | pos += adArrayLength; |
| | | AttributeType attrType = instance.atDecodeMap.get(adArray); |
| | | LinkedHashSet<String> options = instance.aoDecodeMap.get(adArray); |
| | | AttributeType attrType = atDecodeMap.get(adArray); |
| | | LinkedHashSet<String> options = aoDecodeMap.get(adArray); |
| | | if ((attrType == null) || (options == null)) |
| | | { |
| | | Message message = ERR_COMPRESSEDSCHEMA_UNRECOGNIZED_AD_TOKEN. |
| | | get(bytesToHex(adArray.array())); |
| | | throw new DirectoryException( |
| | | DirectoryServer.getServerErrorResultCode(), |
| | | message); |
| | | Message message = ERR_COMPRESSEDSCHEMA_UNRECOGNIZED_AD_TOKEN.get( |
| | | bytesToHex(adArray.array())); |
| | | throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), |
| | | message); |
| | | } |
| | | |
| | | |
| | |
| | | valueLength = 0; |
| | | for (int j=0; j < valueLengthBytes; j++, pos++) |
| | | { |
| | | valueLength = |
| | | (valueLength << 8) | (encodedEntry[pos] & 0xFF); |
| | | valueLength = (valueLength << 8) | (encodedEntry[pos] & 0xFF); |
| | | } |
| | | } |
| | | |
| | | byte[] valueBytes = new byte[valueLength]; |
| | | System.arraycopy(encodedEntry, pos, valueBytes, 0, valueLength); |
| | | pos += valueLength; |
| | | values.add(new AttributeValue(attrType, |
| | | new ASN1OctetString(valueBytes))); |
| | | values.add(new AttributeValue(attrType, new ASN1OctetString(valueBytes))); |
| | | } |
| | | |
| | | return new Attribute(attrType, attrType.getPrimaryName(), options, |
| | | values); |
| | | return new Attribute(attrType, attrType.getPrimaryName(), options, values); |
| | | } |
| | | |
| | | |
| | |
| | | * |
| | | * @return The byte array containing the encoded int value. |
| | | */ |
| | | private static byte[] encodeInt(int intValue) |
| | | private byte[] encodeInt(int intValue) |
| | | { |
| | | byte[] array; |
| | | if (intValue <= 0xFF) |