/*******************************************************************************
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
*******************************************************************************/
package com.liferay.ide.server.core;
import com.liferay.ide.core.LiferayCore;
import com.liferay.ide.core.util.CoreUtil;
import com.liferay.ide.core.util.StringPool;
import com.liferay.ide.sdk.core.ISDKListener;
import com.liferay.ide.sdk.core.SDKManager;
import com.liferay.ide.server.core.portal.AbstractPortalBundleFactory;
import com.liferay.ide.server.core.portal.BundleDeployer;
import com.liferay.ide.server.core.portal.PortalBundle;
import com.liferay.ide.server.core.portal.PortalBundleFactory;
import com.liferay.ide.server.core.portal.PortalRuntime;
import com.liferay.ide.server.remote.IRemoteServer;
import com.liferay.ide.server.remote.IServerManagerConnection;
import com.liferay.ide.server.remote.ServerManagerConnection;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.wst.server.core.IRuntime;
import org.eclipse.wst.server.core.IRuntimeLifecycleListener;
import org.eclipse.wst.server.core.IRuntimeType;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.IServerLifecycleListener;
import org.eclipse.wst.server.core.IServerListener;
import org.eclipse.wst.server.core.IServerType;
import org.eclipse.wst.server.core.ServerCore;
import org.eclipse.wst.server.core.ServerEvent;
import org.eclipse.wst.server.core.internal.Base;
import org.eclipse.wst.server.core.internal.IMemento;
import org.eclipse.wst.server.core.internal.XMLMemento;
import org.eclipse.wst.server.core.model.RuntimeDelegate;
import org.osgi.framework.BundleContext;
import org.osgi.service.prefs.BackingStoreException;
/**
* The activator class controls the plugin life cycle
*
* @author Greg Amerson
* @author Simon Jiang
*/
@SuppressWarnings( "restriction" )
public class LiferayServerCore extends Plugin
{
public static final String BUNDLE_OUTPUT_ERROR_MARKER_TYPE = "com.liferay.ide.server.core.BundleOutputErrorMarker";
private static Map<String, BundleDeployer> bundleDeployers;
private static Map<String, IServerManagerConnection> connections = null;
// The shared instance
private static LiferayServerCore plugin;
// The plugin ID
public static final String PLUGIN_ID = "com.liferay.ide.server.core"; //$NON-NLS-1$
private static IPluginPublisher[] pluginPublishers = null;
private static PortalBundleFactory[] portalBundleFactories;
private static IRuntimeDelegateValidator[] runtimeDelegateValidators;
private static ILiferayRuntimeStub[] runtimeStubs;
public static IStatus createErrorStatus( Exception e )
{
return error( e.getMessage(), e );
}
public static IStatus createErrorStatus( String pluginId, String msg )
{
return new Status( IStatus.ERROR, pluginId, msg );
}
public static IStatus createErrorStatus( String pluginId, String msg, Throwable e )
{
return new Status( IStatus.ERROR, pluginId, msg, e );
}
public static IStatus createWarningStatus( String message )
{
return new Status( IStatus.WARNING, PLUGIN_ID, message );
}
public static IStatus createWarningStatus( String message, String id )
{
return new Status( IStatus.WARNING, id, message );
}
public static IStatus createWarningStatus( String message, String id, Exception e )
{
return new Status( IStatus.WARNING, id, message, e );
}
public static IStatus error( String msg )
{
return createErrorStatus( PLUGIN_ID, msg );
}
public static IStatus error( String msg, Throwable t )
{
return new Status( IStatus.ERROR, PLUGIN_ID, msg, t );
}
public static BundleDeployer getBundleDeployer( final IServer server )
{
BundleDeployer retval = null;
if( bundleDeployers == null )
{
bundleDeployers = new HashMap<>();
ServerCore.addServerLifecycleListener( new IServerLifecycleListener()
{
@Override
public void serverAdded( IServer server )
{
}
@Override
public void serverChanged( IServer server )
{
}
@Override
public void serverRemoved( IServer s )
{
if( server.equals( s ) )
{
BundleDeployer deployer = bundleDeployers.get( server.getId() );
if( deployer != null )
{
deployer = null;
bundleDeployers.remove( server.getId() );
}
}
}
});
}
retval = bundleDeployers.get( server.getId() );
if( retval != null )
{
if( !retval.ping() )
{
retval = null;
}
}
if( retval == null )
{
PortalRuntime runtime = (PortalRuntime) server.getRuntime().loadAdapter( PortalRuntime.class, null );
retval = new BundleDeployer( runtime.getPortalBundle().getJmxRemotePort() );
bundleDeployers.put( server.getId(), retval );
server.addServerListener( new IServerListener()
{
@Override
public void serverChanged( ServerEvent event )
{
bundleDeployers.remove( server.getId() );
}
});
}
return retval;
}
/**
* Returns the shared instance
*
* @return the shared instance
*/
public static LiferayServerCore getDefault()
{
return plugin;
}
public static URL getPluginEntry( String path )
{
return getDefault().getBundle().getEntry( path );
}
public static IPluginPublisher getPluginPublisher( String facetId, String runtimeTypeId )
{
if( CoreUtil.isNullOrEmpty( facetId ) || CoreUtil.isNullOrEmpty( runtimeTypeId ) )
{
return null;
}
IPluginPublisher retval = null;
IPluginPublisher[] publishers = getPluginPublishers();
if( publishers != null && publishers.length > 0 )
{
for( IPluginPublisher publisher : publishers )
{
if( publisher != null && facetId.equals( publisher.getFacetId() ) &&
runtimeTypeId.equals( publisher.getRuntimeTypeId() ) )
{
retval = publisher;
break;
}
}
}
return retval;
}
public static IPluginPublisher[] getPluginPublishers()
{
if( pluginPublishers == null )
{
IConfigurationElement[] elements =
Platform.getExtensionRegistry().getConfigurationElementsFor( IPluginPublisher.ID );
try
{
List<IPluginPublisher> deployers = new ArrayList<IPluginPublisher>();
for( IConfigurationElement element : elements )
{
final Object o = element.createExecutableExtension( "class" ); //$NON-NLS-1$
if( o instanceof AbstractPluginPublisher )
{
AbstractPluginPublisher pluginDeployer = (AbstractPluginPublisher) o;
pluginDeployer.setFacetId( element.getAttribute( "facetId" ) ); //$NON-NLS-1$
pluginDeployer.setRuntimeTypeId( element.getAttribute( "runtimeTypeId" ) ); //$NON-NLS-1$
deployers.add( pluginDeployer );
}
}
pluginPublishers = deployers.toArray( new IPluginPublisher[0] );
}
catch( Exception e )
{
logError( "Unable to get plugin deployer extensions", e ); //$NON-NLS-1$
}
}
return pluginPublishers;
}
public static PortalBundle newPortalBundle( final IPath bundlePath )
{
PortalBundleFactory[] factories = getPortalBundleFactories();
if( factories != null )
{
for( PortalBundleFactory portalBundleFactory : factories )
{
IPath path = portalBundleFactory.canCreateFromPath( bundlePath );
if( path != null )
{
return portalBundleFactory.create( path );
}
}
}
return null;
}
public static PortalBundleFactory[] getPortalBundleFactories()
{
if( portalBundleFactories == null )
{
final IConfigurationElement[] elements =
Platform.getExtensionRegistry().getConfigurationElementsFor( PortalBundleFactory.EXTENSION_ID );
try
{
final List<PortalBundleFactory> bundleFactories = new ArrayList<PortalBundleFactory>();
for( IConfigurationElement element : elements )
{
final Object o = element.createExecutableExtension( "class" );
if( o instanceof PortalBundleFactory )
{
AbstractPortalBundleFactory portalBundleFactory = (AbstractPortalBundleFactory) o;
portalBundleFactory.setBundleFactoryType( element.getAttribute( "type" ) );
bundleFactories.add( portalBundleFactory );
}
}
portalBundleFactories = bundleFactories.toArray( new PortalBundleFactory[0] );
}
catch( Exception e )
{
logError( "Unable to get PortalBundleFactory extensions", e ); //$NON-NLS-1$
}
}
return portalBundleFactories;
}
public static PortalBundleFactory getPortalBundleFactories(final String type)
{
PortalBundleFactory[] factories = getPortalBundleFactories();
if ( factories != null )
{
for( PortalBundleFactory portalBundleFactory : factories )
{
if ( portalBundleFactory.getType().equals( type ))
{
return portalBundleFactory;
}
}
}
return null;
}
public static PortalLaunchParticipant[] getPortalLaunchParticipants()
{
PortalLaunchParticipant[] retval = null;
final IConfigurationElement[] elements =
Platform.getExtensionRegistry().getConfigurationElementsFor(
"com.liferay.ide.server.core.portalLaunchParticipants" );
try
{
final List<PortalLaunchParticipant> participants = new ArrayList<PortalLaunchParticipant>();
for( IConfigurationElement element : elements )
{
final Object o = element.createExecutableExtension( "class" ); //$NON-NLS-1$
if( o instanceof PortalLaunchParticipant )
{
PortalLaunchParticipant participant = (PortalLaunchParticipant) o;
participants.add( participant );
}
}
retval = participants.toArray( new PortalLaunchParticipant[0] );
}
catch( Exception e )
{
logError( "Unable to get portal launch participants", e ); //$NON-NLS-1$
}
return retval;
}
public static URL getPortalSupportLibURL()
{
try
{
return FileLocator.toFileURL( LiferayServerCore.getPluginEntry( "/portal-support/portal-support.jar" ) );
}
catch( IOException e )
{
}
return null;
}
/**
* Return the install location preference.
*
* @param key a runtime type id
* @return the install location
*/
public static String getPreference( String key )
{
return InstanceScope.INSTANCE.getNode( PLUGIN_ID ).get( key, "" );
}
public static IServerManagerConnection getRemoteConnection( final IRemoteServer server )
{
IServerManagerConnection retval = null;
if( connections == null )
{
connections = new HashMap<String, IServerManagerConnection>();
}
if( server != null )
{
IServerManagerConnection service = connections.get( server.getId() );
if( service == null )
{
service = new ServerManagerConnection();
updateConnectionSettings( server, service );
connections.put( server.getId(), service );
}
else
{
updateConnectionSettings( server, service );
}
retval = service;
}
return retval;
}
public static IRuntimeDelegateValidator[] getRuntimeDelegateValidators()
{
if( runtimeDelegateValidators == null )
{
IConfigurationElement[] elements =
Platform.getExtensionRegistry().getConfigurationElementsFor( IRuntimeDelegateValidator.ID );
try
{
List<IRuntimeDelegateValidator> validators = new ArrayList<IRuntimeDelegateValidator>();
for( IConfigurationElement element : elements )
{
final Object o = element.createExecutableExtension( "class" ); //$NON-NLS-1$
final String runtimeTypeId = element.getAttribute( "runtimeTypeId" ); //$NON-NLS-1$
if( o instanceof AbstractRuntimeDelegateValidator )
{
AbstractRuntimeDelegateValidator validator = (AbstractRuntimeDelegateValidator) o;
validator.setRuntimeTypeId( runtimeTypeId );
validators.add( validator );
}
}
runtimeDelegateValidators = validators.toArray( new IRuntimeDelegateValidator[0] );
}
catch( Exception e )
{
logError( "Unable to get IRuntimeDelegateValidator extensions", e ); //$NON-NLS-1$
}
}
return runtimeDelegateValidators;
}
public static ILiferayRuntimeStub getRuntimeStub( String stubTypeId )
{
ILiferayRuntimeStub retval = null;
ILiferayRuntimeStub[] stubs = getRuntimeStubs();
if( !CoreUtil.isNullOrEmpty( stubs ) )
{
for( ILiferayRuntimeStub stub : stubs )
{
if( stub.getRuntimeStubTypeId().equals( stubTypeId ) )
{
retval = stub;
break;
}
}
}
return retval;
}
public static ILiferayRuntimeStub[] getRuntimeStubs()
{
if( runtimeStubs == null )
{
IConfigurationElement[] elements =
Platform.getExtensionRegistry().getConfigurationElementsFor( ILiferayRuntimeStub.EXTENSION_ID );
if( !CoreUtil.isNullOrEmpty( elements ) )
{
List<ILiferayRuntimeStub> stubs = new ArrayList<ILiferayRuntimeStub>();
for( IConfigurationElement element : elements )
{
String runtimeTypeId = element.getAttribute( ILiferayRuntimeStub.RUNTIME_TYPE_ID );
String name = element.getAttribute( ILiferayRuntimeStub.NAME );
boolean isDefault = Boolean.parseBoolean( element.getAttribute( ILiferayRuntimeStub.DEFAULT ) );
try
{
LiferayRuntimeStub stub = new LiferayRuntimeStub();
stub.setRuntimeTypeId( runtimeTypeId );
stub.setName( name );
stub.setDefault( isDefault );
stubs.add( stub );
}
catch( Exception e )
{
logError( "Could not create liferay runtime stub.", e ); //$NON-NLS-1$
}
}
runtimeStubs = stubs.toArray( new ILiferayRuntimeStub[0] );
}
}
return runtimeStubs;
}
public static IPath getTempLocation( String prefix, String fileName )
{
return getDefault().getStateLocation().append( "tmp" ).append( //$NON-NLS-1$
prefix + "/" + System.currentTimeMillis() + ( CoreUtil.isNullOrEmpty( fileName ) ? StringPool.EMPTY : "/" + fileName ) ); //$NON-NLS-1$ //$NON-NLS-2$
}
public static IStatus info( String msg )
{
return new Status( IStatus.INFO, PLUGIN_ID, msg );
}
public static void logError( Exception e )
{
getDefault().getLog().log( new Status( IStatus.ERROR, PLUGIN_ID, e.getMessage(), e ) );
}
public static void logError( IStatus status )
{
getDefault().getLog().log( status );
}
public static void logError( String msg )
{
logError( error( msg ) );
}
public static void logError( String msg, Throwable e )
{
getDefault().getLog().log( new Status( IStatus.ERROR, PLUGIN_ID, msg, e ) );
}
public static void logError( Throwable t )
{
getDefault().getLog().log( new Status( IStatus.ERROR, PLUGIN_ID, t.getMessage(), t ) );
}
public static void logInfo( IStatus status )
{
getDefault().getLog().log( status );
}
public static void logInfo( String msg )
{
logInfo( info( msg ) );
}
public static void setPreference( String key, String value )
{
try
{
InstanceScope.INSTANCE.getNode( PLUGIN_ID ).put( key, value );
InstanceScope.INSTANCE.getNode( PLUGIN_ID ).flush();
}
catch( BackingStoreException e )
{
LiferayServerCore.logError( "Unable to save preference", e );
}
}
public static void updateConnectionSettings( IRemoteServer server )
{
updateConnectionSettings( server, getRemoteConnection( server ) );
}
public static void updateConnectionSettings( IRemoteServer server, IServerManagerConnection remoteConnection )
{
remoteConnection.setHost( server.getHost() );
remoteConnection.setHttpPort( server.getHTTPPort() );
remoteConnection.setManagerContextPath( server.getServerManagerContextPath() );
remoteConnection.setUsername( server.getUsername() );
remoteConnection.setPassword( server.getPassword() );
}
public static IStatus validateRuntimeDelegate( RuntimeDelegate runtimeDelegate )
{
if( runtimeDelegate.getRuntime().isStub() )
{
return Status.OK_STATUS;
}
String runtimeTypeId = runtimeDelegate.getRuntime().getRuntimeType().getId();
IRuntimeDelegateValidator[] validators = getRuntimeDelegateValidators();
if( !CoreUtil.isNullOrEmpty( validators ) )
{
for( IRuntimeDelegateValidator validator : validators )
{
if( runtimeTypeId.equals( validator.getRuntimeTypeId() ) )
{
IStatus status = validator.validateRuntimeDelegate( runtimeDelegate );
if( !status.isOK() )
{
return status;
}
}
}
}
return Status.OK_STATUS;
}
private IRuntimeLifecycleListener runtimeLifecycleListener;
private ISDKListener sdkListener;
private IServerLifecycleListener serverLifecycleListener;
/**
* The constructor
*/
public LiferayServerCore()
{
}
private boolean addRuntimeToMemento( IRuntime runtime, IMemento memento )
{
if( runtime instanceof Base )
{
final Base base = (Base) runtime;
try
{
final Method save = Base.class.getDeclaredMethod( "save", IMemento.class );
if( save != null )
{
save.setAccessible( true );
save.invoke( base, memento );
}
return true;
}
catch( Exception e )
{
LiferayServerCore.logError( "Unable to add runtime to memento", e );
}
}
return false;
}
private boolean addServerToMemento( IServer server, IMemento memento )
{
if( server instanceof Base )
{
final Base base = (Base) server;
try
{
final Method save = Base.class.getDeclaredMethod( "save", IMemento.class );
if( save != null )
{
save.setAccessible( true );
save.invoke( base, memento );
}
return true;
}
catch( Exception e )
{
LiferayServerCore.logError( "Unable to add server to memento", e );
}
}
return false;
}
private void copyMemento( IMemento from, IMemento to )
{
for( String name : from.getNames() )
{
to.putString( name, from.getString( name ) );
}
}
private synchronized void saveGlobalRuntimeSettings( IRuntime runtime )
{
final IRuntimeType runtimeType = runtime.getRuntimeType();
if( runtimeType != null && runtimeType.getId().startsWith( "com.liferay" ) )
{
try
{
LiferayCore.GLOBAL_SETTINGS_PATH.toFile().mkdirs();
final File runtimesGlobalFile =
LiferayCore.GLOBAL_SETTINGS_PATH.append( "runtimes.xml" ).toFile();
final Set<IMemento> existing = new HashSet<IMemento>();
if( runtimesGlobalFile.exists() )
{
try
{
final IMemento existingMemento =
XMLMemento.loadMemento( new FileInputStream( runtimesGlobalFile ) );
if( existingMemento != null )
{
final IMemento[] children = existingMemento.getChildren( "runtime" );
if( ! CoreUtil.isNullOrEmpty( children ) )
{
for( IMemento child : children )
{
final IPath loc = Path.fromPortableString( child.getString( "location" ) );
if( loc != null && loc.toFile().exists() )
{
boolean duplicate =
ServerCore.findRuntime( child.getString( "id" ) ) != null;
if( ! duplicate )
{
existing.add( child );
}
}
}
}
}
}
catch( Exception e )
{
}
}
final Map<String, IMemento> mementos = new HashMap<String, IMemento>();
final XMLMemento runtimeMementos = XMLMemento.createWriteRoot( "runtimes" );
for( IMemento exist : existing )
{
final IMemento copy = runtimeMementos.createChild( "runtime" );
copyMemento( exist, copy );
mementos.put( copy.getString( "id" ), copy );
}
for( IRuntime r : ServerCore.getRuntimes() )
{
if( mementos.get( r.getId() ) == null && r.getRuntimeType() != null )
{
final IMemento rMemento = runtimeMementos.createChild( "runtime" );
if( addRuntimeToMemento( r, rMemento ) )
{
mementos.put( r.getId(), rMemento );
}
}
}
final FileOutputStream fos = new FileOutputStream( runtimesGlobalFile );
runtimeMementos.save( fos );
}
catch( Exception e )
{
LiferayServerCore.logError( "Unable to save global runtime settings", e );
}
}
}
private synchronized void saveGlobalServerSettings( IServer server )
{
final IServerType serverType = server.getServerType();
if( serverType != null && serverType.getId().startsWith( "com.liferay" ) )
{
try
{
LiferayCore.GLOBAL_SETTINGS_PATH.toFile().mkdirs();
final File globalServersFile = LiferayCore.GLOBAL_SETTINGS_PATH.append( "servers.xml" ).toFile();
final Set<IMemento> existing = new HashSet<IMemento>();
if( globalServersFile.exists() )
{
try
{
final IMemento existingMemento =
XMLMemento.loadMemento( new FileInputStream( globalServersFile ) );
if( existingMemento != null )
{
final IMemento[] children = existingMemento.getChildren( "server" );
if( ! CoreUtil.isNullOrEmpty( children ) )
{
for( IMemento child : children )
{
final boolean duplicate =
ServerCore.findServer( child.getString( "id" ) ) != null;
if( ! duplicate )
{
existing.add( child );
}
}
}
}
}
catch( Exception e )
{
}
}
final Map<String, IMemento> mementos = new HashMap<String, IMemento>();
final XMLMemento serverMementos = XMLMemento.createWriteRoot( "servers" );
for( IMemento exist : existing )
{
final IMemento copy = serverMementos.createChild( "server" );
copyMemento( exist, copy );
mementos.put( copy.getString( "id" ), copy );
}
for( IServer s : ServerCore.getServers() )
{
if( mementos.get( s.getId() ) == null && s.getServerType() != null )
{
final IMemento sMemento = serverMementos.createChild( "server" );
if( addServerToMemento( s, sMemento ) )
{
mementos.put( s.getId(), sMemento );
}
}
}
if( mementos.size() > 0 )
{
final FileOutputStream fos = new FileOutputStream( globalServersFile );
serverMementos.save( fos );
}
}
catch( Exception e )
{
LiferayServerCore.logError( "Unable to save global server settings", e );
}
}
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext )
*/
@Override
public void start( BundleContext context ) throws Exception
{
super.start( context );
plugin = this;
this.runtimeLifecycleListener = new IRuntimeLifecycleListener()
{
@Override
public void runtimeAdded( IRuntime runtime )
{
saveGlobalRuntimeSettings( runtime );
}
@Override
public void runtimeChanged( IRuntime runtime )
{
saveGlobalRuntimeSettings( runtime );
}
@Override
public void runtimeRemoved( IRuntime runtime )
{
saveGlobalRuntimeSettings( runtime );
}
};
this.serverLifecycleListener = new IServerLifecycleListener()
{
@Override
public void serverAdded( IServer server )
{
saveGlobalServerSettings( server );
}
@Override
public void serverChanged( IServer server )
{
saveGlobalServerSettings( server );
}
@Override
public void serverRemoved( IServer server )
{
saveGlobalServerSettings( server );
if( connections.get( server.getId() ) != null )
{
connections.put( server.getId(), null );
}
}
};
ServerCore.addRuntimeLifecycleListener( this.runtimeLifecycleListener );
ServerCore.addServerLifecycleListener( this.serverLifecycleListener );
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext )
*/
@Override
public void stop( BundleContext context ) throws Exception
{
plugin = null;
super.stop( context );
SDKManager.getInstance().removeSDKListener( this.sdkListener );
ServerCore.removeRuntimeLifecycleListener( runtimeLifecycleListener );
ServerCore.removeServerLifecycleListener( serverLifecycleListener );
}
}