/*******************************************************************************
* Copyright (c) 2007, 2014 compeople AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* compeople AG - initial API and implementation
*******************************************************************************/
package org.eclipse.riena.internal.core.injector.extension;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.riena.core.wire.Wire;
import org.eclipse.riena.internal.core.Activator;
/**
* An invocation handler that lazily creates an executable extension on demand.
*/
final class LazyExecutableExtension implements InvocationHandler {
private final BundleContext bundleContext;
private final IConfigurationElement configurationElement;
private final String attributeName;
private final boolean wire;
private volatile Object delegate;
static Object newInstance(final Class<?> returnType, final IConfigurationElement configurationElement,
final String attributeName, final boolean wire) {
return Proxy.newProxyInstance(returnType.getClassLoader(), new Class[] { returnType },
new LazyExecutableExtension(getBundleContext(returnType), configurationElement, attributeName, wire));
}
private LazyExecutableExtension(final BundleContext bundleContext,
final IConfigurationElement configurationElement, final String attributeName, final boolean wire) {
this.bundleContext = bundleContext;
this.configurationElement = configurationElement;
this.attributeName = attributeName;
this.wire = wire;
}
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
// Double-check idiom for lazy initialization of instance fields (Joshua Bloch, Effective Java, Item 71)
Object temp = delegate;
if (temp == null) {
synchronized (this) {
temp = delegate;
if (temp == null) {
final Object temp2 = configurationElement.createExecutableExtension(attributeName);
if (wire) {
Wire.instance(temp2).andStart(bundleContext);
}
delegate = temp = temp2;
}
}
}
try {
return method.invoke(delegate, args);
} catch (final InvocationTargetException e) {
throw e.getTargetException();
}
}
private static BundleContext getBundleContext(final Class<?> returnType) {
final Bundle bundle = FrameworkUtil.getBundle(returnType);
if (bundle != null) {
final BundleContext bundleContext = bundle.getBundleContext();
if (bundleContext != null) {
return bundleContext;
}
}
return Activator.getDefault().getContext();
}
}