/**
   * Remove a service listener. The listener is removed from the context bundle's list of listeners.
   * See {@link #getBundle() getBundle()} for a definition of context bundle.
   *
   * <p>If this method is called with a listener which is not registered, then this method does
   * nothing.
   *
   * @param listener The service listener to remove.
   * @exception java.lang.IllegalStateException If the bundle context has stopped.
   */
  public void removeServiceListener(ServiceListener listener) {
    checkValid();

    if (listener == null) {
      throw new IllegalArgumentException();
    }
    framework.getServiceRegistry().removeServiceListener(this, listener);
  }
  /**
   * Add a service listener with a filter. {@link ServiceListener}s are notified when a service has
   * a lifecycle state change. See {@link #getServiceReferences(String, String)
   * getServiceReferences} for a description of the filter syntax. The listener is added to the
   * context bundle's list of listeners. See {@link #getBundle() getBundle()} for a definition of
   * context bundle.
   *
   * <p>The listener is called if the filter criteria is met. To filter based upon the class of the
   * service, the filter should reference the "objectClass" property. If the filter paramater is
   * <code>null</code>, all services are considered to match the filter.
   *
   * <p>If the Java runtime environment supports permissions, then additional filtering is done.
   * {@link AbstractBundle#hasPermission(Object) Bundle.hasPermission} is called for the bundle
   * which defines the listener to validate that the listener has the {@link ServicePermission}
   * permission to <code>"get"</code> the service using at least one of the named classes the
   * service was registered under.
   *
   * @param listener The service listener to add.
   * @param filter The filter criteria.
   * @exception InvalidSyntaxException If the filter parameter contains an invalid filter string
   *     which cannot be parsed.
   * @see ServiceEvent
   * @see ServiceListener
   * @exception java.lang.IllegalStateException If the bundle context has stopped.
   */
  public void addServiceListener(ServiceListener listener, String filter)
      throws InvalidSyntaxException {
    checkValid();

    if (listener == null) {
      throw new IllegalArgumentException();
    }
    framework.getServiceRegistry().addServiceListener(this, listener, filter);
  }
  /**
   * Get a service's service object. Retrieves the service object for a service. A bundle's use of a
   * service is tracked by a use count. Each time a service's service object is returned by {@link
   * #getService}, the context bundle's use count for the service is incremented by one. Each time
   * the service is release by {@link #ungetService}, the context bundle's use count for the service
   * is decremented by one. When a bundle's use count for a service drops to zero, the bundle should
   * no longer use the service. See {@link #getBundle()} for a definition of context bundle.
   *
   * <p>This method will always return <code>null</code> when the service associated with this
   * reference has been unregistered.
   *
   * <p>The following steps are followed to get the service object:
   *
   * <ol>
   *   <li>If the service has been unregistered, <code>null</code> is returned.
   *   <li>The context bundle's use count for this service is incremented by one.
   *   <li>If the context bundle's use count for the service is now one and the service was
   *       registered with a {@link ServiceFactory}, the {@link ServiceFactory#getService
   *       ServiceFactory.getService} method is called to create a service object for the context
   *       bundle. This service object is cached by the framework. While the context bundle's use
   *       count for the service is greater than zero, subsequent calls to get the services's
   *       service object for the context bundle will return the cached service object. <br>
   *       If the service object returned by the {@link ServiceFactory} is not an <code>instanceof
   *       </code> all the classes named when the service was registered or the {@link
   *       ServiceFactory} throws an exception, <code>null</code> is returned and a {@link
   *       FrameworkEvent} of type {@link FrameworkEvent#ERROR} is broadcast.
   *   <li>The service object for the service is returned.
   * </ol>
   *
   * @param reference A reference to the service whose service object is desired.
   * @return A service object for the service associated with this reference, or <code>null</code>
   *     if the service is not registered.
   * @exception java.lang.SecurityException If the caller does not have {@link ServicePermission}
   *     permission to "get" the service using at least one of the named classes the service was
   *     registered under and the Java runtime environment supports permissions.
   * @exception java.lang.IllegalStateException If the bundle context has stopped.
   * @see #ungetService
   * @see ServiceFactory
   */
  public <S> S getService(ServiceReference<S> reference) {
    checkValid();
    if (reference == null)
      throw new NullPointerException("A null service reference is not allowed."); // $NON-NLS-1$
    synchronized (contextLock) {
      if (servicesInUse == null)
        // Cannot predict how many services a bundle will use, start with a small table.
        servicesInUse = new HashMap<ServiceRegistrationImpl<?>, ServiceUse<?>>(10);
    }

    @SuppressWarnings("unchecked")
    S service =
        (S) framework.getServiceRegistry().getService(this, (ServiceReferenceImpl<S>) reference);
    return service;
  }
  /** Destroy the wrapper. This is called when the bundle is stopped. */
  protected void close() {
    valid = false; /* invalidate context */

    final ServiceRegistry registry = framework.getServiceRegistry();

    registry.removeAllServiceListeners(this);
    framework.removeAllListeners(this);

    /* service's registered by the bundle, if any, are unregistered. */
    registry.unregisterServices(this);

    /* service's used by the bundle, if any, are released. */
    registry.releaseServicesInUse(this);

    synchronized (contextLock) {
      servicesInUse = null;
    }
  }
  /**
   * Unget a service's service object. Releases the service object for a service. If the context
   * bundle's use count for the service is zero, this method returns <code>false</code>. Otherwise,
   * the context bundle's use count for the service is decremented by one. See {@link #getBundle()}
   * for a definition of context bundle.
   *
   * <p>The service's service object should no longer be used and all references to it should be
   * destroyed when a bundle's use count for the service drops to zero.
   *
   * <p>The following steps are followed to unget the service object:
   *
   * <ol>
   *   <li>If the context bundle's use count for the service is zero or the service has been
   *       unregistered, <code>false</code> is returned.
   *   <li>The context bundle's use count for this service is decremented by one.
   *   <li>If the context bundle's use count for the service is now zero and the service was
   *       registered with a {@link ServiceFactory}, the {@link ServiceFactory#ungetService
   *       ServiceFactory.ungetService} method is called to release the service object for the
   *       context bundle.
   *   <li><code>true</code> is returned.
   * </ol>
   *
   * @param reference A reference to the service to be released.
   * @return <code>false</code> if the context bundle's use count for the service is zero or if the
   *     service has been unregistered, otherwise <code>true</code>.
   * @exception java.lang.IllegalStateException If the bundle context has stopped.
   * @see #getService
   * @see ServiceFactory
   */
  public boolean ungetService(ServiceReference<?> reference) {
    checkValid();

    return framework.getServiceRegistry().ungetService(this, (ServiceReferenceImpl<?>) reference);
  }
  /**
   * Get a service reference. Retrieves a {@link ServiceReference} for a service which implements
   * the named class.
   *
   * <p>This reference is valid at the time of the call to this method, but since the framework is a
   * very dynamic environment, services can be modified or unregistered at anytime.
   *
   * <p>This method is provided as a convenience for when the caller is interested in any service
   * which implements a named class. This method is the same as calling {@link #getServiceReferences
   * getServiceReferences} with a <code>null</code> filter string but only a single {@link
   * ServiceReference} is returned.
   *
   * @param clazz The class name which the service must implement.
   * @return A {@link ServiceReference} object, or <code>null</code> if no services are registered
   *     which implement the named class.
   * @see #getServiceReferences
   */
  public ServiceReference<?> getServiceReference(String clazz) {
    checkValid();

    return framework.getServiceRegistry().getServiceReference(this, clazz);
  }
 public ServiceReference<?>[] getAllServiceReferences(String clazz, String filter)
     throws InvalidSyntaxException {
   checkValid();
   return framework.getServiceRegistry().getServiceReferences(this, clazz, filter, true);
 }
 /**
  * Register a service with multiple names. This method registers the given service object with the
  * given properties under the given class names. A {@link ServiceRegistration} object is returned.
  * The {@link ServiceRegistration} object is for the private use of the bundle registering the
  * service and should not be shared with other bundles. The registering bundle is defined to be
  * the context bundle. See {@link #getBundle()} for a definition of context bundle. Other bundles
  * can locate the service by using either the {@link #getServiceReferences getServiceReferences}
  * or {@link #getServiceReference getServiceReference} method.
  *
  * <p>A bundle can register a service object that implements the {@link ServiceFactory} interface
  * to have more flexiblity in providing service objects to different bundles.
  *
  * <p>The following steps are followed to register a service:
  *
  * <ol>
  *   <li>If the service parameter is not a {@link ServiceFactory}, an <code>
  *       IllegalArgumentException</code> is thrown if the service parameter is not an <code>
  *       instanceof</code> all the classes named.
  *   <li>The service is added to the framework's service registry and may now be used by other
  *       bundles.
  *   <li>A {@link ServiceEvent} of type {@link ServiceEvent#REGISTERED} is synchronously sent.
  *   <li>A {@link ServiceRegistration} object for this registration is returned.
  * </ol>
  *
  * @param clazzes The class names under which the service can be located. The class names in this
  *     array will be stored in the service's properties under the key "objectClass".
  * @param service The service object or a {@link ServiceFactory} object.
  * @param properties The properties for this service. The keys in the properties object must all
  *     be Strings. Changes should not be made to this object after calling this method. To update
  *     the service's properties call the {@link ServiceRegistration#setProperties
  *     ServiceRegistration.setProperties} method. This parameter may be <code>null</code> if the
  *     service has no properties.
  * @return A {@link ServiceRegistration} object for use by the bundle registering the service to
  *     update the service's properties or to unregister the service.
  * @exception java.lang.IllegalArgumentException If one of the following is true:
  *     <ul>
  *       <li>The service parameter is null.
  *       <li>The service parameter is not a {@link ServiceFactory} and is not an <code>instanceof
  *           </code> all the named classes in the clazzes parameter.
  *     </ul>
  *
  * @exception java.lang.SecurityException If the caller does not have {@link ServicePermission}
  *     permission to "register" the service for all the named classes and the Java runtime
  *     environment supports permissions.
  * @exception java.lang.IllegalStateException If the bundle context has stopped.
  * @see ServiceRegistration
  * @see ServiceFactory
  */
 public ServiceRegistration<?> registerService(
     String[] clazzes, Object service, Dictionary<String, ?> properties) {
   checkValid();
   return framework.getServiceRegistry().registerService(this, clazzes, service, properties);
 }