Move the temporal service dependency to the trunk.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@657704 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalDependency.java b/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalDependency.java
new file mode 100644
index 0000000..5b3c853
--- /dev/null
+++ b/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalDependency.java
@@ -0,0 +1,154 @@
+/* 

+ * 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.ipojo.handler.temporal;

+

+import java.lang.reflect.Array;

+

+import org.apache.felix.ipojo.FieldInterceptor;

+import org.apache.felix.ipojo.util.DependencyModel;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.Filter;

+import org.osgi.framework.ServiceReference;

+

+/**

+* Temporal dependency.

+* A temporal dependency waits (block) for the availability of the service.

+* If no provider arrives in the specified among of time, a runtime exception is thrown.

+* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+*/

+public class TemporalDependency extends DependencyModel implements FieldInterceptor {

+    

+    /**

+     * Timeout.

+     */

+    private long m_timeout;

+

+    /**

+     * Constructor.

+     * @param spec : service specification

+     * @param agg : is the dependency aggregate ?

+     * @param filter : LDAP filter

+     * @param context : service context

+     * @param timeout : timeout

+     * @param handler : Handler managing this dependency

+     */

+    public TemporalDependency(Class spec, boolean agg, Filter filter, BundleContext context, long timeout, TemporalHandler handler) {

+        super(spec, agg, true, filter, null, DependencyModel.DYNAMIC_BINDING_POLICY, context, handler);

+        this.m_timeout = timeout;

+    }

+

+    /**

+     * The dependency has been reconfigured.

+     * @param arg0 : new service references

+     * @param arg1 : old service references

+     * @see org.apache.felix.ipojo.util.DependencyModel#onDependencyReconfiguration(org.osgi.framework.ServiceReference[], org.osgi.framework.ServiceReference[])

+     */

+    public void onDependencyReconfiguration(ServiceReference[] arg0, ServiceReference[] arg1) { 

+        throw new UnsupportedOperationException("Reconfiguration not yet supported");

+    }

+

+    /**

+     * A provider arrives.

+     * @param arg0 : service reference of the new provider.

+     * @see org.apache.felix.ipojo.util.DependencyModel#onServiceArrival(org.osgi.framework.ServiceReference)

+     */

+    public void onServiceArrival(ServiceReference arg0) {

+        // Notify if a thread is waiting.

+        synchronized (this) {

+            notifyAll();

+        }

+    }

+

+    /**

+     * A provider leaves.

+     * Nothing to do.

+     * @param arg0 : leaving service references.

+     * @see org.apache.felix.ipojo.util.DependencyModel#onServiceDeparture(org.osgi.framework.ServiceReference)

+     */

+    public synchronized void onServiceDeparture(ServiceReference arg0) { }

+    

+    /**

+     * The code require a value of the monitored field.

+     * If providers are available, the method return service object(s) immediately. 

+     * Else, the thread is blocked until an arrival. If no provider arrives during 

+     * the among of time specified, the method throws a Runtime Exception.

+     * @param arg0 : POJO instance asking for  the service

+     * @param arg1 : field name

+     * @param arg2 : previous value

+     * @return the object to inject.

+     * @see org.apache.felix.ipojo.FieldInterceptor#onGet(java.lang.Object, java.lang.String, java.lang.Object)

+     */

+    public synchronized Object onGet(Object arg0, String arg1, Object arg2) {

+        ServiceReference[] refs = getServiceReferences();

+        if (refs != null) {

+            // Immediate return.

+            if (isAggregate()) {

+                Object[] svc = (Object[]) Array.newInstance(getSpecification(), refs.length);

+                for (int i = 0; i < svc.length; i++) {

+                    svc[i] = getService(refs[i]);

+                }

+                return svc;

+            } else {

+                return getService(refs[0]);

+            }

+        } else {

+            // Begin to wait ...

+            long enter = System.currentTimeMillis();

+            boolean exhausted = false;

+            ServiceReference ref = null;

+            synchronized (this) {

+                while (getServiceReference() == null && ! exhausted) {

+                    try {

+                        wait(1);

+                    } catch (InterruptedException e) {

+                        // We was interrupted ....

+                    } finally {

+                        long end = System.currentTimeMillis(); 

+                        exhausted = (end - enter) > m_timeout;

+                    }

+                }

+            }

+            // Check 

+            if (exhausted) {

+                // Timeout, throw an exception

+                throw new RuntimeException("Service " + getSpecification().getName() + " unavailable : timeout");

+            } else {

+                ref = getServiceReference();

+                if (isAggregate()) {

+                    Object[] svc = (Object[]) Array.newInstance(getSpecification(), 1);

+                    svc[0] = ref;

+                    return svc[0];

+                } else {

+                    return getService(ref);

+                }

+            }

+        }

+    }

+

+    /**

+     * The monitored field receives a value.

+     * Nothing to do.

+     * @param arg0 : POJO setting the value.

+     * @param arg1 : field name

+     * @param arg2 : received value

+     * @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) { }

+

+}

diff --git a/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalHandler.java b/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalHandler.java
new file mode 100644
index 0000000..ebe4818
--- /dev/null
+++ b/ipojo/temporal.dependency.handler/src/main/java/org/apache/felix/ipojo/handler/temporal/TemporalHandler.java
@@ -0,0 +1,156 @@
+/* 

+ * 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.ipojo.handler.temporal;

+

+import java.util.ArrayList;

+import java.util.Dictionary;

+import java.util.List;

+

+import org.apache.felix.ipojo.ConfigurationException;

+import org.apache.felix.ipojo.PrimitiveHandler;

+import org.apache.felix.ipojo.metadata.Element;

+import org.apache.felix.ipojo.parser.FieldMetadata;

+import org.apache.felix.ipojo.parser.PojoMetadata;

+import org.apache.felix.ipojo.util.DependencyModel;

+import org.apache.felix.ipojo.util.DependencyStateListener;

+import org.osgi.framework.Filter;

+import org.osgi.framework.InvalidSyntaxException;

+

+/**

+* Temporal dependency handler.

+* A temporal dependency waits (block) for the availability of the service.

+* If no provider arrives in the specified among of time, a runtime exception is thrown.

+* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+*/

+public class TemporalHandler extends PrimitiveHandler implements DependencyStateListener {

+    

+    /**

+     * Default timeout if not specified.

+     */

+    public static final int DEFAULT_TIMEOUT = 3000;

+    

+    /**

+     * Handler namespace.

+     */

+    public static final String NAMESPACE = "org.apache.felix.ipojo.handler.temporal";

+    

+    /**

+     * List of managed dependencies.

+     */

+    private List/*<deps>*/ m_dependencies = new ArrayList(1);

+

+    /**

+     * Start method. Starts managed dependencies.

+     * @see org.apache.felix.ipojo.Handler#start()

+     */

+    public void start() {

+        for (int i = 0; i < m_dependencies.size(); i++) {

+            ((TemporalDependency) m_dependencies.get(i)).start();

+        }

+    }

+    

+    /**

+     * Stop  method. Stops managed dependencies.

+     * @see org.apache.felix.ipojo.Handler#stop()

+     */

+    public void stop() {

+        for (int i = 0; i < m_dependencies.size(); i++) {

+            ((TemporalDependency) m_dependencies.get(i)).stop();

+        }

+        m_dependencies.clear();

+    }

+

+    /**

+     * Configure method.

+     * Create managed dependencies.

+     * @param meta : component type metadata.

+     * @param dictionary : instance configuration.

+     * @throws ConfigurationException : the dependency is not configured correctly

+     * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)

+     */

+    public void configure(Element meta, Dictionary dictionary) throws ConfigurationException {

+        PojoMetadata manipulation = getFactory().getPojoMetadata();

+        Element[] deps = meta.getElements("requires", NAMESPACE);

+        for (int i = 0; i < deps.length; i++) {

+            if (!deps[i].containsAttribute("field") || m_dependencies.contains(deps[i].getAttribute("field"))) {

+                error("One temporal dependency must be attached to a field or the field is already used");

+                return;

+            }

+            String field = deps[i].getAttribute("field");

+

+            FieldMetadata fieldmeta = manipulation.getField(field);

+            if (fieldmeta == null) {

+                error("The field " + field + " does not exist in the class " + getInstanceManager().getClassName());

+                return;

+            }             

+                        

+            String fil = deps[i].getAttribute("filter");

+            Filter filter = null; 

+            if (fil != null) {

+                try {

+                    filter = getInstanceManager().getContext().createFilter(fil);

+                } catch (InvalidSyntaxException e) {

+                    error("Cannot create the field from " + fil + ": " + e.getMessage());

+                    return;

+                }

+            }

+            

+            boolean agg = false;

+            String aggregate = meta.getAttribute("aggregate"); 

+            if (aggregate != null) {

+                agg = aggregate.equalsIgnoreCase("true");

+            }

+

+            String spec = fieldmeta.getFieldType();

+            if (spec.endsWith("[]")) {

+                agg = true;

+                spec = spec.substring(0, spec.length() - 2);

+            }

+            

+            long timeout = DEFAULT_TIMEOUT;

+            if (deps[i].containsAttribute("timeout")) {

+                timeout = new Long(deps[i].getAttribute("timeout")).longValue();

+            }

+            

+            Class specification = DependencyModel.loadSpecification(spec, getInstanceManager().getContext());

+            TemporalDependency dep = new TemporalDependency(specification, agg, filter, getInstanceManager().getContext(), timeout, this);

+            m_dependencies.add(dep);

+            

+            getInstanceManager().register(fieldmeta, dep);

+        }        

+    }

+

+    /**

+     * Nothing to do.

+     * A temporal dependency is always valid.

+     * @param dependencymodel : dependency.

+     * @see org.apache.felix.ipojo.util.DependencyStateListener#invalidate(org.apache.felix.ipojo.util.DependencyModel)

+     */

+    public void invalidate(DependencyModel dependencymodel) {    }

+

+    /**

+     * Nothing to do.

+     * A temporal dependency is always valid.

+     * @param dependencymodel : dependency.

+     * @see org.apache.felix.ipojo.util.DependencyStateListener#validate(org.apache.felix.ipojo.util.DependencyModel)

+     */

+    public void validate(DependencyModel dependencymodel) {    }

+    

+

+}

diff --git a/ipojo/temporal.dependency.handler/src/main/resources/metadata.xml b/ipojo/temporal.dependency.handler/src/main/resources/metadata.xml
new file mode 100644
index 0000000..bd52e4c
--- /dev/null
+++ b/ipojo/temporal.dependency.handler/src/main/resources/metadata.xml
@@ -0,0 +1,24 @@
+<!--

+	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.

+-->

+<ipojo>

+	<handler

+		classname="org.apache.felix.ipojo.handler.temporal.TemporalHandler"

+		name="requires" namespace="org.apache.felix.ipojo.handler.temporal">

+	</handler>

+</ipojo>
\ No newline at end of file