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

Jean-Noël Rouvignac
29.33.2016 5d8dba35b0c44d205b5448747ed0a7f8f86ce563
code cleanup

Move code from ViewEntryPanel to SimplifiedViewEntryPanel when it was the only caller.
In SimplifiedViewEntryPanel.getSortedAttributes(), removed unnecessary double call to updateAttributes()
5 files modified
367 ■■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/SimplifiedViewEntryPanel.java 217 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/ViewEntryPanel.java 63 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/AllowDenyFilter.java 5 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPRequestHandler.java 42 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/ReplLDIFOutputStream.java 40 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/SimplifiedViewEntryPanel.java
@@ -76,6 +76,7 @@
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.RDN;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.forgerock.opendj.ldap.schema.Syntax;
import org.opends.guitools.controlpanel.datamodel.BinaryValue;
import org.opends.guitools.controlpanel.datamodel.CheckEntrySyntaxException;
import org.opends.guitools.controlpanel.datamodel.CustomSearchResult;
@@ -134,7 +135,7 @@
  private final String CONFIRM_PASSWORD = "opendj-confirm-password";
  /** Map containing as key the attribute name and as value a localizable message. */
  private final static Map<String, LocalizableMessage> hmFriendlyAttrNames = new HashMap<>();
  private static final Map<String, LocalizableMessage> hmFriendlyAttrNames = new HashMap<>();
  /**
   * Map containing as key an object class and as value the preferred naming
   * attribute for the objectclass.
@@ -460,11 +461,12 @@
    {
      for (final String attr : sortedAttributes)
      {
        String lcAttr = attr.toLowerCase();
        JLabel label = getLabelForAttribute(attr, sr);
        if (isRequired(attr, sr))
        {
          Utilities.setRequiredIcon(label);
          requiredAttrs.add(attr.toLowerCase());
          requiredAttrs.add(lcAttr);
        }
        List<Object> values = sr.getAttributeValues(attr);
        if (values.isEmpty())
@@ -488,7 +490,7 @@
          {
            pwds.add(getPasswordStringValue(o));
          }
          lastUserPasswords.put(attr.toLowerCase(), pwds);
          lastUserPasswords.put(lcAttr, pwds);
        }
        JComponent comp = getReadWriteComponent(attr, values);
@@ -502,8 +504,8 @@
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        attributesPanel.add(comp, gbc);
        gbc.insets.top = 10;
        hmLabels.put(attr.toLowerCase(), label);
        hmComponents.put(attr.toLowerCase(), comp);
        hmLabels.put(lcAttr, label);
        hmComponents.put(lcAttr, comp);
        if (isPasswordAttr)
        {
@@ -588,11 +590,12 @@
  private int anchor1(List<Object> values)
  {
    if (values.size() > 1)
    int size = values.size();
    if (size > 1)
    {
      return GridBagConstraints.NORTHWEST;
    }
    if (values.size() == 1)
    else if (size == 1)
    {
      Object v = values.get(0);
      if (v instanceof String && ((String) v).contains("\n"))
@@ -605,7 +608,6 @@
  private JLabel getLabelForAttribute(String attrName, CustomSearchResult sr)
  {
    LocalizableMessageBuilder l = new LocalizableMessageBuilder();
    int index = attrName.indexOf(";");
    String basicAttrName;
    String subType;
@@ -624,26 +626,21 @@
      // TODO: use message
      subType = "binary";
    }
    LocalizableMessageBuilder l = new LocalizableMessageBuilder();
    boolean isNameAttribute = isAttrName(basicAttrName, sr);
    if (isNameAttribute)
    {
      l.append(NAME);
      if (subType != null)
      {
        l.append(NAME).append(" (").append(subType).append(")");
      }
      else
      {
        l.append(NAME);
        l.append(" (").append(subType).append(")");
      }
    }
    else
    {
      LocalizableMessage friendly = hmFriendlyAttrNames.get(basicAttrName.toLowerCase());
      if (friendly == null)
      {
        l.append(attrName);
      }
      else
      if (friendly != null)
      {
        l.append(friendly);
        if (subType != null)
@@ -651,32 +648,31 @@
          l.append(" (").append(subType).append(")");
        }
      }
      else
      {
        l.append(attrName);
      }
    }
    hmDisplayedNames.put(attrName.toLowerCase(), l.toString());
    l.append(":");
    return Utilities.createPrimaryLabel(l.toMessage());
  }
  private Collection<String> getSortedAttributes(CustomSearchResult sr,
      boolean isReadOnly)
  private Collection<String> getSortedAttributes(CustomSearchResult sr, boolean isReadOnly)
  {
    LinkedHashSet<String> attrNames = new LinkedHashSet<>();
//  Get all attributes that the entry can have
    Set<String> attributes = new LinkedHashSet<>();
    ArrayList<String> entryAttrs = new ArrayList<>(sr.getAttributeNames());
    ArrayList<String> attrsWithNoOptions = new ArrayList<>();
    List<String> entryAttrs = new ArrayList<>(sr.getAttributeNames());
    List<String> attrsWithNoOptions = new ArrayList<>();
    for (String attr : entryAttrs)
    {
      AttributeDescription attrDesc = AttributeDescription.valueOf(attr);
      attrsWithNoOptions.add(attrDesc.getNameOrOID().toLowerCase());
    }
    List<Object> values =
      sr.getAttributeValues(ServerConstants.OBJECTCLASS_ATTRIBUTE_TYPE_NAME);
    // Put first the attributes associated with the objectclass in
    // hmOrderedAttrNames
    // Put first the attributes associated with the objectclass in hmOrderedAttrNames
    LinkedHashSet<String> attrNames = new LinkedHashSet<>();
    List<Object> values = sr.getAttributeValues(ServerConstants.OBJECTCLASS_ATTRIBUTE_TYPE_NAME);
    for (Object o : values)
    {
      String ocName = (String)o;
@@ -686,14 +682,7 @@
        for (String attr : attrs)
        {
          int index = attrsWithNoOptions.indexOf(attr.toLowerCase());
          if (index != -1)
          {
            attrNames.add(entryAttrs.get(index));
          }
          else
          {
            attrNames.add(attr);
          }
          attrNames.add(index != -1 ? entryAttrs.get(index) : attr);
        }
      }
    }
@@ -744,12 +733,11 @@
          }
        }
      }
      // Now try to put first the attributes for which we have a friendly
      // name (the most common ones).
      updateAttributes(attributes, requiredAttributes, entryAttrs, attrsWithNoOptions, true);
      updateAttributes(attributes, requiredAttributes, entryAttrs, attrsWithNoOptions, false);
      updateAttributes(attributes, allowedAttributes, entryAttrs, attrsWithNoOptions, true);
      updateAttributes(attributes, allowedAttributes, entryAttrs, attrsWithNoOptions, false);
      updateAttributes(attributes, requiredAttributes, entryAttrs, attrsWithNoOptions);
      updateAttributes(attributes, allowedAttributes, entryAttrs, attrsWithNoOptions);
      attributes.addAll(entryAttrs);
      attributes.add("aci");
@@ -787,22 +775,17 @@
  private void updateAttributes(
      Collection<String> attributes,
      Set<String> newAttributes,
      ArrayList<String> entryAttrs,
      ArrayList<String> attrsWithNoOptions,
      boolean addIfFriendlyName)
      List<String> entryAttrs,
      List<String> attrsWithNoOptions)
  {
    for (String attr : newAttributes)
    {
      String attrLc = attr.toLowerCase();
      boolean hasFriendlyName = hmFriendlyAttrNames.get(attrLc) != null;
      if (hasFriendlyName == addIfFriendlyName)
      {
        int index = attrsWithNoOptions.indexOf(attrLc);
      int index = attrsWithNoOptions.indexOf(attr.toLowerCase());
        if (index != -1)
        {
          attributes.add(entryAttrs.get(index));
        }
        else if (hasCertificateSyntax(attr, getInfo().getServerDescriptor().getSchema()))
      else if (hasCertificateSyntax(attr))
        {
          attributes.add(attr + ";binary");
        }
@@ -812,10 +795,29 @@
        }
      }
    }
  private boolean hasCertificateSyntax(String attrName)
  {
    Schema schema = getInfo().getServerDescriptor().getSchema();
    boolean isCertificate = false;
    // Check all the attributes that we consider binaries.
    if (schema != null)
    {
      String attributeName = AttributeDescription.valueOf(attrName).getNameOrOID().toLowerCase();
      if (schema.hasAttributeType(attributeName))
      {
        AttributeType attr = schema.getAttributeType(attributeName);
        Syntax syntax = attr.getSyntax();
        if (syntax != null)
        {
          isCertificate = SchemaConstants.SYNTAX_CERTIFICATE_OID.equals(syntax.getOID());
        }
      }
    }
    return isCertificate;
  }
  private JComponent getReadOnlyComponent(final String attrName,
      List<Object> values)
  private JComponent getReadOnlyComponent(final String attrName, List<Object> values)
  {
//  GridLayout is used to avoid the 512 limit of GridBagLayout
    JPanel panel = new JPanel(new GridBagLayout());
@@ -962,7 +964,7 @@
              Utilities.centerGoldenMean(editOcDlg,
                  Utilities.getParentDialog(SimplifiedViewEntryPanel.this));
            }
            if (newValue == null && ocDescriptor != null)
            if (ocDescriptor != null)
            {
              editOcPanel.setValue(ocDescriptor);
            }
@@ -1143,7 +1145,6 @@
  private boolean isRequired(String attrName, CustomSearchResult sr)
  {
    Schema schema = getInfo().getServerDescriptor().getSchema();
    if (schema != null)
    {
@@ -1209,11 +1210,10 @@
    }
    for (String attrName : requiredAttrs)
    {
      if (!!getValues(attrName).isEmpty())
      if (getValues(attrName).isEmpty())
      {
        setPrimaryInvalid(hmLabels.get(attrName));
        errors.add(ERR_CTRL_PANEL_ATTRIBUTE_REQUIRED.get(
            hmDisplayedNames.get(attrName)));
        errors.add(ERR_CTRL_PANEL_ATTRIBUTE_REQUIRED.get(hmDisplayedNames.get(attrName)));
      }
    }
@@ -1376,11 +1376,7 @@
    {
      AttributeType attr = schema.getAttributeType(attrName);
      // There is no name for a regex syntax.
      String syntaxName = attr.getSyntax().getName();
      if (syntaxName != null)
      {
        return SchemaConstants.SYNTAX_DN_NAME.equalsIgnoreCase(syntaxName);
      }
      return SchemaConstants.SYNTAX_DN_NAME.equalsIgnoreCase(attr.getSyntax().getName());
    }
    return false;
  }
@@ -1409,10 +1405,16 @@
  private void appendLDIFLines(StringBuilder sb, String attrName)
  {
    List<Object> values = getValues(attrName);
    if (!values.isEmpty())
    {
      appendLDIFLines(sb, attrName, values);
      appendLDIFLines(sb, attrName, getValues(attrName));
    }
  }
  private void appendLDIFLines(StringBuilder sb, String attrName, List<Object> values)
  {
    for (Object value : values)
    {
      appendLDIFLine(sb, attrName, value);
    }
  }
@@ -1425,42 +1427,16 @@
      DN oldDN = DN.valueOf(searchResult.getDN());
      if (oldDN.size() > 0)
      {
        RDN rdn = oldDN.rdn();
        List<AVA> avas = new ArrayList<>();
        for (AVA ava : rdn)
        {
          AttributeType attrType = ava.getAttributeType();
          String attrName = ava.getAttributeName();
          ByteString value = ava.getAttributeValue();
          List<String> values = getDisplayedStringValues(attrName);
          if (!values.contains(value.toString()))
          {
            if (!values.isEmpty())
            {
              String firstNonEmpty = getFirstNonEmpty(values);
              if (firstNonEmpty != null)
              {
                avas.add(new AVA(attrType, attrName, ByteString.valueOfUtf8(firstNonEmpty)));
              }
            }
          }
          else
          {
            avas.add(new AVA(attrType, attrName, value));
          }
        }
        List<AVA> avas = toAvas(oldDN.rdn());
        if (avas.isEmpty())
        {
          // Check the attributes in the order that we display them and use
          // the first one.
          // Check the attributes in the order that we display them and use the first one.
          Schema schema = getInfo().getServerDescriptor().getSchema();
          if (schema != null)
          {
            for (String attrName : hmEditors.keySet())
            {
              if (isPassword(attrName) ||
                  isConfirmPassword(attrName))
              if (isPassword(attrName) || isConfirmPassword(attrName))
              {
                continue;
              }
@@ -1502,12 +1478,41 @@
    return sb.toString();
  }
  private List<AVA> toAvas(RDN rdn)
  {
    List<AVA> avas = new ArrayList<>();
    for (AVA ava : rdn)
    {
      AttributeType attrType = ava.getAttributeType();
      String attrName = ava.getAttributeName();
      ByteString value = ava.getAttributeValue();
      List<String> values = getDisplayedStringValues(attrName);
      if (!values.contains(value.toString()))
      {
        if (!values.isEmpty())
        {
          String firstNonEmpty = getFirstNonEmpty(values);
          if (firstNonEmpty != null)
          {
            avas.add(new AVA(attrType, attrName, ByteString.valueOfUtf8(firstNonEmpty)));
          }
        }
      }
      else
      {
        avas.add(new AVA(attrType, attrName, value));
      }
    }
    return avas;
  }
  private String getFirstNonEmpty(List<String> values)
  {
    for (String v : values)
    {
      v = v.trim();
      if (v.length() > 0)
      if (!v.isEmpty())
      {
        return v;
      }
@@ -1684,20 +1689,9 @@
  {
    for (String attrName : hmLabels.keySet())
    {
      Component label = hmLabels.get(attrName);
      Component comp = hmComponents.get(attrName);
      if (showAll || requiredAttrs.contains(attrName))
      {
        label.setVisible(true);
        comp.setVisible(true);
      }
      else
      {
        boolean hasValue = hasValue(hmEditors.get(attrName));
        label.setVisible(hasValue);
        comp.setVisible(hasValue);
      }
      final boolean visible = showAll || requiredAttrs.contains(attrName) || hasValue(hmEditors.get(attrName));
      hmLabels    .get(attrName).setVisible(visible);
      hmComponents.get(attrName).setVisible(visible);
    }
    repaint();
  }
@@ -1845,7 +1839,7 @@
        for (String line : lines)
        {
          line = line.trim();
          if (line.length() > 0)
          if (!line.isEmpty())
          {
            values.add(line);
          }
@@ -1870,11 +1864,8 @@
            throw new RuntimeException("Unexpected error: "+pe);
          }
        }
        else
        {
          return o;
        }
      }
    }
  }
}
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/ViewEntryPanel.java
@@ -39,7 +39,6 @@
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.forgerock.opendj.ldap.schema.ObjectClassType;
import org.forgerock.opendj.ldap.schema.Syntax;
import org.opends.guitools.controlpanel.datamodel.BinaryValue;
import org.opends.guitools.controlpanel.datamodel.CustomSearchResult;
import org.opends.guitools.controlpanel.datamodel.ObjectClassValue;
@@ -100,8 +99,7 @@
   * @param isReadOnly whether the entry is read-only or not.
   * @param path the tree path associated with the entry in the tree.
   */
  public abstract void update(CustomSearchResult sr, boolean isReadOnly,
      TreePath path);
  public abstract void update(CustomSearchResult sr, boolean isReadOnly, TreePath path);
  /**
   * Adds a title panel to the container.
@@ -163,13 +161,12 @@
    }
    // TODO: With big entries this is pretty slow.  Until there is a fix, try
    // simply to update the dn
    Entry entry = null;
    String dn = getDisplayedDN();
    if (dn != null && !dn.equals(title.getText()))
    {
      title.setText(dn);
    }
    LDAPEntryChangedEvent ev = new LDAPEntryChangedEvent(this, entry);
    LDAPEntryChangedEvent ev = new LDAPEntryChangedEvent(this, null);
    for (LDAPEntryChangedListener listener : listeners)
    {
      listener.entryChanged(ev);
@@ -255,11 +252,7 @@
      {
        if (objectClass.getObjectClassType() == ObjectClassType.STRUCTURAL)
        {
          if (structuralObjectClass == null)
          {
            structuralObjectClass = objectClass;
          }
          else if (objectClass.isDescendantOf(structuralObjectClass))
          if (structuralObjectClass == null || objectClass.isDescendantOf(structuralObjectClass))
          {
            structuralObjectClass = objectClass;
          }
@@ -350,22 +343,6 @@
  }
  /**
   * Appends the LDIF lines corresponding to the different values of an
   * attribute to the provided StringBuilder.
   * @param sb the StringBuilder that must be updated.
   * @param attrName the attribute name.
   * @param values the attribute values.
   */
  protected void appendLDIFLines(StringBuilder sb, String attrName,
      List<Object> values)
  {
    for (Object value : values)
    {
      appendLDIFLine(sb, attrName, value);
    }
  }
  /**
   * Appends the LDIF line corresponding to the value of an
   * attribute to the provided StringBuilder.
   * @param sb the StringBuilder that must be updated.
@@ -450,34 +427,6 @@
  }
  /**
   * Returns <CODE>true</CODE> if the provided attribute name has certificate
   * syntax and <CODE>false</CODE> otherwise.
   * @param attrName the attribute name.
   * @param schema the schema.
   * @return <CODE>true</CODE> if the provided attribute name has certificate
   * syntax and <CODE>false</CODE> otherwise.
   */
  protected boolean hasCertificateSyntax(String attrName, Schema schema)
  {
    boolean isCertificate = false;
    // Check all the attributes that we consider binaries.
    if (schema != null)
    {
      String attributeName = AttributeDescription.valueOf(attrName).getNameOrOID().toLowerCase();
      if (schema.hasAttributeType(attributeName))
      {
        AttributeType attr = schema.getAttributeType(attributeName);
        Syntax syntax = attr.getSyntax();
        if (syntax != null)
        {
          isCertificate = SchemaConstants.SYNTAX_CERTIFICATE_OID.equals(syntax.getOID());
        }
      }
    }
    return isCertificate;
  }
  /**
   * Gets the values associated with a given attribute.  The values are the
   * ones displayed in the panel.
   * @param attrName the attribute name.
@@ -552,13 +501,11 @@
  }
  /**
   * Returns the list of superior object classes (to top) for a given object
   * class.
   * Returns the list of superior object classes (to top) for a given object class.
   * @param oc the object class.
   * @return the set of superior object classes for a given object classes.
   */
  protected Set<String> getObjectClassSuperiorValues(
      ObjectClass oc)
  protected Set<String> getObjectClassSuperiorValues(ObjectClass oc)
  {
    Set<String> names = new LinkedHashSet<>();
    Set<ObjectClass> parents = oc.getSuperiorClasses();
opendj-server-legacy/src/main/java/org/opends/server/protocols/http/AllowDenyFilter.java
@@ -76,14 +76,13 @@
    return next.handle(context, request);
  }
  static final Promise<Response, NeverThrowsException> forbidden()
  private static final Promise<Response, NeverThrowsException> forbidden()
  {
    return Promises.newResultPromise(new Response(Status.FORBIDDEN));
  }
  static final Promise<Response, NeverThrowsException> internalError()
  private static final Promise<Response, NeverThrowsException> internalError()
  {
    return Promises.newResultPromise(new Response(Status.INTERNAL_SERVER_ERROR));
  }
}
opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPRequestHandler.java
@@ -28,16 +28,15 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.forgerock.i18n.LocalizableMessage;
import org.opends.server.api.DirectoryThread;
import org.opends.server.api.ServerShutdownListener;
import org.opends.server.core.DirectoryServer;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.io.ASN1Reader;
import org.forgerock.opendj.ldap.DecodeException;
import org.opends.server.api.DirectoryThread;
import org.opends.server.api.ServerShutdownListener;
import org.opends.server.types.DisconnectReason;
import org.opends.server.types.InitializationException;
import org.opends.server.types.LDAPException;
@@ -57,7 +56,6 @@
  /** Indicates whether the Directory Server is in the process of shutting down. */
  private volatile boolean shutdownRequested;
  /** The current set of selection keys. */
  private volatile SelectionKey[] keys = new SelectionKey[0];
