/*******************************************************************************
* 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.ui.internal.servlet;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.text.MessageFormat;
import org.eclipse.core.runtime.*;
import org.eclipse.rwt.internal.*;
import org.eclipse.rwt.internal.engine.RWTServletContextListener;
import org.eclipse.rwt.internal.lifecycle.*;
import org.eclipse.rwt.internal.resources.ResourceManager;
import org.eclipse.rwt.internal.resources.ResourceRegistry;
import org.eclipse.rwt.internal.service.*;
import org.eclipse.rwt.internal.theme.ResourceLoader;
import org.eclipse.rwt.internal.theme.ThemeManager;
import org.eclipse.rwt.lifecycle.PhaseListener;
import org.eclipse.rwt.resources.IResource;
import org.eclipse.rwt.service.ISettingStoreFactory;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.preferences.WorkbenchFileSettingStoreFactory;
import org.osgi.framework.Bundle;
/**
* The underlying W4Toolkit runtime engine expects some configuration
* infos read by the IEngineConfig implementation. We abuse the
* <code>EngineConfigWrapper</code> to fake an appropriate environment
* for the library.
*/
// TODO: [fappel] clean replacement mechanism that is anchored in W4Toolkit core
final class EngineConfigWrapper implements IEngineConfig {
private final static String FOLDER
= EngineConfigWrapper.class.getPackage().getName().replace( '.', '/' );
// path to a w4toolkit configuration file on the classpath
private final static String CONFIG = FOLDER +"/config.xml";
// extension point id for adapter factory registration
private static final String ID_ADAPTER_FACTORY
= "org.eclipse.rap.ui.adapterfactory";
// extension point id for entry point registration
private static final String ID_ENTRY_POINT
= "org.eclipse.rap.ui.entrypoint";
// extension point id for custom theme registration
private static final String ID_THEMES
= "org.eclipse.rap.ui.themes";
// extension point id for custom themeable widget registration
private static final String ID_THEMEABLE_WIDGETS
= "org.eclipse.rap.ui.themeableWidgets";
// extension point id for phase listener registration
private static final String ID_PHASE_LISTENER
= "org.eclipse.rap.ui.phaselistener";
// extension point id for registration of resources (i.e. javascript)
// which needed to be loaded at page startup
private static final String ID_RESOURCES
= "org.eclipse.rap.ui.resources";
// extension point id for registration of a setting store factories
private static final String ID_SETTING_STORES
= "org.eclipse.rap.ui.settingstores";
private final EngineConfig engineConfig;
EngineConfigWrapper() {
engineConfig = new EngineConfig( findContextPath().toString() );
registerPhaseListener();
registerRWTLifeCycle();
registerResourceManagerFactory();
registerSettingStoreFactory();
registerWorkbenchEntryPoint();
registerThemeableWidgets();
registerThemes();
registerFactories();
registerResources();
registerLifeCycleServiceHandlerConfigurer();
registerUICallBackServiceHandler();
}
public File getClassDir() {
return engineConfig.getClassDir();
}
public File getConfigFile() {
File result = engineConfig.getConfigFile();
if( !result.exists() ) {
result.getParentFile().mkdirs();
try {
result.createNewFile();
createConfiguration( result );
} catch( final IOException shouldNotHappen ) {
throw new RuntimeException( shouldNotHappen );
}
}
return result;
}
public File getLibDir() {
return engineConfig.getLibDir();
}
public File getServerContextDir() {
return engineConfig.getServerContextDir();
}
public File getSourceDir() {
return engineConfig.getSourceDir();
}
//////////////////
// helping methods
private static void registerPhaseListener() {
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint point = registry.getExtensionPoint( ID_PHASE_LISTENER );
IConfigurationElement[] elements = point.getConfigurationElements();
for( int i = 0; i < elements.length; i++ ) {
try {
PhaseListener listener
= ( PhaseListener )elements[ i ].createExecutableExtension( "class" );
PhaseListenerRegistry.add( listener );
} catch( final CoreException ce ) {
WorkbenchPlugin.getDefault().getLog().log( ce.getStatus() );
}
}
}
private static void registerResourceManagerFactory() {
ResourceManager.register( new ResourceManagerFactory() );
}
private static void registerSettingStoreFactory() {
// determine which factory to use via an environment setting / config.ini
ISettingStoreFactory result = null;
String factoryId
= System.getProperty( RWTServletContextListener.SETTING_STORE_FACTORY_PARAM );
if( factoryId != null ) {
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint point = registry.getExtensionPoint( ID_SETTING_STORES );
IConfigurationElement[] elements = point.getConfigurationElements();
for( int i = 0; i < elements.length; i++ ) {
String id = elements[ i ].getAttribute( "id" );
if( factoryId.equals( id ) ) {
try {
Object obj = elements[ i ].createExecutableExtension( "class" );
if( obj instanceof ISettingStoreFactory ) {
result = ( ISettingStoreFactory )obj;
}
} catch( CoreException cex ) {
WorkbenchPlugin.log( cex.getStatus() );
}
}
}
if( result == null ) {
String msg = "Warning: could not find the factory with id '"
+ factoryId
+ "' in org.eclipse.rap.ui.settingstores";
WorkbenchPlugin.log( WorkbenchPlugin.getStatus( new Throwable( msg ) ) );
}
}
if( result == null ) {
result = new WorkbenchFileSettingStoreFactory(); // default
}
SettingStoreManager.register( result );
}
private static void registerFactories() {
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint point = registry.getExtensionPoint( ID_ADAPTER_FACTORY );
IConfigurationElement[] elements = point.getConfigurationElements();
for( int i = 0; i < elements.length; i++ ) {
String contributorName = elements[ i ].getContributor().getName();
String factoryName = elements[ i ].getAttribute( "factoryClass" );
String adaptableName = elements[ i ].getAttribute( "adaptableClass" );
try {
Bundle bundle = Platform.getBundle( contributorName );
Class factoryClass = bundle.loadClass( factoryName );
Class adaptableClass = bundle.loadClass( adaptableName );
AdapterFactoryRegistry.add( factoryClass, adaptableClass );
} catch( final Throwable thr ) {
String text = "Could not register adapter factory ''{0}'' "
+ "for the adapter type ''{1}''.";
Object[] param = new Object[] { factoryName, adaptableName};
String msg = MessageFormat.format( text, param );
Status status = new Status( IStatus.ERROR,
contributorName,
IStatus.OK,
msg,
thr );
WorkbenchPlugin.getDefault().getLog().log( status );
}
}
}
private static void registerWorkbenchEntryPoint() {
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint point = registry.getExtensionPoint( ID_ENTRY_POINT );
IConfigurationElement[] elements = point.getConfigurationElements();
for( int i = 0; i < elements.length; i++ ) {
String contributorName = elements[ i ].getContributor().getName();
String className = elements[ i ].getAttribute( "class" );
String parameter = elements[ i ].getAttribute( "parameter" );
String id = elements[ i ].getAttribute( "id" );
try {
Bundle bundle = Platform.getBundle( contributorName );
Class clazz = bundle.loadClass( className );
EntryPointManager.register( parameter, clazz );
EntryPointExtension.bind( id, parameter );
} catch( final Throwable thr ) {
String text = "Could not register entry point ''{0}'' "
+ "with request startup parameter ''{1}''.";
Object[] param = new Object[] { className, parameter };
String msg = MessageFormat.format( text, param );
IStatus status = new Status( IStatus.ERROR,
contributorName,
IStatus.OK,
msg,
thr );
WorkbenchPlugin.getDefault().getLog().log( status );
}
}
}
private static void registerThemeableWidgets() {
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint ep = registry.getExtensionPoint( ID_THEMEABLE_WIDGETS );
IConfigurationElement[] widgetExts = ep.getConfigurationElements();
for( int i = 0; i < widgetExts.length; i++ ) {
String contributorName = widgetExts[ i ].getContributor().getName();
String widgetClass = widgetExts[ i ].getAttribute( "class" );
try {
final Bundle bundle = Platform.getBundle( contributorName );
ResourceLoader resLoader = new ResourceLoader() {
public InputStream getResourceAsStream( final String resourceName )
throws IOException
{
InputStream result = null;
URL url = bundle.getResource( resourceName );
if( url != null ) {
result = url.openStream();
}
return result;
}
};
Class widget;
widget = bundle.loadClass( widgetClass );
ThemeManager.getInstance().addThemeableWidget( widget, resLoader );
} catch( final Throwable e ) {
String text = "Could not register themeable widget ''{0}''.";
Object[] param = new Object[] { widgetClass };
String msg = MessageFormat.format( text, param );
Status status = new Status( IStatus.ERROR,
contributorName,
IStatus.OK,
msg,
e );
WorkbenchPlugin.getDefault().getLog().log( status );
// Display startup error in stderr
String reason;
if( e instanceof ClassNotFoundException ) {
reason = "Class not found";
} else {
reason = e.getMessage();
}
System.err.println( "ERROR: " + msg + " Reason: " + reason );
}
}
}
private static void registerThemes() {
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint ep = registry.getExtensionPoint( ID_THEMES );
IConfigurationElement[] elements = ep.getConfigurationElements();
ThemeManager.getInstance().initialize();
for( int i = 0; i < elements.length; i++ ) {
String contributorName = elements[ i ].getContributor().getName();
String themeId = elements[ i ].getAttribute( "id" );
String themeFile = elements[ i ].getAttribute( "file" );
String themeName = elements[ i ].getAttribute( "name" );
try {
final Bundle bundle = Platform.getBundle( contributorName );
ResourceLoader resLoader = new ResourceLoader() {
public InputStream getResourceAsStream( final String resourceName )
throws IOException
{
InputStream result = null;
URL url = bundle.getResource( resourceName );
if( url != null ) {
result = url.openStream();
}
return result;
}
};
ThemeManager.getInstance().registerTheme( themeId,
themeName,
themeFile,
resLoader );
} catch( final Throwable e ) {
String text = "Could not register custom theme ''{0}'' "
+ "from file ''{1}''.";
Object[] param = new Object[] { themeId, themeFile };
String msg = MessageFormat.format( text, param );
Status status = new Status( IStatus.ERROR,
contributorName,
IStatus.OK,
msg,
e );
WorkbenchPlugin.getDefault().getLog().log( status );
// Display startup error in stderr
System.err.println( "ERROR: " + msg + " Reason: " + e.getMessage() );
}
}
}
private static void registerRWTLifeCycle() {
// TODO: [fappel] ugly, ugly, ugly - replace this.
// Create the only valid lifecycle for RAP
try {
Class clazz = LifeCycleFactory.class;
Field field = clazz.getDeclaredField( "globalLifeCycle" );
field.setAccessible( true );
field.set( null, new RWTLifeCycle() );
} catch( final Throwable shouldNotHappen ) {
throw new RuntimeException( shouldNotHappen );
}
}
// determine a faked context directory
private static IPath findContextPath() {
Bundle bundle = Platform.getBundle( PlatformUI.PLUGIN_ID );
IPath stateLocation = Platform.getStateLocation( bundle );
return stateLocation.append( "context" );
}
private static void createConfiguration( final File destination )
throws FileNotFoundException, IOException
{
ClassLoader loader = EngineConfigWrapper.class.getClassLoader();
InputStream is = loader.getResourceAsStream( CONFIG );
try {
OutputStream out = new FileOutputStream( destination );
try {
int character = is.read();
while( character != -1 ) {
out.write( character );
character = is.read();
}
} finally {
out.close();
}
} finally {
is.close();
}
}
private void registerLifeCycleServiceHandlerConfigurer() {
LifeCycleServiceHandler.configurer
= new LifeCycleServiceHandlerConfigurer();
}
private static void registerResources() {
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint point = registry.getExtensionPoint( ID_RESOURCES );
IConfigurationElement[] elements = point.getConfigurationElements();
for( int i = 0; i < elements.length; i++ ) {
try {
IResource resource
= ( IResource )elements[ i ].createExecutableExtension( "class" );
ResourceRegistry.add( resource );
} catch( final CoreException ce ) {
WorkbenchPlugin.getDefault().getLog().log( ce.getStatus() );
}
}
}
private static void registerUICallBackServiceHandler() {
ServiceManager.registerServiceHandler( UICallBackServiceHandler.HANDLER_ID,
new UICallBackServiceHandler() );
}
}