/* * 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.runtime.itest.components; import java.util.HashMap; import java.util.Map; import org.apache.felix.dm.annotation.api.Component; import org.apache.felix.dm.annotation.api.Composition; import org.apache.felix.dm.annotation.api.Destroy; import org.apache.felix.dm.annotation.api.Init; import org.apache.felix.dm.annotation.api.Property; import org.apache.felix.dm.annotation.api.Registered; import org.apache.felix.dm.annotation.api.ServiceDependency; import org.apache.felix.dm.annotation.api.Start; import org.apache.felix.dm.annotation.api.Stop; import org.apache.felix.dm.itest.util.Ensure; import org.osgi.framework.ServiceRegistration; /** * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> */ @SuppressWarnings("rawtypes") public class CompositeAnnotations { public interface C1Service { } public interface Dependency extends Runnable { } /** * This service is also composed of the Component object. */ @Component public static class C1 implements C1Service { public final static String ENSURE = "CompositeAnnotations.C1"; /* We are composed of this object, which will also be injected with our dependencies */ private final C2 m_c2 = new C2(); /* This dependency filter will be configured from our init method */ @ServiceDependency(name = "D") public volatile Dependency m_runnable; /* Object used to check that methods are called in the proper sequence */ @ServiceDependency(filter = "(name=" + ENSURE + ")") private volatile Ensure m_sequencer; /** * Dynamically configure our "D" dependency, using a dependency customization map */ @Init Map<String, String> init() { m_sequencer.step(1); // Configure a filter for our dependency whose name is "D" Map<String, String> customization = new HashMap<String, String>(); customization.put("D.filter", "(foo=bar2)"); customization.put("D.required", "true"); return customization; } /** * Return the list of object our service is composed of */ @Composition Object[] getComposition() { return new Object[]{this, m_c2}; } /** * Our Service is starting, and our Composites will also be */ @Start void start() { m_sequencer.step(3); m_runnable.run(); /* step 4 */ // Our Component.start() method should be called once this method returns. } /** * Our provided service has been registered into the OSGi service registry. */ @Registered void registered(ServiceRegistration sr) { m_sequencer.step(7); } /** * Our Service is stopping, and our Composites will also be */ @Stop void stop() { m_sequencer.step(9); // Our Component.stop() method should be called once this method returns. } /** * Our Service is destroying, and our Composites will also be. */ @Destroy void destroy() { m_sequencer.step(11); // Our Component.destroy() method should be called once this method returns. } } /** * The CompositeService is also made up of this Class. */ public static class C2 { // Injected dependency (from CompositeService) private volatile Ensure m_sequencer; // Injected dependency (from CompositeService) public volatile Dependency m_runnable; // lifecycle callback (same method as the one from CompositeService) void init() { m_sequencer.step(2); } // lifecycle callback (same method as the one from CompositeService) void start() { m_sequencer.step(5); m_runnable.run(); /* step 6 */ } void registered(ServiceRegistration sr) { if (sr == null) { m_sequencer.throwable(new Exception("null service registration")); } m_sequencer.step(8); } // lifecycle callback (same method as the one from CompositeService) void stop() { m_sequencer.step(10); } // lifecycle callback (same method as the one from CompositeService) void destroy() { m_sequencer.step(12); } } @Component(properties = @Property(name = "foo", value = "bar1")) public static class Dependency1 implements Dependency { public final static String ENSURE = "CompositeAnnotations.Dependency1"; @ServiceDependency(filter = "(name=" + ENSURE + ")") volatile Ensure m_sequencer; @Start void start() { System.out.println("Dependency1.start"); } public void run() { m_sequencer.step(Integer.MAX_VALUE); // Makes the test fail. } } @Component(properties = @Property(name = "foo", value = "bar2")) public static class Dependency2 implements Dependency { public final static String ENSURE = "CompositeAnnotations.Dependency2"; @ServiceDependency(filter = "(name=" + ENSURE + ")") volatile Ensure m_sequencer; @Start void start() { System.out.println("Dependency2.start"); } public void run() { m_sequencer.step(); } } }