mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

jvergara
08.03.2009 953a5f95f82af133dc8c758641bf9f5f521493b7
Fix for issue 3686 (makeldif does not parse redirect to file based attribute)

The fix for the issue consists basically in two parts.

1. Update the parser in the class TemplateFile to handle correctly the attributes referring to an URL (like usercertificate:< file:///mycertificate) and base64 attributes (usercertificate:: <base64 value>).

2. Update the class TemplateEntry to get the LDIF representation of the entry. The interfaces in Branch, LDIFWriter, MakeLDIFInputStream and EntryWriter have also been updated to handle TemplateEntry.
9 files modified
473 ■■■■ changed files
opends/src/server/org/opends/server/tools/makeldif/Branch.java 4 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/EntryWriter.java 6 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/MakeLDIF.java 5 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/MakeLDIFInputStream.java 13 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/Template.java 10 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/TemplateEntry.java 254 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/TemplateFile.java 24 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/TemplateLine.java 83 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/LDIFWriter.java 74 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/makeldif/Branch.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 */
package org.opends.server.tools.makeldif;
import org.opends.messages.Message;
@@ -415,7 +415,7 @@
      }
    }
    if (! entryWriter.writeEntry(entry.toEntry()))
    if (! entryWriter.writeEntry(entry))
    {
      return TagResult.STOP_PROCESSING;
    }
opends/src/server/org/opends/server/tools/makeldif/EntryWriter.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 */
package org.opends.server.tools.makeldif;
@@ -30,8 +30,6 @@
import java.io.IOException;
import org.opends.server.types.Entry;
/**
@@ -54,7 +52,7 @@
   *
   * @throws  MakeLDIFException  If some other problem occurs.
   */
  public boolean writeEntry(Entry entry)
  public boolean writeEntry(TemplateEntry entry)
         throws IOException, MakeLDIFException;
