Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 403628 | Differences between
and this patch

Collapse All | Expand All

(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManager.java (-11 / +17 lines)
Lines 271-295 class LifecycleManager implements DisposableBean { Link Here
271
	 * @param bundle
271
	 * @param bundle
272
	 */
272
	 */
273
	protected void maybeCloseApplicationContextFor(Bundle bundle) {
273
	protected void maybeCloseApplicationContextFor(Bundle bundle) {
274
		final ConfigurableOsgiBundleApplicationContext context =
274
		final ConfigurableOsgiBundleApplicationContext context = managedContexts.remove(bundle.getBundleId());
275
				(ConfigurableOsgiBundleApplicationContext) managedContexts.remove(Long.valueOf(bundle.getBundleId()));
276
		if (context == null) {
275
		if (context == null) {
277
			return;
276
			return;
278
		}
277
		}
279
278
280
		RunnableTimedExecution.execute(new Runnable() {
279
        Runnable shutdownTask = new Runnable() {
281
280
282
			private final String toString = "Closing runnable for context " + context.getDisplayName();
281
            private final String toString = "Closing runnable for context " + context.getDisplayName();
283
282
284
			public void run() {
283
            public void run() {
285
				closeApplicationContext(context);
284
                closeApplicationContext(context);
286
			}
285
            }
287
286
288
			public String toString() {
287
            public String toString() {
289
				return toString;
288
                return toString;
290
			}
289
            }
290
291
        };
292
293
        if (extenderConfiguration.shouldShutdownAsynchronously()) {
294
            RunnableTimedExecution.execute(shutdownTask, extenderConfiguration.getShutdownWaitTime(), shutdownTaskExecutor);
295
        } else {
296
            shutdownTask.run();
297
        }
291
298
292
		}, extenderConfiguration.getShutdownWaitTime(), shutdownTaskExecutor);
293
	}
299
	}
294
300
295
	/**
301
	/**
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfiguration.java (-4 / +31 lines)
Lines 42-48 import org.springframework.util.ObjectUtils; Link Here
42
import java.io.UnsupportedEncodingException;
42
import java.io.UnsupportedEncodingException;
43
import java.net.URL;
43
import java.net.URL;
44
import java.net.URLDecoder;
44
import java.net.URLDecoder;
45
import java.util.*;
45
import java.util.ArrayList;
46
import java.util.Collections;
47
import java.util.Enumeration;
48
import java.util.List;
49
import java.util.Properties;
50
import java.util.Timer;
46
51
47
/**
52
/**
48
 * Configuration class for the extender. Takes care of locating the extender specific configurations and merging the
53
 * Configuration class for the extender. Takes care of locating the extender specific configurations and merging the
Lines 67-72 public class ExtenderConfiguration implements BundleActivator { Link Here
67
72
68
	private static final String PROPERTIES_NAME = "extenderProperties";
73
	private static final String PROPERTIES_NAME = "extenderProperties";
69
74
75
    private static final String SHUTDOWN_ASYNCHRONOUS_KEY = "shutdown.asynchronously";
76
70
	private static final String SHUTDOWN_WAIT_KEY = "shutdown.wait.time";
77
	private static final String SHUTDOWN_WAIT_KEY = "shutdown.wait.time";
71
78
72
	private static final String PROCESS_ANNOTATIONS_KEY = "process.annotations";
79
	private static final String PROCESS_ANNOTATIONS_KEY = "process.annotations";
Lines 91-97 public class ExtenderConfiguration implements BundleActivator { Link Here
91
	// default dependency wait time (in milliseconds)
98
	// default dependency wait time (in milliseconds)
92
	private static final long DEFAULT_DEP_WAIT = ConfigUtils.DIRECTIVE_TIMEOUT_DEFAULT * 1000;
99
	private static final long DEFAULT_DEP_WAIT = ConfigUtils.DIRECTIVE_TIMEOUT_DEFAULT * 1000;
93
	private static final boolean DEFAULT_NS_BUNDLE_STATE = true;
100
	private static final boolean DEFAULT_NS_BUNDLE_STATE = true;
94
	private static final long DEFAULT_SHUTDOWN_WAIT = 10 * 1000;
101
	private static final boolean DEFAULT_SHUTDOWN_ASYNCHRONOUS = true;
102
    private static final long DEFAULT_SHUTDOWN_WAIT = 10 * 1000;
103
95
	private static final boolean DEFAULT_PROCESS_ANNOTATION = false;
104
	private static final boolean DEFAULT_PROCESS_ANNOTATION = false;
96
105
97
	private ConfigurableOsgiBundleApplicationContext extenderConfiguration;
106
	private ConfigurableOsgiBundleApplicationContext extenderConfiguration;
Lines 106-111 public class ExtenderConfiguration implements BundleActivator { Link Here
106
115
107
	private long shutdownWaitTime, dependencyWaitTime;
116
	private long shutdownWaitTime, dependencyWaitTime;
108
117
118
    private boolean shutdownAsynchronously;
119
109
	private boolean processAnnotation, nsBundledResolved;
120
	private boolean processAnnotation, nsBundledResolved;
110
121
111
	private OsgiBundleApplicationContextEventMulticaster eventMulticaster;
122
	private OsgiBundleApplicationContextEventMulticaster eventMulticaster;
Lines 128-134 public class ExtenderConfiguration implements BundleActivator { Link Here
128
	// fields reading/writing lock
139
	// fields reading/writing lock
129
	private final Object lock = new Object();
140
	private final Object lock = new Object();
130
141
131
	/**
142
    /**
132
	 * Constructs a new <code>ExtenderConfiguration</code> instance. Locates the extender configuration, creates an
143
	 * Constructs a new <code>ExtenderConfiguration</code> instance. Locates the extender configuration, creates an
133
	 * application context which will returned the extender items.
144
	 * application context which will returned the extender items.
134
	 * 
145
	 * 
Lines 209-215 public class ExtenderConfiguration implements BundleActivator { Link Here
209
220
210
		synchronized (lock) {
221
		synchronized (lock) {
211
			shutdownWaitTime = getShutdownWaitTime(properties);
222
			shutdownWaitTime = getShutdownWaitTime(properties);
212
			dependencyWaitTime = getDependencyWaitTime(properties);
223
			shutdownAsynchronously = getShutdownAsynchronously(properties);
224
            dependencyWaitTime = getDependencyWaitTime(properties);
213
			processAnnotation = getProcessAnnotations(properties);
225
			processAnnotation = getProcessAnnotations(properties);
214
		}
226
		}
215
227
Lines 302-307 public class ExtenderConfiguration implements BundleActivator { Link Here
302
	private Properties createDefaultProperties() {
314
	private Properties createDefaultProperties() {
303
		Properties properties = new Properties();
315
		Properties properties = new Properties();
304
		properties.setProperty(SHUTDOWN_WAIT_KEY, "" + DEFAULT_SHUTDOWN_WAIT);
316
		properties.setProperty(SHUTDOWN_WAIT_KEY, "" + DEFAULT_SHUTDOWN_WAIT);
317
        properties.setProperty(SHUTDOWN_ASYNCHRONOUS_KEY, "" + DEFAULT_SHUTDOWN_ASYNCHRONOUS);
305
		properties.setProperty(PROCESS_ANNOTATIONS_KEY, "" + DEFAULT_PROCESS_ANNOTATION);
318
		properties.setProperty(PROCESS_ANNOTATIONS_KEY, "" + DEFAULT_PROCESS_ANNOTATION);
306
		properties.setProperty(WAIT_FOR_DEPS_TIMEOUT_KEY, "" + DEFAULT_DEP_WAIT);
319
		properties.setProperty(WAIT_FOR_DEPS_TIMEOUT_KEY, "" + DEFAULT_DEP_WAIT);
307
320
Lines 388-393 public class ExtenderConfiguration implements BundleActivator { Link Here
388
		return Long.parseLong(properties.getProperty(SHUTDOWN_WAIT_KEY));
401
		return Long.parseLong(properties.getProperty(SHUTDOWN_WAIT_KEY));
389
	}
402
	}
390
403
404
    private boolean getShutdownAsynchronously(Properties properties) {
405
        return Boolean.valueOf(properties.getProperty(SHUTDOWN_ASYNCHRONOUS_KEY));
406
    }
407
391
	private long getDependencyWaitTime(Properties properties) {
408
	private long getDependencyWaitTime(Properties properties) {
392
		return Long.parseLong(properties.getProperty(WAIT_FOR_DEPS_TIMEOUT_KEY));
409
		return Long.parseLong(properties.getProperty(WAIT_FOR_DEPS_TIMEOUT_KEY));
393
	}
410
	}
Lines 452-457 public class ExtenderConfiguration implements BundleActivator { Link Here
452
		}
469
		}
453
	}
470
	}
454
471
472
    /**
473
     * @return whether the application context shutdown during the bundle stop phase shall be
474
     *         performed asynchronously.
475
     */
476
    public boolean shouldShutdownAsynchronously() {
477
        synchronized (lock) {
478
            return this.shutdownAsynchronously;
479
        }
480
    }
481
455
	/**
482
	/**
456
	 * Returns the dependencyWaitTime.
483
	 * Returns the dependencyWaitTime.
457
	 * 
484
	 * 
(-)a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationCustomSettingsTest.java (-1 / +5 lines)
Lines 80-86 public class ExtenderConfigurationCustomSettingsTest extends TestCase { Link Here
80
		assertEquals(300, config.getShutdownWaitTime());
80
		assertEquals(300, config.getShutdownWaitTime());
81
	}
81
	}
82
82
83
	public void testShouldProcessAnnotation() throws Exception {
83
    public void testShutdownAsynchronously() throws Exception {
84
        assertFalse(config.shouldShutdownAsynchronously());
85
    }
86
87
    public void testShouldProcessAnnotation() throws Exception {
84
		assertTrue(config.shouldProcessAnnotation());
88
		assertTrue(config.shouldProcessAnnotation());
85
	}
89
	}
86
90
(-)a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/support/ExtenderConfigurationDefaultSettingsTest.java (-1 / +5 lines)
Lines 66-72 public class ExtenderConfigurationDefaultSettingsTest extends TestCase { Link Here
66
		assertEquals(10 * 1000, config.getShutdownWaitTime());
66
		assertEquals(10 * 1000, config.getShutdownWaitTime());
67
	}
67
	}
68
68
69
	public void testShouldProcessAnnotation() throws Exception {
69
    public void testShutdownAsynchronously() throws Exception {
70
        assertTrue(config.shouldShutdownAsynchronously());
71
    }
72
73
    public void testShouldProcessAnnotation() throws Exception {
70
		assertFalse(config.shouldProcessAnnotation());
74
		assertFalse(config.shouldProcessAnnotation());
71
	}
75
	}
72
76
(-)a/extender/src/test/resources/org/eclipse/gemini/blueprint/extender/internal/support/extender-custom-config.xml (-2 / +1 lines)
Lines 24-29 Link Here
24
		<prop key="smth">bla</prop>
24
		<prop key="smth">bla</prop>
25
		<prop key="dependencies.wait.time">200</prop>
25
		<prop key="dependencies.wait.time">200</prop>
26
		<prop key="shutdown.wait.time">300</prop>
26
		<prop key="shutdown.wait.time">300</prop>
27
        <prop key="shutdown.asynchronously">false</prop>
27
		<prop key="process.annotations">true</prop>
28
		<prop key="process.annotations">true</prop>
28
	</util:properties>
29
	</util:properties>
29
</beans>
30
</beans>
30
- 
31
during
31
during
32
LifecycleManager#maybeCloseApplicationContextFor(Bundle)
32
LifecycleManager#maybeCloseApplicationContextFor(Bundle)
33
in Apache Felix
33
in Apache Felix
34
(https://bugs.eclipse.org/bugs/show_bug.cgi?id=403628)
34
(https://bugs.eclipse.org/bugs/show_bug.cgi?id=403628)
35
- Added documentation
35
- Added documentation
36
- Improved test coverage of the LifecycleManager
36
- Improved test coverage of the LifecycleManager
37
--
38
docs/src/docbkx/reference/deployment.xml           |  12 +-
37
docs/src/docbkx/reference/deployment.xml           |  12 +-
39
.../internal/activator/LifecycleManager.java       |  18 ++-
38
.../internal/activator/LifecycleManager.java       |  18 ++-
40
.../internal/activator/LifecycleManagerTest.java   | 122 +++++++++++++++++++++
39
.../internal/activator/LifecycleManagerTest.java   | 122 +++++++++++++++++++++
41
3 files changed, 146 insertions(+), 6 deletions(-)
40
3 files changed, 146 insertions(+), 6 deletions(-)
42
create mode 100644 extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManagerTest.java
41
create mode 100644 extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManagerTest.java
(-)a/docs/src/docbkx/reference/deployment.xml (-1 / +11 lines)
Lines 469-475 Blueprint-Bundle: config/account-data-context.xml, config/osgi-*.xml Link Here
469
                <entry>The amount of time the extender will wait for each application context to shutdown gracefully. Expressed in milliseconds.</entry>
469
                <entry>The amount of time the extender will wait for each application context to shutdown gracefully. Expressed in milliseconds.</entry>
470
                <entry>10000 ms (10 s)</entry>
470
                <entry>10000 ms (10 s)</entry>
471
              </row>
471
              </row>
472
              
472
473
              <row>
474
                <entry><literal>shutdown.asynchronously</literal></entry>
475
                <entry><classname>boolean</classname></entry>
476
                <entry>
477
                    Whether the extender shall shutdown each application context asynchronously. If <literal>false</literal>,
478
                    the <literal>shutdown.wait.time</literal> is ignored. Accordingly, application contexts blocking during close will block the bundle shutdown.
479
                </entry>
480
                <entry><literal>true</literal></entry>
481
              </row>
482
473
              <row>
483
              <row>
474
                <entry><literal>dependencies.wait.time</literal></entry>
484
                <entry><literal>dependencies.wait.time</literal></entry>
475
                <entry><classname>java.lang.Long</classname></entry>
485
                <entry><classname>java.lang.Long</classname></entry>
(-)a/extender/src/main/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManager.java (-5 / +13 lines)
Lines 276-284 class LifecycleManager implements DisposableBean { Link Here
276
			return;
276
			return;
277
		}
277
		}
278
278
279
        maybeClose(context);
280
	}
281
282
    protected void maybeClose(final ConfigurableOsgiBundleApplicationContext context) {
283
        final String displayName = context.getDisplayName();
279
        Runnable shutdownTask = new Runnable() {
284
        Runnable shutdownTask = new Runnable() {
280
285
281
            private final String toString = "Closing runnable for context " + context.getDisplayName();
286
            private final String toString = "Closing runnable for context " + displayName;
282
287
283
            public void run() {
288
            public void run() {
284
                closeApplicationContext(context);
289
                closeApplicationContext(context);
Lines 293-304 class LifecycleManager implements DisposableBean { Link Here
293
        if (extenderConfiguration.shouldShutdownAsynchronously()) {
298
        if (extenderConfiguration.shouldShutdownAsynchronously()) {
294
            RunnableTimedExecution.execute(shutdownTask, extenderConfiguration.getShutdownWaitTime(), shutdownTaskExecutor);
299
            RunnableTimedExecution.execute(shutdownTask, extenderConfiguration.getShutdownWaitTime(), shutdownTaskExecutor);
295
        } else {
300
        } else {
296
            shutdownTask.run();
301
            try {
302
                shutdownTask.run();
303
            } catch (Exception e) {
304
                log.error(displayName + " context shutdown failed.", e);
305
            }
297
        }
306
        }
307
    }
298
308
299
	}
309
    /**
300
301
	/**
302
	 * Closes an application context. This is a convenience methods that invokes the event notification as well.
310
	 * Closes an application context. This is a convenience methods that invokes the event notification as well.
303
	 * 
311
	 * 
304
	 * @param ctx
312
	 * @param ctx
(-)a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManagerTest.java (-2 / +122 lines)
Added Link Here
0
- 
1
package org.eclipse.gemini.blueprint.extender.internal.activator;
2
3
import junit.framework.TestCase;
4
import org.easymock.MockControl;
5
import org.eclipse.gemini.blueprint.context.ConfigurableOsgiBundleApplicationContext;
6
import org.eclipse.gemini.blueprint.extender.internal.support.ExtenderConfiguration;
7
8
import static java.lang.Thread.yield;
9
10
/**
11
 * @author Olaf Otto
12
 */
13
public class LifecycleManagerTest extends TestCase {
14
    private MockControl contextControl = MockControl.createControl(ConfigurableOsgiBundleApplicationContext.class);
15
    private ConfigurableOsgiBundleApplicationContext context = (ConfigurableOsgiBundleApplicationContext) contextControl.getMock();
16
17
    private MockControl osgiContextProcessorControl = MockControl.createControl(OsgiContextProcessor.class);
18
    private OsgiContextProcessor osgiContextProcessor = (OsgiContextProcessor) osgiContextProcessorControl.getMock();
19
20
    private boolean shouldShutdownAsynchronously;
21
22
    // Cannot mock a class with easymock 1.2
23
    ExtenderConfiguration configuration = new ExtenderConfiguration() {
24
        @Override
25
        public boolean shouldShutdownAsynchronously() {
26
            return shouldShutdownAsynchronously;
27
        }
28
29
        @Override
30
        public long getShutdownWaitTime() {
31
            return 0L;
32
        }
33
    };
34
35
    private LifecycleManager testee = new LifecycleManager(this.configuration, null, null, null, this.osgiContextProcessor, null, null);
36
37
    public void testSuccessfulAsynchronousShutdown() throws Exception {
38
        withAsynchronousShutdownDisabled();
39
        withSuccessfulContextClose();
40
        withPreAndPostProcessing();
41
42
        shutdownContext();
43
44
        verifyContextIsClosed();
45
        verifyOsgiContextProcessorInteractions();
46
    }
47
48
    public void testSuccessfulSynchronousShutdown() throws Exception {
49
        withAsynchronousShutdownEnabled();
50
        withSuccessfulContextClose();
51
        withPreAndPostProcessing();
52
53
        shutdownContext();
54
55
        verifyContextIsClosed();
56
        verifyOsgiContextProcessorInteractions();
57
    }
58
59
    public void testFailingAsynchronousShutdown() throws Exception {
60
        withAsynchronousShutdownEnabled();
61
        withFailingApplicationContextClose();
62
        withPreAndPostProcessing();
63
64
        shutdownContext();
65
        yield();
66
67
        verifyContextIsClosed();
68
        verifyOsgiContextProcessorInteractions();
69
    }
70
71
    public void testFailingSynchronousShutdown() {
72
        withAsynchronousShutdownDisabled();
73
        withFailingApplicationContextClose();
74
        withPreAndPostProcessing();
75
76
        shutdownContext();
77
78
        verifyContextIsClosed();
79
        verifyOsgiContextProcessorInteractions();
80
    }
81
82
    private void withFailingApplicationContextClose() {
83
        this.context.getDisplayName();
84
        this.contextControl.setReturnValue("Display name");
85
        this.context.close();
86
        this.contextControl.setThrowable(new RuntimeException("THIS IS AN EXPECTED TEST EXCEPTION"));
87
    }
88
89
    private void verifyContextIsClosed() {
90
        this.contextControl.verify();
91
    }
92
93
    private void verifyOsgiContextProcessorInteractions() {
94
        this.osgiContextProcessorControl.verify();
95
    }
96
97
    private void withPreAndPostProcessing() {
98
        this.osgiContextProcessor.preProcessClose(this.context);
99
        this.osgiContextProcessor.postProcessClose(this.context);
100
    }
101
102
    private void withSuccessfulContextClose() {
103
        this.context.close();
104
        this.context.getDisplayName();
105
        this.contextControl.setDefaultReturnValue("Nothing");
106
    }
107
108
    private void shutdownContext() {
109
        this.contextControl.replay();
110
        this.osgiContextProcessorControl.replay();
111
112
        this.testee.maybeClose(this.context);
113
    }
114
115
    private void withAsynchronousShutdownDisabled() {
116
        this.shouldShutdownAsynchronously = false;
117
    }
118
119
    private void withAsynchronousShutdownEnabled() {
120
        this.shouldShutdownAsynchronously = true;
121
    }
122
}
1
during
123
during
2
LifecycleManager#maybeCloseApplicationContextFor(Bundle)
124
LifecycleManager#maybeCloseApplicationContextFor(Bundle)
3
in Apache Felix
125
in Apache Felix
4
(https://bugs.eclipse.org/bugs/show_bug.cgi?id=403628)
126
(https://bugs.eclipse.org/bugs/show_bug.cgi?id=403628)
5
- Added missing license headers
127
- Added missing license headers
6
--
7
.../extender/internal/activator/LifecycleManagerTest.java  | 14 ++++++++++++++
128
.../extender/internal/activator/LifecycleManagerTest.java  | 14 ++++++++++++++
8
1 file changed, 14 insertions(+)
129
1 file changed, 14 insertions(+)
(-)a/extender/src/test/java/org/eclipse/gemini/blueprint/extender/internal/activator/LifecycleManagerTest.java (-1 / +14 lines)
Lines 1-3 Link Here
1
/******************************************************************************
2
 * Copyright (c) 2006, 2010 VMware Inc., Oracle Inc.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * and Apache License v2.0 which accompanies this distribution.
6
 * The Eclipse Public License is available at
7
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
8
 * is available at http://www.opensource.org/licenses/apache2.0.php.
9
 * You may elect to redistribute this code under either of these licenses.
10
 *
11
 * Contributors:
12
 *   VMware Inc.
13
 *   Oracle Inc.
14
 *****************************************************************************/
1
package org.eclipse.gemini.blueprint.extender.internal.activator;
15
package org.eclipse.gemini.blueprint.extender.internal.activator;
2
16
3
import junit.framework.TestCase;
17
import junit.framework.TestCase;
4
- 

Return to bug 403628