/*******************************************************************************
* Copyright (c) 2002, 2008 Innoopract Informationssysteme GmbH.
* 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:
* Innoopract Informationssysteme GmbH - initial API and implementation
******************************************************************************/
package org.eclipse.rwt.internal.lifecycle;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.rwt.AdapterFactory;
import org.eclipse.rwt.lifecycle.ILifeCycleAdapter;
import org.eclipse.rwt.lifecycle.IWidgetLifeCycleAdapter;
import org.eclipse.swt.internal.widgets.displaykit.DisplayLCAFacade;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Widget;
public final class LifeCycleAdapterFactory implements AdapterFactory {
private static final Class[] ADAPTER_LIST = new Class[] {
ILifeCycleAdapter.class,
};
// Holds the single display life cycle adapter. MUST be created lazily
// because its constructor needs a resource manager to be in place
private static IDisplayLifeCycleAdapter displayAdapter;
// Maps widget classes to their respective life cycle adapters
// Key: Class<Widget>, value: IWidgetLifeCycleAdapter
private static final Map widgetAdapters = new HashMap();
public Object getAdapter( final Object adaptable, final Class adapter ) {
Object result = null;
if( isDisplayLCA( adaptable, adapter ) ) {
result = getDisplayLCA();
} else if( isWidgetLCA( adaptable, adapter ) ) {
result = getWidgetLCA( adaptable.getClass() );
}
return result;
}
public Class[] getAdapterList() {
return ADAPTER_LIST;
}
///////////////////////////////////////////////////////////
// Helping methods to obtain life cycle adapter for display
private boolean isDisplayLCA( final Object adaptable, final Class adapter ) {
return adaptable instanceof Display && adapter == ILifeCycleAdapter.class;
}
private static synchronized ILifeCycleAdapter getDisplayLCA() {
if( displayAdapter == null ) {
displayAdapter = DisplayLCAFacade.getDisplayLCA();
}
return displayAdapter;
}
////////////////////////////////////////////////////////////
// Helping methods to obtain life cycle adapters for widgets
private boolean isWidgetLCA( final Object adaptable, final Class adapter ) {
return adaptable instanceof Widget && adapter == ILifeCycleAdapter.class;
}
private static synchronized ILifeCycleAdapter getWidgetLCA(
final Class clazz )
{
// Note [fappel]: Since this code is performance critical, don't change
// anything without checking it against a profiler.
ILifeCycleAdapter result = ( ILifeCycleAdapter )widgetAdapters.get( clazz );
if( result == null ) {
ILifeCycleAdapter adapter = null;
Class superClass = clazz;
while( !Object.class.equals( superClass ) && adapter == null ) {
adapter = loadWidgetLCA( superClass );
if( adapter == null ) {
superClass = superClass.getSuperclass();
}
}
widgetAdapters.put( clazz, adapter );
result = adapter;
}
if( result == null ) {
String text = "Failed to obtain life cycle adapter for class ''{0}\''.";
Object[] params = new Object[]{ clazz.getName() };
String msg = MessageFormat.format( text, params );
throw new LifeCycleAdapterException( msg );
}
return result;
}
private static IWidgetLifeCycleAdapter loadWidgetLCA( final Class clazz ) {
IWidgetLifeCycleAdapter result = null;
String packageName = clazz.getPackage().getName();
String[] variants = LifeCycleAdapterUtil.getPackageVariants( packageName );
for( int i = 0; result == null && i < variants.length; i++ ) {
StringBuffer buffer = new StringBuffer();
buffer.append( variants[ i ] );
buffer.append( "." );
String simpleClassName = LifeCycleAdapterUtil.getSimpleClassName( clazz );
buffer.append( simpleClassName.toLowerCase() );
buffer.append( "kit." );
buffer.append( simpleClassName );
buffer.append( "LCA" );
String classToLoad = buffer.toString();
ClassLoader loader = clazz.getClassLoader();
try {
Class adapterClass = loader.loadClass( classToLoad );
result = ( IWidgetLifeCycleAdapter )adapterClass.newInstance();
} catch( final Throwable thr ) {
// ignore and try to load next package name variant
}
}
return result;
}
}