| | |
| | | import java.util.LinkedHashMap; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | |
| | |
| | | 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.AttributeBuilder; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.Attributes; |
| | | import org.opends.server.types.ByteArray; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import org.opends.server.types.DirectoryException; |
| | |
| | | private ConcurrentHashMap<ByteArray,AttributeType> atDecodeMap; |
| | | |
| | | // The map between encoded representations and attribute options. |
| | | private ConcurrentHashMap<ByteArray,LinkedHashSet<String>> aoDecodeMap; |
| | | private ConcurrentHashMap<ByteArray,Set<String>> aoDecodeMap; |
| | | |
| | | // The map between encoded representations and object class sets. |
| | | 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<Set<String>,ByteArray>> adEncodeMap; |
| | | |
| | | // The map between object class sets and encoded representations. |
| | | private ConcurrentHashMap<Map<ObjectClass,String>,ByteArray> ocEncodeMap; |
| | |
| | | */ |
| | | 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>(); |
| | | atDecodeMap = new ConcurrentHashMap<ByteArray, AttributeType>(); |
| | | aoDecodeMap = new ConcurrentHashMap<ByteArray, Set<String>>(); |
| | | ocDecodeMap = new ConcurrentHashMap<ByteArray, Map<ObjectClass, String>>(); |
| | | adEncodeMap = new ConcurrentHashMap |
| | | <AttributeType, ConcurrentHashMap<Set<String>, ByteArray>>(); |
| | | ocEncodeMap = new ConcurrentHashMap<Map<ObjectClass, String>, ByteArray>(); |
| | | |
| | | adCounter = new AtomicInteger(1); |
| | | ocCounter = new AtomicInteger(1); |
| | |
| | | atDecodeMap.put(token, attrType); |
| | | aoDecodeMap.put(token, options); |
| | | |
| | | ConcurrentHashMap<LinkedHashSet<String>,ByteArray> map = |
| | | adEncodeMap.get(attrType); |
| | | ConcurrentHashMap<Set<String>, ByteArray> map = adEncodeMap |
| | | .get(attrType); |
| | | if (map == null) |
| | | { |
| | | map = new ConcurrentHashMap<LinkedHashSet<String>,ByteArray>(1); |
| | | map = new ConcurrentHashMap<Set<String>, ByteArray>(1); |
| | | map.put(options, token); |
| | | adEncodeMap.put(attrType, map); |
| | | } |
| | |
| | | for (ByteArray token : atDecodeMap.keySet()) |
| | | { |
| | | AttributeType attrType = atDecodeMap.get(token); |
| | | LinkedHashSet<String> options = aoDecodeMap.get(token); |
| | | Set<String> options = aoDecodeMap.get(token); |
| | | |
| | | ArrayList<ASN1Element> elements = |
| | | new ArrayList<ASN1Element>(options.size()+2); |
| | |
| | | throws DirectoryException |
| | | { |
| | | AttributeType type = attribute.getAttributeType(); |
| | | LinkedHashSet<String> options = attribute.getOptions(); |
| | | Set<String> options = attribute.getOptions(); |
| | | |
| | | ConcurrentHashMap<LinkedHashSet<String>,ByteArray> map = |
| | | adEncodeMap.get(type); |
| | | ConcurrentHashMap<Set<String>, ByteArray> map = adEncodeMap.get(type); |
| | | if (map == null) |
| | | { |
| | | byte[] array; |
| | | synchronized (adEncodeMap) |
| | | { |
| | | map = new ConcurrentHashMap<LinkedHashSet<String>,ByteArray>(1); |
| | | map = new ConcurrentHashMap<Set<String>,ByteArray>(1); |
| | | |
| | | int intValue = adCounter.getAndIncrement(); |
| | | array = encodeInt(intValue); |
| | |
| | | */ |
| | | private byte[] encodeAttribute(byte[] adArray, Attribute attribute) |
| | | { |
| | | LinkedHashSet<AttributeValue> values = attribute.getValues(); |
| | | int totalValuesLength = 0; |
| | | byte[][] subArrays = new byte[values.size()*2][]; |
| | | byte[][] subArrays = new byte[attribute.size()*2][]; |
| | | int pos = 0; |
| | | for (AttributeValue v : values) |
| | | for (AttributeValue v : attribute) |
| | | { |
| | | byte[] vBytes = v.getValueBytes(); |
| | | byte[] lBytes = ASN1Element.encodeLength(vBytes.length); |
| | |
| | | } |
| | | |
| | | byte[] adArrayLength = ASN1Element.encodeLength(adArray.length); |
| | | byte[] countBytes = ASN1Element.encodeLength(values.size()); |
| | | byte[] countBytes = ASN1Element.encodeLength(attribute.size()); |
| | | int totalLength = adArrayLength.length + adArray.length + |
| | | countBytes.length + totalValuesLength; |
| | | byte[] array = new byte[totalLength]; |
| | |
| | | ByteArray adArray = new ByteArray(new byte[adArrayLength]); |
| | | System.arraycopy(encodedEntry, pos, adArray.array(), 0, adArrayLength); |
| | | pos += adArrayLength; |
| | | |
| | | AttributeType attrType = atDecodeMap.get(adArray); |
| | | LinkedHashSet<String> options = aoDecodeMap.get(adArray); |
| | | Set<String> options = aoDecodeMap.get(adArray); |
| | | if ((attrType == null) || (options == null)) |
| | | { |
| | | Message message = ERR_COMPRESSEDSCHEMA_UNRECOGNIZED_AD_TOKEN.get( |
| | |
| | | } |
| | | |
| | | |
| | | // Read the appropriate number of values. |
| | | LinkedHashSet<AttributeValue> values = |
| | | new LinkedHashSet<AttributeValue>(numValues); |
| | | for (int i=0; i < numValues; i++) |
| | | // For the common case of a single value with no options, generate |
| | | // less garbage. |
| | | if (numValues == 1 && options.isEmpty()) |
| | | { |
| | | int valueLength = encodedEntry[pos] & 0x7F; |
| | | if (valueLength != encodedEntry[pos++]) |
| | | { |
| | | int valueLengthBytes = valueLength; |
| | | valueLength = 0; |
| | | for (int j=0; j < valueLengthBytes; j++, pos++) |
| | | for (int j = 0; j < valueLengthBytes; j++, pos++) |
| | | { |
| | | 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))); |
| | | } |
| | | |
| | | return new Attribute(attrType, attrType.getPrimaryName(), options, values); |
| | | return Attributes.create(attrType, new AttributeValue(attrType, |
| | | new ASN1OctetString(valueBytes))); |
| | | } |
| | | else |
| | | { |
| | | // Read the appropriate number of values. |
| | | AttributeBuilder builder = new AttributeBuilder(attrType); |
| | | builder.setOptions(options); |
| | | builder.setInitialCapacity(numValues); |
| | | for (int i = 0; i < numValues; i++) |
| | | { |
| | | int valueLength = encodedEntry[pos] & 0x7F; |
| | | if (valueLength != encodedEntry[pos++]) |
| | | { |
| | | int valueLengthBytes = valueLength; |
| | | valueLength = 0; |
| | | for (int j = 0; j < valueLengthBytes; j++, pos++) |
| | | { |
| | | valueLength = (valueLength << 8) | (encodedEntry[pos] & 0xFF); |
| | | } |
| | | } |
| | | |
| | | byte[] valueBytes = new byte[valueLength]; |
| | | System.arraycopy(encodedEntry, pos, valueBytes, 0, valueLength); |
| | | pos += valueLength; |
| | | builder.add(new AttributeValue(attrType, |
| | | new ASN1OctetString(valueBytes))); |
| | | } |
| | | |
| | | return builder.toAttribute(); |
| | | } |
| | | } |
| | | |
| | | |