/*******************************************************************************
* 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.tomcat.core.util;
import com.liferay.ide.core.ILiferayConstants;
import com.liferay.ide.core.util.CoreUtil;
import com.liferay.ide.core.util.FileListing;
import com.liferay.ide.core.util.StringPool;
import com.liferay.ide.project.core.util.ProjectUtil;
import com.liferay.ide.server.core.ILiferayRuntime;
import com.liferay.ide.server.core.IPluginPublisher;
import com.liferay.ide.server.core.LiferayServerCore;
import com.liferay.ide.server.tomcat.core.ILiferayTomcatConstants;
import com.liferay.ide.server.tomcat.core.ILiferayTomcatRuntime;
import com.liferay.ide.server.tomcat.core.ILiferayTomcatServer;
import com.liferay.ide.server.tomcat.core.LiferayTomcatPlugin;
import com.liferay.ide.server.tomcat.core.LiferayTomcatRuntime70;
import com.liferay.ide.server.tomcat.core.LiferayTomcatServerBehavior;
import com.liferay.ide.server.util.LiferayPortalValueLoader;
import com.liferay.ide.server.util.ServerUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.jst.server.tomcat.core.internal.TomcatVersionHelper;
import org.eclipse.jst.server.tomcat.core.internal.xml.Factory;
import org.eclipse.jst.server.tomcat.core.internal.xml.server40.Context;
import org.eclipse.jst.server.tomcat.core.internal.xml.server40.ServerInstance;
import org.eclipse.wst.common.project.facet.core.IFacetedProject;
import org.eclipse.wst.common.project.facet.core.IProjectFacet;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.IRuntime;
import org.eclipse.wst.server.core.IRuntimeWorkingCopy;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.IServerListener;
import org.eclipse.wst.server.core.ServerCore;
import org.eclipse.wst.server.core.ServerEvent;
import org.osgi.framework.Version;
/**
* @author Greg Amerson
* @author Simon Jiang
* @author Terry Jia
*/
@SuppressWarnings( "restriction" )
public class LiferayTomcatUtil
{
private static String CONFIG_DIR = "conf"; //$NON-NLS-1$
public static final String CONFIG_TYPE_SERVER = "server"; //$NON-NLS-1$
public static final String CONFIG_TYPE_VERSION = "version"; //$NON-NLS-1$
private static String DEFAULT_PORTAL_CONTEXT_FILE = "ROOT.xml"; //$NON-NLS-1$
private static String DEFAULT_PORTAL_DIR = "/webapps/ROOT"; //$NON-NLS-1$
private static String HOST_NAME = "localhost"; //$NON-NLS-1$
// to read liferay info from manifest need at least version 6.2.0
private static final Version MANIFEST_VERSION_REQUIRED = ILiferayConstants.V620;
private static String SERVICE_NAME = "Catalina"; //$NON-NLS-1$
public static void addRuntimeVMArgments(
List<String> runtimeVMArgs, IPath installPath, IPath configPath, IPath deployPath, boolean isTestEnv,
IServer currentServer, ILiferayTomcatServer liferayTomcatServer )
{
runtimeVMArgs.add( "-Dfile.encoding=UTF8" ); //$NON-NLS-1$
runtimeVMArgs.add( "-Dorg.apache.catalina.loader.WebappClassLoader.ENABLE_CLEAR_REFERENCES=false" ); //$NON-NLS-1$
runtimeVMArgs.add( "-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager" ); //$NON-NLS-1$
ILiferayRuntime runtime = ServerUtil.getLiferayRuntime( currentServer );
Version portalVersion = new Version( getVersion( runtime ) );
if( CoreUtil.compareVersions( portalVersion, LiferayTomcatRuntime70.leastSupportedVersion ) < 0 )
{
runtimeVMArgs.add( "-Djava.security.auth.login.config=\"" + configPath.toOSString() + "/conf/jaas.config\"" ); //$NON-NLS-1$ //$NON-NLS-2$
}
else
{
runtimeVMArgs.add( "-Djava.net.preferIPv4Stack=true" ); //$NON-NLS-1$
}
runtimeVMArgs.add( "-Djava.util.logging.config.file=\"" + installPath.toOSString() + //$NON-NLS-1$
"/conf/logging.properties\"" ); //$NON-NLS-1$
runtimeVMArgs.add( "-Djava.io.tmpdir=\"" + installPath.toOSString() + "/temp\"" ); //$NON-NLS-1$ //$NON-NLS-2$
final boolean useDefaultPortalServerSettings = liferayTomcatServer.getUseDefaultPortalServerSettings();
if ( useDefaultPortalServerSettings )
{
addUserDefaultVMArgs( runtimeVMArgs );
}
else
{
addUserVMArgs( runtimeVMArgs, currentServer, liferayTomcatServer );
File externalPropertiesFile =
getExternalPropertiesFile( installPath, configPath, currentServer, liferayTomcatServer );
runtimeVMArgs.add( "-Dexternal-properties=\"" + externalPropertiesFile.getAbsolutePath() + "\"" );
}
}
private static void addUserDefaultVMArgs( List<String> runtimeVMArgs )
{
String[] memoryArgs = ILiferayTomcatConstants.DEFAULT_MEMORY_ARGS.split( StringPool.SPACE );
if( memoryArgs != null )
{
for( String arg : memoryArgs )
{
runtimeVMArgs.add( arg );
}
}
}
private static void addUserVMArgs(
List<String> runtimeVMArgs, IServer currentServer, ILiferayTomcatServer portalTomcatServer )
{
String[] memoryArgs = ILiferayTomcatConstants.DEFAULT_MEMORY_ARGS.split( StringPool.SPACE );
String userTimezone = ILiferayTomcatConstants.DEFAULT_USER_TIMEZONE;
if( currentServer != null && portalTomcatServer != null )
{
memoryArgs = DebugPlugin.parseArguments( portalTomcatServer.getMemoryArgs() );
userTimezone = portalTomcatServer.getUserTimezone();
}
if( memoryArgs != null )
{
for( String arg : memoryArgs )
{
runtimeVMArgs.add( arg );
}
}
runtimeVMArgs.add( "-Duser.timezone=" + userTimezone ); //$NON-NLS-1$
}
public static IStatus canAddModule( IModule module, IServer currentServer )
{
IProject project = module.getProject();
if( project != null )
{
IFacetedProject facetedProject = ProjectUtil.getFacetedProject( project );
if( facetedProject != null )
{
IProjectFacet liferayFacet = ProjectUtil.getLiferayFacet( facetedProject );
if( liferayFacet != null )
{
String facetId = liferayFacet.getId();
IRuntime runtime = null;
try
{
runtime = ServerUtil.getRuntime( project );
}
catch( CoreException e )
{
}
if( runtime != null )
{
IPluginPublisher pluginPublisher =
LiferayServerCore.getPluginPublisher( facetId, runtime.getRuntimeType().getId() );
if( pluginPublisher != null )
{
IStatus status = pluginPublisher.canPublishModule( currentServer, module );
if( !status.isOK() )
{
return status;
}
}
}
}
}
}
return Status.OK_STATUS;
}
/*
* Added for IDE-646
*/
protected static IPath checkAndReturnCustomPortalDir( IPath appServerDir )
{
IPath retval = null;
if( appServerDir != null )
{
File contextFile =
appServerDir.append( CONFIG_DIR ).append( SERVICE_NAME ).append( HOST_NAME ).append(
DEFAULT_PORTAL_CONTEXT_FILE ).toFile();
if( contextFile.exists() )
{
Context tcPortalContext = loadContextFile( contextFile );
if( tcPortalContext != null )
{
String docBase = tcPortalContext.getDocBase();
if( docBase != null )
{
return new Path( docBase );
}
}
}
if( retval == null )
{
retval = appServerDir.append( DEFAULT_PORTAL_DIR );
}
}
return retval;
}
public static void displayToggleMessage( String msg, String key )
{
// UIUtil.postInfoWithToggle(
// Msgs.liferayTomcatServer, msg, Msgs.notShowMessage, false, LiferayTomcatPlugin.getPreferenceStore(), key );
}
private static File ensurePortalIDEPropertiesExists(
IPath installPath, IPath configPath, IServer currentServer, ILiferayTomcatServer portalServer )
{
IPath idePropertiesPath = installPath.append( "../portal-ide.properties" ); //$NON-NLS-1$
String hostName = "localhost"; //$NON-NLS-1$
try
{
ServerInstance server =
TomcatVersionHelper.getCatalinaServerInstance( configPath.append( "conf/server.xml" ), null, null ); //$NON-NLS-1$
hostName = server.getHost().getName();
}
catch( Exception e )
{
LiferayTomcatPlugin.logError( e );
}
// read portal-developer.properties
// Properties devProps = new Properties();
// IPath devPropertiesPath =
// installPath.append("webapps/ROOT/WEB-INF/classes/portal-developer.properties");
// if (devPropertiesPath.toFile().exists()) {
// devProps.load(new FileReader(devPropertiesPath.toFile()));
// }
// if (idePropertiesPath.toFile().exists()) {
// String value =
// CoreUtil.readPropertyFileValue(idePropertiesPath.toFile(),
// "auto.deploy.tomcat.conf.dir");
// if (configPath.append("conf/Catalina/"+hostName).toFile().equals(new
// File(value))) {
// return;
// }
// }
Properties props = new Properties();
if( portalServer != null && portalServer.getServerMode() == ILiferayTomcatConstants.DEVELOPMENT_SERVER_MODE )
{
props.put( "include-and-override", "portal-developer.properties" );
}
props.put( "com.liferay.portal.servlet.filters.etag.ETagFilter", "false" ); //$NON-NLS-1$ //$NON-NLS-2$
props.put( "com.liferay.portal.servlet.filters.header.HeaderFilter", "false" ); //$NON-NLS-1$ //$NON-NLS-2$
props.put( "json.service.auth.token.enabled", "false" ); //$NON-NLS-1$ //$NON-NLS-2$
props.put( "auto.deploy.tomcat.conf.dir", configPath.append( "conf/Catalina/" + hostName ).toOSString() ); //$NON-NLS-1$ //$NON-NLS-2$
if( currentServer != null && portalServer != null )
{
IPath runtimLocation = currentServer.getRuntime().getLocation();
String autoDeployDir = portalServer.getAutoDeployDirectory();
if( !ILiferayTomcatConstants.DEFAULT_AUTO_DEPLOYDIR.equals( autoDeployDir ) )
{
IPath autoDeployDirPath = new Path( autoDeployDir );
if( autoDeployDirPath.isAbsolute() && autoDeployDirPath.toFile().exists() )
{
props.put( "auto.deploy.deploy.dir", portalServer.getAutoDeployDirectory() ); //$NON-NLS-1$
}
else
{
File autoDeployDirFile = new File( runtimLocation.toFile(), autoDeployDir );
if( autoDeployDirFile.exists() )
{
props.put( "auto.deploy.deploy.dir", autoDeployDirFile.getPath() ); //$NON-NLS-1$
}
}
}
props.put( "auto.deploy.interval", portalServer.getAutoDeployInterval() ); //$NON-NLS-1$
}
// props.put( "json.service.public.methods", "*" );
props.put( "jsonws.web.service.public.methods", "*" ); //$NON-NLS-1$ //$NON-NLS-2$
File file = idePropertiesPath.toFile();
try
{
props.store( new FileOutputStream( file ), null );
}
catch( Exception e )
{
LiferayTomcatPlugin.logError( e );
}
return file;
}
public static IPath[] getAllUserClasspathLibraries( IPath runtimeLocation, IPath portalDir )
{
List<IPath> libs = new ArrayList<IPath>();
IPath libFolder = runtimeLocation.append( "lib" ); //$NON-NLS-1$
IPath extLibFolder = runtimeLocation.append( "lib/ext" ); //$NON-NLS-1$
IPath webinfLibFolder = portalDir.append( "WEB-INF/lib" ); //$NON-NLS-1$
try
{
List<File> libFiles = FileListing.getFileListing( new File( libFolder.toOSString() ) );
for( File lib : libFiles )
{
if( lib.exists() && lib.getName().endsWith( ".jar" ) ) //$NON-NLS-1$
{
libs.add( new Path( lib.getPath() ) );
}
}
List<File> extLibFiles = FileListing.getFileListing( new File( extLibFolder.toOSString() ) );
for( File lib : extLibFiles )
{
if( lib.exists() && lib.getName().endsWith( ".jar" ) ) //$NON-NLS-1$
{
libs.add( new Path( lib.getPath() ) );
}
}
libFiles = FileListing.getFileListing( new File( webinfLibFolder.toOSString() ) );
for( File lib : libFiles )
{
if( lib.exists() && lib.getName().endsWith( ".jar" ) ) //$NON-NLS-1$
{
libs.add( new Path( lib.getPath() ) );
}
}
}
catch( FileNotFoundException e )
{
LiferayTomcatPlugin.logError( e );
}
return libs.toArray( new IPath[0] );
}
public static String getConfigInfoFromCache( String configType, IPath portalDir )
{
IPath configInfoPath = null;
if( configType.equals( CONFIG_TYPE_VERSION ) )
{
configInfoPath = LiferayTomcatPlugin.getDefault().getStateLocation().append( "version.properties" ); //$NON-NLS-1$
}
else if( configType.equals( CONFIG_TYPE_SERVER ) )
{
configInfoPath = LiferayTomcatPlugin.getDefault().getStateLocation().append( "serverInfos.properties" ); //$NON-NLS-1$
}
else
{
return null;
}
File configInfoFile = configInfoPath.toFile();
String portalDirKey = CoreUtil.createStringDigest( portalDir.toPortableString() );
Properties properties = new Properties();
if( configInfoFile.exists() )
{
try
{
FileInputStream fileInput = new FileInputStream( configInfoFile );
properties.load( fileInput );
fileInput.close();
String configInfo = (String) properties.get( portalDirKey );
if( !CoreUtil.isNullOrEmpty( configInfo ) )
{
return configInfo;
}
}
catch( Exception e )
{
}
}
return null;
}
public static String getConfigInfoFromManifest( String configType, IPath portalDir )
{
File implJar = portalDir.append( "WEB-INF/lib/portal-impl.jar" ).toFile(); //$NON-NLS-1$
String version = null;
String serverInfo = null;
if( implJar.exists() )
{
try
{
@SuppressWarnings( "resource" )
JarFile jar = new JarFile( implJar );
Manifest manifest = jar.getManifest();
Attributes attributes = manifest.getMainAttributes();
version = attributes.getValue( "Liferay-Portal-Version" ); //$NON-NLS-1$
serverInfo = attributes.getValue( "Liferay-Portal-Server-Info" ); //$NON-NLS-1$
if( CoreUtil.compareVersions( Version.parseVersion( version ), MANIFEST_VERSION_REQUIRED ) < 0 )
{
version = null;
serverInfo = null;
}
}
catch( IOException e )
{
LiferayTomcatPlugin.logError( e );
}
}
if( configType.equals( CONFIG_TYPE_VERSION ) )
{
return version;
}
if( configType.equals( CONFIG_TYPE_SERVER ) )
{
return serverInfo;
}
return null;
}
private static File getExternalPropertiesFile(
IPath installPath, IPath configPath, IServer currentServer, ILiferayTomcatServer portalServer )
{
File retval = null;
if( portalServer != null )
{
File portalIdePropFile =
ensurePortalIDEPropertiesExists( installPath, configPath, currentServer, portalServer );
retval = portalIdePropFile;
String externalProperties = portalServer.getExternalProperties();
if( !CoreUtil.isNullOrEmpty( externalProperties ) )
{
File externalPropertiesFile = setupExternalPropertiesFile( portalIdePropFile, externalProperties );
if( externalPropertiesFile != null )
{
retval = externalPropertiesFile;
}
}
}
return retval;
}
public static ILiferayTomcatRuntime getLiferayTomcatRuntime( IRuntime runtime )
{
if( runtime != null )
{
return (ILiferayTomcatRuntime) runtime.createWorkingCopy().loadAdapter( ILiferayTomcatRuntime.class, null );
}
return null;
}
public static IPath getPortalDir( IPath appServerDir )
{
return checkAndReturnCustomPortalDir( appServerDir );
}
public static String getVersion( ILiferayRuntime runtime )
{
String version = getConfigInfoFromCache( CONFIG_TYPE_VERSION, runtime.getAppServerPortalDir() );
if( version == null )
{
version = getConfigInfoFromManifest( CONFIG_TYPE_VERSION, runtime.getAppServerPortalDir() );
if( version == null )
{
final LiferayPortalValueLoader loader = new LiferayPortalValueLoader( runtime.getUserLibs() );
final Version loadedVersion = loader.loadVersionFromClass();
if( loadedVersion != null )
{
version = loadedVersion.toString();
}
}
if( version != null )
{
saveConfigInfoIntoCache( CONFIG_TYPE_VERSION, version, runtime.getAppServerPortalDir() );
}
}
return version;
}
public static boolean isExtProjectContext( Context context )
{
return false;
}
public static boolean isLiferayModule( IModule module )
{
boolean retval = false;
if( module != null )
{
IProject project = module.getProject();
retval = ProjectUtil.isLiferayFacetedProject( project );
}
return retval;
}
public static Context loadContextFile( File contextFile )
{
FileInputStream fis = null;
Context context = null;
if( contextFile != null && contextFile.exists() )
{
try
{
Factory factory = new Factory();
factory.setPackageName( "org.eclipse.jst.server.tomcat.core.internal.xml.server40" ); //$NON-NLS-1$
fis = new FileInputStream( contextFile );
context = (Context) factory.loadDocument( fis );
if( context != null )
{
String path = context.getPath();
// If path attribute is not set, derive from file name
if( path == null )
{
String fileName = contextFile.getName();
path = fileName.substring( 0, fileName.length() - ".xml".length() ); //$NON-NLS-1$
if( "ROOT".equals( path ) ) //$NON-NLS-1$
path = StringPool.EMPTY;
context.setPath( StringPool.FORWARD_SLASH + path );
}
}
}
catch( Exception e )
{
// may be a spurious xml file in the host dir?
}
finally
{
try
{
fis.close();
}
catch( IOException e )
{
// ignore
}
}
}
return context;
}
public static IPath modifyLocationForBundle( IPath currentLocation )
{
IPath modifiedLocation = null;
if( currentLocation == null || CoreUtil.isNullOrEmpty( currentLocation.toOSString() ) )
{
return null;
}
File location = currentLocation.toFile();
if( location.exists() && location.isDirectory() )
{
// check to see if this location contains tomcat dir *tomcat*
File[] files = location.listFiles();
boolean matches = false;
String pattern = ".*tomcat.*"; //$NON-NLS-1$
File tomcatDir = null;
for( File file : files )
{
if( file.isDirectory() && file.getName().matches( pattern ) )
{
matches = true;
tomcatDir = file;
break;
}
}
if( matches && tomcatDir != null )
{
modifiedLocation = new Path( tomcatDir.getPath() );
}
}
return modifiedLocation;
}
public static void saveConfigInfoIntoCache( String configType, String configInfo, IPath portalDir )
{
IPath versionsInfoPath = null;
if( configType.equals( CONFIG_TYPE_VERSION ) )
{
versionsInfoPath = LiferayTomcatPlugin.getDefault().getStateLocation().append( "version.properties" ); //$NON-NLS-1$
}
else if( configType.equals( CONFIG_TYPE_SERVER ) )
{
versionsInfoPath = LiferayTomcatPlugin.getDefault().getStateLocation().append( "serverInfos.properties" ); //$NON-NLS-1$
}
if( versionsInfoPath != null )
{
File versionInfoFile = versionsInfoPath.toFile();
if( configInfo != null )
{
String portalDirKey = CoreUtil.createStringDigest( portalDir.toPortableString() );
Properties properties = new Properties();
try
{
FileInputStream fileInput = new FileInputStream( versionInfoFile );
properties.load( fileInput );
fileInput.close();
}
catch( FileNotFoundException e )
{
// ignore filenotfound we likely just haven't had a file written yet.
}
catch( IOException e )
{
LiferayTomcatPlugin.logError( e );
}
properties.put( portalDirKey, configInfo );
try
{
FileOutputStream fileOutput = new FileOutputStream( versionInfoFile );
properties.store( fileOutput, StringPool.EMPTY );
fileOutput.close();
}
catch( Exception e )
{
LiferayTomcatPlugin.logError( e );
}
}
}
}
private static File setupExternalPropertiesFile( File portalIdePropFile, String externalPropertiesPath )
{
File retval = null;
// first check to see if there is an external properties file
File externalPropertiesFile = new File( externalPropertiesPath );
if( externalPropertiesFile.exists() )
{
ExternalPropertiesConfiguration props = new ExternalPropertiesConfiguration();
try
{
props.load( new FileInputStream( externalPropertiesFile ) );
props.setProperty( "include-and-override", portalIdePropFile.getAbsolutePath() ); //$NON-NLS-1$
props.setHeader( "# Last modified by Liferay IDE " + new Date() ); //$NON-NLS-1$
props.save( new FileOutputStream( externalPropertiesFile ) );
retval = externalPropertiesFile;
}
catch( Exception e )
{
retval = null;
}
}
else
{
retval = null; // don't setup an external properties file
}
return retval;
}
public static void syncStopServer( final IServer server )
{
if( server.getServerState() != IServer.STATE_STARTED )
{
return;
}
final LiferayTomcatServerBehavior serverBehavior =
(LiferayTomcatServerBehavior) server.loadAdapter( LiferayTomcatServerBehavior.class, null );
Thread shutdownThread = new Thread()
{
@Override
public void run()
{
serverBehavior.stop( true );
synchronized( server )
{
try
{
server.wait( 5000 );
}
catch( InterruptedException e )
{
}
}
}
};
IServerListener shutdownListener = new IServerListener()
{
@Override
public void serverChanged( ServerEvent event )
{
if( event.getState() == IServer.STATE_STOPPED )
{
synchronized( server )
{
server.notifyAll();
}
}
}
};
server.addServerListener( shutdownListener );
try
{
shutdownThread.start();
shutdownThread.join();
}
catch( InterruptedException e )
{
}
server.removeServerListener( shutdownListener );
}
public static IStatus validateRuntimeStubLocation( String runtimeTypeId, IPath runtimeStubLocation )
{
try
{
IRuntimeWorkingCopy runtimeStub = ServerCore.findRuntimeType( runtimeTypeId ).createRuntime( null, null );
runtimeStub.setLocation( runtimeStubLocation );
runtimeStub.setStub( true );
return runtimeStub.validate( null );
}
catch( Exception e )
{
return LiferayTomcatPlugin.createErrorStatus( e );
}
}
}