/**
   * Registers an object consisting of the set of attributes in <i>object</i>. The registration will
   * be retained for <i>forHowLong</i> seconds.
   */
  public void register(Attribute[] object, int forHowLong) throws Exception {

    StringBuffer allAttributes = new StringBuffer();
    String completeObject;
    byte[][] messageBytes = {null, null};

    for (int i = 0; i < object.length; i++)
      allAttributes.append(object[i].name + ":" + object[i].value + "\t");
    allAttributes.append("\t");
    completeObject = allAttributes.toString();
    messageBytes[0] = (new CString(completeObject)).toBytes();
    messageBytes[1] = NwsMessage.toBytes(forHowLong);

    messagePrelude();
    NwsMessage.send(connection, NS_REGISTER, NwsMessage.concatenateBytes(messageBytes));
    NwsMessage.receive(connection, this);
    messagePostlude();
  }
  /**
   * Returns the set of registered objects that match <i>filter</i>, an LDAP-style search filter.
   * Each term in a search filter specifies, in parentheses, an attribute name and a value or value
   * range which the retrieved objects must have. NWS name servers support the relational operators
   * =, &lt;=, and &gt;=, and wild cards (*) can be included in the value of the = operator. Logical
   * AND (&), OR (|) and NOT (!) operations may be used as prefix operators, surrounded by another
   * set of parentheses, to combine filter terms into more complex filters. A typical filter:
   * "(&(hostType=sensor)(|((port=8030))(!(port=80*))))" This would retrieve all sensor
   * registrations that have a port attribute which is either equal to 8030 or does not begin with
   * 80.
   */
  public Attribute[][] search(String filter) throws Exception {

    Vector allObjects;
    int attributeEnd;
    Vector attributes;
    int objectEnd;
    String object;
    String results;
    Attribute[][] returnValue;

    messagePrelude();
    NwsMessage.send(connection, NS_SEARCH, (new CString(filter)).toBytes());
    results = (String) NwsMessage.receive(connection, this);
    messagePostlude();

    allObjects = new Vector();
    while (!results.equals("")) {
      objectEnd = results.indexOf("\t\t");
      if (objectEnd == -1) break; /* Shouldn't happen. */
      object = results.substring(0, objectEnd + 1);
      results = results.substring(objectEnd + 2);
      attributes = new Vector();
      while (!object.equals("")) {
        attributeEnd = object.indexOf("\t");
        attributes.addElement(new Attribute(object.substring(0, attributeEnd)));
        object = object.substring(attributeEnd + 1);
      }
      allObjects.addElement(attributes);
    }

    returnValue = new Attribute[allObjects.size()][];
    for (int i = 0; i < returnValue.length; i++) {
      returnValue[i] = new Attribute[((Vector) allObjects.elementAt(i)).size()];
      for (int j = 0; j < returnValue[i].length; j++)
        returnValue[i][j] = (Attribute) ((Vector) allObjects.elementAt(i)).elementAt(j);
    }
    return returnValue;
  }
 public void unregister(String filter) throws Exception {
   messagePrelude();
   NwsMessage.send(connection, NS_UNREGISTER, (new CString(filter)).toBytes());
   NwsMessage.receive(connection, this);
   messagePostlude();
 }