@Test
  public void testByServiceInfoServiceTracker() throws Exception {
    ServiceAgent serviceAgent = SLP.newServiceAgent(newSettings());
    UserAgent userAgent = SLP.newUserAgent(newSettings());
    final AtomicInteger counter = new AtomicInteger();

    userAgent.addServiceNotificationListener(
        new ServiceNotificationListener() {
          public void serviceRegistered(ServiceNotificationEvent event) {
            counter.incrementAndGet();
          }

          public void serviceDeregistered(ServiceNotificationEvent event) {
            counter.decrementAndGet();
          }
        });

    serviceAgent.start();
    userAgent.start();

    ByServiceInfoServiceTracker tracker =
        new ByServiceInfoServiceTracker(bundleContext, serviceAgent);
    tracker.open();

    ServiceRegistration serviceRegistration =
        bundleContext.registerService(
            ServiceInfo.class.getName(),
            new ServiceInfo(
                new ServiceURL("service:printer:lpr://myprinter/myqueue"),
                Locale.ENGLISH.getLanguage(),
                Scopes.DEFAULT,
                Attributes.from("(printer-compression-supported=deflate, gzip)")),
            null);

    Thread.sleep(500);

    Assert.assertEquals(1, tracker.size());
    Assert.assertEquals(1, counter.get());

    serviceRegistration.unregister();

    Thread.sleep(500);

    Assert.assertEquals(0, tracker.size());
    Assert.assertEquals(0, counter.get());

    tracker.close();

    userAgent.stop();
    serviceAgent.stop();
  }
  protected void deserializeBody(byte[] bytes) throws ServiceLocationException {
    int offset = 0;
    setSLPError(SLPError.from(readInt(bytes, offset, ERROR_CODE_BYTES_LENGTH)));

    // The message may be truncated if an error occurred (RFC 2608, Chapter 7)
    if (getSLPError() != SLPError.NO_ERROR && bytes.length == ERROR_CODE_BYTES_LENGTH) return;

    offset += ERROR_CODE_BYTES_LENGTH;
    setBootTime(readInt(bytes, offset, BOOT_TIME_BYTES_LENGTH));

    offset += BOOT_TIME_BYTES_LENGTH;
    int urlLength = readInt(bytes, offset, URL_LENGTH_BYTES_LENGTH);

    offset += URL_LENGTH_BYTES_LENGTH;
    setURL(readString(bytes, offset, urlLength, true));

    offset += urlLength;
    int scopesLength = readInt(bytes, offset, SCOPES_LENGTH_BYTES_LENGTH);

    offset += SCOPES_LENGTH_BYTES_LENGTH;
    setScopes(Scopes.from(readStringArray(bytes, offset, scopesLength, false)));

    offset += scopesLength;
    int attrsLength = readInt(bytes, offset, ATTRIBUTES_LENGTH_BYTES_LENGTH);

    offset += ATTRIBUTES_LENGTH_BYTES_LENGTH;
    setAttributes(Attributes.from(readString(bytes, offset, attrsLength, false)));

    offset += attrsLength;
    int securityParamsLength = readInt(bytes, offset, SPI_LENGTH_BYTES_LENGTH);

    offset += SPI_LENGTH_BYTES_LENGTH;
    setSecurityParamIndexes(readStringArray(bytes, offset, securityParamsLength, true));

    offset += securityParamsLength;
    int authBlocksCount = readInt(bytes, offset, AUTH_BLOCKS_COUNT_BYTES_LENGTH);

    offset += AUTH_BLOCKS_COUNT_BYTES_LENGTH;
    if (authBlocksCount > 0) {
      AuthenticationBlock[] blocks = new AuthenticationBlock[authBlocksCount];
      for (int i = 0; i < authBlocksCount; ++i) {
        blocks[i] = new AuthenticationBlock();
        offset += blocks[i].deserialize(bytes, offset);
      }
      setAuthenticationBlocks(blocks);
    }
  }
  @Test
  public void testServiceNotificationListenerWithFilterServiceTracker() throws Exception {
    UserAgent userAgent = SLP.newUserAgent(newSettings());
    ServiceAgent serviceAgent = SLP.newServiceAgent(newSettings());
    final AtomicInteger counter = new AtomicInteger();

    userAgent.start();
    serviceAgent.start();

    ServiceNotificationListenerServiceTracker tracker =
        new ServiceNotificationListenerServiceTracker(
            bundleContext, bundleContext.createFilter("(&(foo=bar)(car=cdr))"), userAgent);
    tracker.open();

    Dictionary<String, String> dictionary = new Hashtable<String, String>();
    dictionary.put("foo", "bar");
    dictionary.put("car", "cdr");
    ServiceRegistration serviceRegistration =
        bundleContext.registerService(
            ServiceNotificationListener.class.getName(),
            new ServiceNotificationListener() {
              public void serviceRegistered(ServiceNotificationEvent event) {
                if ("service:jmx:rmi:///jndi/jmxrmi"
                    .equals(event.getService().getServiceURL().getURL())) {
                  counter.incrementAndGet();
                }
              }

              public void serviceDeregistered(ServiceNotificationEvent event) {
                if ("service:jmx:rmi:///jndi/jmxrmi"
                    .equals(event.getService().getServiceURL().getURL())) {
                  counter.decrementAndGet();
                }
              }
            },
            dictionary);

    ServiceURL serviceURL = new ServiceURL("service:jmx:rmi:///jndi/jmxrmi");
    ServiceInfo service =
        new ServiceInfo(
            serviceURL,
            Locale.ENGLISH.getLanguage(),
            Scopes.DEFAULT,
            Attributes.from("(a=1,2),(b=true),(c=string),(d=\\FF\\00),e"));

    serviceAgent.register(service);

    Thread.sleep(1000);

    Assert.assertEquals(1, tracker.size());
    Assert.assertEquals(1, counter.get());

    serviceAgent.deregister(service.getServiceURL(), service.getLanguage());

    Thread.sleep(1000);

    Assert.assertEquals(1, tracker.size());
    Assert.assertEquals(0, counter.get());

    serviceRegistration.unregister();

    Thread.sleep(500);

    Assert.assertEquals(0, tracker.size());
    Assert.assertEquals(0, counter.get());

    dictionary.put("foo", "bad-value");
    serviceRegistration =
        bundleContext.registerService(
            ServiceNotificationListener.class.getName(),
            new ServiceNotificationListener() {
              public void serviceRegistered(ServiceNotificationEvent event) {
                if ("service:jmx:rmi:///jndi/jmxrmi"
                    .equals(event.getService().getServiceURL().getURL())) {
                  counter.incrementAndGet();
                }
              }

              public void serviceDeregistered(ServiceNotificationEvent event) {
                if ("service:jmx:rmi:///jndi/jmxrmi"
                    .equals(event.getService().getServiceURL().getURL())) {
                  counter.decrementAndGet();
                }
              }
            },
            dictionary);

    serviceAgent.register(service);

    Thread.sleep(1000);

    Assert.assertEquals(0, tracker.size());
    Assert.assertEquals(0, counter.get());

    serviceAgent.deregister(service.getServiceURL(), service.getLanguage());

    Thread.sleep(1000);

    Assert.assertEquals(0, tracker.size());
    Assert.assertEquals(0, counter.get());

    serviceRegistration.unregister();

    Thread.sleep(500);

    Assert.assertEquals(0, tracker.size());
    Assert.assertEquals(0, counter.get());

    tracker.close();

    serviceAgent.stop();
    userAgent.stop();
  }