Author: clement
Date: Mon Jul  7 07:38:16 2008
New Revision: 674506

URL: http://svn.apache.org/viewvc?rev=674506&view=rev
Log:
Add the onTimeout support to the temporal dependencies.
It's now possible to specify the action to do when the timeout occurs. Several 
possibilities are offered :
- nullable injects a nullable object
- default-implementation  injects a default-implementation
- empty-array injects an empty array (must be an aggregate dependency)
- null injects null

When no onTimeout action are provided, the handler throws a runtime exception.

Moreover, now it is possible to indicate an infinite timeout with 
timeout="infinite" or timeout=-1" in the handler description. 

Modified:
    
felix/trunk/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalDependency.java
    
felix/trunk/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalHandler.java

Modified: 
felix/trunk/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalDependency.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalDependency.java?rev=674506&r1=674505&r2=674506&view=diff
==============================================================================
--- 
felix/trunk/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalDependency.java
 (original)
+++ 
felix/trunk/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalDependency.java
 Mon Jul  7 07:38:16 2008
@@ -19,8 +19,12 @@
 package org.apache.felix.ipojo.handler.temporal;
 
 import java.lang.reflect.Array;
+import java.lang.reflect.Proxy;
 
 import org.apache.felix.ipojo.FieldInterceptor;
+import org.apache.felix.ipojo.Nullable;
+import org.apache.felix.ipojo.PrimitiveHandler;
+import org.apache.felix.ipojo.handlers.dependency.NullableObject;
 import org.apache.felix.ipojo.util.DependencyModel;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Filter;
@@ -38,6 +42,32 @@
      * Timeout.
      */
     private long m_timeout;
+    
+    /**
+     * Default-Implementation
+     */
+    private String m_di;
+    
+    /**
+     * Nullable object / Default-Implementation instance if used
+     */
+    private Object m_nullableObject;
+    
+    /**
+     * Handler managing this dependency.
+     */
+    private PrimitiveHandler m_handler;
+    
+    /**
+     * Timetout policy.
+     * Null inject null
+     * Nullable injects a nullable object or an array with a nullable object
+     * Default-Implementation inject an object created from the specified 
injected
+     * implementation or an array with it
+     * Empty array inject an empty array (must be an aggregate dependency)
+     * No policy (0) throw a runtime exception when the timeout occurs     * 
+     */
+    private int m_policy;
 
     /**
      * Constructor.
@@ -48,9 +78,12 @@
      * @param timeout : timeout
      * @param handler : Handler managing this dependency
      */
-    public TemporalDependency(Class spec, boolean agg, Filter filter, 
BundleContext context, long timeout, TemporalHandler handler) {
+    public TemporalDependency(Class spec, boolean agg, Filter filter, 
BundleContext context, long timeout, int policy, String defaultImpl, 
TemporalHandler handler) {
         super(spec, agg, true, filter, null, 
DependencyModel.DYNAMIC_BINDING_POLICY, context, handler);
-        this.m_timeout = timeout;
+        m_di = defaultImpl;
+        m_policy = policy;
+        m_timeout = timeout;
+        m_handler = handler;
     }
 
     /**
@@ -126,20 +159,85 @@
             }
             // Check 
             if (exhausted) {
-                // Timeout, throw an exception
-                throw new RuntimeException("Service " + 
getSpecification().getName() + " unavailable : timeout");
+               return onTimeout();
             } else {
                 ref = getServiceReference();
                 if (isAggregate()) {
                     Object[] svc = (Object[]) 
Array.newInstance(getSpecification(), 1);
-                    svc[0] = ref;
-                    return svc[0];
+                    svc[0] = getService(ref);
+                    return svc;
                 } else {
                     return getService(ref);
                 }
             }
         }
     }
+    
+    public void start() {
+       super.start();
+        switch(m_policy) {
+            case TemporalHandler.NULL:
+                m_nullableObject = null;
+                break;
+            case TemporalHandler.NULLABLE:
+                // To load the proxy we use the POJO class loader. Indeed, this
+                // classloader imports iPOJO (so can access to Nullable) and 
has
+                // access to the service specification.
+                try {
+                    m_nullableObject = Proxy.newProxyInstance(m_handler
+                            .getInstanceManager().getClazz().getClassLoader(),
+                            new Class[] { getSpecification(), Nullable.class },
+                            new NullableObject()); // NOPMD
+                    if (isAggregate()) {
+                        Object[] array = (Object[]) 
Array.newInstance(getSpecification(), 1);
+                        array[0] = m_nullableObject;
+                        m_nullableObject = array;                        
+                    }
+                } catch (NoClassDefFoundError e) {
+                    // A NoClassDefFoundError is thrown if the specification 
uses a
+                    // class not accessible by the actual instance.
+                    // It generally comes from a missing import.
+                    throw new IllegalStateException(
+                            "Cannot create the Nullable object, a referenced 
class cannot be loaded: "
+                                    + e.getMessage());
+                }
+
+                break;
+            case TemporalHandler.DEFAULT_IMPLEMENTATION:
+             // Create the default-implementation object.
+                try {
+                    Class clazz = m_handler.getInstanceManager().getContext()
+                            .getBundle().loadClass(m_di);
+                    m_nullableObject = clazz.newInstance();
+                } catch (IllegalAccessException e) {
+                    throw new IllegalStateException(
+                            "Cannot load the default-implementation " + m_di
+                                    + " : " + e.getMessage());
+                } catch (InstantiationException e) {
+                    throw new IllegalStateException(
+                            "Cannot load the default-implementation " + m_di
+                                    + " : " + e.getMessage());
+                } catch (ClassNotFoundException e) {
+                    throw new IllegalStateException(
+                            "Cannot load the default-implementation " + m_di
+                                    + " : " + e.getMessage());
+                }
+                if (isAggregate()) {
+                    Object[] array = (Object[]) 
Array.newInstance(getSpecification(), 1);
+                    array[0] = m_nullableObject;
+                    m_nullableObject = array;
+                }
+                break;
+            case TemporalHandler.EMPTY_ARRAY:
+                m_nullableObject = Array.newInstance(getSpecification(), 0);
+                break;
+        }
+       }
+    
+    public void stop() {
+       super.stop();
+       m_nullableObject = null;
+    }
 
     /**
      * The monitored field receives a value.
@@ -150,5 +248,21 @@
      * @see org.apache.felix.ipojo.FieldInterceptor#onSet(java.lang.Object, 
java.lang.String, java.lang.Object)
      */
     public void onSet(Object arg0, String arg1, Object arg2) { }
+    
+    /**
+     * Implements the timeout policy according to the specified configuration
+     */
+    private Object onTimeout() {
+        switch(m_policy) {
+            case TemporalHandler.NULL:
+            case TemporalHandler.NULLABLE:
+            case TemporalHandler.DEFAULT_IMPLEMENTATION:
+            case TemporalHandler.EMPTY_ARRAY:
+                return m_nullableObject;
+            default: 
+                // Throws a runtime exception
+                throw new RuntimeException("Service " + 
getSpecification().getName() + " unavailable : timeout");
+        }
+    }
 
 }

