blob: 2aecba46074e16c123bdd11c39cb9506b8cb36ae [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2006, 2010 VMware Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
* is available at http://www.opensource.org/licenses/apache2.0.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* VMware Inc.
*****************************************************************************/
package org.eclipse.gemini.blueprint.config.internal.adapter;
import java.lang.reflect.Method;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.gemini.blueprint.context.support.internal.security.SecurityUtils;
import org.eclipse.gemini.blueprint.service.exporter.OsgiServiceRegistrationListener;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Adapter/wrapper class that handles listener with custom method invocation. Similar in functionality to
* {@link org.eclipse.gemini.blueprint.config.internal.adapter.OsgiServiceLifecycleListenerAdapter}.
*
* @author Costin Leau
*
*/
public class OsgiServiceRegistrationListenerAdapter implements OsgiServiceRegistrationListener, InitializingBean,
BeanFactoryAware {
private static final Log log = LogFactory.getLog(OsgiServiceRegistrationListenerAdapter.class);
/** does the target implement the listener interface */
private boolean isListener;
private String registrationMethod, unregistrationMethod;
/** actual target */
private Object target;
/** target bean name (when dealing with cycles) */
private String targetBeanName;
/** bean factory used for retrieving the target when dealing with cycles */
private BeanFactory beanFactory;
/** init flag */
private boolean initialized;
/**
* Map of methods keyed by the first parameter which indicates the service type expected.
*/
private Map<Class<?>, List<Method>> registrationMethods, unregistrationMethods;
private boolean isBlueprintCompliant = false;
public void afterPropertiesSet() {
Assert.notNull(beanFactory);
Assert.isTrue(target != null || StringUtils.hasText(targetBeanName),
"one of 'target' or 'targetBeanName' properties has to be set");
if (target != null)
initialized = true;
// do validation (on the target type)
initialize();
// postpone target initialization until one of bind/unbind method is called
}
private void retrieveTarget() {
target = beanFactory.getBean(targetBeanName);
initialized = true;
}
/**
* Initialise adapter. Determine custom methods and do validation.
*/
private void initialize() {
Class<?> clazz = (target == null ? beanFactory.getType(targetBeanName) : target.getClass());
isListener = OsgiServiceRegistrationListener.class.isAssignableFrom(clazz);
if (isListener)
if (log.isDebugEnabled())
log.debug(clazz.getName() + " is a registration listener");
registrationMethods =
CustomListenerAdapterUtils.determineCustomMethods(clazz, registrationMethod, isBlueprintCompliant);
unregistrationMethods =
CustomListenerAdapterUtils.determineCustomMethods(clazz, unregistrationMethod, isBlueprintCompliant);
if (!isListener && (registrationMethods.isEmpty() && unregistrationMethods.isEmpty()))
throw new IllegalArgumentException("Target object needs to implement "
+ OsgiServiceRegistrationListener.class.getName()
+ " or custom registered/unregistered methods have to be specified");
if (log.isTraceEnabled()) {
StringBuilder builder = new StringBuilder();
builder.append("Discovered bind methods=");
builder.append(registrationMethods.values());
builder.append("\nunbind methods=");
builder.append(unregistrationMethods.values());
log.trace(builder.toString());
}
}
public void registered(final Object service, final Map serviceProperties) {
boolean trace = log.isTraceEnabled();
if (trace)
log.trace("Invoking registered method with props=" + serviceProperties);
if (!initialized)
retrieveTarget();
boolean isSecurityEnabled = System.getSecurityManager() != null;
AccessControlContext acc = null;
if (isSecurityEnabled) {
acc = SecurityUtils.getAccFrom(beanFactory);
}
// first call interface method (if it exists)
if (isListener) {
if (trace)
log.trace("Invoking listener interface methods");
try {
if (isSecurityEnabled) {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((OsgiServiceRegistrationListener) target).registered(service, serviceProperties);
return null;
}
}, acc);
} else {
((OsgiServiceRegistrationListener) target).registered(service, serviceProperties);
}
} catch (Exception ex) {
if (ex instanceof PrivilegedActionException) {
ex = ((PrivilegedActionException) ex).getException();
}
log.warn("Standard registered method on [" + target.getClass().getName() + "] threw exception", ex);
}
}
if (isSecurityEnabled) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
CustomListenerAdapterUtils.invokeCustomMethods(target, registrationMethods, service,
serviceProperties);
return null;
}
}, acc);
} else {
CustomListenerAdapterUtils.invokeCustomMethods(target, registrationMethods, service, serviceProperties);
}
}
public void unregistered(final Object service, final Map serviceProperties) {
boolean trace = log.isTraceEnabled();
if (trace)
log.trace("Invoking unregistered method with props=" + serviceProperties);
if (!initialized)
retrieveTarget();
boolean isSecurityEnabled = System.getSecurityManager() != null;
AccessControlContext acc = null;
if (isSecurityEnabled) {
acc = SecurityUtils.getAccFrom(beanFactory);
}
// first call interface method (if it exists)
if (isListener) {
if (trace)
log.trace("Invoking listener interface methods");
try {
if (isSecurityEnabled) {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((OsgiServiceRegistrationListener) target).unregistered(service, serviceProperties);
return null;
}
}, acc);
} else {
((OsgiServiceRegistrationListener) target).unregistered(service, serviceProperties);
}
} catch (Exception ex) {
log.warn("Standard unregistered method on [" + target.getClass().getName() + "] threw exception", ex);
}
}
if (isSecurityEnabled) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
CustomListenerAdapterUtils.invokeCustomMethods(target, unregistrationMethods, service,
serviceProperties);
return null;
}
}, acc);
} else {
CustomListenerAdapterUtils.invokeCustomMethods(target, unregistrationMethods, service, serviceProperties);
}
}
/**
* @param registrationMethod The registrationMethod to set.
*/
public void setRegistrationMethod(String registrationMethod) {
this.registrationMethod = registrationMethod;
}
/**
* @param unregistrationMethod The unregistrationMethod to set.
*/
public void setUnregistrationMethod(String unregistrationMethod) {
this.unregistrationMethod = unregistrationMethod;
}
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
/**
* @param target The target to set.
*/
public void setTarget(Object target) {
this.target = target;
}
/**
* @param targetBeanName The targetBeanName to set.
*/
public void setTargetBeanName(String targetBeanName) {
this.targetBeanName = targetBeanName;
}
public void setBlueprintCompliant(boolean compliant) {
this.isBlueprintCompliant = compliant;
}
}