Return-Path: X-Original-To: apmail-felix-commits-archive@www.apache.org Delivered-To: apmail-felix-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id C252E18AB8 for ; Fri, 18 Dec 2015 16:59:10 +0000 (UTC) Received: (qmail 19963 invoked by uid 500); 18 Dec 2015 16:59:10 -0000 Delivered-To: apmail-felix-commits-archive@felix.apache.org Received: (qmail 19921 invoked by uid 500); 18 Dec 2015 16:59:10 -0000 Mailing-List: contact commits-help@felix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@felix.apache.org Delivered-To: mailing list commits@felix.apache.org Received: (qmail 19912 invoked by uid 99); 18 Dec 2015 16:59:10 -0000 Received: from Unknown (HELO spamd2-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 18 Dec 2015 16:59:10 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd2-us-west.apache.org (ASF Mail Server at spamd2-us-west.apache.org) with ESMTP id 22BA51A1330 for ; Fri, 18 Dec 2015 16:59:10 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd2-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 1.246 X-Spam-Level: * X-Spam-Status: No, score=1.246 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RP_MATCHES_RCVD=-0.554] autolearn=disabled Received: from mx1-eu-west.apache.org ([10.40.0.8]) by localhost (spamd2-us-west.apache.org [10.40.0.9]) (amavisd-new, port 10024) with ESMTP id nkxCr0VH33AK for ; Fri, 18 Dec 2015 16:59:01 +0000 (UTC) Received: from mailrelay1-us-west.apache.org (mailrelay1-us-west.apache.org [209.188.14.139]) by mx1-eu-west.apache.org (ASF Mail Server at mx1-eu-west.apache.org) with ESMTP id 1A52E201A4 for ; Fri, 18 Dec 2015 16:59:00 +0000 (UTC) Received: from svn01-us-west.apache.org (svn.apache.org [10.41.0.6]) by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id 3646DE0053 for ; Fri, 18 Dec 2015 16:58:59 +0000 (UTC) Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id F020F3A022E for ; Fri, 18 Dec 2015 16:58:58 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1720825 - in /felix/sandbox/pderop/dependencymanager-lambda: org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/ org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ or... Date: Fri, 18 Dec 2015 16:58:58 -0000 To: commits@felix.apache.org From: pderop@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20151218165858.F020F3A022E@svn01-us-west.apache.org> Author: pderop Date: Fri Dec 18 16:58:58 2015 New Revision: 1720825 URL: http://svn.apache.org/viewvc?rev=1720825&view=rev Log: Finished BundleDependency + Tests. Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/BundleDependencyReflectTest.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/BundleDependencyTest.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/BundleDependencyBuilder.java Removed: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/BundleDepenencyBuilder.java Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ComponentBuilder.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/BundleDependencyBuilderImpl.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ComponentBuilderImpl.java felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ExtendedComponentBase.java Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/BundleDependencyReflectTest.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/BundleDependencyReflectTest.java?rev=1720825&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/BundleDependencyReflectTest.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/BundleDependencyReflectTest.java Fri Dec 18 16:58:58 2015 @@ -0,0 +1,175 @@ +/* + * 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.builder.lambda.itest; + +import org.junit.Assert; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; +import org.osgi.framework.Bundle; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.component; + +/** + * @author Felix Project Team + */ +public class BundleDependencyReflectTest extends TestBase { + private final static String BSN = "org.apache.felix.metatype"; + + public void testBundleDependencies() { + DependencyManager m = getDM(); + // create a service provider and consumer + MyConsumer c = new MyConsumer(); + Component consumer = component(m, comp -> comp.impl(c).withBundle(bundle -> bundle.callbacks("add", "remove"))); + + // check if at least one bundle was found + c.check(); + // remove the consumer again + m.remove(consumer); + // check if all bundles were removed correctly + c.doubleCheck(); + + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + String filter = "(Bundle-SymbolicName=" + BSN + ")"; + Component consumerWithFilter = + component(m, comp -> comp.impl(new FilteredConsumer(e)).withBundle(bundle-> bundle.filter(filter).callbacks("add", null, "remove"))); + e.step(2); + // remove the consumer again + m.remove(consumerWithFilter); + e.step(4); + } + + public void testRequiredBundleDependency() { + DependencyManager m = getDM(); + + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + Component consumerWithFilter = m.createComponent() + .setImplementation(new FilteredConsumerRequired(e)) + .add(m.createBundleDependency() + .setRequired(true) + .setFilter("(Bundle-SymbolicName=" + BSN + ")") + .setCallbacks("add", "remove") + ); + // add a consumer with a filter + m.add(consumerWithFilter); + e.waitForStep(1, 5000); + // remove the consumer again + m.remove(consumerWithFilter); + e.waitForStep(2, 5000); + } + + public void testRequiredBundleDependencyWithComponentArgInCallbackMethod() { + DependencyManager m = getDM(); + + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + Component consumerWithFilter = m.createComponent() + .setImplementation(new FilteredConsumerRequiredWithComponentArg(e)) + .add(m.createBundleDependency() + .setRequired(true) + .setFilter("(Bundle-SymbolicName=" + BSN + ")") + .setCallbacks("add", "remove") + ); + // add a consumer with a filter + m.add(consumerWithFilter); + e.waitForStep(1, 5000); + // remove the consumer again + m.remove(consumerWithFilter); + e.waitForStep(2, 5000); + } + + static class MyConsumer { + private volatile int m_count = 0; + + public void add(Bundle b) { + System.out.println("Consumer.add(" + b.getSymbolicName() + ")"); + Assert.assertNotNull("bundle instance must not be null", b); + m_count++; + } + + public void check() { + Assert.assertTrue("we should have found at least one bundle", m_count > 0); + } + + public void remove(Bundle b) { + System.out.println("Consumer.remove(" + b.getSymbolicName() + ")"); + m_count--; + } + + public void doubleCheck() { + Assert.assertEquals("all bundles we found should have been removed again", 0, m_count); + } + } + + static class FilteredConsumer { + private final Ensure m_ensure; + + public FilteredConsumer(Ensure e) { + m_ensure = e; + } + + public void add(Bundle b) { + m_ensure.step(1); + } + + public void remove(Bundle b) { + m_ensure.step(3); + } + } + + static class FilteredConsumerRequired { + private final Ensure m_ensure; + + public FilteredConsumerRequired(Ensure e) { + m_ensure = e; + } + + public void add(Bundle b) { + System.out.println("Bundle is " + b); +// Assert.assertNotNull(b); + if (b.getSymbolicName().equals(BSN)) { + m_ensure.step(1); + } + } + + public void remove(Bundle b) { + Assert.assertNotNull(b); + if (b.getSymbolicName().equals(BSN)) { + m_ensure.step(2); + } + } + } + + static class FilteredConsumerRequiredWithComponentArg extends FilteredConsumerRequired { + public FilteredConsumerRequiredWithComponentArg(Ensure e) { + super(e); + } + + public void add(Component component, Bundle b) { + Assert.assertNotNull(component); + super.add(b); + } + + public void remove(Component component, Bundle b) { + Assert.assertNotNull(component); + super.remove(b); + } + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/BundleDependencyTest.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/BundleDependencyTest.java?rev=1720825&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/BundleDependencyTest.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/builder/lambda/itest/BundleDependencyTest.java Fri Dec 18 16:58:58 2015 @@ -0,0 +1,177 @@ +/* + * 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.builder.lambda.itest; + +import org.junit.Assert; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; +import org.osgi.framework.Bundle; +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.component; + +/** + * @author Felix Project Team + */ +public class BundleDependencyTest extends TestBase { + private final static String BSN = "org.apache.felix.metatype"; + + public void testBundleDependencies() { + DependencyManager m = getDM(); + // create a service provider and consumer + MyConsumer c = new MyConsumer(); + Component consumer = component(m, comp -> comp + .impl(c).withBundle(bundle -> bundle.onAdd(MyConsumer::add).onRemove(MyConsumer::remove))); + + // check if at least one bundle was found + c.check(); + // remove the consumer again + m.remove(consumer); + // check if all bundles were removed correctly + c.doubleCheck(); + + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + String filter = "(Bundle-SymbolicName=" + BSN + ")"; + Component consumerWithFilter = component(m, comp -> comp + .impl(new FilteredConsumer(e)) + .withBundle(bundle-> bundle.filter(filter).onAdd(FilteredConsumer::add).onRemove(FilteredConsumer::remove))); + e.step(2); + // remove the consumer again + m.remove(consumerWithFilter); + e.step(4); + } + + public void testRequiredBundleDependency() { + DependencyManager m = getDM(); + + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + Component consumerWithFilter = m.createComponent() + .setImplementation(new FilteredConsumerRequired(e)) + .add(m.createBundleDependency() + .setRequired(true) + .setFilter("(Bundle-SymbolicName=" + BSN + ")") + .setCallbacks("add", "remove") + ); + // add a consumer with a filter + m.add(consumerWithFilter); + e.waitForStep(1, 5000); + // remove the consumer again + m.remove(consumerWithFilter); + e.waitForStep(2, 5000); + } + + public void testRequiredBundleDependencyWithComponentArgInCallbackMethod() { + DependencyManager m = getDM(); + + // helper class that ensures certain steps get executed in sequence + Ensure e = new Ensure(); + Component consumerWithFilter = m.createComponent() + .setImplementation(new FilteredConsumerRequiredWithComponentArg(e)) + .add(m.createBundleDependency() + .setRequired(true) + .setFilter("(Bundle-SymbolicName=" + BSN + ")") + .setCallbacks("add", "remove") + ); + // add a consumer with a filter + m.add(consumerWithFilter); + e.waitForStep(1, 5000); + // remove the consumer again + m.remove(consumerWithFilter); + e.waitForStep(2, 5000); + } + + static class MyConsumer { + private volatile int m_count = 0; + + public void add(Bundle b) { + System.out.println("Consumer.add(" + b.getSymbolicName() + ")"); + Assert.assertNotNull("bundle instance must not be null", b); + m_count++; + } + + public void check() { + Assert.assertTrue("we should have found at least one bundle", m_count > 0); + } + + public void remove(Bundle b) { + System.out.println("Consumer.remove(" + b.getSymbolicName() + ")"); + m_count--; + } + + public void doubleCheck() { + Assert.assertEquals("all bundles we found should have been removed again", 0, m_count); + } + } + + static class FilteredConsumer { + private final Ensure m_ensure; + + public FilteredConsumer(Ensure e) { + m_ensure = e; + } + + public void add(Bundle b) { + m_ensure.step(1); + } + + public void remove(Bundle b) { + m_ensure.step(3); + } + } + + static class FilteredConsumerRequired { + private final Ensure m_ensure; + + public FilteredConsumerRequired(Ensure e) { + m_ensure = e; + } + + public void add(Bundle b) { + System.out.println("Bundle is " + b); +// Assert.assertNotNull(b); + if (b.getSymbolicName().equals(BSN)) { + m_ensure.step(1); + } + } + + public void remove(Bundle b) { + Assert.assertNotNull(b); + if (b.getSymbolicName().equals(BSN)) { + m_ensure.step(2); + } + } + } + + static class FilteredConsumerRequiredWithComponentArg extends FilteredConsumerRequired { + public FilteredConsumerRequiredWithComponentArg(Ensure e) { + super(e); + } + + public void add(Component component, Bundle b) { + Assert.assertNotNull(component); + super.add(b); + } + + public void remove(Component component, Bundle b) { + Assert.assertNotNull(component); + super.remove(b); + } + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/BundleDependencyBuilder.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/BundleDependencyBuilder.java?rev=1720825&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/BundleDependencyBuilder.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/BundleDependencyBuilder.java Fri Dec 18 16:58:58 2015 @@ -0,0 +1,320 @@ +package org.apache.felix.dm.builder.lambda; + +import java.util.Dictionary; +import java.util.function.Supplier; + +import org.apache.felix.dm.BundleDependency; +import org.apache.felix.dm.Component; +import org.apache.felix.dm.builder.lambda.Functions.Consumer; +import org.apache.felix.dm.builder.lambda.Functions.Consumer2; +import org.apache.felix.dm.builder.lambda.Functions.SerializableLambda; +import org.osgi.framework.Bundle; + +/** + * Defines a dependency on a bundle. + * + * @author Felix Project Team + */ +public interface BundleDependencyBuilder extends DependencyBuilder { + /** + * Defines a method reference on a component class method. The callback method takes Bundle parameter. + * @param the type of the component instance on which this method reference is applied + */ + @FunctionalInterface + public interface InstanceBundle extends SerializableLambda { + /** + * Signature of the callback method. + * @param instance the component instance on which the callback has to be called + * @param bundle to inject + */ + void call(I instance, Bundle bundle); + } + + /** + * Defines a method reference on a component instance. The callback method takes Component and a Bundle in parameters. + * @param the type of the component instance on which this method reference is applied + */ + @FunctionalInterface + public interface InstanceComponentBundle extends SerializableLambda { + /** + * Signature of the callback method. + * @param instance the component instance on which the callback has to be called + * @param component the component on which this dependency has been added. + * @param bundle the bundle to inject. + */ + void call(I instance, Component component, Bundle bundle); + } + + /** + * Sets the add callbacks for this dependency. The callback can be used as hooks whenever a dependency is added. + * When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param callback the method to call when a bundle was added + * @return the bundle dependency + */ + public BundleDependencyBuilder onAdd(String callback); + + /** + * Sets the change callbacks for this dependency. The callback can be used as hooks whenever a dependency is changed. + * When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param callback the method to call when a bundle was changed + * @return the bundle dependency + */ + public BundleDependencyBuilder onChange(String callback); + + /** + * Sets the remove callbacks for this dependency. The callback can be used as hooks whenever a dependency is removed. + * When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param callback the method to call when a bundle was removed + * @return the bundle dependency + */ + public BundleDependencyBuilder onRemove(String callback); + + /** + * Sets the callbacks for this dependency. These callbacks can be used as hooks whenever a dependency is added, changed or + * removed. When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param added the method to call when a bundle was added + * @param removed the method to call when a bundle was removed + * @return the bundle dependency + */ + public BundleDependencyBuilder callbacks(String added, String removed); + + /** + * Sets the callbacks for this dependency. These callbacks can be used as hooks whenever a dependency is added, changed or + * removed. When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param added the method to call when a bundle was added + * @param changed the method to call when a bundle was changed + * @param removed the method to call when a bundle was removed + * @return the bundle dependency + */ + public BundleDependencyBuilder callbacks(String added, String changed, String removed); + + /** + * Sets the callbacks for this dependency. These callbacks can be used as hooks whenever a dependency is added, changed or + * removed. They are called on the instance you provide. When you specify callbacks, the auto configuration feature is + * automatically turned off, because we're assuming you don't need it in this case. + * + * @param instance the instance to call the callbacks on + * @param added the method to call when a bundle was added + * @param changed the method to call when a bundle was changed + * @param removed the method to call when a bundle was removed + * @return the bundle dependency builder + */ + public BundleDependencyBuilder callbacks(Object instance, String added, String changed, String removed); + + /** + * Sets the add callbacks instance for this dependency. These callbacks can be used as hooks whenever a dependency is added. When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param added the method to call when a bundle was added + * @return the bundle dependency + */ + public BundleDependencyBuilder onAdd(Consumer add); + + /** + * Sets the add callbacks instance for this dependency. These callbacks can be used as hooks whenever a dependency is added. When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param added the method to call when a bundle was added + * @return the bundle dependency + */ + public BundleDependencyBuilder onAdd(InstanceBundle add); + + /** + * Sets the add callbacks instance for this dependency. These callbacks can be used as hooks whenever a dependency is added. When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param added the method to call when a bundle was added. the callback is invoked with the component on which this dependency is added, and the added bundle. + * @return the bundle dependency + */ + public BundleDependencyBuilder onAdd(Consumer2 add); + + /** + * Sets the add callbacks instance for this dependency. These callbacks can be used as hooks whenever a dependency is added. When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param added the method to call on one of the component instances when a bundle was added. the callback is invoked with the component on which this dependency is added, and the added bundle. + * @return the bundle dependency + */ + public BundleDependencyBuilder onAdd(InstanceComponentBundle add); + + /** + * Sets the change callbacks instance for this dependency. These callbacks can be used as hooks whenever a dependency is changed. When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param added the method to call when a bundle was changed + * @return the bundle dependency + */ + public BundleDependencyBuilder onChange(Consumer add); + + /** + * Sets the changed callbacks instance for this dependency. These callbacks can be used as hooks whenever a dependency is changed. When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param change the method to call when a bundle was changed + * @return the bundle dependency + */ + public BundleDependencyBuilder onChange(InstanceBundle change); + + /** + * Sets the changed callbacks instance for this dependency. These callbacks can be used as hooks whenever a dependency is changed. When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param change the method to call when a bundle was changed. the callback is invoked with the component on which this dependency is added, and the added bundle. + * @return the bundle dependency + */ + public BundleDependencyBuilder onChange(Consumer2 change); + + /** + * Sets the changed callbacks instance for this dependency. These callbacks can be used as hooks whenever a dependency is changed. When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param change the method to call on one of the component instances when a bundle was changed. the callback is invoked with the component on which this dependency is added, and the added bundle. + * @return the bundle dependency + */ + public BundleDependencyBuilder onChange(InstanceComponentBundle change); + + /** + * Sets the remove callbacks instance for this dependency. These callbacks can be used as hooks whenever a dependency is removed. When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param remove the method to call when a bundle was remove + * @return the bundle dependency + */ + public BundleDependencyBuilder onRemove(Consumer remove); + + /** + * Sets the remove callbacks instance for this dependency. These callbacks can be used as hooks whenever a dependency is removed. When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param remove the method to call when a bundle was removed + * @return the bundle dependency + */ + public BundleDependencyBuilder onRemove(InstanceBundle remove); + + /** + * Sets the remove callbacks instance for this dependency. These callbacks can be used as hooks whenever a dependency is remove. When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param removed the method to call when a bundle was removed. the callback is invoked with the component on which this dependency is removed, and the added bundle. + * @return the bundle dependency + */ + public BundleDependencyBuilder onRemove(Consumer2 remove); + + /** + * Sets the remove callbacks instance for this dependency. These callbacks can be used as hooks whenever a dependency is removed. When you specify callbacks, the auto configuration feature is automatically turned off, because we're assuming + * you don't need it in this case. + * + * @param remove the method to call on one of the component instances when a bundle was removed. the callback is invoked with the component on which this dependency is added, and the added bundle. + * @return the bundle dependency + */ + public BundleDependencyBuilder onRemove(InstanceComponentBundle remove); + + /** + * Enables auto configuration for this dependency. This means the component implementation (composition) will be + * injected with this bundle dependency automatically. + * + * @param autoConfig true to enable auto configuration + * @return the bundle dependency builder + */ + public BundleDependencyBuilder autoConfig(boolean autoConfig); + + /** + * Enables auto configuration for this dependency. This means the component implementation (composition) will be + * injected with this bundle dependency automatically. + * + * @return the bundle dependency builder + */ + public BundleDependencyBuilder autoConfig(); + + /** + * Sets the dependency to be required. + * + * @param required true if this bundle dependency is required + * @return the bundle dependency builder + */ + public BundleDependencyBuilder required(boolean required); + + /** + * Sets the dependency to be required. + * + * @param required true if this bundle dependency is required + * @return the bundle dependency builder + */ + public BundleDependencyBuilder required(); + + /** + * Sets the bundle to depend on directly. + * + * @param bundle the bundle to depend on + * @return the bundle dependency builder + */ + public BundleDependencyBuilder bundle(Bundle bundle); + + /** + * Sets the filter condition to depend on. Filters are matched against the full manifest of a bundle. + * + * @param filter the filter condition + * @return the bundle dependency builder + * @throws IllegalArgumentException if the filter is invalid + */ + public BundleDependencyBuilder filter(String filter) throws IllegalArgumentException; + + /** + * Sets the bundle state mask to depend on. The OSGi BundleTracker explains this mask in more detail, but + * it is basically a mask with flags for each potential state a bundle can be in. + * + * @param mask the mask to use + * @return the bundle dependency builder + */ + public BundleDependencyBuilder mask(int mask); + + /** + * Sets property propagation. If set to true any bundle manifest properties will be added + * to the service properties of the component that has this dependency (if it registers as a service). + * + * @param propagate true to propagate the bundle manifest properties + * @return the bundle dependency builder + */ + public BundleDependencyBuilder propagate(boolean propagate); + + /** + * Sets property propagation. any bundle manifest properties will be added + * to the service properties of the component that has this dependency (if it registers as a service). + * + * @return the bundle dependency builder + */ + public BundleDependencyBuilder propagate(); + + /** + * Sets an Object instance and a callback method used to propagate some properties to the provided service properties. + * The method will be invoked on the specified object instance and must have one of the following signatures: + *
  • Dictionary callback(ServiceReference, Object service) + *
  • Dictionary callback(ServiceReference) + *
