blob: 8ae646a3a218950dbd9576ea17b879f42031f1bd [file] [log] [blame]
Felix Meschberger42764b82009-08-18 07:51:00 +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.cm.integration;
20
21
Felix Meschberger13e91512009-08-20 11:23:32 +000022import java.io.File;
Felix Meschberger42764b82009-08-18 07:51:00 +000023import java.io.IOException;
24import java.io.InputStream;
Felix Meschbergerc67f9dc2009-08-31 13:03:11 +000025import java.lang.reflect.Field;
26import java.lang.reflect.Method;
Felix Meschberger42764b82009-08-18 07:51:00 +000027import java.util.Dictionary;
Felix Meschberger007c50e2011-10-20 12:39:38 +000028import java.util.HashSet;
Felix Meschberger42764b82009-08-18 07:51:00 +000029import java.util.Hashtable;
Felix Meschberger007c50e2011-10-20 12:39:38 +000030import java.util.Set;
Felix Meschberger13e91512009-08-20 11:23:32 +000031
Felix Meschbergerc67f9dc2009-08-31 13:03:11 +000032import junit.framework.AssertionFailedError;
Felix Meschberger42764b82009-08-18 07:51:00 +000033import junit.framework.TestCase;
34
Felix Meschberger13e91512009-08-20 11:23:32 +000035import org.apache.felix.cm.integration.helper.BaseTestActivator;
Felix Meschberger8659e392009-08-19 05:46:49 +000036import org.apache.felix.cm.integration.helper.ManagedServiceTestActivator;
Felix Meschbergerc67f9dc2009-08-31 13:03:11 +000037import org.apache.felix.cm.integration.helper.UpdateThreadSignalTask;
Felix Meschberger42764b82009-08-18 07:51:00 +000038import org.junit.After;
39import org.junit.Before;
Guillaume Nodet34730932012-12-14 16:40:08 +000040
41import javax.inject.Inject;
42
Felix Meschberger13e91512009-08-20 11:23:32 +000043import org.ops4j.pax.exam.CoreOptions;
Felix Meschberger42764b82009-08-18 07:51:00 +000044import org.ops4j.pax.exam.Option;
Felix Meschbergerf2641a22010-08-25 08:45:50 +000045import org.ops4j.pax.exam.OptionUtils;
Guillaume Nodet34730932012-12-14 16:40:08 +000046import org.ops4j.pax.exam.TestProbeBuilder;
47import org.ops4j.pax.exam.junit.ProbeBuilder;
48import org.ops4j.pax.tinybundles.core.TinyBundles;
Felix Meschberger42764b82009-08-18 07:51:00 +000049import org.osgi.framework.Bundle;
50import org.osgi.framework.BundleContext;
51import org.osgi.framework.BundleException;
52import org.osgi.framework.Constants;
53import org.osgi.framework.InvalidSyntaxException;
54import org.osgi.framework.ServiceReference;
55import org.osgi.service.cm.Configuration;
56import org.osgi.service.cm.ConfigurationAdmin;
57import org.osgi.util.tracker.ServiceTracker;
58
Guillaume Nodet34730932012-12-14 16:40:08 +000059import static org.ops4j.pax.exam.CoreOptions.*;
60
Felix Meschberger42764b82009-08-18 07:51:00 +000061
62public abstract class ConfigurationTestBase
63{
64
Felix Meschbergerf2641a22010-08-25 08:45:50 +000065 // the name of the system property providing the bundle file to be installed and tested
66 protected static final String BUNDLE_JAR_SYS_PROP = "project.bundle.file";
67
68 // the default bundle jar file name
69 protected static final String BUNDLE_JAR_DEFAULT = "target/configadmin.jar";
70
71 // the JVM option to set to enable remote debugging
72 protected static final String DEBUG_VM_OPTION = "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=30303";
73
74 // the actual JVM option set, extensions may implement a static
75 // initializer overwriting this value to have the configuration()
76 // method include it when starting the OSGi framework JVM
77 protected static String paxRunnerVmOption = null;
78
Felix Meschberger42764b82009-08-18 07:51:00 +000079 @Inject
80 protected BundleContext bundleContext;
81
82 protected Bundle bundle;
83
84 protected ServiceTracker configAdminTracker;
85
Felix Meschberger007c50e2011-10-20 12:39:38 +000086 private Set<String> configurations = new HashSet<String>();
87
Felix Meschberger42764b82009-08-18 07:51:00 +000088 protected static final String PROP_NAME = "theValue";
89 protected static final Dictionary<String, String> theConfig;
90
91 static
92 {
93 theConfig = new Hashtable<String, String>();
94 theConfig.put( PROP_NAME, PROP_NAME );
95 }
96
97
98 @org.ops4j.pax.exam.junit.Configuration
99 public static Option[] configuration()
100 {
Felix Meschbergerf2641a22010-08-25 08:45:50 +0000101 final String bundleFileName = System.getProperty( BUNDLE_JAR_SYS_PROP, BUNDLE_JAR_DEFAULT );
102 final File bundleFile = new File( bundleFileName );
103 if ( !bundleFile.canRead() )
104 {
105 throw new IllegalArgumentException( "Cannot read from bundle file " + bundleFileName + " specified in the "
106 + BUNDLE_JAR_SYS_PROP + " system property" );
107 }
108
109 final Option[] base = options(
Guillaume Nodet34730932012-12-14 16:40:08 +0000110 workingDirectory("target/paxexam/"),
111 cleanCaches(true),
112 junitBundles(),
113 mavenBundle("org.ops4j.pax.tinybundles", "tinybundles", "1.0.0"),
114 bundle(bundleFile.toURI().toString())
Felix Meschberger42764b82009-08-18 07:51:00 +0000115 );
Guillaume Nodet34730932012-12-14 16:40:08 +0000116 final Option option = ( paxRunnerVmOption != null ) ? vmOption( paxRunnerVmOption ) : null;
117 return OptionUtils.combine( base, option );
Felix Meschberger42764b82009-08-18 07:51:00 +0000118 }
119
120
121 @Before
122 public void setUp()
123 {
124 configAdminTracker = new ServiceTracker( bundleContext, ConfigurationAdmin.class.getName(), null );
125 configAdminTracker.open();
126 }
127
128
129 @After
130 public void tearDown() throws BundleException
131 {
132 if ( bundle != null )
133 {
134 bundle.uninstall();
135 }
136
Felix Meschberger007c50e2011-10-20 12:39:38 +0000137 for ( String pid : configurations )
138 {
139 deleteConfig( pid );
140 }
141
Felix Meschberger42764b82009-08-18 07:51:00 +0000142 configAdminTracker.close();
143 configAdminTracker = null;
144 }
145
146
147 protected Bundle installBundle( final String pid ) throws BundleException
148 {
Felix Meschberger8659e392009-08-19 05:46:49 +0000149 return installBundle( pid, ManagedServiceTestActivator.class );
Felix Meschberger42764b82009-08-18 07:51:00 +0000150 }
151
152
153 protected Bundle installBundle( final String pid, final Class<?> activatorClass ) throws BundleException
154 {
Felix Meschberger6f5b69e2009-08-19 09:39:21 +0000155 return installBundle( pid, activatorClass, activatorClass.getName() );
156 }
157
158
Guillaume Nodet34730932012-12-14 16:40:08 +0000159 @ProbeBuilder
160 public TestProbeBuilder buildProbe( TestProbeBuilder builder ) {
161 return builder.setHeader(Constants.EXPORT_PACKAGE, "org.apache.felix.cm.integration.helper");
162 }
163
Felix Meschberger6f5b69e2009-08-19 09:39:21 +0000164 protected Bundle installBundle( final String pid, final Class<?> activatorClass, final String location )
165 throws BundleException
166 {
Felix Meschberger8659e392009-08-19 05:46:49 +0000167 final String activatorClassName = activatorClass.getName();
Guillaume Nodet34730932012-12-14 16:40:08 +0000168 final InputStream bundleStream = TinyBundles.bundle()
169 .set(Constants.BUNDLE_SYMBOLICNAME, activatorClassName)
Felix Meschberger13e91512009-08-20 11:23:32 +0000170 .set( Constants.BUNDLE_VERSION, "0.0.11" )
171 .set( Constants.IMPORT_PACKAGE, "org.apache.felix.cm.integration.helper" )
172 .set( Constants.BUNDLE_ACTIVATOR, activatorClassName )
173 .set( BaseTestActivator.HEADER_PID, pid )
Guillaume Nodet34730932012-12-14 16:40:08 +0000174 .build( TinyBundles.withBnd() );
Felix Meschberger42764b82009-08-18 07:51:00 +0000175
176 try
177 {
Felix Meschberger6f5b69e2009-08-19 09:39:21 +0000178 return bundleContext.installBundle( location, bundleStream );
Felix Meschberger42764b82009-08-18 07:51:00 +0000179 }
180 finally
181 {
182 try
183 {
184 bundleStream.close();
185 }
186 catch ( IOException ioe )
187 {
188 }
189 }
190 }
191
192
Felix Meschbergerc67f9dc2009-08-31 13:03:11 +0000193 protected void delay()
Felix Meschberger42764b82009-08-18 07:51:00 +0000194 {
Felix Meschbergerc67f9dc2009-08-31 13:03:11 +0000195 Object ca = configAdminTracker.getService();
196 if ( ca != null )
197 {
198 try
199 {
200
201 Field caf = ca.getClass().getDeclaredField( "configurationManager" );
202 caf.setAccessible( true );
203 Object cm = caf.get( ca );
204
205 Field cmf = cm.getClass().getDeclaredField( "updateThread" );
206 cmf.setAccessible( true );
207 Object ut = cmf.get( cm );
208
209 Method utm = ut.getClass().getDeclaredMethod( "schedule" );
210 utm.setAccessible( true );
211
212 UpdateThreadSignalTask signalTask = new UpdateThreadSignalTask();
213 utm.invoke( ut, signalTask );
214 signalTask.waitSignal();
215
216 return;
217 }
218 catch ( AssertionFailedError afe )
219 {
220 throw afe;
221 }
222 catch ( Throwable t )
223 {
224 // ignore any problem and revert to timed delay (might log this)
225 }
226 }
227
228 // no configadmin or failure while setting up task
Felix Meschberger42764b82009-08-18 07:51:00 +0000229 try
230 {
231 Thread.sleep( 300 );
232 }
233 catch ( InterruptedException ie )
234 {
235 // dont care
236 }
237 }
238
239
240 protected Bundle getCmBundle()
241 {
242 final ServiceReference caref = configAdminTracker.getServiceReference();
243 return ( caref == null ) ? null : caref.getBundle();
244 }
245
246
247 protected ConfigurationAdmin getConfigurationAdmin()
248 {
249 ConfigurationAdmin ca = ( ConfigurationAdmin ) configAdminTracker.getService();
250 if ( ca == null )
251 {
252 TestCase.fail( "Missing ConfigurationAdmin service" );
253 }
254 return ca;
255 }
256
257
Felix Meschberger8659e392009-08-19 05:46:49 +0000258 protected Configuration configure( final String pid )
Felix Meschberger42764b82009-08-18 07:51:00 +0000259 {
Felix Meschberger8659e392009-08-19 05:46:49 +0000260 return configure( pid, null, true );
261 }
262
263
264 protected Configuration configure( final String pid, final String location, final boolean withProps )
265 {
266 final ConfigurationAdmin ca = getConfigurationAdmin();
Felix Meschberger42764b82009-08-18 07:51:00 +0000267 try
268 {
Felix Meschberger8659e392009-08-19 05:46:49 +0000269 final Configuration config = ca.getConfiguration( pid, location );
270 if ( withProps )
271 {
272 config.update( theConfig );
273 }
274 return config;
Felix Meschberger42764b82009-08-18 07:51:00 +0000275 }
276 catch ( IOException ioe )
277 {
278 TestCase.fail( "Failed updating configuration " + pid + ": " + ioe.toString() );
Felix Meschberger8659e392009-08-19 05:46:49 +0000279 return null; // keep the compiler quiet
280 }
281 }
282
283
284 protected Configuration createFactoryConfiguration( final String factoryPid )
285 {
286 return createFactoryConfiguration( factoryPid, null, true );
287 }
288
289
290 protected Configuration createFactoryConfiguration( final String factoryPid, final String location,
291 final boolean withProps )
292 {
293 final ConfigurationAdmin ca = getConfigurationAdmin();
294 try
295 {
Felix Meschberger007c50e2011-10-20 12:39:38 +0000296 final Configuration config = ca.createFactoryConfiguration( factoryPid, location );
Felix Meschberger8659e392009-08-19 05:46:49 +0000297 if ( withProps )
298 {
299 config.update( theConfig );
300 }
301 return config;
302 }
303 catch ( IOException ioe )
304 {
305 TestCase.fail( "Failed updating factory configuration " + factoryPid + ": " + ioe.toString() );
306 return null; // keep the compiler quiet
Felix Meschberger42764b82009-08-18 07:51:00 +0000307 }
308 }
309
310
311 protected Configuration getConfiguration( final String pid )
312 {
Felix Meschberger8659e392009-08-19 05:46:49 +0000313 final ConfigurationAdmin ca = getConfigurationAdmin();
Felix Meschberger42764b82009-08-18 07:51:00 +0000314 try
315 {
316 final String filter = "(" + Constants.SERVICE_PID + "=" + pid + ")";
Felix Meschberger8659e392009-08-19 05:46:49 +0000317 final Configuration[] configs = ca.listConfigurations( filter );
Felix Meschberger42764b82009-08-18 07:51:00 +0000318 if ( configs != null && configs.length > 0 )
319 {
320 return configs[0];
321 }
322 }
323 catch ( InvalidSyntaxException ise )
324 {
325 // unexpected
326 }
327 catch ( IOException ioe )
328 {
329 TestCase.fail( "Failed listing configurations " + pid + ": " + ioe.toString() );
330 }
331
332 TestCase.fail( "No Configuration " + pid + " found" );
333 return null;
334 }
335
336
Felix Meschberger8659e392009-08-19 05:46:49 +0000337 protected void deleteConfig( final String pid )
Felix Meschberger42764b82009-08-18 07:51:00 +0000338 {
Felix Meschberger8659e392009-08-19 05:46:49 +0000339 final ConfigurationAdmin ca = getConfigurationAdmin();
Felix Meschberger42764b82009-08-18 07:51:00 +0000340 try
341 {
Felix Meschberger007c50e2011-10-20 12:39:38 +0000342 configurations.remove( pid );
Felix Meschberger8659e392009-08-19 05:46:49 +0000343 final Configuration config = ca.getConfiguration( pid );
Felix Meschberger42764b82009-08-18 07:51:00 +0000344 config.delete();
345 }
346 catch ( IOException ioe )
347 {
348 TestCase.fail( "Failed deleting configuration " + pid + ": " + ioe.toString() );
349 }
350 }
351
352
Felix Meschberger42764b82009-08-18 07:51:00 +0000353 protected void deleteFactoryConfigurations( String factoryPid )
354 {
355 ConfigurationAdmin ca = getConfigurationAdmin();
356 try
357 {
358 final String filter = "(service.factoryPid=" + factoryPid + ")";
Felix Meschberger8659e392009-08-19 05:46:49 +0000359 Configuration[] configs = ca.listConfigurations( filter );
Felix Meschberger42764b82009-08-18 07:51:00 +0000360 if ( configs != null )
361 {
Felix Meschberger8659e392009-08-19 05:46:49 +0000362 for ( Configuration configuration : configs )
Felix Meschberger42764b82009-08-18 07:51:00 +0000363 {
Felix Meschberger007c50e2011-10-20 12:39:38 +0000364 configurations.remove( configuration.getPid() );
Felix Meschberger42764b82009-08-18 07:51:00 +0000365 configuration.delete();
366 }
367 }
368 }
369 catch ( InvalidSyntaxException ise )
370 {
371 // unexpected
372 }
373 catch ( IOException ioe )
374 {
375 TestCase.fail( "Failed deleting configurations " + factoryPid + ": " + ioe.toString() );
376 }
377 }
378}