/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.core.plugin.container;
import java.io.File;
import java.net.URI;
import java.net.URL;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.SystemUtils;
import org.eclipse.core.runtime.internal.adaptor.EclipseLogHook;
import org.eclipse.osgi.baseadaptor.HookConfigurator;
import org.eclipse.osgi.baseadaptor.HookRegistry;
import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.eclipse.osgi.internal.baseadaptor.BaseHookConfigurator;
import org.eclipse.osgi.launch.EquinoxFactory;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.launch.Framework;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.UrlResource;
import org.springframework.util.ResourceUtils;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import com.google.common.io.Resources;
import com.enonic.cms.core.plugin.PluginManager;
public abstract class OsgiContainer
implements Constants, PluginManager
{
private final static Logger LOG = LoggerFactory.getLogger( OsgiContainer.class );
private static final String VFS_CONTENTS_FOLDER = "contents";
private Framework framework;
private BundleInstaller bundleInstaller;
private File tmpDir;
private Map<String, String> createConfigMap()
throws Exception
{
final Map<String, String> map = Maps.newHashMap();
map.put( FRAMEWORK_STORAGE, this.tmpDir.getAbsolutePath() );
map.put( FRAMEWORK_STORAGE_CLEAN, FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT );
map.put( HookRegistry.PROP_HOOK_CONFIGURATORS, BaseHookConfigurator.class.getName() +
"," + DynamicHookConfigurator.class.getName() );
map.put( HookRegistry.PROP_HOOK_CONFIGURATORS_EXCLUDE, EclipseLogHook.class.getName() );
final File installArea = new File( this.tmpDir, "__install" );
installArea.mkdirs();
map.put( "osgi.install.area", installArea.toURI().toString() );
final File frameworkJar = new File( installArea, "framework.jar" );
map.put( "osgi.framework", frameworkJar.toURI().toString() );
copyFrameworkJar( frameworkJar );
return map;
}
@PostConstruct
public final void start()
{
try
{
this.tmpDir = Files.createTempDir();
this.framework = new EquinoxFactory().newFramework( createConfigMap() );
this.framework.start();
this.bundleInstaller = new BundleInstaller( this.framework.getBundleContext() );
start( this.framework.getBundleContext() );
}
catch ( Exception e )
{
LOG.error( "Cannot start container.", e );
}
}
@PreDestroy
public final void stop()
{
try
{
this.framework.stop();
this.framework.waitForStop( 5000 );
FileUtils.deleteDirectory( this.tmpDir );
}
catch ( Exception e )
{
LOG.error( "Cannot stop container correctly.", e );
}
}
protected abstract void start( BundleContext context )
throws Exception;
@Autowired
public final void setHookConfigurator( final HookConfigurator configurator )
{
HookConfiguratorAccessor.getInstance().set( configurator );
}
public final void install( final File file )
{
this.bundleInstaller.install( file );
}
public final void uninstall( final File file )
{
this.bundleInstaller.uninstall( file );
}
private void copyFrameworkJar( final File targetFile )
throws Exception
{
URL location = FrameworkProperties.class.getProtectionDomain().getCodeSource().getLocation();
final String locationFile = location.getFile();
LOG.info( "Location of framework.jar : " + locationFile );
if ( locationFile.endsWith( ".jar!/" ) ) // for IBM Websphere 8.5 Liberty Profile
{
String absolutePath = locationFile.substring( 0, locationFile.length() - 2 );
location = new URL( absolutePath );
}
else if ( ResourceUtils.URL_PROTOCOL_VFS.equals( location.getProtocol() ) ) // JBOSS 7.1.1 VFS
{
final URI uri = ResourceUtils.toURI( location );
final UrlResource urlResource = new UrlResource( uri );
final File file = urlResource.getFile();
String absolutePath = file.getAbsolutePath();
if ( !absolutePath.endsWith( urlResource.getFilename() ) )
{
// removing /contents folder from path and adding unpacked jar to path.
absolutePath =
absolutePath.substring( 0, absolutePath.length() - VFS_CONTENTS_FOLDER.length() ) + urlResource.getFilename();
}
final StringBuilder stringBuilder = new StringBuilder( "file:/" );
if ( !SystemUtils.IS_OS_WINDOWS ) // windows already has one slash in path like /c:/Program Files/....
{
stringBuilder.append( '/' );
}
stringBuilder.append( absolutePath );
location = new URL( stringBuilder.toString() );
}
LOG.info( "Copying " + location.toString() + " to " + targetFile.toString() );
Files.copy( Resources.newInputStreamSupplier( location ), targetFile );
}
}