Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryAspect.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryAspect.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryAspect.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryAspect.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,84 @@ +/* + * 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.dependencymanager.lambda.samples.dictionary; + +import java.util.Dictionary; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.osgi.service.log.LogService; + +import aQute.bnd.annotation.metatype.Configurable; + +/** + * This aspect applies to the English DictionaryService, and allows to decorate it with some + * custom English words, which are configurable from WebConsole. + * + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class DictionaryAspect implements DictionaryService { + /** + * This is the service this aspect is applying to. + */ + private volatile DictionaryService m_originalDictionary; + + /** + * We store all configured words in a thread-safe data structure, because ConfigAdmin may + * invoke our updated method at any time. + */ + private CopyOnWriteArrayList<String> m_words = new CopyOnWriteArrayList<String>(); + + /** + * We'll use the OSGi log service for logging. If no log service is available, then we'll + * use a NullObject. + */ + private LogService m_log; + + /** + * Defines a configuration dependency for retrieving our english custom words (by default, + * our PID is our full class name). + */ + protected void addWords(Dictionary<String, ?> config) { + if (config != null) { + // We use the bnd "Configurable" helper in order to get an implementation for our DictionaryConfiguration interface. + DictionaryConfiguration cnf = Configurable.createConfigurable(DictionaryConfiguration.class, config); + m_words.clear(); + for (String word : cnf.words()) { + m_words.add(word); + } + } + } + + /** + * Our Aspect Service is starting and is about to be registered in the OSGi regsitry. + */ + protected void start() { + m_log.log(LogService.LOG_INFO, "Starting aspect Dictionary with words: " + m_words + + "; original dictionary service=" + m_originalDictionary); + } + + /** + * Checks if a word is found from our custom word list. if not, delegate to the decorated + * dictionary. + */ + public boolean checkWord(String word) { + m_log.log(LogService.LOG_INFO, "DictionaryAspect: checking word " + word + " (original dictionary=" + + m_originalDictionary + ")"); + if (m_words.contains(word)) { + return true; + } + return m_originalDictionary.checkWord(word); + } + + public String toString() { + return "DictionaryAspect: words=" + m_words + "; original dictionary=" + m_originalDictionary; + } +}
Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryAspectConfiguration.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryAspectConfiguration.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryAspectConfiguration.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryAspectConfiguration.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,37 @@ +/* + * 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.dependencymanager.lambda.samples.dictionary; + +import java.util.List; + +import aQute.bnd.annotation.metatype.Meta.AD; +import aQute.bnd.annotation.metatype.Meta.OCD; + +/** + * This interface describes the configuration for our DictionaryAspect component. We are using the bnd metatype + * annotations, allowing to configure our Dictionary Services from web console. + * + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +@OCD(name="Spell Checker Aspect Dictionary (api)", + description = "Declare here the list of english words to be added into the default english dictionary") +public interface DictionaryAspectConfiguration { + @AD(description = "Dictionary aspect words") + List<String> words(); +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryConfiguration.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryConfiguration.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryConfiguration.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryConfiguration.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,41 @@ +/* + * 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.dependencymanager.lambda.samples.dictionary; + +import java.util.List; + +import aQute.bnd.annotation.metatype.Meta.AD; +import aQute.bnd.annotation.metatype.Meta.OCD; + +/** + * This interface describes the configuration for our DictionaryImpl component. We are using the bnd metatype + * annotations, allowing to configure our Dictionary Services from web console. + * + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +@OCD(name="Spell Checker Dictionary (api)", + factory = true, + description = "Declare here some Dictionary instances, allowing to instantiates some DictionaryService services for a given dictionary language") +public interface DictionaryConfiguration { + @AD(description = "Describes the dictionary language", deflt = "en") + String lang(); + + @AD(description = "Declare here the list of words supported by this dictionary.") + List<String> words(); +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryImpl.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryImpl.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryImpl.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryImpl.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,96 @@ +/* + * 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.dependencymanager.lambda.samples.dictionary; + +import java.util.Dictionary; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.osgi.service.log.LogService; + +import aQute.bnd.annotation.metatype.Configurable; + +/** + * A Dictionary Service, instantiated from webconsole, when you add some configurations instances to the + * DictionaryConfiguration factory pid. The Configuration metatype informations is described using the + * bnd metatype information (see the DictionaryConfiguration interface). + * + * You must configure at least one Dictionary from web console, since the SpellCheck won't start if no Dictionary + * Service is available. + * + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class DictionaryImpl implements DictionaryService { + /** + * The key of our config admin dictionary values. + */ + final static String WORDS = "words"; + + /** + * We store all configured words in a thread-safe data structure, because ConfigAdmin + * may invoke our updated method at any time. + */ + private CopyOnWriteArrayList<String> m_words = new CopyOnWriteArrayList<String>(); + + /** + * We'll use the OSGi log service for logging. If no log service is available, then we'll use a NullObject. + */ + private LogService m_log; + + /** + * Our Dictionary language. + */ + private String m_lang; + + /** + * Our service will be initialized from ConfigAdmin. + * @param config The configuration where we'll lookup our words list (key=".words"). + */ + protected void updated(Dictionary<String, ?> config) { + if (config != null) { + // We use the bnd "Configurable" helper in order to get an implementation for our DictionaryConfiguration interface. + DictionaryConfiguration cnf = Configurable.createConfigurable(DictionaryConfiguration.class, config); + + m_lang = cnf.lang(); + m_words.clear(); + for (String word : cnf.words()) { + m_words.add(word); + } + } + } + + /** + * A new Dictionary Service is starting (because a new factory configuration has been created + * from webconsole). + */ + protected void start() { + m_log.log(LogService.LOG_INFO, "Starting Dictionary Service with language: " + m_lang); + } + + /** + * Check if a word exists if the list of words we have been configured from ConfigAdmin/WebConsole. + */ + public boolean checkWord(String word) { + return m_words.contains(word); + } + + @Override + public String toString() { + return "Dictionary: language=" + m_lang + ", words=" + m_words; + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryService.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryService.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryService.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/DictionaryService.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,35 @@ +/* + * 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.dependencymanager.lambda.samples.dictionary; + +/** + * A simple service interface that defines a dictionary service. A dictionary + * service simply verifies the existence of a word. + * + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public interface DictionaryService { + /** + * Check for the existence of a word. + * + * @param word the word to be checked. + * @return true if the word is in the dictionary, false otherwise. + */ + public boolean checkWord(String word); +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/README URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/README?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/README (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/README Sun Dec 13 22:23:57 2015 @@ -0,0 +1,41 @@ +/* + * 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. + */ + +This sample shows a "SpellChecker" application (using DM API) which provides a +"dictionary:spellcheck" GOGO shell command. The GOGO "dictionary:spellcheck" command accepts a +string as parameter, which is checked for proper existence. The SpellChecker class has a +required/multiple (1..N) dependency over every available "DictionaryService" services, which are +internally used by the SpellChecker command, when checking word existence. + +A DictionaryService is defined using a FactoryConfigurationAdapterService , allowing to instantiate +many "DictionaryService" instances when some configurations are added to the +"Spell Checker Configuration (api)" factory pid from web +console. The factory pid configuration metatypes are defined using the bnd "metatype" annotations +(see DictionaryConfiguration.java). + +The DictionaryService is decorated with a DictionaryAspect, which you can instantiate by adding a +configuration to the "Spell Checker Aspect Dictionary (api)" pid from web console. The +aspect configuration metatype is also declared using the bnd metatype annotations (see +DictionaryAspectConfiguration.java). + +Before running this sample, go to webconsole, and add some words in the Spell Checker Configuration (api) factory PID, and +in the Spell Checker Aspect Dictionary (api) PID. + +Then go to gogo shell, and type dm help. You will normally see the dictionary:spellcheck command. +Type dictionary:spellcheck <some words configured either in the spell checker configuration, or in the spell checker aspect configuration, +and the dictionary will check for proper word existance in the configuration. + Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/SpellChecker.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/SpellChecker.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/SpellChecker.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/dictionary/SpellChecker.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,75 @@ +/* + * 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.dependencymanager.lambda.samples.dictionary; + +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.apache.felix.service.command.Descriptor; +import org.osgi.service.log.LogService; + +/** + * Felix "spellcheck" Gogo Shell Command. This command allows to check if some given words are valid or not. + * This command will be activated only if (at least) one DictionaryService has been injected. + * To create a Dictionary Service, you have to go the the web console and add a configuration in the + * "Dictionary Configuration" factory pid. + * + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class SpellChecker { + /** + * We'll use the OSGi log service for logging. If no log service is available, then we'll use a NullObject. + */ + private volatile LogService m_log; + + /** + * We'll store all Dictionaries in a concurrent list, in order to avoid method synchronization. + * (Auto-Injected from Activator, at any time). + */ + private final Iterable<DictionaryService> m_dictionaries = new ConcurrentLinkedQueue<>(); + + /** + * Lifecycle method callback, used to check if our service has been activated. + */ + protected void start() { + m_log.log(LogService.LOG_WARNING, "Spell Checker started"); + } + + /** + * Lifecycle method callback, used to check if our service has been activated. + */ + protected void stop() { + m_log.log(LogService.LOG_WARNING, "Spell Checker stopped"); + } + + // --- Gogo Shell command + + @Descriptor("checks if word is found from an available dictionary") + public void spellcheck(@Descriptor("the word to check") String word) { + m_log.log(LogService.LOG_INFO, "Checking spelling of word \"" + word + "\" using the following dictionaries: " + + m_dictionaries); + + for (DictionaryService dictionary : m_dictionaries) { + if (dictionary.checkWord(word)) { + System.out.println("word " + word + " is correct"); + return; + } + } + System.err.println("word " + word + " is incorrect"); + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/Activator.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/Activator.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/Activator.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/Activator.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,40 @@ +/* + * 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.dependencymanager.lambda.samples.factory; + +import static java.lang.System.out; + +import org.apache.felix.dm.builder.lambda.DependencyActivatorBase; +import org.osgi.service.log.LogService; + +/** + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class Activator extends DependencyActivatorBase { + @Override + public void init() throws Exception { + out.println("type \"log info\" to see the logs emitted by this test."); + + component(comp -> comp + .provides(Provider.class) + .factory(ProviderFactory::new, ProviderFactory::create) + .withService(LogService.class, srv -> srv.required().onAdd(ProviderImpl::set)) + .onStart(ProviderImpl::start)); + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/Provider.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/Provider.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/Provider.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/Provider.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,25 @@ +/* + * 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.dependencymanager.lambda.samples.factory; + +/** + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public interface Provider { +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/ProviderFactory.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/ProviderFactory.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/ProviderFactory.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/ProviderFactory.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,7 @@ +package org.apache.felix.dependencymanager.lambda.samples.factory; + +public class ProviderFactory { + public Object create() { + return new ProviderImpl(); + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/ProviderImpl.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/ProviderImpl.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/ProviderImpl.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/ProviderImpl.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,38 @@ +/* + * 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.dependencymanager.lambda.samples.factory; + +import org.osgi.service.log.LogService; + +/** + * This is the main implementation for our "Provider" service. + * This service is using a composition of two participants, which are used to provide the service + * (ProviderParticipant1, and ProviderParticipant2). + * + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class ProviderImpl implements Provider { + private volatile LogService m_log; + + void set(LogService log) { m_log = log; } + + void start() { + m_log.log(LogService.LOG_INFO, "ProviderImpl.start()"); + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/README URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/README?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/README (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/factory/README Sun Dec 13 22:23:57 2015 @@ -0,0 +1,27 @@ +/* + * 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. + */ + +This sample is an example usage of DM composite components. A composite component is implemented +using a composition of multiple object instances, which are used to implement a given complex +service. Here, we define a "Provider" service, which is implemented by three object instances: +ProviderImpl, ProviderParticipant1, ProviderParticipant2. + +Dependencies are injected in all objects being part of the composition. + +To see logs, type this command under the gogo shell: + +g! log info|grep compositefactory Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/Activator.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/Activator.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/Activator.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/Activator.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,53 @@ +/* + * 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.dependencymanager.lambda.samples.future; + +import static java.lang.System.out; + +import org.apache.felix.dm.builder.lambda.DependencyActivatorBase; +import org.osgi.service.log.LogService; + +/** + * Defines two components: FelixSite which provides some informations about the Felix Web site, + * and Test, which depends in the FelixSite service. + * + * The FelixSite component will asynchronously download the Felix web page, and uses a "CompletableFuture" + * dependency, in order to block the activation of the FelixSite service, until the web page is downloaded and parsed. + * + * The download is done using some CompletableFuture asynchronous tasks. + * + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class Activator extends DependencyActivatorBase { + @Override + public void init() throws Exception { + out.println("type \"log info\" to see the logs emitted by this test."); + + // Define the FelixSiteInfo component that provides some informations about the Felix web site. + component(comp -> comp + .provides(SiteInfo.class) + .factory(() -> new SiteInfoImpl("http://felix.apache.org/")) + .withService(LogService.class, srv -> srv.onAdd(SiteInfoImpl::bind))); + + // Define the FelixSite component that depends on the FelixSiteInfo service + component(comp -> comp + .impl(DisplaySite.class) + .withService(LogService.class).withService(SiteInfo.class)); + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/DisplaySite.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/DisplaySite.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/DisplaySite.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/DisplaySite.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,13 @@ +package org.apache.felix.dependencymanager.lambda.samples.future; + +import org.osgi.service.log.LogService; + +public class DisplaySite { + volatile SiteInfo m_siteInfo; + volatile LogService m_log; + + void start() { + m_log.log(LogService.LOG_INFO, "DisplaySite.start(): links available from the Felix web site: " + m_siteInfo.getLinks()); + } + +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/README URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/README?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/README (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/README Sun Dec 13 22:23:57 2015 @@ -0,0 +1,54 @@ +The purpose of this sample is to show an example usage of the new "CompletableFuture" dependency that has been +added in the dm-lambda library. CompletableFuture java8 class provides functional operations and promotes an asynchronous event-driven model. + +But when you go for asynchronous model, then in some situation you have to take care. For instance assuming you want to +initialize a component from the init method using some asynchronous stuff, then the init method may return before the async operations +have completed; and the component.start() callback may then be called too early. And what about if you want to add dependencies from the init() method +and you want to wait for the async operations before adding the dependency ? In this case you would have to block on the CompletableFuture +but this is something you don't want to do. + +So, to avoid blocking or some boilerplate code, a new (required) CompletableFuture dependency has been added (in the dm-lambda library), +and you can use it to block the component in the init state, until a given "CompletableFuture" completes. +The new dependency is implemented as all other dependencies, and it extends the org.apache.felix.dm.context.AbstractDependency class. + +Now, let's describe the sample: we have a "SiteInfoImpl" component that is using a CompletableFuture from its init method +in order to asynchronously download and parse an URL from the web. When the page content is downloaded, then the hrefs +(links) contained in the URL page are parsed. The component state remains in the init state until the page is downloaded. + +Here is the activator: + +public class Activator extends DependencyActivatorBase { + @Override + public void init() throws Exception { + // Define the SiteInfo component that provides some informations about the Felix web site. + component(comp -> comp + .provides(SiteInfo.class) + .factory(() -> new SiteInfoImpl("http://felix.apache.org/")) + .withService(LogService.class, srv -> srv.onAdd(SiteInfoImpl::bind))); + + // Define a component that depends on the SiteInfo service + component(comp -> comp + .impl(DisplaySite.class) + .withService(LogService.class).withService(SiteInfo.class)); + } +} + +Nothing special so far. + +Now let's take a look at the SiteInfoImpl.init() method: + + void init(Component c) { + // Asynchronously download and parse the links from the web page. + // We use a completable future that is then added as a dependency to our component, which + // will be started once the future has completed. + + CompletableFuture<List<String>> links = + CompletableFuture.supplyAsync(() -> downloadSite(m_url)) + .thenApply(this::getSiteLinks); + + component(c, builder -> builder.withFuture(", b -> b.thenAccept(this::setLinks))); + } + +So, the "builder.withFuture(links, b -> b.thenAccept(this::setLinks))" code simply defines a "completable future" dependency that will be available once the +"links" future has completed, and the method reference passed to the b.thenAccept method will be invoked exactly if you would have invoked +the same method on the CompletableFuture "links" object. Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/SiteInfo.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/SiteInfo.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/SiteInfo.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/SiteInfo.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,16 @@ +package org.apache.felix.dependencymanager.lambda.samples.future; + +import java.util.List; + +/** + * A Service which provides informations about the Felix web site. + */ +public interface SiteInfo { + + /** + * Returns the links (href) available from the Felix web site. + * @return the links available from the Felix web site + */ + List<String> getLinks(); + +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/SiteInfoImpl.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/SiteInfoImpl.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/SiteInfoImpl.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/future/SiteInfoImpl.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,88 @@ +package org.apache.felix.dependencymanager.lambda.samples.future; + +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.component; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; +import java.util.concurrent.CompletableFuture; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.felix.dm.Component; +import org.osgi.service.log.LogService; + +/** + * A Component which provides general informations about a given web site + * (this simple example just displays the number of links it finds from a given URL. + * The url is retrieved asynchronously using a CompletableFuture class. + * The Component is also using a "withFuture" dependency that allows to wait for the + * completion of the CompletableFuture, before registering the SiteInfo OSGi service. + */ +public class SiteInfoImpl implements SiteInfo { + private LogService m_log; + final static String HREF_PATTERN = "<a\\s+href\\s*=\\s*(\"[^\"]*\"|[^\\s>]*)\\s*>"; + List<String> m_links; // web page hrefs (links). + final String m_url; + + public SiteInfoImpl(String url) { + m_url = url; + } + + void bind(LogService log) { + m_log = log; + } + + void init(Component c) { + // Asynchronously calculate the number of links from the web site. + // We use a completable future that is then added as a dependency to our component, which + // will be started on the future has completed. + + CompletableFuture<List<String>> links = + CompletableFuture.supplyAsync(() -> downloadSite(m_url)) + .thenApply(this::getSiteLinks); + + component(c, builder -> builder.withFuture(links, b -> b.thenAccept(this::setLinks))); + } + + // Called when our future has completed. + void setLinks(List<String> links) { + m_links = links; + } + + // once our future has completed, our component is started. + void start() { + m_log.log(LogService.LOG_INFO, "Service starting: number of links found from " + m_url + ": " + m_links.size()); + } + + @Override + public List<String> getLinks() { + return m_links; + } + + private String downloadSite(String url) { + try (Scanner in = new Scanner(new URL(url).openStream())) { + StringBuilder builder = new StringBuilder(); + while (in.hasNextLine()) { + builder.append(in.nextLine()); + builder.append("\n"); + } + return builder.toString(); + } catch (IOException ex) { + RuntimeException rex = new RuntimeException(); + rex.initCause(ex); + throw rex; + } + } + + List<String> getSiteLinks(String content) { + Pattern pattern = Pattern.compile(HREF_PATTERN, Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(content); + List<String> result = new ArrayList<>(); + while (matcher.find()) + result.add(matcher.group(1)); + return result; + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/Activator.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/Activator.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/Activator.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/Activator.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,50 @@ +/* + * 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.dependencymanager.lambda.samples.hello; + +import static java.lang.System.out; + +import org.apache.felix.dm.builder.lambda.DependencyActivatorBase; +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.log.LogService; + +/** + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class Activator extends DependencyActivatorBase { + @Override + public void init() throws Exception { + out.println("type \"log info\" to see the logs emitted by this test."); + + component(comp -> comp + .provides(ServiceProvider.class) + .onStart(ServiceProviderImpl::activate) + .properties("foo", "bar", "gabu", "zo") // foo=bar, gabu=zo + .impl(ServiceProviderImpl.class) + .withService(LogService.class, srv -> srv.onAdd(ServiceProviderImpl::bind))); + + component(comp -> comp + .impl(ServiceConsumer.class) + .withService(LogService.class) + .withService(ServiceProvider.class, srv -> srv.filter("(foo=bar)")) + .withConfiguration(conf -> conf.pid(ServiceConsumer.class).onUpdate(ServiceConsumer::updated))); + + component(comp -> comp.impl(Configurator.class).withService(ConfigurationAdmin.class)); + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/Configurator.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/Configurator.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/Configurator.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/Configurator.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,20 @@ +package org.apache.felix.dependencymanager.lambda.samples.hello; + +import java.io.IOException; +import java.util.Dictionary; +import java.util.Hashtable; + +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; + +public class Configurator { + volatile ConfigurationAdmin m_cm; // injected by reflection. + + void start() throws IOException { + // Configure the ServiceConsumer component + Configuration c = m_cm.getConfiguration(ServiceConsumer.class.getName(), null); + Dictionary<String, Object> props = new Hashtable<>(); + props.put("foo", "bar"); + c.update(props); + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/README URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/README?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/README (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/README Sun Dec 13 22:23:57 2015 @@ -0,0 +1,23 @@ +/* + * 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. + */ + +This sample provides a DM Activator declaring one service consumer and a service provider. The +ServiceConsumer is also depending on a configuration pid (see org.apache.felix.dependencymanager.samples.hello.Configurator). +To see logs, just type this under gogo shell: + +g! log info|grep hello.annot + Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/ServiceConsumer.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/ServiceConsumer.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/ServiceConsumer.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/ServiceConsumer.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,43 @@ +/* + * 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.dependencymanager.lambda.samples.hello; + +import java.util.Dictionary; + +import org.osgi.service.log.LogService; + +/** + * Our service consumer. We depend on a ServiceProvider, and on a configuration. + * + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class ServiceConsumer { + volatile ServiceProvider service; + volatile LogService log; + Dictionary<?, ?> conf; + + public void updated(Dictionary<String, Object> conf) { + this.conf = conf; + } + + public void start() { + log.log(LogService.LOG_INFO, "ServiceConsumer.start: calling service.hello()"); + this.service.hello(); + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/ServiceProvider.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/ServiceProvider.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/ServiceProvider.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/ServiceProvider.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,28 @@ +/* + * 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.dependencymanager.lambda.samples.hello; + +/** + * The interface for our service provider. + * + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public interface ServiceProvider { + public void hello(); +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/ServiceProviderImpl.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/ServiceProviderImpl.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/ServiceProviderImpl.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/hello/ServiceProviderImpl.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,41 @@ +/* + * 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.dependencymanager.lambda.samples.hello; + +import org.osgi.service.log.LogService; + +/** + * The implementation for our service provider. + * + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class ServiceProviderImpl implements ServiceProvider { + volatile LogService log; + + void bind(LogService log) { this.log = log; } + + void activate() { + log.log(LogService.LOG_INFO, "ServiceProviderImpl.start"); + } + + @Override + public void hello() { + log.log(LogService.LOG_INFO, "ServiceProviderImpl.hello"); + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/Activator.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/Activator.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/Activator.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/Activator.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,53 @@ +/* + * 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.dependencymanager.lambda.samples.rx.completable; + +import static java.lang.System.out; + +import org.apache.felix.dm.builder.lambda.DependencyActivatorBase; +import org.osgi.service.log.LogService; + +/** + * Defines two components: FelixSite which provides some informations about the Felix Web site, + * and Test, which depends in the FelixSite service. + * + * The FelixSite component will asynchronously download the Felix web page, and uses a "CompletableFuture" + * dependency, in order to block the activation of the FelixSite service, until the web page is downloaded and parsed. + * + * The download is done using some CompletableFuture asynchronous tasks. + * + * @author <a href="mailto:[email protected]">Felix Project Team</a> + */ +public class Activator extends DependencyActivatorBase { + @Override + public void init() throws Exception { + out.println("type \"log info\" to see the logs emitted by this test."); + + // Define the FelixSiteInfo component that provides some informations about the Felix web site. + component(comp -> comp + .provides(SiteInfo.class) + .factory(() -> new SiteInfoImpl("http://felix.apache.org/")) + .withService(LogService.class, srv -> srv.onAdd(SiteInfoImpl::bind))); + + // Define the FelixSite component that depends on the FelixSiteInfo service + component(comp -> comp + .impl(DisplaySite.class) + .withService(LogService.class).withService(SiteInfo.class)); + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/DisplaySite.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/DisplaySite.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/DisplaySite.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/DisplaySite.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,13 @@ +package org.apache.felix.dependencymanager.lambda.samples.rx.completable; + +import org.osgi.service.log.LogService; + +public class DisplaySite { + volatile SiteInfo m_siteInfo; + volatile LogService m_log; + + void start() { + m_log.log(LogService.LOG_INFO, "DisplaySite.start(): links available from the Felix web site: " + m_siteInfo.getLinks()); + } + +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/ObservableCompletableFuture.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/ObservableCompletableFuture.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/ObservableCompletableFuture.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/ObservableCompletableFuture.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,23 @@ +package org.apache.felix.dependencymanager.lambda.samples.rx.completable; + +import java.util.concurrent.CompletableFuture; + +import io.reactivex.Observable; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; + +class ObservableCompletableFuture<T> extends CompletableFuture<T> { + private final Disposable m_subscription; + + public ObservableCompletableFuture(Observable<T> observable) { + m_subscription = observable + .subscribeOn(Schedulers.io()) + .subscribe(this::complete, this::completeExceptionally); + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + m_subscription.dispose(); + return super.cancel(mayInterruptIfRunning); + } +} \ No newline at end of file Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/README URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/README?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/README (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/README Sun Dec 13 22:23:57 2015 @@ -0,0 +1,106 @@ +The purpose of this sample is to experiment RxJava(2.0) and DependencyManager lambda; and to check if some hooks have +to be added into DM-lambda in order to build some RxJava applications on top it. + +So, in this sample, we have a use case where RxJava is used to download and parse an URL from the web, in order to count the number of +hrefs (links) contained in the URL page, and we do this from a component.init() method. +Now, the problem is that the page is downloaded asynchronously using RxJava, and when the component init() method returns, +any services implemented by the component are registered. Moreover, the component start() method is called while the download is still pending. + +So, ultimately, we would need some kind of required dependency on something in order to make sure that the component remains in the +init state, until the page has been downloaded and parsed. + +Now, there is something new to DM-lambda: a new kind of dependency has been introduced: you can now +define a dependency on a "CompletableFuture", using the "ComponentBuilder.withFuture" method. +Such dependency allows to block the activation of a component (its a required dependency) until a given completableFuture completes. + +Here is an example: you have a Download component and from the Activator, you declare this: + +public class Activator extends DependencyActivatorBase { + public void init() throws Exception { + CompletableFuture<String> pageFuture = + CompletableFuture.supplyAsync(() -> downloadSite("http://felix.apache.org/")) + + component(comp -> comp + .provides(DownloadService.class) + .impl(Download.class) + .withService(LogService.class, srv -> srv.onAdd(FelixSiteImpl::bind)) + .withFuture(pageFuture, depbuilder -> depbuilder.thenAccept(content -> Download::setContent))); + + } +} + +Here, notice the new "withFuture" dependency: it's a required dependency that takes a CompletableFuture (pageFuture), and also the +callback that will be invoked when the future will have completed (thenAccept). +The "thenAccept" method has the same purpose as the one from the CompletableFuture.thenAccept method. + +So, now, the nice thing is that wrapping an RxObservable to CompletableFuture is simple and can be done using the following helper class: + +class ObservableCompletableFuture<T> extends CompletableFuture<T> { + private final Disposable m_subscription; + + public ObservableCompletableFuture(Observable<T> observable) { + m_subscription = observable + .subscribeOn(Schedulers.io()) + .subscribe(this::complete, this::completeExceptionally); + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + m_subscription.dispose(); + return super.cancel(mayInterruptIfRunning); + } +} + +This simple class takes in the constructor an Observable<T>, and subscribes to it. +So, when the Observable completes, the "this::complete" calls the CompletableFuture.complete() method in order +to propagate the completion of the Observable to the CompletableFuture. + +Now let's go with a concrete example: Using this class above allows to build nice DM components without boilerplate code, like this: + +1) from the Activator, you can for example define a service providing component like this: + +Activator.java: + + // Define the FelixSiteInfo component that provides some informations about the Felix web site. + component(comp -> comp + .provides(SiteInfo.class) + .impl(SiteInfoImpl.class) + .withService(LogService.class, srv -> srv.onAdd(SiteInfoImpl::bind))); + + 2) and from the SiteInfoImpl.init() method: + + FelixSiteImpl.java: + + void init(Component c) { + // Asynchronously calculate the number of links from the Felix web site. + // We use Rx to define an asynchrous Observable task, and we wrap it to a CompletableFuture + // that is used as a Dependency Manager "Future" dependency, in order to block the activation of + // our component until the felix site has been downloaded and parsed. + + Observable<List<String>> links = downloadSite("http://felix.apache.org/") + .map(this::getSiteLinks); + + component(c, comp -> comp + .withFuture(toFuture(links), futuredep -> futuredep.thenAccept(this::setLinks))); + } + + // Called when our future has completed. + void setLinks(List<String> links) { + m_felixLinks = links; + } + + // once our future has completed, our component is started. + void start() { + m_log.log(LogService.LOG_INFO, + "Service starting: number of links found from Apache Felix site=" + m_felixLinks.size()); + } + +The important part to understand is the following: + + + component(c, comp -> comp + .withFuture(toFuture(links), futuredep -> futuredep.thenAccept(this::setLinks))); + +here, we wrap the links (which is an Observable<List<String>> into the ObservableCompletableFuture helper that was +presented previously. And when the CompletableFuture will complete , it will call the "thenAccept(this::setLinks)" method in order to inject +the result into the component before the component.start() method, exactly in the same manner when a required dependency is injected before start(). \ No newline at end of file Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/SiteInfo.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/SiteInfo.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/SiteInfo.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/SiteInfo.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,16 @@ +package org.apache.felix.dependencymanager.lambda.samples.rx.completable; + +import java.util.List; + +/** + * A Service which provides informations about the Felix web site. + */ +public interface SiteInfo { + + /** + * Returns the links (href) available from the Felix web site. + * @return the links available from the Felix web site + */ + List<String> getLinks(); + +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/SiteInfoImpl.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/SiteInfoImpl.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/SiteInfoImpl.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/completable/SiteInfoImpl.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,106 @@ +package org.apache.felix.dependencymanager.lambda.samples.rx.completable; + +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.component; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; +import java.util.concurrent.CompletableFuture; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.felix.dm.Component; +import org.osgi.service.log.LogService; + +import io.reactivex.Observable; + +/** + * A Component which provides general informations about a given web site + * (this simple example just displays the number of links it finds from a given URL. + * The url is downloaded asynchronously using a CompletableFuture class. + * The Component is also using a "withFuture" dependency that allows to wait for the + * completion of the CompletableFuture, before registering the SiteInfo OSGi service. + */ +public class SiteInfoImpl implements SiteInfo { + final static String HREF_PATTERN = "<a\\s+href\\s*=\\s*(\"[^\"]*\"|[^\\s>]*)\\s*>"; + LogService m_log; + String m_url; + List<String> m_links; // List of hrefs contained in the web page referenced by m_url URL. + + + public SiteInfoImpl(String url) { + m_url = url; + } + + void bind(LogService log) { + m_log = log; + } + + void init(Component c) { + // Asynchronously calculate the number of links from the web site. + // We use Rx to define an asynchronous Observable task, and we wrap it to a CompletableFuture + // that is used as a Dependency Manager "Future" dependency, in order to block the activation of + // our component until the page has been downloaded and parsed. + + Observable<List<String>> links = downloadSite(m_url) + .map(this::getSiteLinks); + + component(c, comp -> comp + .withFuture(toFuture(links), futuredep -> futuredep.thenAccept(this::setLinks))); + } + + // Called when our future has completed. + void setLinks(List<String> links) { + m_links = links; + } + + // once our future has completed, our component is started. + void start() { + m_log.log(LogService.LOG_INFO, "Service starting: number of links found from site=" + m_links.size()); + } + + @Override + public List<String> getLinks() { + return m_links; + } + + private Observable<String> downloadSite(String url) { + return Observable.create(subscriber -> { + try (Scanner in = new Scanner(new URL(url).openStream())) { + StringBuilder builder = new StringBuilder(); + while (in.hasNextLine()) { + builder.append(in.nextLine()); + builder.append("\n"); + } + subscriber.onNext(builder.toString()); + } catch (IOException ex) { + RuntimeException rex = new RuntimeException(); + rex.initCause(ex); + throw rex; + } + }); + } + + private List<String> getSiteLinks(String content) { + Pattern pattern = Pattern.compile(HREF_PATTERN, Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(content); + List<String> result = new ArrayList<>(); + while (matcher.find()) + result.add(matcher.group(1)); + return (result); + } + + /** + * Converts {@link rx.Observable} to {@link java.util.concurrent.CompletableFuture}. Takes + * only the first value produced by observable. + * + * @param observable + * @param <T> + * @return + */ + public static <T> CompletableFuture<T> toFuture(Observable<T> observable) { + return new ObservableCompletableFuture<T>(observable); + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/observable/Activator.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/observable/Activator.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/observable/Activator.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/observable/Activator.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,34 @@ +/* + * 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.dependencymanager.lambda.samples.rx.observable; + +import static java.lang.System.out; + +import org.apache.felix.dm.builder.lambda.DependencyActivatorBase; +import org.osgi.service.log.LogService; + +public class Activator extends DependencyActivatorBase { + + @Override + protected void init() throws Exception { + out.println("type \"log info\" to see the logs emitted by this test."); + component(comp -> comp.impl(ObservableComponent.class).withService(LogService.class)); + } + +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/observable/ObservableComponent.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/observable/ObservableComponent.java?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/observable/ObservableComponent.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/observable/ObservableComponent.java Sun Dec 13 22:23:57 2015 @@ -0,0 +1,85 @@ +/* + * 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.dependencymanager.lambda.samples.rx.observable; + +import static org.apache.felix.dm.builder.lambda.DependencyActivatorBase.component; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; +import org.osgi.service.log.LogService; + +import io.reactivex.Observable; +import io.reactivex.internal.subscriptions.EmptySubscription; + +public class ObservableComponent { + DependencyManager m_dm; // injected + LogService m_log; // injected + + public static class DocumentViewer { + final String m_title; + public DocumentViewer(String title) { + m_title = title; + } + void start() { + // Display the title in the GUI + } + } + + // Returns a List of website URLs based on a text search + Observable<List<String>> query(String text) { + if (text.equals("rxjava")) { + return Observable.just(Arrays.asList("https://github.com/ReactiveX/RxJava", "https://en.wikipedia.org/wiki/Reactive_programming")); + } else { + return Observable.just(Collections.emptyList()); + } + } + + Observable<String> getTitle(String url) { + if (url.equals("https://github.com/ReactiveX/RxJava")) { + return Observable.just("ReactiveX/RxJava"); + } else if (url.equals("https://en.wikipedia.org/wiki/Reactive_programming")) { + return Observable.just("Reactive Programming"); + } else { + return Observable.just((String) null); + } + } + + void start() { + m_log.log(LogService.LOG_INFO, "query ..."); + query("rxjava") + .flatMap(urls -> Observable.fromStream(urls.stream())) + .flatMap(url -> getTitle(url)) + .filter(title -> title != null) + .flatMap(title -> createObservableComponent(title)) + .subscribe(component -> m_log.log(LogService.LOG_INFO, "Component started :" + component)); + } + + Observable<Component> createObservableComponent(String title) { + return Observable.create(publisher -> { + publisher.onSubscribe(EmptySubscription.INSTANCE); + component(m_dm, builder -> builder + .factory(() -> new DocumentViewer(title)) + .onStart(publisher::onNext)); + }); + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/observable/README URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/observable/README?rev=1719841&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/observable/README (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/src/org/apache/felix/dependencymanager/lambda/samples/rx/observable/README Sun Dec 13 22:23:57 2015 @@ -0,0 +1,32 @@ +The purpose of this sample is to experiment RxJava(2.0) and DependencyManager lambda; and to check if some hooks have +to be added into DM-lambda in order to build some RxJava applications on top it. + +So, in this sample, A DM component is built from code (see ObservableComponent.java) using RxJava style. +That is: using some Rx "Observables" and a chain of map() calls to build the DM component. + +So, basically, The sample first transforms a DM Component into an "Observable". +Turning any object to an Rx Observable is easy, using the Observable<T>.create(Publisher publisher) method. +For example: + + Observable<Component> createObservableComponent(String componentParameters) { + return Observable.create(publisher -> { + publisher.onSubscribe(EmptySubscription.INSTANCE); + component(m_dm, builder -> builder + .factory(() -> new SomeDMComponent(componentParameters)) + .onStart(publisher::onNext)); // will trigger next action in the map() chain only AFTER component is started. + }); + } + +So, the component can then be created using a flow of map() transformations calls like in the following example: + + query("rxjava") // returns Observable<List<String>> (list of URLs). + .flatMap(urls -> Observable.fromStream(urls.stream())) // Loop on each URL returned by the query + .flatMap(url -> getTitle(url)) // get the title of the current URL page content + .filter(title -> title != null) // Ignore page without title + .flatMap(title -> createObservableComponent(title)) // and create a component for the current title + .subscribe(component -> System.out.println("Component has started: " + component)); + +The query(String search) returns an Observable<List<String>> representing the URLS in the web that match the given text search. +The subscriber will be called only after the Component has been started, because the createObservableComponent method only calls +the "publisher::onNext" method once the component is fully active (see "onStart(publisher::onNext))" call in the +createObservableComponent function. Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/test/.gitignore URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda.samples/test/.gitignore?rev=1719841&view=auto ============================================================================== (empty) Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/.classpath URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/.classpath?rev=1719841&view=auto ============================================================================== Binary file - no diff available. Propchange: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/.classpath ------------------------------------------------------------------------------ svn:mime-type = application/xml
