/******************************************************************************* * 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.remote; import com.liferay.ide.core.IWebProject; import com.liferay.ide.core.LiferayCore; import com.liferay.ide.core.util.StringPool; import com.liferay.ide.server.core.LiferayServerCore; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import org.apache.commons.io.IOUtils; import org.eclipse.core.resources.IContainer; 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.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.wst.server.core.model.IModuleResourceDelta; /** * @author Simon Jiang */ public abstract class AbstractRemoteServerPublisher implements IRemoteServerPublisher { private IProject project; public AbstractRemoteServerPublisher( IProject project ) { this.project = project; } protected void addRemoveProps( IPath deltaPath, IResource deltaResource, ZipOutputStream zip, Map<ZipEntry, String> deleteEntries, String deletePrefix ) throws IOException { String archive = removeArchive( deltaPath.toPortableString() ); ZipEntry zipEntry = null; // check to see if we already have an entry for this archive for( ZipEntry entry : deleteEntries.keySet() ) { if( entry.getName().startsWith( archive ) ) { zipEntry = entry; } } if( zipEntry == null ) { zipEntry = new ZipEntry( archive + "META-INF/" + deletePrefix + "-partialapp-delete.props" ); //$NON-NLS-1$ //$NON-NLS-2$ } String existingFiles = deleteEntries.get( zipEntry ); // String file = encodeRemovedPath(deltaPath.toPortableString().substring(archive.length())); String file = deltaPath.toPortableString().substring( archive.length() ); if( deltaResource.getType() == IResource.FOLDER ) { file += "/.*"; //$NON-NLS-1$ } deleteEntries.put( zipEntry, ( existingFiles != null ? existingFiles : StringPool.EMPTY ) + ( file + "\n" ) ); //$NON-NLS-1$ } protected void addToZip( IPath path, IResource resource, ZipOutputStream zip, boolean adjustGMTOffset ) throws IOException, CoreException { switch( resource.getType() ) { case IResource.FILE: ZipEntry zipEntry = new ZipEntry( path.toString() ); zip.putNextEntry( zipEntry ); InputStream contents = ( (IFile) resource ).getContents(); if( adjustGMTOffset ) { TimeZone currentTimeZone = TimeZone.getDefault(); Calendar currentDt = new GregorianCalendar( currentTimeZone, Locale.getDefault() ); // Get the Offset from GMT taking current TZ into account int gmtOffset = currentTimeZone.getOffset( currentDt.get( Calendar.ERA ), currentDt.get( Calendar.YEAR ), currentDt.get( Calendar.MONTH ), currentDt.get( Calendar.DAY_OF_MONTH ), currentDt.get( Calendar.DAY_OF_WEEK ), currentDt.get( Calendar.MILLISECOND ) ); zipEntry.setTime( System.currentTimeMillis() + ( gmtOffset * -1 ) ); } try { IOUtils.copy( contents, zip ); } finally { contents.close(); } break; case IResource.FOLDER: case IResource.PROJECT: IContainer container = (IContainer) resource; IResource[] members = container.members(); for( IResource res : members ) { addToZip( path.append( res.getName() ), res, zip, adjustGMTOffset ); } } } protected IProject getProject() { return this.project; } protected void processResourceDeltas( IModuleResourceDelta[] deltas, ZipOutputStream zip, Map<ZipEntry, String> deleteEntries, String deletePrefix, String deltaPrefix, boolean adjustGMTOffset ) throws IOException, CoreException { for( IModuleResourceDelta delta : deltas ) { final int deltaKind = delta.getKind(); final IResource deltaResource = (IResource) delta.getModuleResource().getAdapter( IResource.class ); final IProject deltaProject = deltaResource.getProject(); // IDE-110 IDE-648 final IWebProject lrproject = LiferayCore.create( IWebProject.class, deltaProject ); if( lrproject != null ) { final IFolder webappRoot = lrproject.getDefaultDocrootFolder(); IPath deltaPath = null; if( webappRoot != null && webappRoot.exists() ) { final IPath deltaFullPath = deltaResource.getFullPath(); final IPath containerFullPath = webappRoot.getFullPath(); deltaPath = new Path( deltaPrefix + deltaFullPath.makeRelativeTo( containerFullPath ) ); if( deltaPath != null && deltaPath.segmentCount() > 0 ) { break; } } if( deltaKind == IModuleResourceDelta.ADDED || deltaKind == IModuleResourceDelta.CHANGED ) { addToZip( deltaPath, deltaResource, zip, adjustGMTOffset ); } else if( deltaKind == IModuleResourceDelta.REMOVED ) { addRemoveProps( deltaPath, deltaResource, zip, deleteEntries, deletePrefix ); } else if( deltaKind == IModuleResourceDelta.NO_CHANGE ) { IModuleResourceDelta[] children = delta.getAffectedChildren(); processResourceDeltas( children, zip, deleteEntries, deletePrefix, deltaPrefix, adjustGMTOffset ); } } } } public IPath publishModuleDelta( String archiveName, IModuleResourceDelta[] deltas, String deletePrefix, boolean adjustGMTOffset ) throws CoreException { IPath path = LiferayServerCore.getTempLocation( "partial-war", archiveName ); //$NON-NLS-1$ FileOutputStream outputStream = null; ZipOutputStream zip = null; File warfile = path.toFile(); warfile.getParentFile().mkdirs(); try { outputStream = new FileOutputStream( warfile ); zip = new ZipOutputStream( outputStream ); Map<ZipEntry, String> deleteEntries = new HashMap<ZipEntry, String>(); processResourceDeltas( deltas, zip, deleteEntries, deletePrefix, StringPool.EMPTY, adjustGMTOffset ); for( ZipEntry entry : deleteEntries.keySet() ) { zip.putNextEntry( entry ); zip.write( deleteEntries.get( entry ).getBytes() ); } // if ((removedResources != null) && (removedResources.size() > 0)) { // writeRemovedResources(removedResources, zip); // } } catch( Exception ex ) { ex.printStackTrace(); } finally { if( zip != null ) { try { zip.close(); } catch( IOException localIOException1 ) { } } } return new Path( warfile.getAbsolutePath() ); } private String removeArchive( String archive ) { int index = Math.max( archive.lastIndexOf( ".war" ), archive.lastIndexOf( ".jar" ) ); //$NON-NLS-1$ //$NON-NLS-2$ if( index >= 0 ) { return archive.substring( 0, index + 5 ); } return StringPool.EMPTY; } }