@@ -70,13 +68,10 @@
  /** Lock object for synchronizing access to the pending connections queue. */
  private final Object pendingConnectionsLock = new Object();
  /** The list of connections ready for request processing. */
  private LinkedList<LDAPClientConnection> readyConnections = new LinkedList<>();
  private final LinkedList<LDAPClientConnection> readyConnections = new LinkedList<>();
  /** The selector that will be used to monitor the client connections. */
  private final Selector selector;
  /** The name to use for this request handler. */
  private final String handlerName;
@@ -459,41 +454,12 @@
    return connList;
  }
  /**
   * Retrieves the human-readable name for this shutdown listener.
   *
   * @return  The human-readable name for this shutdown listener.
   */
  @Override
  public String getShutdownListenerName()
  {
    return handlerName;
  }
  /**
   * Causes this request handler to register itself as a shutdown listener with
   * the Directory Server.  This must be called if the connection handler is
   * shut down without closing all associated connections, otherwise the thread
   * would not be stopped by the server.
   */
  public void registerShutdownListener()
  {
    DirectoryServer.registerShutdownListener(this);
  }
  /**
   * Indicates that the Directory Server has received a request to stop running
   * and that this shutdown listener should take any action necessary to prepare
   * for it.
   *
   * @param  reason  The human-readable reason for the shutdown.
   */
  @Override
  public void processServerShutdown(LocalizableMessage reason)
  {
opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/ReplLDIFOutputStream.java
@@ -30,14 +30,14 @@
       extends OutputStream
{
  /** The number of entries to be exported. */
  long numEntries;
  private final long numEntries;
  /** The current number of entries exported. */
  private long numExportedEntries;
  String entryBuffer = "";
  private String entryBuffer = "";
  /** The checksum for computing the generation id. */
  private GenerationIdChecksum checkSum = new GenerationIdChecksum();
  private final GenerationIdChecksum checkSum = new GenerationIdChecksum();
  /**
   * Creates a new ReplLDIFOutputStream related to a replication
@@ -68,24 +68,23 @@
  @Override
  public void write(byte b[], int off, int len) throws IOException
  {
    int endOfEntryIndex;
    int endIndex;
    String ebytes = "";
    ebytes = ebytes.concat(entryBuffer);
    String ebytes = entryBuffer;
    entryBuffer = "";
    ebytes = ebytes.concat(new String(b, off, len));
    endIndex = ebytes.length();
    ebytes = ebytes + new String(b, off, len);
    int endIndex = ebytes.length();
    while (true)
    {
      // if we have the bytes for an entry, let's make an entry and send it
      endOfEntryIndex = ebytes.indexOf(ServerConstants.EOL +
          ServerConstants.EOL);
      if ( endOfEntryIndex >= 0 )
      int endOfEntryIndex = ebytes.indexOf(ServerConstants.EOL + ServerConstants.EOL);
      if (endOfEntryIndex < 0)
      {
        // a next call to us will provide more bytes to make an entry
        entryBuffer = entryBuffer.concat(ebytes);
        break;
      }
        endOfEntryIndex += 2;
        entryBuffer = ebytes.substring(0, endOfEntryIndex);
@@ -109,22 +108,11 @@
          // no more data to process
          break;
        }
        else
        {
          // loop to the data of the next entry
          ebytes = ebytes.substring(endOfEntryIndex,
                                    endIndex);
      ebytes = ebytes.substring(endOfEntryIndex, endIndex);
          endIndex = ebytes.length();
        }
      }
      else
      {
        // a next call to us will provide more bytes to make an entry
        entryBuffer = entryBuffer.concat(ebytes);
        break;
      }
    }
  }
  /**
   * Return the number of exported entries.