/*******************************************************************************
* 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.project.core.modules;
import com.liferay.ide.core.util.FileListing;
import com.liferay.ide.project.core.ProjectCore;
import com.liferay.ide.project.core.util.TargetPlatformUtil;
import com.liferay.ide.server.core.portal.PortalRuntime;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.wst.server.core.IServer;
/**
* @author Lovett Li
*/
public class ServiceWrapperCommand
{
private final IServer _server;
private String _serviceWrapperName;
public ServiceWrapperCommand( IServer server )
{
_server = server;
}
public ServiceWrapperCommand( IServer _server, String _serviceWrapperName )
{
this._server = _server;
this._serviceWrapperName = _serviceWrapperName;
}
public ServiceContainer execute() throws Exception
{
if( _server == null )
{
return getServiceWrapperFromTargetPlatform();
}
else
{
Map<String, String[]> dynamicServiceWrappers = getDynamicServiceWrapper();
ServiceContainer result;
if( _serviceWrapperName == null )
{
result =
new ServiceContainer( Arrays.asList( dynamicServiceWrappers.keySet().toArray( new String[0] ) ) );
}
else
{
String[] wrapperBundle = dynamicServiceWrappers.get( _serviceWrapperName );
result = new ServiceContainer( wrapperBundle[0], wrapperBundle[1] ,wrapperBundle[2] );
}
return result;
}
}
private File checkStaticWrapperFile() throws IOException
{
final URL url =
FileLocator.toFileURL( ProjectCore.getDefault().getBundle().getEntry( "OSGI-INF/wrappers-static.json" ) );
final File servicesFile = new File( url.getFile() );
if( servicesFile.exists() )
{
return servicesFile;
}
throw new FileNotFoundException( "can't find static services file wrappers-static.json" );
}
private Map<String,String[]> getDynamicServiceWrapper() throws IOException
{
final IPath bundleLibPath =
( (PortalRuntime) _server.getRuntime().loadAdapter( PortalRuntime.class, null ) ).getAppServerLibGlobalDir();
final IPath bundleServerPath =
( (PortalRuntime) _server.getRuntime().loadAdapter( PortalRuntime.class, null ) ).getAppServerDir();
final Map<String, String[]> map = new LinkedHashMap<>();
List<File> libFiles;
File portalkernelJar = null;
try
{
libFiles = FileListing.getFileListing( new File( bundleLibPath.toOSString() ) );
for( File lib : libFiles )
{
if( lib.exists() && lib.getName().endsWith( "portal-kernel.jar" ) )
{
portalkernelJar = lib;
break;
}
}
libFiles = FileListing.getFileListing( new File( bundleServerPath.append( "../osgi" ).toOSString() ) );
libFiles.add( portalkernelJar );
if( !libFiles.isEmpty() )
{
for( File lib : libFiles )
{
if( lib.getName().endsWith( ".lpkg" ) )
{
try(JarFile jar = new JarFile( lib ))
{
Enumeration<JarEntry> enu = jar.entries();
while( enu.hasMoreElements() )
{
JarInputStream jarInputStream = null;
try
{
JarEntry entry = enu.nextElement();
String name = entry.getName();
if( name.contains( ".api-" ) )
{
JarEntry jarentry = jar.getJarEntry( name );
InputStream inputStream = jar.getInputStream( jarentry );
jarInputStream = new JarInputStream( inputStream );
JarEntry nextJarEntry;
while( ( nextJarEntry = jarInputStream.getNextJarEntry() ) != null )
{
String entryName = nextJarEntry.getName();
getServiceWrapperList( map, entryName, jarInputStream );
}
}
}
catch( Exception e )
{
}
finally
{
if( jarInputStream != null )
{
jarInputStream.close();
}
}
}
}
}
else if( lib.getName().endsWith( "api.jar" ) || lib.getName().equals( "portal-kernel.jar" ) )
{
JarInputStream jarinput = null;
try(JarFile jar = new JarFile( lib ))
{
jarinput = new JarInputStream( new FileInputStream( lib ) );
Enumeration<JarEntry> enu = jar.entries();
while( enu.hasMoreElements() )
{
JarEntry entry = enu.nextElement();
String name = entry.getName();
getServiceWrapperList( map, name, jarinput );
}
}
catch( IOException e )
{
}
finally
{
if( jarinput != null )
{
jarinput.close();
}
}
}
}
}
}
catch( FileNotFoundException e )
{
}
return map;
}
private void getServiceWrapperList( final Map<String,String[]> wrapperMap, String name, JarInputStream jarInputStream )
{
if( name.endsWith( "ServiceWrapper.class" ) && !( name.contains( "$" ) ) )
{
name = name.replaceAll( "\\\\", "." ).replaceAll( "/", "." );
name = name.substring( 0, name.lastIndexOf( "." ) );
Attributes mainAttributes = jarInputStream.getManifest().getMainAttributes();
String bundleName = mainAttributes.getValue( "Bundle-SymbolicName" );
String version = mainAttributes.getValue( "Bundle-Version" );
String group = "";
if( bundleName.equals( "com.liferay.portal.kernel" ) )
{
group = "com.liferay.portal";
}
else
{
int ordinalIndexOf = StringUtils.ordinalIndexOf( bundleName, ".", 2 );
if( ordinalIndexOf != -1 )
{
group = bundleName.substring( 0, ordinalIndexOf );
}
}
wrapperMap.put( name, new String[] { group, bundleName, version } );
}
}
private ServiceContainer getServiceWrapperFromTargetPlatform() throws Exception
{
ServiceContainer result;
if( _serviceWrapperName == null )
{
result = TargetPlatformUtil.getServiceWrapperList();
}
else
{
result = TargetPlatformUtil.getServiceWrapperBundle( _serviceWrapperName );
}
return result;
}
private void updateServiceWrapperStaticFile( final Map<String, String[]> wrappers ) throws Exception
{
final File wrappersFile = checkStaticWrapperFile();
final ObjectMapper mapper = new ObjectMapper();
final Job job = new WorkspaceJob( "Update ServiceWrapper static file...")
{
@Override
public IStatus runInWorkspace( IProgressMonitor monitor )
{
try
{
mapper.writeValue( wrappersFile, wrappers );
}
catch( IOException e )
{
return Status.CANCEL_STATUS;
}
return Status.OK_STATUS;
}
};
job.schedule();
}
}