/******************************************************************************* * 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; } }