+ * @param instance the Object instance which is used to retrieve propagated service properties + * @param method the method to invoke for retrieving the properties to be propagated to the service properties. + * @return this service dependency. builder + */ + public BundleDependencyBuilder propagate(Object instance, String method); + + /** + * Sets an Object instance and a callback method used to propagate some properties to the provided service properties. + * The method will be invoked on the specified object instance and must have one of the following signatures: + *
  • Dictionary callback(ServiceReference, Object service) + *
  • Dictionary callback(ServiceReference) + *
+ * @param instance the Object instance which is used to retrieve propagated service properties + * @return this service dependency. builder + */ + public BundleDependencyBuilder propagate(Supplier> instance); +} Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ComponentBuilder.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ComponentBuilder.java?rev=1720825&r1=1720824&r2=1720825&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ComponentBuilder.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/ComponentBuilder.java Fri Dec 18 16:58:58 2015 @@ -146,19 +146,26 @@ public interface ComponentBuilder B withService(Class service, Consumer> consumer); /** * Adds a configuration dependency. - * @param consumer the lambda used to configuration the configuration dependency. + * @param consumer the lambda used to build the configuration dependency. * @return this builder. */ B withConfiguration(Consumer consumer); /** + * Adds a bundle dependency. + * @param consumer the lambda used to build the bundle dependency. + * @return this builder. + */ + B withBundle(Consumer consumer); + + /** * TODO * @param future * @return Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/BundleDependencyBuilderImpl.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/BundleDependencyBuilderImpl.java?rev=1720825&r1=1720824&r2=1720825&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/BundleDependencyBuilderImpl.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/BundleDependencyBuilderImpl.java Fri Dec 18 16:58:58 2015 @@ -11,12 +11,28 @@ import java.util.stream.Stream; import org.apache.felix.dm.BundleDependency; import org.apache.felix.dm.Component; -import org.apache.felix.dm.builder.lambda.BundleDepenencyBuilder; +import org.apache.felix.dm.DependencyManager; +import org.apache.felix.dm.builder.lambda.BundleDependencyBuilder; import org.apache.felix.dm.builder.lambda.Functions.Consumer; import org.apache.felix.dm.builder.lambda.Functions.Consumer2; import org.osgi.framework.Bundle; -public class BundleDependencyBuilderImpl implements BundleDepenencyBuilder { +public class BundleDependencyBuilderImpl implements BundleDependencyBuilder { + private String m_added; + private String m_changed; + private String m_removed; + private Object m_instance; + private boolean m_autoConfig = true; + private boolean m_required = true; + private Bundle m_bundle; + private String m_filter; + private int m_stateMask = -1; + private boolean m_propagate; + private Object m_propagateInstance; + private String m_propagateMethod; + private Supplier> m_propagateSupplier; + private final Component m_component; + /** * This interface (lambda) is called when we want to invoke a method reference. the lambda is called with all necessary dependency * informations. @@ -31,50 +47,74 @@ public class BundleDependencyBuilderImpl } /** - * List of service (add/change/remove) callbacks. + * List of service (add/change/remove) callbacks (method references). */ private final Map>> m_refs = new HashMap<>(); - - private String m_added; - private String m_changed; - private String m_removed; - private Object m_instance; - private boolean m_reflection; - + /** + * Class used to call a supplier that returns Propagated properties + */ + private class Propagate { + @SuppressWarnings("unused") + Dictionary propagate() { + return m_propagateSupplier.get(); + } + } + public BundleDependencyBuilderImpl (Component component) { + m_component = component; + } - @Override - public BundleDepenencyBuilder callbacks(String added, String changed, String removed) { - m_added = added; - m_changed = changed; - m_removed = removed; - m_reflection = true; + @Override + public BundleDependencyBuilder onAdd(String callback) { + return callbacks(callback, null, null); + } + + @Override + public BundleDependencyBuilder onChange(String callback) { + return callbacks(null, callback, null); + } + + @Override + public BundleDependencyBuilder onRemove(String callback) { + return callbacks(null, null, callback); + } + + @Override + public BundleDependencyBuilder callbacks(String added, String removed) { + return callbacks(added, null, removed); + } + + @Override + public BundleDependencyBuilder callbacks(String added, String changed, String removed) { + if (m_refs.size() != 0) throw new IllegalArgumentException("some method references have already been set."); + m_added = added != null ? added : m_added; + m_changed = changed != null ? changed : m_changed; + m_removed = removed != null ? removed : m_removed; + m_autoConfig = false; return this; } @Override - public BundleDepenencyBuilder callbacks(Object instance, String added, String changed, String removed) { + public BundleDependencyBuilder callbacks(Object instance, String added, String changed, String removed) { callbacks(added, changed, removed); m_instance = instance; return this; } @Override - public BundleDepenencyBuilder onAdd(Consumer add) { - Objects.equals(m_reflection, false); + public BundleDependencyBuilder onAdd(Consumer add) { return setCallbackRef("add", (instance, component, bundle) -> add.accept(bundle)); } @Override - public BundleDepenencyBuilder onAdd(Consumer2 add) { - return this; + public BundleDependencyBuilder onAdd(Consumer2 add) { + return setCallbackRef("add", (instance, component, bundle) -> add.accept(component, bundle)); } @SuppressWarnings("unchecked") @Override - public BundleDepenencyBuilder onAdd(InstanceBundle add) { - Objects.equals(m_reflection, false); + public BundleDependencyBuilder onAdd(InstanceBundle add) { String type = Helpers.getLambdaGenericType(add); return setComponentInstanceCallbackRef("add", type, (inst, component, bundle) -> add.call((I) inst, bundle)); @@ -82,96 +122,228 @@ public class BundleDependencyBuilderImpl @SuppressWarnings("unchecked") @Override - public BundleDepenencyBuilder onAdd(InstanceComponentBundle add) { - Objects.equals(m_reflection, false); + public BundleDependencyBuilder onAdd(InstanceComponentBundle add) { String type = Helpers.getLambdaGenericType(add); return setComponentInstanceCallbackRef("add", type, (inst, component, bundle) -> add.call((I) inst, component, bundle)); } + + @Override + public BundleDependencyBuilder onChange(Consumer add) { + return setCallbackRef("change", (instance, component, bundle) -> add.accept(bundle)); + } + + @Override + public BundleDependencyBuilder onChange(Consumer2 change) { + return setCallbackRef("change", (instance, component, bundle) -> change.accept(component, bundle)); + } + @SuppressWarnings("unchecked") @Override - public BundleDepenencyBuilder autoConfig(boolean autoConfig) { - // TODO Auto-generated method stub + public BundleDependencyBuilder onChange(InstanceBundle change) { + String type = Helpers.getLambdaGenericType(change); + return setComponentInstanceCallbackRef("change", type, + (inst, component, bundle) -> change.call((I) inst, bundle)); + } + + @SuppressWarnings("unchecked") + @Override + public BundleDependencyBuilder onChange(InstanceComponentBundle change) { + String type = Helpers.getLambdaGenericType(change); + return setComponentInstanceCallbackRef("change", type, + (inst, component, bundle) -> change.call((I) inst, component, bundle)); + } + + @Override + public BundleDependencyBuilder onRemove(Consumer remove) { + return setCallbackRef("remove", (instance, component, bundle) -> remove.accept(bundle)); + } + + @Override + public BundleDependencyBuilder onRemove(Consumer2 remove) { + return setCallbackRef("remove", (instance, component, bundle) -> remove.accept(component, bundle)); + } + + @SuppressWarnings("unchecked") + @Override + public BundleDependencyBuilder onRemove(InstanceBundle remove) { + String type = Helpers.getLambdaGenericType(remove); + return setComponentInstanceCallbackRef("remove", type, + (inst, component, bundle) -> remove.call((I) inst, bundle)); + } + + @SuppressWarnings("unchecked") + @Override + public BundleDependencyBuilder onRemove(InstanceComponentBundle remove) { + String type = Helpers.getLambdaGenericType(remove); + return setComponentInstanceCallbackRef("remove", type, + (inst, component, bundle) -> remove.call((I) inst, component, bundle)); + } + + @Override + public BundleDependencyBuilder autoConfig(boolean autoConfig) { + m_autoConfig = true; + return this; + } + + @Override + public BundleDependencyBuilder autoConfig() { + autoConfig(true); return this; } @Override - public BundleDepenencyBuilder autoConfig() { - // TODO Auto-generated method stub + public BundleDependencyBuilder required(boolean required) { + m_required = required; return this; } @Override - public BundleDepenencyBuilder required(boolean required) { - // TODO Auto-generated method stub + public BundleDependencyBuilder required() { + required(true); return this; } @Override - public BundleDepenencyBuilder required() { - // TODO Auto-generated method stub + public BundleDependencyBuilder bundle(Bundle bundle) { + m_bundle = bundle; return this; } @Override - public BundleDepenencyBuilder bundle(Bundle bundle) { - // TODO Auto-generated method stub + public BundleDependencyBuilder filter(String filter) throws IllegalArgumentException { + m_filter = filter; return this; } @Override - public BundleDepenencyBuilder filter(String filter) throws IllegalArgumentException { - // TODO Auto-generated method stub + public BundleDependencyBuilder mask(int mask) { + m_stateMask = mask; return this; } @Override - public BundleDepenencyBuilder mask(int mask) { - // TODO Auto-generated method stub + public BundleDependencyBuilder propagate(boolean propagate) { + m_propagate = propagate; return this; } @Override - public BundleDepenencyBuilder propagate(boolean propagate) { - // TODO Auto-generated method stub + public BundleDependencyBuilder propagate() { + propagate(true); return this; } @Override - public BundleDepenencyBuilder propagate(Object instance, String method) { - // TODO Auto-generated method stub + public BundleDependencyBuilder propagate(Object instance, String method) { + if (m_propagateSupplier != null || m_propagate) throw new IllegalStateException("Propagate callback already set."); + Objects.nonNull(method); + Objects.nonNull(instance); + m_propagateInstance = instance; + m_propagateMethod = method; return this; } @Override - public BundleDepenencyBuilder propagate(Supplier> instance, String method) { - // TODO Auto-generated method stub + public BundleDependencyBuilder propagate(Supplier> instance) { + if (m_propagateInstance != null || m_propagate) throw new IllegalStateException("Propagate callback already set."); + m_propagateSupplier = instance; return this; } @Override public BundleDependency build() { - // TODO Auto-generated method stub - return null; + DependencyManager dm = m_component.getDependencyManager(); + + BundleDependency dep = dm.createBundleDependency(); + dep.setRequired(m_required); + + if (m_filter != null) { + dep.setFilter(m_filter); + } + + if (m_bundle != null) { + dep.setBundle(m_bundle); + } + + if (m_stateMask != -1) { + dep.setStateMask(m_stateMask); + } + + if (m_propagate) { + dep.setPropagate(true); + } else if (m_propagateInstance != null) { + dep.setPropagate(m_propagateInstance, m_propagateMethod); + } else if (m_propagateSupplier != null) { + dep.setPropagate(new Propagate(), "propagate"); + } + + if (m_added != null || m_changed != null || m_removed != null) { + dep.setCallbacks(m_instance, m_added, m_changed, m_removed); + } else if (m_refs.size() > 0) { + Object cb = createCallbackInstance(); + dep.setCallbacks(cb, "add", "change", "remove"); + } + + if (m_autoConfig) { + dep.setAutoConfig(true); + } + return dep; } - private BundleDepenencyBuilder setCallbackRef(String cb, MethodRef ref) { + private BundleDependencyBuilder setCallbackRef(String cb, MethodRef ref) { + requiresNoStringCallbacks(); List> list = m_refs.computeIfAbsent(cb, l -> new ArrayList<>()); list.add((instance, component, bundle) -> ref.accept(null, component, bundle)); return this; } @SuppressWarnings("unchecked") - public BundleDepenencyBuilder setComponentInstanceCallbackRef(String cb, String type, MethodRef ref) { - List> list = m_refs.computeIfAbsent(cb, l -> new ArrayList<>()); - list.add((instance, component, bundle) -> { - Stream.of(component.getInstances()).forEach(inst -> { - if (Helpers.getClassName(inst).equals(type)) { - ref.accept((I) inst, component, bundle); - } - }); - }); - return this; - } + private BundleDependencyBuilder setComponentInstanceCallbackRef(String cb, String type, MethodRef ref) { + requiresNoStringCallbacks(); + List> list = m_refs.computeIfAbsent(cb, l -> new ArrayList<>()); + list.add((instance, component, bundle) -> { + Stream.of(component.getInstances()).forEach(inst -> { + if (Helpers.getClassName(inst).equals(type)) { + ref.accept((I) inst, component, bundle); + } + }); + }); + return this; + } + + @SuppressWarnings("unused") + private Object createCallbackInstance() { + Object cb = null; + + cb = new Object() { + void add(Component c, Bundle bundle) { + invokeMethodRefs("add", c, bundle); + } + + void change(Component c, Bundle bundle) { + invokeMethodRefs("change", c, bundle); + } + + void remove(Component c, Bundle bundle) { + invokeMethodRefs("remove", c, bundle); + } + }; + + return cb; + } + + private void invokeMethodRefs(String method, Component c, Bundle bundle) { + m_refs.computeIfPresent(method, (k, mrefs) -> { + mrefs.forEach(mref -> mref.accept(null, c, bundle)); + return mrefs; + }); + } + + private void requiresNoStringCallbacks() { + if (m_added != null || m_changed != null || m_removed != null) { + throw new IllegalStateException("can't mix method references and string callbacks."); + } + } } Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ComponentBuilderImpl.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ComponentBuilderImpl.java?rev=1720825&r1=1720824&r2=1720825&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ComponentBuilderImpl.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ComponentBuilderImpl.java Fri Dec 18 16:58:58 2015 @@ -16,6 +16,7 @@ import java.util.stream.Stream; import org.apache.felix.dm.Component; import org.apache.felix.dm.Dependency; import org.apache.felix.dm.DependencyManager; +import org.apache.felix.dm.builder.lambda.BundleDependencyBuilder; import org.apache.felix.dm.builder.lambda.ComponentBuilder; import org.apache.felix.dm.builder.lambda.ConfigurationDependencyBuilder; import org.apache.felix.dm.builder.lambda.DependencyBuilder; @@ -147,6 +148,14 @@ public class ComponentBuilderImpl implem consumer.accept(dep); m_dependencyBuilders.add(dep); return this; + } + + @Override + public ComponentBuilderImpl withBundle(Consumer consumer) { + BundleDependencyBuilder dep = new BundleDependencyBuilderImpl(m_component); + consumer.accept(dep); + m_dependencyBuilders.add(dep); + return this; } public ComponentBuilderImpl withFuture(CompletableFuture future, Consumer> consumer) { Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ExtendedComponentBase.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ExtendedComponentBase.java?rev=1720825&r1=1720824&r2=1720825&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ExtendedComponentBase.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ExtendedComponentBase.java Fri Dec 18 16:58:58 2015 @@ -6,6 +6,7 @@ import java.util.function.Function; import java.util.function.Supplier; import org.apache.felix.dm.Component; +import org.apache.felix.dm.builder.lambda.BundleDependencyBuilder; import org.apache.felix.dm.builder.lambda.ComponentBuilder; import org.apache.felix.dm.builder.lambda.ConfigurationDependencyBuilder; import org.apache.felix.dm.builder.lambda.Functions; @@ -94,6 +95,11 @@ public abstract class ExtendedComponentB return (B) this; } + public B withBundle(Consumer consumer) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.withBundle(consumer)); + return (B) this; + } + public B withFuture(CompletableFuture future, Consumer> consumer) { m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.withFuture(future, consumer)); return (B) this;