blob: b9812dd8170997db125425dff9cda72087ee2af0 [file] [log] [blame]
Pierre De Ropfaca2892016-01-31 23:27:05 +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.lambda.itest;
20
21import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
22import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
23
24import org.apache.felix.dm.Component;
25import org.apache.felix.dm.DependencyManager;
26
27/**
28 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
29 */
30public class AspectDynamicsTest extends TestBase {
31
32 public void testDynamicallyAddAndRemoveAspect() {
33 DependencyManager m = getDM();
34 // helper class that ensures certain steps get executed in sequence
35 Ensure e = new Ensure();
36 Ensure aspectStopEnsure = new Ensure();
37 // create a service provider and consumer
38 Component provider = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class).build();
39 Component provider2 = component(m).impl(new ServiceProvider2(e)).provides(ServiceInterface2.class.getName()).build();
Pierre De Rop11527502016-02-18 21:07:16 +000040 Component consumer = component(m).impl(new ServiceConsumer(e)).withSvc(ServiceInterface.class, s->s.add("add").swap("swap")).build();
Pierre De Ropfaca2892016-01-31 23:27:05 +000041 Component aspect = aspect(m, ServiceInterface.class).autoAdd(false).rank(1).impl(new ServiceAspect(e, aspectStopEnsure)).build();
42
43 m.add(consumer);
44 m.add(provider);
45 // the consumer should invoke the provider here, and when done, arrive at step 3
46 // finally wait for step 6 before continuing
47 e.waitForStep(3, 15000);
48
49 m.add(aspect);
50 // after adding the aspect, we wait for its init to be invoked, arriving at
51 // step 4 after an instance bound dependency was added (on a service provided by
52 // provider 2)
53 e.waitForStep(4, 15000);
54
55 m.add(provider2);
56
57 // after adding provider 2, we should now see the client being swapped, so
58 // we wait for step 5 to happen
59 e.waitForStep(5, 15000);
60
61 // now we continue with step 6, which will trigger the next part of the consumer's
62 // run method to be executed
63 e.step(6);
64
65 // invoking step 7, 8 and 9 when invoking the aspect which in turn invokes the
66 // dependency and the original service, so we wait for that to finish here, which
67 // is after step 10 has been reached (the client will now wait for step 12)
68 e.waitForStep(10, 15000);
69
70 m.remove(aspect);
71 aspectStopEnsure.waitForStep(1, 15000);
72 // removing the aspect should trigger step 11 (in the swap method of the consumer)
73 e.waitForStep(11, 15000);
74
75 // step 12 triggers the client to continue
76 e.step(12);
77
78 // wait for step 13, the final invocation of the provided service (without aspect)
79 e.waitForStep(13, 15000);
80
81 // clean up
82 m.remove(provider2);
83 m.remove(provider);
84 m.remove(consumer);
85 e.waitForStep(16, 15000);
86 m.clear();
87 }
88
89 public void testDynamicallyAddAndRemoveAspectRef() {
90 DependencyManager m = getDM();
91 // helper class that ensures certain steps get executed in sequence
92 Ensure e = new Ensure();
93 Ensure aspectStopEnsure = new Ensure();
94 // create a service provider and consumer
95 Component provider = component(m).impl(new ServiceProvider(e)).provides(ServiceInterface.class.getName()).build();
96 Component provider2 = component(m).impl(new ServiceProvider2(e)).provides(ServiceInterface2.class.getName()).build();
Pierre De Rop11527502016-02-18 21:07:16 +000097 Component consumer = component(m).impl(new ServiceConsumer(e)).withSvc(ServiceInterface.class, s->s.add(ServiceConsumer::add).swap(ServiceConsumer::swap)).build();
Pierre De Ropfaca2892016-01-31 23:27:05 +000098 Component aspect = aspect(m, ServiceInterface.class).autoAdd(false).rank(1).impl(new ServiceAspect(e, aspectStopEnsure)).build();
99
100 m.add(consumer);
101 m.add(provider);
102 // the consumer should invoke the provider here, and when done, arrive at step 3
103 // finally wait for step 6 before continuing
104 e.waitForStep(3, 15000);
105
106 m.add(aspect);
107 // after adding the aspect, we wait for its init to be invoked, arriving at
108 // step 4 after an instance bound dependency was added (on a service provided by
109 // provider 2)
110 e.waitForStep(4, 15000);
111
112 m.add(provider2);
113
114 // after adding provider 2, we should now see the client being swapped, so
115 // we wait for step 5 to happen
116 e.waitForStep(5, 15000);
117
118 // now we continue with step 6, which will trigger the next part of the consumer's
119 // run method to be executed
120 e.step(6);
121
122 // invoking step 7, 8 and 9 when invoking the aspect which in turn invokes the
123 // dependency and the original service, so we wait for that to finish here, which
124 // is after step 10 has been reached (the client will now wait for step 12)
125 e.waitForStep(10, 15000);
126
127 m.remove(aspect);
128 aspectStopEnsure.waitForStep(1, 15000);
129 // removing the aspect should trigger step 11 (in the swap method of the consumer)
130 e.waitForStep(11, 15000);
131
132 // step 12 triggers the client to continue
133 e.step(12);
134
135 // wait for step 13, the final invocation of the provided service (without aspect)
136 e.waitForStep(13, 15000);
137
138 // clean up
139 m.remove(provider2);
140 m.remove(provider);
141 m.remove(consumer);
142 e.waitForStep(16, 15000);
143 m.clear();
144 }
145
146 static interface ServiceInterface {
147 public void invoke(Runnable run);
148 }
149
150 static interface ServiceInterface2 {
151 public void invoke();
152 }
153
154 static class ServiceProvider2 implements ServiceInterface2 {
155 private final Ensure m_ensure;
156
157 public ServiceProvider2(Ensure ensure) {
158 m_ensure = ensure;
159 }
160
161 public void invoke() {
162 m_ensure.step(9);
163 }
164 public void stop() {
165 m_ensure.step();
166 }
167 }
168
169 static class ServiceProvider implements ServiceInterface {
170 private final Ensure m_ensure;
171 public ServiceProvider(Ensure e) {
172 m_ensure = e;
173 }
174 public void invoke(Runnable run) {
175 run.run();
176 }
177 public void stop() {
178 m_ensure.step();
179 }
180 }
181
182 static class ServiceAspect implements ServiceInterface {
183 private final Ensure m_ensure;
184 private volatile ServiceInterface m_originalService;
185 private volatile ServiceInterface2 m_injectedService;
186 private volatile Component m_service;
187 private volatile DependencyManager m_manager;
188 private final Ensure m_stopEnsure;
189
190 public ServiceAspect(Ensure e, Ensure stopEnsure) {
191 m_ensure = e;
192 m_stopEnsure = stopEnsure;
193 }
194 public void init() {
195 m_service.add(m_manager.createServiceDependency()
196 .setService(ServiceInterface2.class)
197 .setRequired(true)
198 );
199 m_ensure.step(4);
200 }
201
202 public void invoke(Runnable run) {
203 m_ensure.step(7);
204 m_originalService.invoke(run);
205 m_injectedService.invoke();
206 }
207
208 public void stop() {
209 m_stopEnsure.step(1);
210 }
211 }
212
213 static class ServiceConsumer implements Runnable {
214 private volatile ServiceInterface m_service;
215 private final Ensure m_ensure;
216 private final Ensure.Steps m_swapSteps = new Ensure.Steps(5, 11);
217
218 public ServiceConsumer(Ensure e) {
219 m_ensure = e;
220 }
221
222 void add(ServiceInterface service) {
223 m_service = service;
224 }
225
226 void swap(ServiceInterface oldService, ServiceInterface newService) {
227 System.out.println("swap: old=" + oldService + ", new=" + newService);
228 m_ensure.steps(m_swapSteps);
229 m_service = newService;
230 }
231
232 public void init() {
233 Thread t = new Thread(this);
234 t.start();
235 }
236
237 public void run() {
238 m_ensure.step(1);
239 m_service.invoke(Ensure.createRunnableStep(m_ensure, 2));
240 m_ensure.step(3);
241 m_ensure.waitForStep(6, 15000);
242 m_service.invoke(Ensure.createRunnableStep(m_ensure, 8));
243 m_ensure.step(10);
244 m_ensure.waitForStep(12, 15000);
245 m_service.invoke(Ensure.createRunnableStep(m_ensure, 13));
246 }
247
248 public void stop() {
249 m_ensure.step();
250 }
251 }
252}