Modified: 
felix/trunk/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalHandler.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalHandler.java?rev=674506&r1=674505&r2=674506&view=diff
==============================================================================
--- 
felix/trunk/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalHandler.java
 (original)
+++ 
felix/trunk/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalHandler.java
 Mon Jul  7 07:38:16 2008
@@ -45,6 +45,12 @@
      */
     public static final int DEFAULT_TIMEOUT = 3000;
     
+    public static final int NO_POLICY = 0;
+    public static final int NULLABLE = 1;
+    public static final int DEFAULT_IMPLEMENTATION = 2;
+    public static final int EMPTY_ARRAY = 3;
+    public static final int NULL = 4;
+    
     /**
      * Handler namespace.
      */
@@ -125,11 +131,36 @@
             
             long timeout = DEFAULT_TIMEOUT;
             if (deps[i].containsAttribute("timeout")) {
-                timeout = new 
Long(deps[i].getAttribute("timeout")).longValue();
+                String to = deps[i].getAttribute("timeout");
+                if (to.equalsIgnoreCase("infinite")  || 
to.equalsIgnoreCase("-1")) {
+                    timeout = Long.MAX_VALUE; // Infinite wait time ...
+                } else {
+                    timeout = new 
Long(deps[i].getAttribute("timeout")).longValue();
+                }
             }
             
+            int policy = NO_POLICY;
+            String di = null;
+            String onTimeout = deps[i].getAttribute("onTimeout");
+            if (onTimeout != null) {
+                if (onTimeout.equalsIgnoreCase("nullable")) {
+                    policy = NULLABLE;
+                } else if (onTimeout.equalsIgnoreCase("empty-array")) {
+                    policy = EMPTY_ARRAY;
+                    if (! agg) {
+                        // The empty array policy can only be used on 
aggregate dependencies
+                        error("Cannot use the empty array policy for " + field 
+ " : non aggregate dependency.");
+                    }
+                } else if (onTimeout.equalsIgnoreCase("null")) {
+                    policy = NULL;
+                } else if (onTimeout.length() > 0) {
+                    di = onTimeout;
+                    policy = DEFAULT_IMPLEMENTATION;
+                }
+            }
+         
             Class specification = DependencyModel.loadSpecification(spec, 
getInstanceManager().getContext());
-            TemporalDependency dep = new TemporalDependency(specification, 
agg, filter, getInstanceManager().getContext(), timeout, this);
+            TemporalDependency dep = new TemporalDependency(specification, 
agg, filter, getInstanceManager().getContext(), timeout, policy, di, this);
             m_dependencies.add(dep);
             
             getInstanceManager().register(fieldmeta, dep);


Reply via email to