blob: 46ecf74a8759e96fe0f9b431320cec847841762b [file] [log] [blame]
Pierre De Rop3a00a212015-03-01 09:27:46 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19package org.apache.felix.dm.itest.api;
20
21import java.util.Dictionary;
22import java.util.Hashtable;
23import java.util.Map;
24
25import org.junit.Assert;
26
27import org.apache.felix.dm.Component;
28import org.apache.felix.dm.DependencyManager;
29import org.apache.felix.dm.itest.util.Ensure;
30import org.apache.felix.dm.itest.util.TestBase;
31
32/**
33 * Test for FELIX-4334 issue.
34 *
35 * Three components: A, B and C
36 *
37 * - A provided with property foo=bar
38 * - B adapts A, B has no filters on A, and B.init() method adds an instance bound required dependency to C.
39 * - C depends on A(foo=bar)
40 * - Now someone modifies the service properties of A: foo=bar2
41 * - As a result of that, C becomes unavailable and is unbound from B.
42 * - Since B has an instance bound required dependency to C: B should not be destroyed: it should be called in B.stop(), B.remove(C), B.change(A, "foo=bar2))
43 *
44 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
45 */
46@SuppressWarnings({"unchecked", "rawtypes"})
47public class AdapterWithModifiedInstanceBoundDependencyTest extends TestBase {
48 public static interface A {
49 }
50
51 static class AImpl implements A {
52 final Ensure m_e;
53 AImpl(Ensure e) {
54 m_e = e;
55 }
56 }
57
58 public static interface C {
59 }
60
61 static class CImpl implements C {
62 volatile A m_a;
63 }
64
65 public static interface B {
66 }
67
68 static class BImpl implements B {
69 final Ensure m_e;
70 volatile A m_a;
71 volatile C m_c;
72
73 BImpl(Ensure e) {
74 m_e = e;
75 }
76
77 public void add(A a) {
78 m_e.step(1);
79 }
80
81 void init(Component c) {
82 m_e.step(2);
83 DependencyManager dm = c.getDependencyManager();
84 c.add(dm.createServiceDependency().setService(C.class).setRequired(true).setCallbacks("add", "remove"));
85 }
86
87 public void add(C c) {
88 m_e.step(3);
89 }
90
91 public void start() {
92 m_e.step(4);
93 }
94
95 public void stop() { // C becomes unsatisfied when A properties are changed to foo=bar2
96 m_e.step(5);
97 }
98
99 public void remove(C c) {
100 m_e.step(6);
101 }
102
103 public void change(Map properties, A a) {
104 Assert.assertEquals("bar2", properties.get("foo"));
105 m_e.step(7);
106 }
107
108 public void destroy() {
109 m_e.step(8);
110 }
111
112 public void remove(A a) {
113 m_e.step(9);
114 }
115 }
116
117 public void testAdapterWithChangedInstanceBoundDependency() {
118 DependencyManager m = getDM();
119 Ensure e = new Ensure();
120
121 Dictionary props = new Hashtable();
122 props.put("foo", "bar");
123 Component a = m.createComponent()
124 .setImplementation(new AImpl(e))
125 .setInterface(A.class.getName(), props);
126
127 Component b = m.createAdapterService(A.class, null, "add", "change", "remove")
128 .setInterface(B.class.getName(), null)
129 .setImplementation(new BImpl(e));
130
131 Component c = m.createComponent()
132 .setImplementation(new CImpl())
133 .setInterface(C.class.getName(), null)
134 .add(m.createServiceDependency().setService(A.class, "(foo=bar)").setRequired(true));
135
136 m.add(a);
137 m.add(c);
138 m.add(b);
139
140 e.waitForStep(4, 5000);
141
142 System.out.println("changing A props ...");
143 props = new Hashtable();
144 props.put("foo", "bar2");
145 a.setServiceProperties(props);
146
147 e.waitForStep(7, 5000);
148
149 m.remove(c);
150 m.remove(a);
151 m.remove(b);
152
153 e.waitForStep(9, 5000);
154 }
155}