/*******************************************************************************
* 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.singleton;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.WeakHashMap;
import org.osgi.framework.Bundle;
import org.eclipse.riena.core.singleton.ISingletonInitializer;
import org.eclipse.riena.core.singleton.SingletonFailure;
import org.eclipse.riena.core.util.Nop;
import org.eclipse.riena.core.util.RAPDetector;
import org.eclipse.riena.core.wire.Wire;
/**
* Riena's wrapper for RAP's session based singleton provider. This wrapper
* additionally wires a newly created singleton.
*
* @since 4.0
*/
public final class RAPSingletonProvider {
private static final boolean IS_AVAILABLE;
private static Class<?> sessionSingletonBaseClass;
private static Method getInstanceMethod;
private static final Map<Object, Boolean> WIRED_RAP_SINGLETONS = new WeakHashMap<Object, Boolean>();
private static final String SESSION_SINGLETON_BASE = "org.eclipse.rap.rwt.SessionSingletonBase"; //$NON-NLS-1$
private static final String GET_INSTANCE = "getInstance"; //$NON-NLS-1$
static {
IS_AVAILABLE = RAPDetector.isRAPavailable() && loadSessionSingletonBase();
}
private RAPSingletonProvider() {
Nop.reason("utility"); //$NON-NLS-1$
}
/**
* Load the RAP {@code SessionSingletonBase} class and the
* {@code getInstance} method as a side effect.
*
* @return {@code true} if class and method have been found; otherwise
* {@code false}
*/
private static boolean loadSessionSingletonBase() {
final Bundle rapBundle = RAPDetector.getRWTBundle();
try {
sessionSingletonBaseClass = rapBundle.loadClass(SESSION_SINGLETON_BASE);
getInstanceMethod = sessionSingletonBaseClass.getMethod(GET_INSTANCE, Class.class);
return true;
} catch (final Exception e) {
// There seems to be no RAP available.
return false;
}
}
/**
* Is RAP available and could RAP's singleton creation function be located
* (reflection)?
*
* @return true RAP is available and we can create RAP based singletons;
* otherwise not
*/
public static boolean isAvailable() {
return IS_AVAILABLE;
}
/**
* Return the requested wired RAP session singleton.
*
* @param singletonClass
* the class to create a RAP session based singleton
*
* @return the singleton
*/
public static <S> S getInstance(final Class<S> singletonClass) {
return getInstance(singletonClass, null);
}
/**
* Return the requested probably initialized and wired RAP session
* singleton.
*
* @param singletonClass
* the class to create a RAP session based singleton
* @param initializer
* a optional initializer 'call back' (may be {@code null}
*
* @return the singleton
*/
public static <S> S getInstance(final Class<S> singletonClass, final ISingletonInitializer<S> initializer) {
try {
final S rapSingleton = (S) getInstanceMethod.invoke(sessionSingletonBaseClass, singletonClass);
synchronized (WIRED_RAP_SINGLETONS) {
if (WIRED_RAP_SINGLETONS.put(rapSingleton, Boolean.TRUE) == null) {
if (initializer != null) {
initializer.init(rapSingleton);
}
Wire.instance(rapSingleton).andStart();
}
}
return rapSingleton;
} catch (final Exception e) {
throw new SingletonFailure("Could not instantiate RAP controlled singleton.", e); //$NON-NLS-1$
}
}
}