/**
* Copyright 2013 the original author or authors.
*
* Licensed 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 io.neba.core.blueprint;
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEvent;
import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener;
import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextFailedEvent;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import static io.neba.core.util.BundleUtil.displayNameOf;
import static org.osgi.framework.Bundle.ACTIVE;
import static org.osgi.framework.Bundle.STARTING;
/**
* When an application context activation fails, NEBA removes any previously
* registered resource models, self tests, MVC infrastructure and the like, since these
* are registered before the application context is
* {@link org.springframework.context.ConfigurableApplicationContext#refresh() activated}.
*
* @author Olaf Otto
*/
@Service("osgiApplicationContextListener")
public class ContextFailedHandler extends ContextShutdownHandler
implements OsgiBundleApplicationContextListener<OsgiBundleApplicationContextEvent> {
/**
* This method is executed asynchronously since the original extender thread may try to obtain a lock to the OSGi
* framework's registry state during the stop while holding the event handling lock, which may result in a transitive
* deadlock.
*/
@Override
@Async
public void onOsgiApplicationEvent(OsgiBundleApplicationContextEvent event) {
// We need to use the generic OsgiBundleApplicationContextEvent here and test
// for instanceof since gemini-blueprint does not correctly determine
// the event type we are listening for.
if (event instanceof OsgiBundleContextFailedEvent) {
final Bundle bundle = event.getBundle();
handleStop(bundle);
stop(bundle);
}
}
private void stop(Bundle bundle) {
try {
if (canStop(bundle)) {
bundle.stop();
}
} catch (BundleException e) {
throw new RuntimeException("Unable to stop bundle " + displayNameOf(bundle) + ".", e);
}
}
private boolean canStop(Bundle bundle) {
return bundle.getState() == ACTIVE || bundle.getState() == STARTING;
}
}