/*******************************************************************************
* 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.ui.upgrade;
import com.liferay.ide.core.util.CoreUtil;
import com.liferay.ide.project.core.upgrade.CodeUpgradeOp;
import com.liferay.ide.project.core.util.ProjectUtil;
import com.liferay.ide.project.ui.dialog.CustomProjectSelectionDialog;
import com.liferay.ide.server.util.ServerUtil;
import com.liferay.ide.ui.util.SWTUtil;
import com.liferay.ide.ui.util.UIUtil;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.compare.BufferedContent;
import org.eclipse.compare.CompareConfiguration;
import org.eclipse.compare.CompareEditorInput;
import org.eclipse.compare.CompareUI;
import org.eclipse.compare.IEditableContent;
import org.eclipse.compare.IModificationDate;
import org.eclipse.compare.ITypedElement;
import org.eclipse.compare.structuremergeviewer.DiffNode;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.jface.window.Window;
import org.eclipse.sapphire.ui.forms.FormComponentPart;
import org.eclipse.sapphire.ui.forms.swt.FormComponentPresentation;
import org.eclipse.sapphire.ui.forms.swt.SwtPresentation;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE.SharedImages;
import org.eclipse.wst.server.core.IRuntime;
/**
* @author Andy Wu
*/
public class ConvertedProjectTreesPart extends FormComponentPart
{
public class ConvertedProjectTreesPresentation extends FormComponentPresentation
{
private class CompareItem extends BufferedContent implements ITypedElement, IModificationDate, IEditableContent
{
private String fileName;
private long time;
public CompareItem( String fileName )
{
this.fileName = fileName;
this.time = System.currentTimeMillis();
}
protected InputStream createStream() throws CoreException
{
try
{
return new FileInputStream( new File( fileName ) );
}
catch( FileNotFoundException e )
{
e.printStackTrace();
}
return new ByteArrayInputStream( new byte[0] );
}
public Image getImage()
{
return CompareUI.DESC_CTOOL_NEXT.createImage();
}
public long getModificationDate()
{
return time;
}
public String getName()
{
return fileName;
}
public String getType()
{
return ITypedElement.TEXT_TYPE;
}
public boolean isEditable()
{
return true;
}
public ITypedElement replace( ITypedElement dest, ITypedElement src )
{
return null;
}
public void writeFile()
{
this.writeFile( this.fileName, this.getContent() );
}
private void writeFile( String fileName, byte[] newContent )
{
FileOutputStream fos = null;
try
{
File file = new File( fileName );
if( file.exists() )
{
file.delete();
}
file.createNewFile();
fos = new FileOutputStream( file );
fos.write( newContent );
fos.flush();
}
catch( IOException e )
{
e.printStackTrace();
}
finally
{
try
{
fos.close();
}
catch( IOException e )
{
e.printStackTrace();
}
fos = null;
}
}
}
class LeftViewLabelProvider extends StyledCellLabelProvider
{
private String getFileName( File file )
{
String name = file.getName();
File html = new File( file, "html" );
if( html.exists() && html.isDirectory() )
{
IPath location = Path.fromOSString( file.getAbsolutePath() );
IFile ifile = CoreUtil.getWorkspaceRoot().getFileForLocation( location );
return ifile.getProject().getName();
}
else
{
return name.isEmpty() ? file.getPath() : name;
}
}
@Override
public void update( ViewerCell cell )
{
Object element = cell.getElement();
StyledString text = new StyledString();
File file = (File) element;
if( file.isDirectory() )
{
text.append( getFileName( file ) );
File html = new File( file, "html" );
if( html.exists() && html.isDirectory() )
{
cell.setImage( imageProject );
}
else
{
cell.setImage( imageFolder );
}
String[] files = file.list( new FilenameFilter()
{
@Override
public boolean accept( File dir, String name )
{
if( !name.startsWith( "." ) )
{
return true;
}
else
{
return false;
}
}
} );
if( files != null )
{
text.append( " (" + files.length + ") ", StyledString.COUNTER_STYLER );
}
}
else
{
cell.setImage( imageFile );
text.append( getFileName( file ) );
if( is62FileFound( file ) )
{
text.append( "(found)", StyledString.COUNTER_STYLER );
}
else
{
text.append( "(unfound)", StyledString.DECORATIONS_STYLER );
}
}
cell.setText( text.toString() );
cell.setStyleRanges( text.getStyleRanges() );
super.update( cell );
}
}
class RightViewLabelProvider extends StyledCellLabelProvider
{
private String getFileName( File file )
{
String name = file.getName();
if( name.equals( "resources" ) )
{
IPath location = Path.fromOSString( file.getAbsolutePath() );
IFile ifile = CoreUtil.getWorkspaceRoot().getFileForLocation( location );
return ifile.getProject().getName();
}
else
{
return name.isEmpty() ? file.getPath() : name;
}
}
@Override
public void update( ViewerCell cell )
{
Object element = cell.getElement();
StyledString text = new StyledString();
File file = (File) element;
if( file.isDirectory() )
{
text.append( getFileName( file ) );
if( file.getName().endsWith( "resources" ) )
{
cell.setImage( imageProject );
}
else
{
cell.setImage( imageFolder );
}
String[] files = file.list( new FilenameFilter()
{
@Override
public boolean accept( File dir, String name )
{
if( !name.startsWith( "." ) )
{
return true;
}
else
{
return false;
}
}
} );
if( files != null )
{
text.append( " (" + files.length + ") ", StyledString.COUNTER_STYLER );
}
}
else
{
cell.setImage( imageFile );
text.append( getFileName( file ) );
if( is70FileFound( file ) )
{
text.append( "(found)", StyledString.COUNTER_STYLER );
}
else
{
text.append( "(unfound)", StyledString.DECORATIONS_STYLER );
}
}
cell.setText( text.toString() );
cell.setStyleRanges( text.getStyleRanges() );
super.update( cell );
}
}
class ViewContentProvider implements ITreeContentProvider
{
@Override
public void dispose()
{
}
@Override
public Object[] getChildren( Object parentElement )
{
File file = (File) parentElement;
File[] files = file.listFiles( new FilenameFilter()
{
@Override
public boolean accept( File dir, String name )
{
if( name.startsWith( "." ) )
{
return false;
}
return true;
}
} );
return files;
}
@Override
public Object[] getElements( Object inputElement )
{
return (File[]) inputElement;
}
@Override
public Object getParent( Object element )
{
File file = (File) element;
return file.getParentFile();
}
@Override
public boolean hasChildren( Object element )
{
File file = (File) element;
if( file.isDirectory() )
{
return true;
}
return false;
}
public void inputChanged( Viewer v, Object oldInput, Object newInput )
{
}
}
private String compareType70 = "7.x";
private String compareType62 = "6.2";
private Image imageFile;
private Image imageFolder;
private Image imageProject;
private TreeViewer leftTreeViewer;
private TreeViewer rightTreeViewer;
private String staticPath = "/src/main/resources/META-INF/resources/";
public ConvertedProjectTreesPresentation( FormComponentPart part, SwtPresentation parent, Composite composite )
{
super( part, parent, composite );
}
public void compare( final String originalFile, final String changedFile, final String compareType )
{
CompareConfiguration config = new CompareConfiguration();
config.setLeftEditable( false );
config.setLeftLabel( compareType + " original jsp" );
config.setRightEditable( true );
config.setRightLabel( "custom jsp" );
CompareEditorInput editorInput = new CompareEditorInput( config )
{
CompareItem originalItem = new CompareItem( originalFile );
CompareItem changedItem = new CompareItem( changedFile );
@Override
protected Object prepareInput( IProgressMonitor monitor )
throws InvocationTargetException, InterruptedException
{
return new DiffNode( originalItem, changedItem );
}
@Override
public void saveChanges( IProgressMonitor pm ) throws CoreException
{
super.saveChanges( pm );
changedItem.writeFile();
}
};
editorInput.setTitle( "Jsp File Compare" );
CompareUI.openCompareEditor( editorInput );
}
private void createChildren( Composite container )
{
createImages();
createLeftPart( container );
createRightPart( container );
}
private Image createImage( String symbolicName )
{
Image image = PlatformUI.getWorkbench().getSharedImages().getImage( symbolicName );
if( image.isDisposed() )
{
image = PlatformUI.getWorkbench().getSharedImages().getImageDescriptor( symbolicName ).createImage();
}
return image;
}
private void createImages()
{
this.imageProject = createImage( SharedImages.IMG_OBJ_PROJECT );
this.imageFolder = createImage( ISharedImages.IMG_OBJ_FOLDER );
this.imageFile = createImage( ISharedImages.IMG_OBJ_FILE );
}
private void createLeftPart( Composite parent )
{
ScrolledComposite leftContainer = new ScrolledComposite( parent, SWT.H_SCROLL | SWT.V_SCROLL );
Composite leftPart = SWTUtil.createComposite( leftContainer, 1, 0, GridData.FILL_BOTH );
leftContainer.setLayout( new FillLayout() );
leftContainer.setMinSize( 410, 200 );
leftContainer.setExpandHorizontal( true );
leftContainer.setExpandVertical( true );
leftContainer.setContent( leftPart );
Label leftLabel = new Label( leftPart, SWT.NONE );
leftLabel.setText( "6.2 Custom JSPs (double-click to compare with original)" );
leftTreeViewer = new TreeViewer( leftPart, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER );
GridData gd = new GridData( SWT.FILL, SWT.FILL, true, true );
leftTreeViewer.getTree().setLayoutData( gd );
leftTreeViewer.setContentProvider( new ViewContentProvider() );
leftTreeViewer.setLabelProvider( new LeftViewLabelProvider() );
leftTreeViewer.addDoubleClickListener( new IDoubleClickListener()
{
@Override
public void doubleClick( DoubleClickEvent event )
{
ISelection selection = event.getSelection();
File file = (File) ( (ITreeSelection) selection ).getFirstElement();
if( file.isDirectory() )
{
return;
}
if( is62FileFound( file ) )
{
String[] paths = get62FilePaths( file );
compare( paths[0], paths[1], compareType62 );
}
else
{
MessageDialog.openInformation( Display.getDefault().getActiveShell(), "file not found",
"there is no such file in liferay 62" );
}
}
} );
leftTreeViewer.setSorter( new ViewerSorter()
{
@Override
public int category( Object element )
{
File file = (File) element;
if( file.isDirectory() )
{
return -1;
}
else
{
return super.category( element );
}
}
} );
}
private void createRightPart( Composite parent )
{
ScrolledComposite rightContainer = new ScrolledComposite( parent, SWT.H_SCROLL | SWT.V_SCROLL );
Composite rightPart = SWTUtil.createComposite( rightContainer, 1, 0, GridData.FILL_BOTH );
rightContainer.setLayout( new FillLayout() );
rightContainer.setMinSize( 410, 200 );
rightContainer.setExpandHorizontal( true );
rightContainer.setExpandVertical( true );
rightContainer.setContent( rightPart );
Label rightLabel = new Label( rightPart, SWT.NONE );
rightLabel.setText( "New JSP (double-click to compare with original)" );
rightTreeViewer = new TreeViewer( rightPart, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER );
GridData gd = new GridData( SWT.FILL, SWT.FILL, true, true );
rightTreeViewer.getTree().setLayoutData( gd );
rightTreeViewer.setContentProvider( new ViewContentProvider() );
rightTreeViewer.setLabelProvider( new RightViewLabelProvider() );
rightTreeViewer.addDoubleClickListener( new IDoubleClickListener()
{
@Override
public void doubleClick( DoubleClickEvent event )
{
ISelection selection = event.getSelection();
File file = (File) ( (ITreeSelection) selection ).getFirstElement();
if( file.isDirectory() )
{
return;
}
if( is70FileFound( file ) )
{
String[] paths = get70FilePaths( file );
compare( paths[0], paths[1], compareType70 );
}
else
{
MessageDialog.openInformation( Display.getDefault().getActiveShell(), "file not found",
"there is no such file in liferay 7" );
}
}
} );
rightTreeViewer.setSorter( new ViewerSorter()
{
@Override
public int category( Object element )
{
File file = (File) element;
if( file.isDirectory() )
{
return -1;
}
else
{
return super.category( element );
}
}
} );
}
private String[] get62FilePaths( File file )
{
String filePath = file.getAbsolutePath();
IFile iFile = CoreUtil.getWorkspaceRoot().getFileForLocation( Path.fromOSString( filePath ) );
IProject project = iFile.getProject();
String projectPath = project.getLocation().toOSString();
String customJsp = CustomJspConverter.getCustomJspPath( projectPath );
java.nio.file.Path customJspPath =
project.getFolder( "docroot/" + customJsp ).getLocation().toFile().toPath();
java.nio.file.Path relativePath = customJspPath.relativize( file.toPath() );
String[] paths = new String[2];
paths[0] = null;
paths[1] = filePath;
File original62JspFile =
new File( getLiferay62ServerLocation() + "/tomcat-7.0.42/webapps/ROOT/" + relativePath.toString() );
if( original62JspFile.exists() )
{
paths[0] = original62JspFile.getAbsolutePath();
}
return paths;
}
private String[] get70FilePaths( File file )
{
String filePath = file.getAbsolutePath();
IFile iFile = CoreUtil.getWorkspaceRoot().getFileForLocation( Path.fromOSString( filePath ) );
IFolder resourceFolder = iFile.getProject().getFolder( staticPath );
java.nio.file.Path resourcePath = resourceFolder.getLocation().toFile().toPath();
java.nio.file.Path relativePath = resourcePath.relativize( file.toPath() );
String[] paths = new String[2];
paths[0] = null;
paths[1] = filePath;
IFile original70File = resourceFolder.getFile( "/.ignore/" + relativePath.toString() );
if( original70File.exists() )
{
paths[0] = original70File.getLocation().toOSString();
}
return paths;
}
private List<IProject> getHookProjects()
{
List<IProject> results = new ArrayList<IProject>();
IProject[] projects = CoreUtil.getAllProjects();
for( IProject project : projects )
{
if( ProjectUtil.isHookProject( project ) )
{
results.add( project );
}
}
return results;
}
private File[] getLeftTreeInputs()
{
String[] results = CustomJspConverter.getConvertResult( CustomJspConverter.sourcePrefix );
if( results == null )
{
return null;
}
int size = results.length;
File[] files = new File[size];
for( int i = 0; i < size; i++ )
{
String[] contents = results[i].split( ":" );
IProject project = CoreUtil.getProject( contents[0] );
String customJspPath = contents[1];
files[i] = project.getFolder( "docroot/" + customJspPath ).getLocation().toFile();
}
return files;
}
private String getLiferay62ServerLocation()
{
return op().getLiferay62ServerLocation().content( true );
}
private IRuntime getLiferay70Runtime()
{
String serverName = op().getLiferayServerName().content();
return ServerUtil.getServer( serverName ).getRuntime();
}
private File[] getRightTreeInputs()
{
String[] results = CustomJspConverter.getConvertResult( CustomJspConverter.resultPrefix );
if( results == null )
{
return null;
}
int size = results.length;
File[] files = new File[size];
for( int i = 0; i < size; i++ )
{
File file = new File( results[i], staticPath );
files[i] = file;
}
return files;
}
private boolean is62FileFound( File file )
{
String[] paths = get62FilePaths( file );
if( paths[0] != null )
{
return true;
}
else
{
return false;
}
}
private boolean is70FileFound( File file )
{
String[] paths = get70FilePaths( file );
if( paths[0] != null )
{
return true;
}
else
{
return false;
}
}
private CodeUpgradeOp op()
{
return getLocalModelElement().nearest( CodeUpgradeOp.class );
}
public void refreshTreeViews()
{
File[] leftInputs = getLeftTreeInputs();
leftTreeViewer.setInput( leftInputs );
File[] rightInputs = getRightTreeInputs();
rightTreeViewer.setInput( rightInputs );
}
@Override
public void render()
{
Composite container = new Composite( composite(), SWT.NONE );
GridLayout gridLayout = new GridLayout( 1, true );
container.setLayout( gridLayout );
GridData layoutData = new GridData( SWT.FILL, SWT.FILL, true, true );
layoutData.widthHint = 800;
layoutData.heightHint = 600;
container.setLayoutData( layoutData );
Composite buttonContainer = new Composite( container, SWT.NONE );
buttonContainer.setLayout( new GridLayout( 2, true ) );
Button selectButton = SWTUtil.createButton( buttonContainer, "select projects" );
GridData buttonGridData = new GridData( SWT.LEFT, SWT.LEFT, false, false );
buttonGridData.widthHint = 130;
buttonGridData.heightHint = 40;
selectButton.setLayoutData( buttonGridData );
Button clearButton = SWTUtil.createButton( buttonContainer, "clear results" );
clearButton.setLayoutData( buttonGridData );
selectButton.addSelectionListener( new SelectionAdapter()
{
@Override
public void widgetSelected( SelectionEvent e )
{
runConvertAction();
}
} );
clearButton.addSelectionListener( new SelectionAdapter()
{
@Override
public void widgetSelected( SelectionEvent e )
{
CustomJspConverter.clearConvertResults();
refreshTreeViews();
}
} );
SashForm sashForm = new SashForm( container, SWT.HORIZONTAL | SWT.H_SCROLL );
sashForm.setLayout( new GridLayout( 1, false ) );
GridData sashFormLayoutData = new GridData( GridData.FILL_BOTH );
sashForm.setLayoutData( sashFormLayoutData );
createChildren( sashForm );
sashForm.setWeights( new int[] { 1, 1 } );
refreshTreeViews();
}
private void runConvertAction()
{
CustomProjectSelectionDialog dialog = new CustomProjectSelectionDialog( UIUtil.getActiveShell() );
dialog.setProjects( getHookProjects() );
List<IProject> hookProjects = new ArrayList<>();
if( dialog.open() == Window.OK )
{
final Object[] selectedProjects = dialog.getResult();
if( selectedProjects != null )
{
for( Object project : selectedProjects )
{
if( project instanceof IJavaProject )
{
IJavaProject p = (IJavaProject) project;
hookProjects.add( p.getProject() );
}
}
}
}
int size = hookProjects.size();
if( size < 1 )
{
return;
}
String[] sourcePaths = new String[size];
for( int i = 0; i < size; i++ )
{
sourcePaths[i] = hookProjects.get( i ).getLocation().toOSString();
}
CustomJspConverter converter = new CustomJspConverter();
IRuntime liferay70Runtime = getLiferay70Runtime();
String liferay62ServerLocation = getLiferay62ServerLocation();
if( liferay70Runtime == null || CoreUtil.isNullOrEmpty( liferay62ServerLocation ) )
{
MessageDialog.openError( Display.getDefault().getActiveShell(), "could not convert",
"countn't find liferay 70 or 62 server location" );
return;
}
converter.setLiferay70Runtime( liferay70Runtime );
//TODO
//converter.setUi( this );
//converter.doExecute( sourcePaths );
}
}
@Override
public FormComponentPresentation createPresentation( SwtPresentation parent, Composite composite )
{
return new ConvertedProjectTreesPresentation( this, parent, composite );
}
}