| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.felix.dm.annotation.api; |
| |
| import java.lang.annotation.ElementType; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.lang.annotation.Target; |
| |
| /** |
| * Annotates a method or a field for injecting a Service Dependency. When applied on a class |
| * field, optional unavailable dependencies are injected with a NullObject. |
| * |
| * <p> For "add", "change", "remove" callbacks, the following method signatures are supported: |
| * |
| * <pre>{@code |
| * (Component comp, ServiceReference ref, Service service) |
| * (Component comp, ServiceReference ref, Object service) |
| * (Component comp, ServiceReference ref) |
| * (Component comp, Service service) |
| * (Component comp, Object service) |
| * (Component comp) |
| * (Component comp, Map properties, Service service) |
| * (ServiceReference ref, Service service) |
| * (ServiceReference ref, Object service) |
| * (ServiceReference ref) |
| * (Service service) |
| * (Service service, Map propeerties) |
| * (Map properties, Service, service) |
| * (Service service, Dictionary properties) |
| * (Dictionary properties, Service service) |
| * (Object service) |
| * }</pre> |
| * |
| * <p> For "swap" callbacks, the following method signatures are supported: |
| * |
| * <pre>{@code |
| * (Service old, Service replace) |
| * (Object old, Object replace) |
| * (ServiceReference old, Service old, ServiceReference replace, Service replace) |
| * (ServiceReference old, Object old, ServiceReference replace, Object replace) |
| * (Component comp, Service old, Service replace) |
| * (Component comp, Object old, Object replace) |
| * (Component comp, ServiceReference old, Service old, ServiceReference replace, Service replace) |
| * (Component comp, ServiceReference old, Object old, ServiceReference replace, Object replace) |
| * (ServiceReference old, ServiceReference replace) |
| * (Component comp, ServiceReference old, ServiceReference replace) |
| * }</pre> |
| * |
| * <h3>Usage Examples</h3> |
| * Here, the MyComponent component is injected with a dependency over a "MyDependency" service |
| * |
| * <blockquote><pre> |
| * @Component |
| * class MyComponent { |
| * @ServiceDependency(timeout=15000) |
| * MyDependency dependency; |
| * </pre></blockquote> |
| * |
| * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> |
| */ |
| @Retention(RetentionPolicy.CLASS) |
| @Target({ElementType.METHOD, ElementType.FIELD}) |
| public @interface ServiceDependency |
| { |
| /** |
| * Marker interface used to match any service types. When you set the {@link ServiceDependency#service} attribute to this class, |
| * it means that the dependency will return any services (matching the {@link ServiceDependency#filter()} attribute if it is specified). |
| */ |
| public interface Any { } |
| |
| /** |
| * The type if the service this dependency is applying on. By default, the method parameter |
| * (or the class field) is used as the type. If you want to match all available services, you can set |
| * this attribute to the {@link Any} class. In this case, all services (matching the {@link ServiceDependency#filter()} attribute if it is specified) will |
| * be returned. |
| * @return the service dependency |
| */ |
| Class<?> service() default Object.class; |
| |
| /** |
| * The Service dependency OSGi filter. |
| * @return the service filter |
| */ |
| String filter() default ""; |
| |
| /** |
| * The class for the default implementation, if the dependency is not available. |
| * @return the default implementation class |
| */ |
| Class<?> defaultImpl() default Object.class; |
| |
| /** |
| * Whether the Service dependency is required or not. |
| * @return the required flag |
| */ |
| boolean required() default true; |
| |
| /** |
| * The callback method to be invoked when the service is available. This attribute is only meaningful when |
| * the annotation is applied on a class field. |
| * |
| * @return the add callback |
| */ |
| String added() default ""; |
| |
| /** |
| * The callback method to be invoked when the service properties have changed. |
| * @return the change callback |
| */ |
| String changed() default ""; |
| |
| /** |
| * The callback method to invoke when the service is lost. |
| * @return the remove callback |
| */ |
| String removed() default ""; |
| |
| /** |
| * the method to call when the service was swapped due to addition or removal of an aspect |
| * @return the swap callback |
| */ |
| String swap() default ""; |
| |
| /** |
| * The max time in millis to wait for the dependency availability. |
| * Specifying a positive number allow to block the caller thread between service updates. Only |
| * useful for required stateless dependencies that can be replaced transparently. |
| * A Dynamic Proxy is used to wrap the actual service dependency (which must be an interface). |
| * When the dependency goes away, an attempt is made to replace it with another one which satisfies |
| * the service dependency criteria. If no service replacement is available, then any method invocation |
| * (through the dynamic proxy) will block during a configurable timeout. On timeout, an unchecked |
| * <code>IllegalStateException</code> exception is raised (but the service is not deactivated).<p> |
| * Notice that the changed/removed callbacks are not used when the timeout parameter is greater than -1. |
| * |
| * -1 means no timeout at all (default). 0 means that invocation on a missing service will fail |
| * immediately. A positive number represents the max timeout in millis to wait for the service availability. |
| * |
| * Sample Code: |
| * <blockquote><pre> |
| * @Component |
| * class MyServer implements Runnable { |
| * @ServiceDependency(timeout=15000) |
| * MyDependency dependency;. |
| * |
| * @Start |
| * void start() { |
| * (new Thread(this)).start(); |
| * } |
| * |
| * public void run() { |
| * try { |
| * dependency.doWork(); |
| * } catch (IllegalStateException e) { |
| * t.printStackTrace(); |
| * } |
| * } |
| * </pre></blockquote> |
| * @return the wait time when the dependency is unavailable |
| */ |
| long timeout() default -1; |
| |
| /** |
| * The name used when dynamically configuring this dependency from the init method. |
| * Specifying this attribute allows to dynamically configure the dependency |
| * <code>filter</code> and <code>required</code> flag from the Service's init method. |
| * All unnamed dependencies will be injected before the init() method; so from the init() method, you can |
| * then pick up whatever information needed from already injected (unnamed) dependencies, and configure dynamically |
| * your named dependencies, which will then be calculated once the init() method returns. |
| * |
| * <p> See {@link Init} annotation for an example usage of a dependency dynamically configured from the init method. |
| * @return the dependency name used to dynamically configure the filter and required flag from the init callback. |
| */ |
| String name() default ""; |
| |
| /** |
| * Returns true if the dependency service properties must be published along with the service. |
| * Any additional service properties specified directly are merged with these. |
| * @return true if dependency service properties must be published along with the service, false if not. |
| */ |
| boolean propagate() default false; |
| |
| /** |
| * Configures whether or not this dependency should internally obtain the service object for all tracked service references. |
| * |
| * By default, DM internally dereferences all discovered service references (using |
| * <code>BundleContext.getService(ServiceReference ref)</code> methods. |
| * However, sometimes, your callback only needs the ServiceReference, and sometimes you don't want to dereference the service. |
| * So, in this case you can use the <code>dereference(false)</code> method in order to tell to DM |
| * that it should never internally dereference the service dependency internally. |
| * |
| * @return false if the service must never be dereferenced by dependency manager (internally). |
| */ |
| boolean dereference() default true; |
| } |