opends/src/server/org/opends/server/tools/makeldif/MakeLDIF.java
@@ -37,7 +37,6 @@
import java.util.Random;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.Entry;
import org.opends.server.types.ExistingFileBehavior;
import org.opends.server.types.LDIFExportConfig;
import org.opends.server.types.NullOutputStream;
@@ -430,12 +429,12 @@
   *
   * @throws  MakeLDIFException  If some other problem occurs.
   */
  public boolean writeEntry(Entry entry)
  public boolean writeEntry(TemplateEntry entry)
         throws IOException, MakeLDIFException
  {
    try
    {
      ldifWriter.writeEntry(entry);
      ldifWriter.writeTemplateEntry(entry);
      if ((++entriesWritten % 1000) == 0)
      {
opends/src/server/org/opends/server/tools/makeldif/MakeLDIFInputStream.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 */
package org.opends.server.tools.makeldif;
@@ -35,7 +35,6 @@
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.opends.server.types.Entry;
import org.opends.server.types.LDIFExportConfig;
import org.opends.server.util.LDIFException;
import org.opends.server.util.LDIFWriter;
@@ -73,7 +72,7 @@
  private LDIFWriter ldifWriter;
  // The queue used to hold generated entries until they can be read.
  private LinkedBlockingQueue<Entry> entryQueue;
  private LinkedBlockingQueue<TemplateEntry> entryQueue;
  // The background thread being used to actually generate the entries.
  private MakeLDIFInputStreamThread generatorThread;
@@ -95,7 +94,7 @@
    allGenerated = false;
    closed       = false;
    entryQueue   = new LinkedBlockingQueue<Entry>(10);
    entryQueue   = new LinkedBlockingQueue<TemplateEntry>(10);
    ioException  = null;
    entryBytes   = null;
@@ -210,7 +209,7 @@
  /**
   * {@inheritDoc}
   */
  public boolean writeEntry(Entry entry)
  public boolean writeEntry(TemplateEntry entry)
         throws IOException, MakeLDIFException
  {
    while (! closed)
@@ -261,7 +260,7 @@
   */
  private boolean getNextEntry()
  {
    Entry entry = entryQueue.poll();
    TemplateEntry entry = entryQueue.poll();
    while (entry == null)
    {
      if (closed)
@@ -288,7 +287,7 @@
    try
    {
      entryOutputStream.reset();
      ldifWriter.writeEntry(entry);
      ldifWriter.writeTemplateEntry(entry);
      ldifWriter.flush();
      entryBytes = ByteBuffer.wrap(entryOutputStream.toByteArray());
    }
opends/src/server/org/opends/server/tools/makeldif/Template.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 */
package org.opends.server.tools.makeldif;
import org.opends.messages.Message;
@@ -35,7 +35,6 @@
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import static org.opends.messages.ToolMessages.*;
import static org.opends.server.util.StaticUtils.*;
@@ -362,8 +361,7 @@
        }
      }
      Entry entry = templateEntry.toEntry();
      if (! entryWriter.writeEntry(entry))
      if (! entryWriter.writeEntry(templateEntry))
      {
        return TagResult.STOP_PROCESSING;
      }
@@ -371,8 +369,8 @@
      for (int j=0; j < subordinateTemplates.length; j++)
      {
        TagResult r =
             subordinateTemplates[j].writeEntries(entryWriter, entry.getDN(),
                                                  numEntriesPerTemplate[j]);
             subordinateTemplates[j].writeEntries(entryWriter,
                 templateEntry.getDN(), numEntriesPerTemplate[j]);
        if (! (r.keepProcessingParent() && r.keepProcessingTemplateFile()))
        {
          if (r.keepProcessingTemplateFile())
opends/src/server/org/opends/server/tools/makeldif/TemplateEntry.java
@@ -22,19 +22,24 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 */
package org.opends.server.tools.makeldif;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.*;
import org.opends.server.util.LDIFException;
import static org.opends.server.util.LDIFWriter.appendLDIFSeparatorAndValue;
import static org.opends.server.util.LDIFWriter.writeLDIFLine;
import static org.opends.server.util.StaticUtils.*;
@@ -273,13 +278,24 @@
  }
  /**
   * Retrieves this template entry as an <CODE>Entry</CODE> object.
   * Writes this entry in LDIF form.  No filtering will be
   * performed for this entry, nor will any export plugins be invoked.
   *
   * @return  The <CODE>Entry</CODE> object for this template entry.
   * @param  exportConfig  The configuration that specifies how the
   *                       entry should be written.
   *
   * @return  <CODE>true</CODE> if the entry is actually written, or
   *          <CODE>false</CODE> if it is not for some reason.
   *
   * @throws  IOException  If a problem occurs while writing the
   *                       information.
   *
   * @throws  LDIFException  If a problem occurs while trying to
   *                         determine whether to write the entry.
   */
  public Entry toEntry()
  public boolean toLDIF(LDIFExportConfig exportConfig)
         throws IOException, LDIFException
  {
    // Process all of the attributes for this entry.
    LinkedHashMap<ObjectClass,String> objectClasses =
@@ -288,6 +304,10 @@
         new LinkedHashMap<AttributeType,List<Attribute>>();
    LinkedHashMap<AttributeType,List<Attribute>> operationalAttributes =
         new LinkedHashMap<AttributeType,List<Attribute>>();
    LinkedHashMap<AttributeType, List<Attribute>> urlAttributes =
         new LinkedHashMap<AttributeType, List<Attribute>>();
    LinkedHashMap<AttributeType, List<Attribute>> base64Attributes =
      new LinkedHashMap<AttributeType, List<Attribute>>();
    for (AttributeType t : attributes.keySet())
    {
@@ -316,19 +336,237 @@
      else
      {
        AttributeBuilder builder = new AttributeBuilder(t, t.getNameOrOID());
        AttributeBuilder urlBuilder = null;
        AttributeBuilder base64Builder = null;
        for (TemplateValue v : valueList)
        {
          builder.add(AttributeValues.create(t, v.getValue().toString()));
          AttributeValue value =
            AttributeValues.create(t, v.getValue().toString());
          builder.add(value);
          if (v.getTemplateLine().isURL())
          {
            if (urlBuilder == null)
            {
              urlBuilder = new AttributeBuilder(t, t.getNameOrOID());
            }
            urlBuilder.add(value);
          }
          else if (v.getTemplateLine().isBase64())
          {
            if (base64Builder == null)
            {
              base64Builder = new AttributeBuilder(t, t.getNameOrOID());
            }
            base64Builder.add(value);
          }
        }
        ArrayList<Attribute> attrList = new ArrayList<Attribute>(1);
        attrList.add(builder.toAttribute());
        userAttributes.put(t, attrList);
        if (urlBuilder != null)
        {
          ArrayList<Attribute> urlAttrList = new ArrayList<Attribute>(1);
          urlAttrList.add(urlBuilder.toAttribute());
          urlAttributes.put(t, urlAttrList);
        }
        if (base64Builder != null)
        {
          ArrayList<Attribute> base64AttrList = new ArrayList<Attribute>(1);
          base64AttrList.add(base64Builder.toAttribute());
          base64Attributes.put(t, base64AttrList);
        }
      }
    }
    return new Entry(getDN(), objectClasses, userAttributes,
                     operationalAttributes);
    // Get the information necessary to write the LDIF.
    BufferedWriter writer     = exportConfig.getWriter();
    int            wrapColumn = exportConfig.getWrapColumn();
    boolean        wrapLines  = (wrapColumn > 1);
    // First, write the DN.  It will always be included.
    StringBuilder dnLine = new StringBuilder();
    dnLine.append("dn");
    appendLDIFSeparatorAndValue(dnLine,
        ByteString.valueOf(getDN().toString()));
    writeLDIFLine(dnLine, writer, wrapLines, wrapColumn);
    // Next, the set of objectclasses.
    final boolean typesOnly = exportConfig.typesOnly();
    if (exportConfig.includeObjectClasses())
    {
      if (typesOnly)
      {
        StringBuilder ocLine = new StringBuilder("objectClass:");
        writeLDIFLine(ocLine, writer, wrapLines, wrapColumn);
      }
      else
      {
        for (String s : objectClasses.values())
        {
          StringBuilder ocLine = new StringBuilder();
          ocLine.append("objectClass: ");
          ocLine.append(s);
          writeLDIFLine(ocLine, writer, wrapLines, wrapColumn);
        }
      }
    }
    // Now the set of user attributes.
    for (AttributeType attrType : userAttributes.keySet())
    {
      if (exportConfig.includeAttribute(attrType))
      {
        List<Attribute> attrList = userAttributes.get(attrType);
        for (Attribute a : attrList)
        {
          if (a.isVirtual() &&
              (! exportConfig.includeVirtualAttributes()))
          {
            continue;
          }
          if (typesOnly)
          {
            StringBuilder attrName = new StringBuilder(a.getName());
            for (String o : a.getOptions())
            {
              attrName.append(";");
              attrName.append(o);
            }
            attrName.append(":");
            writeLDIFLine(attrName, writer, wrapLines, wrapColumn);
          }
          else
          {
            StringBuilder attrName = new StringBuilder(a.getName());
            for (String o : a.getOptions())
            {
              attrName.append(";");
              attrName.append(o);
            }
            List<Attribute> urlAttrList = urlAttributes.get(attrType);
            List<Attribute> base64AttrList = base64Attributes.get(attrType);
            for (AttributeValue v : a)
            {
              StringBuilder attrLine = new StringBuilder();
              attrLine.append(attrName);
              boolean isURLValue = false;
              if (urlAttrList != null)
              {
                for (Attribute urlAttr : urlAttrList)
                {
                  for (AttributeValue urlValue : urlAttr)
                  {
                    if (urlValue.equals(v))
                    {
                      isURLValue = true;
                      break;
                    }
                  }
                  if (isURLValue)
                  {
                    break;
                  }
                }
              }
              boolean isBase64Value = false;
              if (base64AttrList != null)
              {
                for (Attribute base64Attr : base64AttrList)
                {
                  for (AttributeValue base64Value : base64Attr)
                  {
                    if (base64Value.equals(v))
                    {
                      isBase64Value = true;
                      break;
                    }
                  }
                  if (isBase64Value)
                  {
                    break;
                  }
                }
              }
              appendLDIFSeparatorAndValue(attrLine,
                                          v.getValue(),
                                          isURLValue,
                                          isBase64Value);
              writeLDIFLine(attrLine, writer, wrapLines, wrapColumn);
            }
          }
        }
      }
    }
    // Next, the set of operational attributes.
    if (exportConfig.includeOperationalAttributes())
    {
      for (AttributeType attrType : operationalAttributes.keySet())
      {
        if (exportConfig.includeAttribute(attrType))
        {
          List<Attribute> attrList =
               operationalAttributes.get(attrType);
          for (Attribute a : attrList)
          {
            if (a.isVirtual() &&
                (! exportConfig.includeVirtualAttributes()))
            {
              continue;
            }
            if (typesOnly)
            {
              StringBuilder attrName = new StringBuilder(a.getName());
              for (String o : a.getOptions())
              {
                attrName.append(";");
                attrName.append(o);
              }
              attrName.append(":");
              writeLDIFLine(attrName, writer, wrapLines, wrapColumn);
            }
            else
            {
              StringBuilder attrName = new StringBuilder(a.getName());
              for (String o : a.getOptions())
              {
                attrName.append(";");
                attrName.append(o);
              }
              for (AttributeValue v : a)
              {
                StringBuilder attrLine = new StringBuilder();
                attrLine.append(attrName);
                appendLDIFSeparatorAndValue(attrLine,
                                            v.getValue());
                writeLDIFLine(attrLine, writer, wrapLines,
                              wrapColumn);
              }
            }
          }
        }
      }
    }
    // Make sure there is a blank line after the entry.
    writer.newLine();
    return true;
  }
}
opends/src/server/org/opends/server/tools/makeldif/TemplateFile.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 */
package org.opends.server.tools.makeldif;
import org.opends.messages.Message;
@@ -1358,9 +1358,25 @@
                                          true);
    // First, find the position of the first non-blank character in the line.
    // First, check whether the value is an URL value: <attrName>:< <url>
    int length = line.length();
    int pos    = colonPos + 1;
    boolean valueIsURL = false;
    boolean valueIsBase64 = false;
    if (pos < length)
    {
      if (lowerLine.charAt(pos) == '<')
      {
        valueIsURL = true;
        pos ++;
      }
      else if (lowerLine.charAt(pos) == ':')
      {
        valueIsBase64 = true;
        pos ++;
      }
    }
    //  Then, find the position of the first non-blank character in the line.
    while ((pos < length) && (lowerLine.charAt(pos) == ' '))
    {
      pos++;
@@ -1395,6 +1411,7 @@
    ArrayList<Tag> tagList = new ArrayList<Tag>();
    StringBuilder buffer = new StringBuilder();
    for ( ; pos < length; pos++)
    {
      char c = line.charAt(pos);
@@ -1488,7 +1505,8 @@
    Tag[] tagArray = new Tag[tagList.size()];
    tagList.toArray(tagArray);
    return new TemplateLine(attributeType, lineNumber, tagArray);
    return new TemplateLine(attributeType, lineNumber, tagArray, valueIsURL,
        valueIsBase64);
  }
opends/src/server/org/opends/server/tools/makeldif/TemplateLine.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 */
package org.opends.server.tools.makeldif;
@@ -30,10 +30,6 @@
import org.opends.server.types.AttributeType;
import static org.opends.server.util.StaticUtils.*;
/**
 * This class defines a line that may appear in a template or branch.  It may
 * contain any number of tags to be evaluated.
@@ -49,23 +45,11 @@
  // The set of tags for this template line.
  private Tag[] tags;
  // Whether this line corresponds to an URL value or not.
  private boolean isURL;
  /**
   * Creates a new template line with the provided information.
   *
   * @param  attributeType  The attribute type for this template line.
   * @param  lineNumber     The line number on which this template line appears
   *                        in the template file.
   * @param  tags           The set of tags for this template line.
   */
  public TemplateLine(AttributeType attributeType, int lineNumber, Tag[] tags)
  {
    this.attributeType = attributeType;
    this.lineNumber    = lineNumber;
    this.tags          = tags;
  }
  // Whether this line corresponds to a base64 encoded value or not.
  private boolean isBase64;
  /**
@@ -95,15 +79,64 @@
  /**
   * Retrieves the set of tags for this template line.
   * Returns whether the value of this template line corresponds to an URL
   * or not.
   *
   * @return  The set of tags for this template line.
   * @return <CODE>true</CODE> if the value of this template line corresponds
   * to an URL and <CODE>false</CODE> otherwise.
   */
  public Tag[] getTags()
  public boolean isURL()
  {
    return tags;
    return isURL;
  }
  /**
   * Returns whether the value of this template line corresponds to a Base64
   * encoded value or not.
   *
   * @return <CODE>true</CODE> if the value of this template line corresponds
   * to a Base64 encoded value and <CODE>false</CODE> otherwise.
   */
  public boolean isBase64()
  {
    return isBase64;
  }
  /**
   * Creates a new template line with the provided information.
   *
   * @param  attributeType  The attribute type for this template line.
   * @param  lineNumber     The line number on which this template line appears
   *                        in the template file.
   * @param  tags           The set of tags for this template line.
   */
  public TemplateLine(AttributeType attributeType, int lineNumber, Tag[] tags)
  {
    this(attributeType, lineNumber, tags, false, false);
  }
  /**
   * Creates a new template line with the provided information.
   *
   * @param  attributeType  The attribute type for this template line.
   * @param  lineNumber     The line number on which this template line appears
   *                        in the template file.
   * @param  tags           The set of tags for this template line.
   * @param  isURL          Whether this template line's value is an URL or not.
   * @param  isBase64       Whether this template line's value is Base64 encoded
   *                        or not.
   */
  public TemplateLine(AttributeType attributeType, int lineNumber, Tag[] tags,
      boolean isURL, boolean isBase64)
  {
    this.attributeType = attributeType;
    this.lineNumber    = lineNumber;
    this.tags          = tags;
    this.isURL         = isURL;
    this.isBase64      = isBase64;
  }
  /**
opends/src/server/org/opends/server/util/LDIFWriter.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 */
package org.opends.server.util;
@@ -37,6 +37,7 @@
import org.opends.messages.Message;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.tools.makeldif.TemplateEntry;
import org.opends.server.types.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -248,6 +249,30 @@
  }
  /**
   * Writes the provided template entry to LDIF.
   *
   * @param  templateEntry  The template entry to be written.  It must not be
   * <CODE>null</CODE>.
   *
   * @return  <CODE>true</CODE> if the entry was actually written, or
   *          <CODE>false</CODE> if it was not because of the export
   *          configuration.
   *
   * @throws  IOException  If a problem occurs while writing the template entry
   *                       to LDIF.
   *
   * @throws  LDIFException  If a problem occurs while trying to determine
   *                         whether to include the temlate entry in the export.
   */
  public boolean writeTemplateEntry(TemplateEntry templateEntry)
  throws IOException, LDIFException
  {
    ensureNotNull(templateEntry);
    //  Delegate to TemplateEntry.toLDIF(...)
    return templateEntry.toLDIF(exportConfig);
  }
  /**
   * Writes a change record entry for the provided change record.
@@ -770,19 +795,58 @@
  public static void appendLDIFSeparatorAndValue(StringBuilder buffer,
                                                 ByteSequence valueBytes)
  {
    appendLDIFSeparatorAndValue(buffer, valueBytes, false, false);
  }
  /**
   * Appends an LDIF separator and properly-encoded form of the given
   * value to the provided buffer.  If the value is safe to include
   * as-is, then a single colon, a single space, space, and the
   * provided value will be appended.  Otherwise, two colons, a single
   * space, and a base64-encoded form of the value will be appended.
   * @param  buffer      The buffer to which the information should be
   *                     appended.  It must not be <CODE>null</CODE>.
   * @param  valueBytes  The value to append to the buffer.  It must not be
   *                     <CODE>null</CODE>.
   * @param isURL        Whether the provided value is an URL value or not.
   * @param isBase64     Whether the provided value is a base 64 value or not.
   */
  public static void appendLDIFSeparatorAndValue(StringBuilder buffer,
      ByteSequence valueBytes, boolean isURL, boolean isBase64)
  {
    ensureNotNull(buffer, valueBytes);
    // If the value is empty, then just append a single colon and a single
    // space.
    // If the value is empty, then just append a single colon (the URL '<' if
    // required) and a single space.
    if ((valueBytes == null) || (valueBytes.length() == 0))
    {
      if (isURL)
      {
        buffer.append(":< ");
      }
      else if (isBase64)
      {
        buffer.append(":: ");
      }
      else
      {
      buffer.append(": ");
      }
      return;
    }
    if (needsBase64Encoding(valueBytes))
    if (isURL)
    {
      buffer.append(":< ");
      buffer.append(valueBytes.toString());
    }
    else if (isBase64)
    {
      buffer.append(":: ");
      buffer.append(valueBytes.toString());
    }
    else if (needsBase64Encoding(valueBytes))
    {
      buffer.append(":: ");
      buffer.append(Base64.encode(valueBytes));