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