opendj-server-legacy/src/main/java/org/opends/server/api/CompressedSchema.java
@@ -47,6 +47,7 @@ import net.jcip.annotations.GuardedBy; import org.forgerock.opendj.ldap.AttributeDescription; import org.forgerock.opendj.ldap.ByteSequenceReader; import org.forgerock.opendj.ldap.ByteString; import org.forgerock.opendj.ldap.ByteStringBuilder; @@ -56,6 +57,7 @@ import org.opends.server.core.ServerContext; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeBuilder; import org.opends.server.types.AttributeDescriptions; import org.opends.server.types.Attributes; import org.opends.server.types.DirectoryException; import org.opends.server.types.ObjectClass; @@ -77,9 +79,9 @@ private static final class Mappings { /** Maps encoded representation's ID to its attribute description (the List's index is the ID). */ private final List<Entry<AttributeType, Set<String>>> adDecodeMap = new CopyOnWriteArrayList<>(); private final List<AttributeDescription> adDecodeMap = new CopyOnWriteArrayList<>(); /** Maps attribute description to its encoded representation's ID. */ private final Map<Entry<AttributeType, Set<String>>, Integer> adEncodeMap; private final Map<AttributeDescription, Integer> adEncodeMap; /** Maps encoded representation's ID to its object class (the List's index is the ID). */ private final List<Map<ObjectClass, String>> ocDecodeMap = new CopyOnWriteArrayList<>(); /** Maps object class to its encoded representation's ID. */ @@ -174,11 +176,11 @@ */ private void reloadAttributeTypeMaps(Mappings mappings, Mappings newMappings) { for (Entry<Entry<AttributeType, Set<String>>, Integer> entry : mappings.adEncodeMap.entrySet()) for (Entry<AttributeDescription, Integer> entry : mappings.adEncodeMap.entrySet()) { Entry<AttributeType, Set<String>> ad = entry.getKey(); AttributeDescription ad = entry.getKey(); Integer id = entry.getValue(); loadAttributeToMaps(id, ad.getKey().getNameOrOID(), ad.getValue(), newMappings); loadAttributeToMaps(id, ad.getAttributeType().getNameOrOID(), ad.getOptions(), newMappings); } } @@ -214,21 +216,20 @@ // Before returning the attribute, make sure that the attribute type is not stale. final Mappings mappings = reloadMappingsIfSchemaChanged(false); final Entry<AttributeType, Set<String>> ad = mappings.adDecodeMap.get(id); final AttributeDescription ad = mappings.adDecodeMap.get(id); if (ad == null) { throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), ERR_COMPRESSEDSCHEMA_UNRECOGNIZED_AD_TOKEN.get(id)); } AttributeType attrType = ad.getKey(); Set<String> options = ad.getValue(); AttributeType attrType = ad.getAttributeType(); // Determine the number of values for the attribute. final int numValues = reader.readBERLength(); // For the common case of a single value with no options, generate less garbage. if (numValues == 1 && options.isEmpty()) if (numValues == 1 && !ad.hasOptions()) { return Attributes.create(attrType, readValue(reader)); } @@ -236,7 +237,7 @@ { // Read the appropriate number of values. final AttributeBuilder builder = new AttributeBuilder(attrType); builder.setOptions(options); builder.setOptions(ad.getOptions()); for (int i = 0; i < numValues; i++) { builder.add(readValue(reader)); @@ -318,9 +319,7 @@ final Attribute attribute) throws DirectoryException { // Re-use or allocate a new ID. final AttributeType type = attribute.getAttributeType(); final Set<String> options = attribute.getOptions(); int id = getAttributeId(new SimpleImmutableEntry<>(type, options)); int id = getAttributeId(AttributeDescriptions.create(attribute)); // Encode the attribute. final byte[] idBytes = encodeId(id); @@ -334,7 +333,7 @@ } } private int getAttributeId(final Entry<AttributeType, Set<String>> ad) throws DirectoryException private int getAttributeId(final AttributeDescription ad) throws DirectoryException { // avoid lazy registration races boolean shared = true; @@ -357,7 +356,7 @@ id = mappings.adDecodeMap.size(); mappings.adDecodeMap.add(ad); mappings.adEncodeMap.put(ad, id); storeAttribute(encodeId(id), ad.getKey().getNameOrOID(), ad.getValue()); storeAttribute(encodeId(id), ad.getAttributeType().getNameOrOID(), ad.getOptions()); } return id; } @@ -434,17 +433,17 @@ * * @return A view of the encoded attributes in this compressed schema. */ protected final Iterable<Entry<byte[], Entry<String, Collection<String>>>> getAllAttributes() protected final Iterable<Entry<byte[], Entry<String, Iterable<String>>>> getAllAttributes() { return new Iterable<Entry<byte[], Entry<String, Collection<String>>>>() return new Iterable<Entry<byte[], Entry<String, Iterable<String>>>>() { @Override public Iterator<Entry<byte[], Entry<String, Collection<String>>>> iterator() public Iterator<Entry<byte[], Entry<String, Iterable<String>>>> iterator() { return new Iterator<Entry<byte[], Entry<String, Collection<String>>>>() return new Iterator<Entry<byte[], Entry<String, Iterable<String>>>>() { private int id; private List<Entry<AttributeType, Set<String>>> adDecodeMap = getMappings().adDecodeMap; private List<AttributeDescription> adDecodeMap = getMappings().adDecodeMap; @Override public boolean hasNext() @@ -453,15 +452,14 @@ } @Override public Entry<byte[], Entry<String, Collection<String>>> next() public Entry<byte[], Entry<String, Iterable<String>>> next() { final byte[] encodedAttribute = encodeId(id); final Entry<AttributeType, Set<String>> ad = adDecodeMap.get(id++); return new SimpleImmutableEntry<byte[], Entry<String, Collection<String>>>( final AttributeDescription ad = adDecodeMap.get(id++); return new SimpleImmutableEntry<byte[], Entry<String, Iterable<String>>>( encodedAttribute, new SimpleImmutableEntry<String, Collection<String>>(ad .getKey().getNameOrOID(), ad.getValue())); new SimpleImmutableEntry<String, Iterable<String>>( ad.getAttributeType().getNameOrOID(), ad.getOptions())); } @Override @@ -531,7 +529,7 @@ * The non-null but possibly empty set of attribute options. * @return The attribute type description. */ protected final Entry<AttributeType, Set<String>> loadAttribute( protected final AttributeDescription loadAttribute( final byte[] encodedAttribute, final String attributeName, final Collection<String> attributeOptions) { @@ -552,12 +550,12 @@ * attribute description encodeMap and decodeMap maps id to entry * @return The attribute type description. */ private Entry<AttributeType, Set<String>> loadAttributeToMaps(final int id, final String attributeName, final Collection<String> attributeOptions, final Mappings mappings) private AttributeDescription loadAttributeToMaps(final int id, final String attributeName, final Iterable<String> attributeOptions, final Mappings mappings) { final AttributeType type = DirectoryServer.getAttributeTypeOrDefault(attributeName); final Set<String> options = getOptions(attributeOptions); final Entry<AttributeType, Set<String>> ad = new SimpleImmutableEntry<>(type, options); final AttributeDescription ad = AttributeDescriptions.create(type, options); exclusiveLock.lock(); try { @@ -583,17 +581,25 @@ } } private Set<String> getOptions(final Collection<String> attributeOptions) private Set<String> getOptions(final Iterable<String> attributeOptions) { switch (attributeOptions.size()) Iterator<String> it = attributeOptions.iterator(); if (!it.hasNext()) { case 0: return Collections.emptySet(); case 1: return Collections.singleton(attributeOptions.iterator().next()); default: return new LinkedHashSet<>(attributeOptions); } String firstOption = it.next(); if (!it.hasNext()) { return Collections.singleton(firstOption); } LinkedHashSet<String> results = new LinkedHashSet<>(); results.add(firstOption); while (it.hasNext()) { results.add(it.next()); } return results; } /** @@ -695,7 +701,7 @@ * If an error occurred while persisting the encoded attribute. */ protected void storeAttribute(final byte[] encodedAttribute, final String attributeName, final Collection<String> attributeOptions) final String attributeName, final Iterable<String> attributeOptions) throws DirectoryException { // Do nothing by default. @@ -706,7 +712,7 @@ * to do nothing. Calls to this method are synchronized, so implementations * can assume that this method is not being called by other threads. Note that * this method is not thread-safe with respect to * {@link #storeAttribute(byte[], String, Collection)}. * {@link #storeAttribute(byte[], String, Iterable)}. * * @param encodedObjectClasses * The encoded object classes. opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/PersistentCompressedSchema.java
@@ -105,7 +105,7 @@ @Override protected void storeAttribute(final byte[] encodedAttribute, final String attributeName, final Collection<String> attributeOptions) final String attributeName, final Iterable<String> attributeOptions) throws DirectoryException { try opendj-server-legacy/src/main/java/org/opends/server/core/DefaultCompressedSchema.java
@@ -26,6 +26,10 @@ */ package org.opends.server.core; import static org.opends.messages.CoreMessages.*; import static org.opends.server.config.ConfigConstants.*; import static org.opends.server.util.StaticUtils.*; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -43,10 +47,6 @@ import org.opends.server.api.CompressedSchema; import org.opends.server.types.DirectoryException; import static org.opends.messages.CoreMessages.*; import static org.opends.server.config.ConfigConstants.*; import static org.opends.server.util.StaticUtils.*; /** * This class provides a default implementation of a compressed schema manager * that will store the schema definitions in a binary file @@ -78,7 +78,7 @@ /** {@inheritDoc} */ @Override protected void storeAttribute(final byte[] encodedAttribute, final String attributeName, final Collection<String> attributeOptions) final String attributeName, final Iterable<String> attributeOptions) throws DirectoryException { save(); @@ -236,8 +236,7 @@ // are the attribute options. writer.writeStartSequence(); int adCounter = 1; for (final Entry<byte[], Entry<String, Collection<String>>> mapEntry : getAllAttributes()) for (final Entry<byte[], Entry<String, Iterable<String>>> mapEntry : getAllAttributes()) { writer.writeStartSequence(); writer.writeOctetString(ByteString.wrap(mapEntry.getKey())); opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/EntryHistorical.java
@@ -29,16 +29,28 @@ import static org.opends.messages.ReplicationMessages.*; import static org.opends.server.replication.plugin.HistAttrModificationKey.*; import java.util.*; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.UUID; import org.forgerock.i18n.slf4j.LocalizedLogger; import org.forgerock.opendj.ldap.AttributeDescription; import org.forgerock.opendj.ldap.ByteString; import org.forgerock.opendj.ldap.ModificationType; import org.forgerock.opendj.ldap.schema.AttributeType; import org.opends.server.core.DirectoryServer; import org.opends.server.replication.common.CSN; import org.opends.server.replication.protocol.OperationContext; import org.forgerock.opendj.ldap.schema.AttributeType; import org.opends.server.types.*; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeBuilder; import org.opends.server.types.AttributeDescriptions; import org.opends.server.types.Attributes; import org.opends.server.types.DN; import org.opends.server.types.Entry; import org.opends.server.types.Modification; import org.opends.server.types.operation.PreOperationAddOperation; import org.opends.server.types.operation.PreOperationModifyDNOperation; import org.opends.server.types.operation.PreOperationModifyOperation; @@ -304,7 +316,7 @@ // Read from this entryHistorical, // Create one empty if none was existing in this entryHistorical. AttributeDescription attrDesc = AttributeDescription.create(modAttr); AttributeDescription attrDesc = AttributeDescriptions.create(modAttr); AttrHistorical attrHist = attributesHistorical.get(attrDesc); if (attrHist == null) { opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/HistoricalAttributeValue.java
@@ -33,6 +33,7 @@ import java.util.LinkedHashSet; import java.util.Set; import org.forgerock.opendj.ldap.AttributeDescription; import org.forgerock.opendj.ldap.ByteString; import org.forgerock.opendj.ldap.ModificationType; import org.forgerock.opendj.ldap.schema.AttributeType; @@ -40,7 +41,7 @@ import org.opends.server.replication.common.CSN; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeBuilder; import org.opends.server.types.AttributeDescription; import org.opends.server.types.AttributeDescriptions; import org.opends.server.types.Modification; /** @@ -137,7 +138,7 @@ isModDN = true; } } this.attrDesc = attrType != null ? AttributeDescription.create(attrType, options) : null; this.attrDesc = attrType != null ? AttributeDescriptions.create(attrType, options) : null; csn = new CSN(token[1]); histKey = HistAttrModificationKey.decodeKey(token[2]); @@ -166,7 +167,7 @@ return attrDesc != null ? attrDesc.getAttributeType() : null; } private Set<String> getOptions() private Iterable<String> getOptions() { return attrDesc != null ? attrDesc.getOptions() : Collections.<String> emptySet(); } opendj-server-legacy/src/main/java/org/opends/server/types/AbstractAttribute.java
@@ -22,12 +22,16 @@ * * * Copyright 2006-2008 Sun Microsystems, Inc. * Portions Copyright 2014-2015 ForgeRock AS * Portions Copyright 2014-2016 ForgeRock AS */ package org.opends.server.types; import static org.opends.server.util.StaticUtils.*; import java.util.Collection; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.forgerock.opendj.ldap.ByteString; import org.forgerock.opendj.ldap.DecodeException; @@ -153,7 +157,43 @@ @Override public boolean hasAllOptions(Collection<String> options) { return AttributeDescription.containsAllOptions(getOptions(), options); // FIXME use AttributeDescription instead return containsAllOptions(getOptions(), options); } private static boolean containsAllOptions(Collection<String> options1, Collection<String> options2) { if (options1 == options2) { return true; } else if (isEmpty(options2)) { return true; } else if (isEmpty(options1)) { return false; } // normalize all options before calling containsAll() Set<String> set1 = toLowercaseSet(options1); Set<String> set2 = toLowercaseSet(options2); return set1.size() >= set2.size() && set1.containsAll(set2); } private static boolean isEmpty(Collection<String> col) { return col == null || col.isEmpty(); } private static SortedSet<String> toLowercaseSet(Collection<String> strings) { final SortedSet<String> results = new TreeSet<>(); for (String s : strings) { results.add(toLowerCase(s)); } return results; } @Override @@ -186,7 +226,24 @@ @Override public boolean hasOption(String option) { return AttributeDescription.containsOption(getOptions(), option); // FIXME use AttributeDescription instead return containsOption(getOptions(), option); } private static boolean containsOption(Set<String> options, String optionToFind) { String normToFind = toLowerCase(optionToFind); // Cannot use Set.contains() because the options are not normalized. for (String o : options) { String norm = toLowerCase(o); if (norm.equals(normToFind)) { return true; } } return false; } /** opendj-server-legacy/src/main/java/org/opends/server/types/AttributeBuilder.java
@@ -26,7 +26,7 @@ */ package org.opends.server.types; import org.forgerock.opendj.ldap.schema.AttributeType; import static org.opends.server.util.StaticUtils.*; import java.util.AbstractSet; import java.util.Collection; @@ -44,14 +44,13 @@ import org.forgerock.opendj.ldap.ByteString; import org.forgerock.opendj.ldap.ConditionResult; import org.forgerock.opendj.ldap.DecodeException; import org.forgerock.opendj.ldap.schema.AttributeType; import org.forgerock.opendj.ldap.schema.MatchingRule; import org.forgerock.util.Reject; import org.forgerock.util.Utils; import org.opends.server.core.DirectoryServer; import org.opends.server.util.CollectionUtils; import static org.opends.server.util.StaticUtils.*; /** * This class provides an interface for creating new non-virtual * {@link Attribute}s, or "real" attributes. @@ -1549,7 +1548,7 @@ * @return <code>true</code> if this attribute builder was * modified. */ public boolean setOptions(Collection<String> options) public boolean setOptions(Iterable<String> options) { boolean isModified = false; opendj-server-legacy/src/main/java/org/opends/server/types/AttributeDescription.java
File was deleted opendj-server-legacy/src/main/java/org/opends/server/types/AttributeDescriptions.java
New file @@ -0,0 +1,70 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at legal-notices/CDDLv1_0.txt. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * Copyright 2015-2016 ForgeRock AS */ package org.opends.server.types; import java.util.Set; import org.forgerock.opendj.ldap.AttributeDescription; import org.forgerock.opendj.ldap.schema.AttributeType; /** Temporary class until we move fully to {@link AttributeDescription}. */ public class AttributeDescriptions { private AttributeDescriptions() { // private for utility class } /** * Creates an attribute description with the attribute type and options of the provided * {@link Attribute}. * * @param attr * The attribute. * @return The attribute description. * @throws NullPointerException * If {@code attributeType} or {@code options} was {@code null}. */ public static AttributeDescription create(Attribute attr) { return create(attr.getAttributeType(), attr.getOptions()); } /** * Creates an attribute description having the provided attribute type and options. * * @param attributeType * The attribute type. * @param options * The attribute options. * @return The attribute description. * @throws NullPointerException * If {@code attributeType} or {@code options} was {@code null}. */ public static AttributeDescription create(AttributeType attributeType, Set<String> options) { return AttributeDescription.create(attributeType, options.toArray(new String[options.size()])); } }