/*******************************************************************************
* Copyright (c) 2005, 2010 IBM Corporation and others.
* 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:
* IBM Corporation - Initial API and implementation
*******************************************************************************/
package com.liferay.ide.server.tomcat.core;
import com.liferay.ide.core.IWebProject;
import com.liferay.ide.core.LiferayCore;
import com.liferay.ide.project.core.util.ProjectUtil;
import com.liferay.ide.server.util.ComponentUtil;
import com.liferay.ide.server.util.ServerUtil;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jst.server.core.IJ2EEModule;
import org.eclipse.jst.server.core.IWebModule;
import org.eclipse.jst.server.tomcat.core.internal.TomcatPlugin;
import org.eclipse.jst.server.tomcat.core.internal.TomcatVersionHelper;
import org.eclipse.jst.server.tomcat.core.internal.xml.server40.ServerInstance;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.model.IModuleResource;
import org.eclipse.wst.server.core.model.IModuleResourceDelta;
import org.eclipse.wst.server.core.model.PublishOperation;
import org.eclipse.wst.server.core.model.ServerBehaviourDelegate;
import org.eclipse.wst.server.core.util.ModuleFile;
import org.eclipse.wst.server.core.util.PublishHelper;
/**
* Tomcat publish helper.
*/
@SuppressWarnings( "restriction" )
public class LiferayPublishOperation extends PublishOperation {
private static final String LIFERAY_WEB_XML_PATH = "WEB-INF/liferay-web.xml"; //$NON-NLS-1$
private static final String WEB_XML_PATH = "WEB-INF/web.xml"; //$NON-NLS-1$
protected LiferayTomcatServerBehavior server;
protected IModule[] module;
protected int kind;
protected int deltaKind;
private PublishHelper helper;
/**
* Construct the operation object to publish the specified module
* to the specified server.
*
* @param server server to which the module will be published
* @param kind kind of publish
* @param module module to publish
* @param deltaKind kind of change
*/
public LiferayPublishOperation(LiferayTomcatServerBehavior server, int kind, IModule[] module, int deltaKind) {
super(Msgs.publishServer, Msgs.publishWebModule);
this.server = server;
this.module = module;
this.kind = kind;
this.deltaKind = deltaKind;
IPath base = server.getRuntimeBaseDirectory();
if (base != null) {
helper = new PublishHelper(base.append("temp").toFile()); //$NON-NLS-1$
}
else {
// We are doomed without a base directory. However, allow the catastrophe
// to occur elsewhere and hope for a useful error message.
helper = new PublishHelper(null);
}
}
/**
* @see PublishOperation#getOrder()
*/
public int getOrder() {
return 0;
}
/**
* @see PublishOperation#getKind()
*/
public int getKind() {
return REQUIRED;
}
/**
* @see PublishOperation#execute(IProgressMonitor, IAdaptable)
*/
public void execute(IProgressMonitor monitor, IAdaptable info) throws CoreException {
List status = new ArrayList();
// If parent web module
if (module.length == 1) {
if ( !ServerUtil.isExtProject( module[0].getProject() ) )
{
publishDir(module[0], status, monitor);
}
}
// Else a child module
else {
Properties p = server.loadModulePublishLocations();
// Try to determine the URI for the child module
IWebModule webModule = (IWebModule)module[0].loadAdapter(IWebModule.class, monitor);
String childURI = null;
if (webModule != null) {
childURI = webModule.getURI(module[1]);
}
// Try to determine if child is binary
IJ2EEModule childModule = (IJ2EEModule)module[1].loadAdapter(IJ2EEModule.class, monitor);
boolean isBinary = false;
if (childModule != null) {
isBinary = childModule.isBinary();
}
if (isBinary) {
publishArchiveModule(childURI, p, status, monitor);
}
else {
publishJar(childURI, p, status, monitor);
}
server.saveModulePublishLocations(p);
}
throwException(status);
server.setModulePublishState2(module, IServer.PUBLISH_STATE_NONE);
}
private void publishDir(IModule module2, List status, IProgressMonitor monitor) throws CoreException {
final IPath path = server.getModuleDeployDirectory(module2);
// Remove if requested or if previously published and are now serving without publishing
if (kind == IServer.PUBLISH_CLEAN || deltaKind == ServerBehaviourDelegate.REMOVED
|| server.getTomcatServer().isServeModulesWithoutPublish()) {
File f = path.toFile();
if (f.exists()) {
try {
IPath baseDir = server.getRuntimeBaseDirectory();
IPath serverXml = baseDir.append("conf").append("server.xml"); //$NON-NLS-1$ //$NON-NLS-2$
ServerInstance oldInstance = TomcatVersionHelper.getCatalinaServerInstance(serverXml, null, null);
IPath contextDir = oldInstance.getContextXmlDirectory(baseDir.append("conf")); //$NON-NLS-1$
String contextFileName = path.lastSegment() + ".xml"; //$NON-NLS-1$
File contextFile = contextDir.append(contextFileName).toFile();
if (contextFile.exists()) {
contextFile.delete();
}
File autoDeployDir =
baseDir.append(server.getLiferayTomcatServer().getAutoDeployDirectory()).toFile();
File autoDeployFile = new File(autoDeployDir, contextFileName);
if (autoDeployFile.exists()) {
autoDeployFile.delete();
}
}
catch (Exception e) {
LiferayTomcatPlugin.logError("Could not delete context xml file.", e); //$NON-NLS-1$
}
IStatus[] stat = PublishHelper.deleteDirectory(f, monitor);
addArrayToList(status, stat);
}
if (deltaKind == ServerBehaviourDelegate.REMOVED
|| server.getTomcatServer().isServeModulesWithoutPublish())
return;
}
IPath baseDir = server.getTomcatServer().getRuntimeBaseDirectory();
IPath autoDeployDir = new Path(server.getLiferayTomcatServer().getAutoDeployDirectory());
boolean serverStopped = server.getServer().getServerState() == IServer.STATE_STOPPED;
if (kind == IServer.PUBLISH_CLEAN || kind == IServer.PUBLISH_FULL) {
IModuleResource[] mr = server.getResources(module);
IStatus[] stat = helper.publishFull(mr, path, monitor);
addArrayToList(status, stat);
clearWebXmlDescriptors(module2.getProject(), path, monitor);
server.moveContextToAutoDeployDir(module2, path, baseDir, autoDeployDir, true, serverStopped);
return;
}
IModuleResourceDelta[] delta = server.getPublishedResourceDelta(module);
// check if we have a anti*Locking directory temp files and copy the resources out there as well
File[] antiDirs = new File[0];
try
{
File tempDir =
server.getLiferayTomcatServer().getTomcatRuntime().getRuntime().getLocation().append( "temp" ).toFile(); //$NON-NLS-1$
antiDirs = tempDir.listFiles
(
new FilenameFilter()
{
public boolean accept( File dir, String name )
{
return name.endsWith( path.lastSegment() );
}
}
);
}
catch( Exception e )
{
}
int size = delta.length;
for (int i = 0; i < size; i++) {
IStatus[] stat = helper.publishDelta(delta[i], path, monitor);
for( File antiDir : antiDirs )
{
if( antiDir.exists() )
{
try
{
helper.publishDelta(delta[i], new Path( antiDir.getCanonicalPath() ), monitor);
}
catch( Exception e)
{
// best effort
}
}
}
addArrayToList(status, stat);
}
// check to see if we need to re-invoke the liferay plugin deployer
String[] paths =
new String[] { WEB_XML_PATH, "WEB-INF/portlet.xml", "WEB-INF/liferay-portlet.xml", //$NON-NLS-1$ //$NON-NLS-2$
"WEB-INF/liferay-display.xml", "WEB-INF/liferay-look-and-feel.xml", "WEB-INF/liferay-hook.xml", //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
"WEB-INF/liferay-layout-templates.xml", "WEB-INF/liferay-plugin-package.properties", //$NON-NLS-1$//$NON-NLS-2$
"WEB-INF/liferay-plugin-package.xml", "WEB-INF/server-config.wsdd", }; //$NON-NLS-1$ //$NON-NLS-2$
for ( IModuleResourceDelta del : delta )
{
if ( ComponentUtil.containsMember( del, paths ) || isHookProjectDelta( del ) )
{
clearWebXmlDescriptors(module2.getProject(), path, monitor);
server.moveContextToAutoDeployDir( module2, path, baseDir, autoDeployDir, true, serverStopped );
break;
}
}
}
private void clearWebXmlDescriptors(IProject project, IPath path, IProgressMonitor monitor)
{
// copy over web.xml so the liferay deployer doesn't copy web.xml filters incorrectly
IModuleResource webXmlRes = getWebXmlFile( project, path );
if ( webXmlRes != null )
{
helper.publishToPath(
new IModuleResource[] { webXmlRes }, path.append( WEB_XML_PATH ), monitor );
}
else
{
File webXmlFile = path.append( WEB_XML_PATH ).toFile();
File liferayWebXmlFile = path.append( LIFERAY_WEB_XML_PATH ).toFile();
if ( webXmlFile.exists() )
{
if ( !webXmlFile.delete() )
{
ProjectUtil.createDefaultWebXml( webXmlFile, project.getName() );
}
}
if ( liferayWebXmlFile.exists() )
{
if ( !liferayWebXmlFile.delete() )
{
ProjectUtil.createDefaultWebXml( liferayWebXmlFile, project.getName() );
}
}
}
}
private boolean isHookProjectDelta( IModuleResourceDelta del )
{
final IResource resource = (IResource) del.getModuleResource().getAdapter( IResource.class );
if( resource != null )
{
return ProjectUtil.isHookProject( resource.getProject() );
}
return false;
}
private IModuleResource getWebXmlFile( IProject project, IPath modelDeployDirectory )
{
// IDE-110 IDE-648
final IWebProject lrproject = LiferayCore.create( IWebProject.class, project );
if( lrproject != null )
{
final IFolder webappRoot = lrproject.getDefaultDocrootFolder();
if( webappRoot != null && webappRoot.exists() )
{
IFile webXml = webappRoot.getFile( new Path( WEB_XML_PATH ) );
if( webXml.exists() )
{
return new ModuleFile( webXml, webXml.getName(), modelDeployDirectory.append( WEB_XML_PATH ) );
}
}
}
return null;
}
private void publishJar(String jarURI, Properties p, List status, IProgressMonitor monitor) throws CoreException {
IPath path = server.getModuleDeployDirectory(module[0]);
boolean moving = false;
// Get URI used for previous publish, if known
String oldURI = (String)p.get(module[1].getId());
if (oldURI != null) {
// If old URI found, detect if jar is moving or changing its name
if (jarURI != null) {
moving = !oldURI.equals(jarURI);
}
}
// If we don't have a jar URI, make a guess so we have one if we need it
if (jarURI == null) {
jarURI = "WEB-INF/lib/" + module[1].getName() + ".jar"; //$NON-NLS-1$//$NON-NLS-2$
}
IPath jarPath = path.append(jarURI);
// Make our best determination of the path to the old jar
IPath oldJarPath = jarPath;
if (oldURI != null) {
oldJarPath = path.append(oldURI);
}
// Establish the destination directory
path = jarPath.removeLastSegments(1);
// Remove if requested or if previously published and are now serving without publishing
if (moving || kind == IServer.PUBLISH_CLEAN || deltaKind == ServerBehaviourDelegate.REMOVED
|| server.getTomcatServer().isServeModulesWithoutPublish()) {
File file = oldJarPath.toFile();
if (file.exists())
file.delete();
p.remove(module[1].getId());
if (deltaKind == ServerBehaviourDelegate.REMOVED
|| server.getTomcatServer().isServeModulesWithoutPublish())
return;
}
if (!moving && kind != IServer.PUBLISH_CLEAN && kind != IServer.PUBLISH_FULL) {
// avoid changes if no changes to module since last publish
IModuleResourceDelta[] delta = server.getPublishedResourceDelta(module);
if (delta == null || delta.length == 0)
return;
}
// make directory if it doesn't exist
if (!path.toFile().exists())
path.toFile().mkdirs();
IModuleResource[] mr = server.getResources(module);
IStatus[] stat = helper.publishZip(mr, jarPath, monitor);
addArrayToList(status, stat);
p.put(module[1].getId(), jarURI);
}
private void publishArchiveModule(String jarURI, Properties p, List status, IProgressMonitor monitor) {
IPath path = server.getModuleDeployDirectory(module[0]);
boolean moving = false;
// Get URI used for previous publish, if known
String oldURI = (String)p.get(module[1].getId());
if (oldURI != null) {
// If old URI found, detect if jar is moving or changing its name
if (jarURI != null) {
moving = !oldURI.equals(jarURI);
}
}
// If we don't have a jar URI, make a guess so we have one if we need it
if (jarURI == null) {
jarURI = "WEB-INF/lib/" + module[1].getName(); //$NON-NLS-1$
}
IPath jarPath = path.append(jarURI);
// Make our best determination of the path to the old jar
IPath oldJarPath = jarPath;
if (oldURI != null) {
oldJarPath = path.append(oldURI);
}
// Establish the destination directory
path = jarPath.removeLastSegments(1);
// Remove if requested or if previously published and are now serving without publishing
if (moving || kind == IServer.PUBLISH_CLEAN || deltaKind == ServerBehaviourDelegate.REMOVED
|| server.getTomcatServer().isServeModulesWithoutPublish()) {
File file = oldJarPath.toFile();
if (file.exists()) {
file.delete();
}
p.remove(module[1].getId());
if (deltaKind == ServerBehaviourDelegate.REMOVED
|| server.getTomcatServer().isServeModulesWithoutPublish())
return;
}
if (!moving && kind != IServer.PUBLISH_CLEAN && kind != IServer.PUBLISH_FULL) {
// avoid changes if no changes to module since last publish
IModuleResourceDelta[] delta = server.getPublishedResourceDelta(module);
if (delta == null || delta.length == 0)
return;
}
// make directory if it doesn't exist
if (!path.toFile().exists())
path.toFile().mkdirs();
IModuleResource[] mr = server.getResources(module);
IStatus[] stat = helper.publishToPath(mr, jarPath, monitor);
addArrayToList(status, stat);
p.put(module[1].getId(), jarURI);
}
/**
* Utility method to throw a CoreException based on the contents of a list of
* error and warning status.
*
* @param status a List containing error and warning IStatus
* @throws CoreException
*/
protected static void throwException(List status) throws CoreException {
if (status == null || status.size() == 0)
return;
if (status.size() == 1) {
IStatus status2 = (IStatus) status.get(0);
throw new CoreException(status2);
}
IStatus[] children = new IStatus[status.size()];
status.toArray(children);
String message = Msgs.errorPublish;
MultiStatus status2 = new MultiStatus(TomcatPlugin.PLUGIN_ID, 0, children, message, null);
throw new CoreException(status2);
}
protected static void addArrayToList(List list, IStatus[] a) {
if (list == null || a == null || a.length == 0)
return;
int size = a.length;
for (int i = 0; i < size; i++)
list.add(a[i]);
}
private static class Msgs extends NLS
{
public static String errorPublish;
public static String publishServer;
public static String publishWebModule;
static
{
initializeMessages( LiferayPublishOperation.class.getName(), Msgs.class );
}
}
}