diff --git a/releng/org.eclipse.rse.build/maps/rse.map b/releng/org.eclipse.rse.build/maps/rse.map index 1502d484dab..c4ebb3b362e 100644 --- a/releng/org.eclipse.rse.build/maps/rse.map +++ b/releng/org.eclipse.rse.build/maps/rse.map @@ -33,7 +33,7 @@ plugin@org.eclipse.rse.efs.ui=v20080606,:pserver:anonymous:none@dev.eclipse.org: plugin@org.eclipse.rse.examples.daytime=v20080604,:pserver:anonymous:none@dev.eclipse.org:/cvsroot/dsdp,,org.eclipse.tm.rse/examples/org.eclipse.rse.examples.daytime plugin@org.eclipse.rse.examples.tutorial=v20080604,:pserver:anonymous:none@dev.eclipse.org:/cvsroot/dsdp,,org.eclipse.tm.rse/examples/org.eclipse.rse.examples.tutorial plugin@org.eclipse.rse.files.ui=v200902011800,:pserver:anonymous:none@dev.eclipse.org:/cvsroot/dsdp,,org.eclipse.tm.rse/plugins/org.eclipse.rse.files.ui -plugin@org.eclipse.rse.importexport=v200902011800,:pserver:anonymous:none@dev.eclipse.org:/cvsroot/dsdp,,org.eclipse.tm.rse/plugins/org.eclipse.rse.importexport +plugin@org.eclipse.rse.importexport=v200902061200,:pserver:anonymous:none@dev.eclipse.org:/cvsroot/dsdp,,org.eclipse.tm.rse/plugins/org.eclipse.rse.importexport plugin@org.eclipse.rse.processes.ui=v200902011800,:pserver:anonymous:none@dev.eclipse.org:/cvsroot/dsdp,,org.eclipse.tm.rse/plugins/org.eclipse.rse.processes.ui plugin@org.eclipse.rse.remotecdt=v200902011800,:pserver:anonymous:none@dev.eclipse.org:/cvsroot/dsdp,,org.eclipse.tm.rse/examples/org.eclipse.rse.remotecdt plugin@org.eclipse.rse.sdk=v200902011800,:pserver:anonymous:none@dev.eclipse.org:/cvsroot/dsdp,,org.eclipse.tm.rse/plugins/org.eclipse.rse.sdk diff --git a/rse/plugins/org.eclipse.rse.importexport/.classpath b/rse/plugins/org.eclipse.rse.importexport/.classpath index ce73933404a..64c5e31b7a2 100644 --- a/rse/plugins/org.eclipse.rse.importexport/.classpath +++ b/rse/plugins/org.eclipse.rse.importexport/.classpath @@ -1,7 +1,7 @@ - - + + diff --git a/rse/plugins/org.eclipse.rse.importexport/.settings/org.eclipse.jdt.core.prefs b/rse/plugins/org.eclipse.rse.importexport/.settings/org.eclipse.jdt.core.prefs index 381fc6eb064..7fb85b98b2d 100644 --- a/rse/plugins/org.eclipse.rse.importexport/.settings/org.eclipse.jdt.core.prefs +++ b/rse/plugins/org.eclipse.rse.importexport/.settings/org.eclipse.jdt.core.prefs @@ -1,8 +1,12 @@ -#Fri Mar 28 14:14:24 CET 2008 +#Fri Feb 06 12:03:25 CET 2009 eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 -org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.doc.comment.support=enabled org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning org.eclipse.jdt.core.compiler.problem.assertIdentifier=error @@ -12,7 +16,7 @@ org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=enabled org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled org.eclipse.jdt.core.compiler.problem.discouragedReference=warning org.eclipse.jdt.core.compiler.problem.emptyStatement=warning -org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning org.eclipse.jdt.core.compiler.problem.fieldHiding=warning org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning @@ -68,4 +72,4 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=di org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.3 +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/rse/plugins/org.eclipse.rse.importexport/META-INF/MANIFEST.MF b/rse/plugins/org.eclipse.rse.importexport/META-INF/MANIFEST.MF index 1424150ab42..26f930523e4 100644 --- a/rse/plugins/org.eclipse.rse.importexport/META-INF/MANIFEST.MF +++ b/rse/plugins/org.eclipse.rse.importexport/META-INF/MANIFEST.MF @@ -6,7 +6,12 @@ Bundle-Version: 1.2.0.qualifier Bundle-Activator: org.eclipse.rse.internal.importexport.RemoteImportExportPlugin Bundle-Localization: plugin Export-Package: org.eclipse.rse.internal.importexport;x-internal:=true, - org.eclipse.rse.internal.importexport.files;x-internal:=true + org.eclipse.rse.internal.importexport.files;x-internal:=true, + org.eclipse.rse.internal.synchronize;x-internal:=true, + org.eclipse.rse.internal.synchronize.filesystem;x-internal:=true, + org.eclipse.rse.internal.synchronize.filesystem.subscriber;x-internal:=true, + org.eclipse.rse.internal.synchronize.filesystem.ui;x-internal:=true, + org.eclipse.rse.internal.synchronize.provisional;x-internal:=true Require-Bundle: org.eclipse.core.runtime, org.eclipse.core.resources, org.eclipse.ui, @@ -16,8 +21,11 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.rse.core;bundle-version="[3.0.0,4.0.0)", org.eclipse.rse.ui;bundle-version="[3.0.0,4.0.0)", org.eclipse.rse.subsystems.files.core;bundle-version="[3.0.0,4.0.0)", - org.eclipse.rse.files.ui;bundle-version="[3.0.0,4.0.0)" + org.eclipse.rse.files.ui;bundle-version="[3.0.0,4.0.0)", + org.eclipse.compare, + org.eclipse.team.core, + org.eclipse.team.ui Bundle-ActivationPolicy: lazy Eclipse-LazyStart: true Bundle-Vendor: %providerName -Bundle-RequiredExecutionEnvironment: J2SE-1.4 +Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/rse/plugins/org.eclipse.rse.importexport/icons/full/wizards/fsicon_wiz.gif b/rse/plugins/org.eclipse.rse.importexport/icons/full/wizards/fsicon_wiz.gif new file mode 100644 index 00000000000..af038fa6959 Binary files /dev/null and b/rse/plugins/org.eclipse.rse.importexport/icons/full/wizards/fsicon_wiz.gif differ diff --git a/rse/plugins/org.eclipse.rse.importexport/plugin.properties b/rse/plugins/org.eclipse.rse.importexport/plugin.properties index fba6bb1c986..950025707fc 100644 --- a/rse/plugins/org.eclipse.rse.importexport/plugin.properties +++ b/rse/plugins/org.eclipse.rse.importexport/plugin.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2007 IBM Corporation and others. +# Copyright (c) 2000, 2009 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 @@ -8,6 +8,7 @@ # Contributors: # IBM Corporation - initial API and implementation # Martin Oberhuber (Wind River) - add providerName +# Takuya Miyamoto - [185925] Integrate Platform/Team Synchronization ############################################################################### # NLS_MESSAGEFORMAT_NONE @@ -46,3 +47,9 @@ ImportToProject.tooltip = Import contents of selected folder to a project # Export from project ExportFromProject.label = Export From Project... ExportFromProject.tooltip = Export contents of project to the selected folder + +# Run synchronization +Synchronize.label = Synchronize with ... +Synchronize.tooltip = Synchronize contents in local with remote + +RSESyncParticipant.name = RSE Synchronize \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.importexport/plugin.xml b/rse/plugins/org.eclipse.rse.importexport/plugin.xml index ca2d36e0f05..bb769ede79c 100644 --- a/rse/plugins/org.eclipse.rse.importexport/plugin.xml +++ b/rse/plugins/org.eclipse.rse.importexport/plugin.xml @@ -1,6 +1,6 @@ @@ -144,5 +145,107 @@ David McKnight (IBM) - [261019] New File/Folder actions available in Wo + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/RemoteImportExportPlugin.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/RemoteImportExportPlugin.java index 078205d6eba..ac50f52f7df 100644 --- a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/RemoteImportExportPlugin.java +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/RemoteImportExportPlugin.java @@ -1,13 +1,14 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2009 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 * Martin Oberhuber (Wind River) - [174945] split importexport icons from rse.ui + * Takuya Miyamoto - [185925] Integrate Platform/Team Synchronization *******************************************************************************/ package org.eclipse.rse.internal.importexport; @@ -21,21 +22,21 @@ public class RemoteImportExportPlugin extends SystemBasePlugin { public static final String PLUGIN_ID ="org.eclipse.rse.importexport"; //$NON-NLS-1$ public static final String HELPPREFIX = "org.eclipse.rse.importexport."; //$NON-NLS-1$ - + // Icons public static final String PREFIX = PLUGIN_ID + "."; //$NON-NLS-1$ public static final String ICON_BANNER_SUFFIX = "BannerIcon"; //$NON-NLS-1$ public static final String ICON_EXT = ".gif"; //$NON-NLS-1$ - // WIZARD ICONS... + // WIZARD ICONS... public static final String ICON_WIZARD_DIR = "full/wizban/"; //$NON-NLS-1$ public static final String ICON_EXPORTWIZARD_ROOT = "export_wiz"; //$NON-NLS-1$ public static final String ICON_EXPORTWIZARD = ICON_WIZARD_DIR + ICON_EXPORTWIZARD_ROOT + ICON_EXT; public static final String ICON_EXPORTWIZARD_ID = PREFIX + ICON_EXPORTWIZARD_ROOT + ICON_BANNER_SUFFIX; public static final String ICON_IMPORTWIZARD_ROOT = "import_wiz"; //$NON-NLS-1$ - public static final String ICON_IMPORTWIZARD = ICON_WIZARD_DIR + ICON_EXPORTWIZARD_ROOT + ICON_EXT; - public static final String ICON_IMPORTWIZARD_ID = PREFIX + ICON_EXPORTWIZARD_ROOT + ICON_BANNER_SUFFIX; - + public static final String ICON_IMPORTWIZARD = ICON_WIZARD_DIR + ICON_IMPORTWIZARD_ROOT + ICON_EXT; + public static final String ICON_IMPORTWIZARD_ID = PREFIX + ICON_IMPORTWIZARD_ROOT + ICON_BANNER_SUFFIX; + //The shared instance. private static RemoteImportExportPlugin plugin; @@ -72,16 +73,16 @@ public class RemoteImportExportPlugin extends SystemBasePlugin { /* (non-Javadoc) * @see org.eclipse.rse.core.SystemBasePlugin#initializeImageRegistry() */ - protected void initializeImageRegistry() + protected void initializeImageRegistry() { //SystemElapsedTimer timer = new SystemElapsedTimer(); //timer.setStartTime(); - + String path = getIconPath(); // Wizards... putImageInRegistry(ICON_EXPORTWIZARD_ID, path+ICON_EXPORTWIZARD); putImageInRegistry(ICON_IMPORTWIZARD_ID, path+ICON_IMPORTWIZARD); - + //timer.setEndTime(); //System.out.println("Time to load images: "+timer); } diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/SystemImportExportResources.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/SystemImportExportResources.java index 7c92cd42f67..58305d8ced6 100644 --- a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/SystemImportExportResources.java +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/SystemImportExportResources.java @@ -1,12 +1,13 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2009 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: * David McKnight (IBM) - [223204] [cleanup] fix broken nls strings in files.ui and others + * Martin Oberhuber (Wind River) - [185925] Support Platform/Team Synchronization *******************************************************************************/ package org.eclipse.rse.internal.importexport; @@ -23,6 +24,8 @@ public class SystemImportExportResources extends NLS { public static String RESID_FILEEXPORT_DESTINATION_TOOLTIP; public static String RESID_FILEEXPORT_DESTINATION_BROWSE_LABEL; public static String RESID_FILEEXPORT_DESTINATION_BROWSE_TOOLTIP; + public static String RESID_FILEEXPORT_REVIEW_LABEL; + public static String RESID_FILEEXPORT_REVIEW_TOOLTIP; public static String RESID_FILEEXPORT_OPTION_OVERWRITE_LABEL; public static String RESID_FILEEXPORT_OPTION_OVERWRITE_TOOLTIP; public static String RESID_FILEEXPORT_OPTION_CREATEALL_LABEL; @@ -41,6 +44,8 @@ public class SystemImportExportResources extends NLS { public static String RESID_FILEIMPORT_TITLE; public static String RESID_FILEIMPORT_PAGE1_TITLE; public static String RESID_FILEIMPORT_PAGE1_DESCRIPTION; + public static String RESID_FILEIMPORT_REVIEW_LABEL; + public static String RESID_FILEIMPORT_REVIEW_TOOLTIP; public static String RESID_FILEIMPORT_OPTION_OVERWRITE_LABEL; public static String RESID_FILEIMPORT_OPTION_OVERWRITE_TOOLTIP; public static String RESID_FILEIMPORT_OPTION_CREATEALL_LABEL; diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/SystemImportExportResources.properties b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/SystemImportExportResources.properties index 696a2e865a5..1b2d5287854 100644 --- a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/SystemImportExportResources.properties +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/SystemImportExportResources.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2008 IBM Corporation and others. +# Copyright (c) 2000, 2009 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 @@ -7,6 +7,7 @@ # # Contributors: # David McKnight (IBM) - [223204] [cleanup] fix broken nls strings in files.ui and others +# Martin Oberhuber (Wind River) - [185925] Support Platform/Team Synchronization ############################################################################### # NLS_MESSAGEFORMAT_NONE @@ -26,6 +27,9 @@ RESID_FILEEXPORT_DESTINATION_TOOLTIP=Select the destination folder by browsing a RESID_FILEEXPORT_DESTINATION_BROWSE_LABEL=Browse... RESID_FILEEXPORT_DESTINATION_BROWSE_TOOLTIP=Select the destination folder by browsing a remote system for it +RESID_FILEEXPORT_REVIEW_LABEL=Review/Synchronize +RESID_FILEEXPORT_REVIEW_TOOLTIP=Review/Synchronize + RESID_FILEEXPORT_OPTION_OVERWRITE_LABEL=Overwrite existing files without warning RESID_FILEEXPORT_OPTION_OVERWRITE_TOOLTIP=If a file being exported already exists remotely, replace it without a message @@ -57,6 +61,9 @@ RESID_FILEIMPORT_OPTION_SETTINGS_DESCFILE_LABEL=Description file: RESID_FILEIMPORT_OPTION_SETTINGS_DESCFILE_PATH_TOOLTIP=Enter the description file path RESID_FILEIMPORT_IMPORTING=Importing: +RESID_FILEIMPORT_REVIEW_LABEL=Review/Synchronize +RESID_FILEIMPORT_REVIEW_TOOLTIP=Review/Synchronize + RESID_FILEIMPORT_OPTION_OVERWRITE_LABEL=Overwrite existing resources without warning RESID_FILEIMPORT_OPTION_OVERWRITE_TOOLTIP=If a file being exported already exists remotely, replace it without a message diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteExportWizardPage1.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteExportWizardPage1.java index e6a2d8d93f6..e1ce3f65137 100644 --- a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteExportWizardPage1.java +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteExportWizardPage1.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2009 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 @@ -11,10 +11,12 @@ * David McKnight (IBM) - [216252] [api][nls] Resource Strings specific to subsystems should be moved from rse.ui into files.ui / shells.ui / processes.ui where possible * David McKnight (IBM) - [216252] MessageFormat.format -> NLS.bind * David McKnight (IBM) - [220547] [api][breaking] SimpleSystemMessage needs to specify a message id and some messages should be shared + * Takuya Miyamoto - [185925] Integrate Platform/Team Synchronization *******************************************************************************/ package org.eclipse.rse.internal.importexport.files; import java.io.File; +import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Iterator; import java.util.List; @@ -25,6 +27,7 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; @@ -39,6 +42,11 @@ import org.eclipse.rse.internal.importexport.RemoteImportExportPlugin; import org.eclipse.rse.internal.importexport.RemoteImportExportResources; import org.eclipse.rse.internal.importexport.RemoteImportExportUtil; import org.eclipse.rse.internal.importexport.SystemImportExportResources; +import org.eclipse.rse.internal.synchronize.RSESyncUtils; +import org.eclipse.rse.internal.synchronize.SynchronizeData; +import org.eclipse.rse.internal.synchronize.provisional.ISynchronizeOperation; +import org.eclipse.rse.internal.synchronize.provisional.SynchronizeOperation; +import org.eclipse.rse.internal.synchronize.provisional.Synchronizer; import org.eclipse.rse.services.clientserver.messages.CommonMessages; import org.eclipse.rse.services.clientserver.messages.ICommonMessageIds; import org.eclipse.rse.services.clientserver.messages.SimpleSystemMessage; @@ -69,7 +77,7 @@ import org.eclipse.ui.dialogs.WizardExportResourcesPage; * * 040510 AR Fix "Create folder" question. Previous fix changed the way we were * asking user if they wanted target folder created, to use RSE - * widgets. But introduced error. + * widgets. But introduced error. */ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Listener, ISystemWizardPage { private Object destinationFolder = null; @@ -80,6 +88,7 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste // widgets private Combo destinationNameField; private Button destinationBrowseButton; + protected Button reviewSynchronizeCheckbox; protected Button overwriteExistingFilesCheckbox; protected Button createDirectoryStructureButton; protected Button createSelectionOnlyButton; @@ -98,9 +107,9 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste private static final String STORE_CREATE_DESCRIPTION_FILE_ID = "RemoteExportWizard.STORE_CREATE_DESCRIPTION_FILE_ID"; //$NON-NLS-1$ private static final String STORE_DESCRIPTION_FILE_NAME_ID = "RemoteExportWizard.STORE_DESCRIPTION_FILE_NAME_ID"; //$NON-NLS-1$ //messages - private static final SystemMessage DESTINATION_EMPTY_MESSAGE = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, + private static final SystemMessage DESTINATION_EMPTY_MESSAGE = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, IRemoteImportExportConstants.FILEMSG_DESTINATION_EMPTY, - IStatus.ERROR, + IStatus.ERROR, RemoteImportExportResources.FILEMSG_DESTINATION_EMPTY, RemoteImportExportResources.FILEMSG_DESTINATION_EMPTY_DETAILS); @@ -161,13 +170,13 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste // SystemWidgetHelpers.setWizardPageMnemonics((Composite)c); // parentComposite = (Composite)c; // if (helpId != null) - // SystemWidgetHelpers.setHelp(parentComposite, helpId); + // SystemWidgetHelpers.setHelp(parentComposite, helpId); // } // else if (c instanceof Button) // { // Mnemonics ms = new Mnemonics(); // ms.setMnemonic((Button)c); - // } + // } // configureMessageLine(); } @@ -199,6 +208,9 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste * @param optionsGroup the group into which the option buttons will be placed */ protected void createOptionsGroupButtons(Group optionsGroup) { + reviewSynchronizeCheckbox = SystemWidgetHelpers.createCheckBox(optionsGroup, 1, null, SystemImportExportResources.RESID_FILEEXPORT_REVIEW_LABEL, + SystemImportExportResources.RESID_FILEEXPORT_REVIEW_TOOLTIP); + reviewSynchronizeCheckbox.addListener(SWT.Selection, this); overwriteExistingFilesCheckbox = SystemWidgetHelpers.createCheckBox(optionsGroup, 1, null, SystemImportExportResources.RESID_FILEEXPORT_OPTION_OVERWRITE_LABEL, SystemImportExportResources.RESID_FILEEXPORT_OPTION_OVERWRITE_TOOLTIP); createDirectoryStructureButton = SystemWidgetHelpers.createRadioButton(optionsGroup, null, SystemImportExportResources.RESID_FILEEXPORT_OPTION_CREATEALL_LABEL, @@ -270,6 +282,12 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste descFilePathLabel.setEnabled(isSaveSettings); descFilePathField.setEnabled(isSaveSettings); descFileBrowseButton.setEnabled(isSaveSettings); + + // if review is selected, the other options are grayed out without save settings + boolean isReview = reviewSynchronizeCheckbox.getSelection(); + overwriteExistingFilesCheckbox.setEnabled(!isReview); + createDirectoryStructureButton.setEnabled(!isReview); + createSelectionOnlyButton.setEnabled(!isReview); } /** @@ -281,11 +299,11 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste */ protected boolean ensureDirectoryExists(File directory) { if (!directory.exists()) { - + String msgTxt = RemoteImportExportResources.FILEMSG_TARGET_EXISTS; String msgDetails = NLS.bind(RemoteImportExportResources.FILEMSG_TARGET_EXISTS_DETAILS, directory.getAbsolutePath()); - - SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, + + SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, IRemoteImportExportConstants.FILEMSG_TARGET_EXISTS, IStatus.ERROR, msgTxt, msgDetails); SystemMessageDialog dlg = new SystemMessageDialog(getContainer().getShell(), msg); @@ -293,8 +311,8 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste if (!directory.mkdirs()) { msgTxt = RemoteImportExportResources.FILEMSG_CREATE_FOLDER_FAILED; msgDetails = NLS.bind(RemoteImportExportResources.FILEMSG_CREATE_FOLDER_FAILED_DETAILS, directory.getAbsolutePath()); - - msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, + + msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, IRemoteImportExportConstants.FILEMSG_CREATE_FOLDER_FAILED, IStatus.ERROR, msgTxt, msgDetails); msg.makeSubstitution(directory.getAbsolutePath()); @@ -317,8 +335,8 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste if (targetDirectory.exists() && !targetDirectory.isDirectory()) { String msgTxt = RemoteImportExportResources.FILEMSG_SOURCE_IS_FILE; String msgDetails = NLS.bind(RemoteImportExportResources.FILEMSG_SOURCE_IS_FILE_DETAILS, targetDirectory.getAbsolutePath()); - - SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, + + SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, IRemoteImportExportConstants.FILEMSG_SOURCE_IS_FILE, IStatus.ERROR, msgTxt, msgDetails); @@ -352,7 +370,7 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste IStatus status = op.getStatus(); if (!status.isOK()) { String msgTxt = NLS.bind(RemoteImportExportResources.FILEMSG_EXPORT_FAILED, status); - SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, + SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, IRemoteImportExportConstants.FILEMSG_EXPORT_FAILED, IStatus.ERROR, msgTxt); SystemMessageDialog dlg = new SystemMessageDialog(getContainer().getShell(), msg); @@ -391,15 +409,44 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste data.setSaveSettings(saveSettingsButton.getSelection()); data.setDescriptionFilePath(getDescriptionLocation()); data.setDestination(getDestinationValue()); - // execute export - ret = executeExportOperation(new RemoteFileExportOperation(data, this)); + + if (!reviewSynchronizeCheckbox.getSelection()) { + // execute export + ret = executeExportOperation(new RemoteFileExportOperation(data, this)); + } else { + // run synchronization + SynchronizeData data2 = new SynchronizeData(data); + if (reviewSynchronizeCheckbox.getSelection()) { + data2.setSynchronizeType(ISynchronizeOperation.SYNC_MODE_UI_REVIEW_INITIAL); + } + try { + ret = new Synchronizer(data2).run(new SynchronizeOperation()); + } catch (Exception e) { + // TODO Auto-generated catch block + ret = false; + e.printStackTrace(); + } + + // save description after synchronize operation + try { + if (data.isSaveSettings()) { + RSESyncUtils.saveDescription(data); + } + } catch (CoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } return ret; } - + String msgTxt = RemoteImportExportResources.FILEMSG_EXPORT_NONE_SELECTED; String msgDetails = RemoteImportExportResources.FILEMSG_EXPORT_NONE_SELECTED_DETAILS; - - SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, + + SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, IRemoteImportExportConstants.FILEMSG_EXPORT_NONE_SELECTED, IStatus.ERROR, msgTxt, msgDetails); setErrorMessage(msg); @@ -456,7 +503,7 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste action.setDefaultConnection(host); action.setPreSelection(path); } - + action.run(); IRemoteFile folder = action.getSelectedFolder(); @@ -543,7 +590,7 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste if (!ret) { String msgTxt = RemoteImportExportResources.MSG_IMPORT_EXPORT_UNABLE_TO_USE_CONNECTION; String msgDetails = RemoteImportExportResources.MSG_IMPORT_EXPORT_UNABLE_TO_USE_CONNECTION_DETAILS; - SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, + SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, IRemoteImportExportConstants.MSG_IMPORT_EXPORT_UNABLE_TO_USE_CONNECTION, IStatus.ERROR, msgTxt, msgDetails); SystemMessageDialog.show(getShell(), msg); @@ -654,7 +701,7 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste } destinationNameField.select(selectionIndex); } - destinationFolder = null; // clear destination + destinationFolder = null; // clear destination IHost conn = Utilities.parseForSystemConnection(path); if (conn != null) { IRemoteFile rf = Utilities.parseForIRemoteFile(path); @@ -676,8 +723,8 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste if (conflictingContainer != null) { String msgTxt = NLS.bind(RemoteImportExportResources.FILEMSG_DESTINATION_CONFLICTING, conflictingContainer); String msgDetails = RemoteImportExportResources.FILEMSG_DESTINATION_CONFLICTING_DETAILS; - - SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, + + SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, IRemoteImportExportConstants.FILEMSG_DESTINATION_CONFLICTING, IStatus.ERROR, msgTxt, msgDetails); setErrorMessage(msg); @@ -763,7 +810,7 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste /** * Returns the name of a container with a location that encompasses targetDirectory. * Returns null if there is no conflict. - * + * * @param targetDirectory the path of the directory to check. * @return the conflicting container name or null */ @@ -773,8 +820,8 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste if (root.getLocation().isPrefixOf(testPath)) return "workspace root"; //UniversalSystemPlugin.getString("IFSexport.rootName"); //$NON-NLS-1$ IProject[] projects = root.getProjects(); for (int i = 0; i < projects.length; i++) { - IPath loc = projects[i].getLocation(); - if (loc != null && loc.isPrefixOf(testPath)) + IPath loc = projects[i].getLocation(); + if (loc != null && loc.isPrefixOf(testPath)) return projects[i].getName(); } return null; @@ -877,8 +924,8 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste if (msgLine != null) msgLine.setErrorMessage(exc); else { - String msgTxt = CommonMessages.MSG_ERROR_UNEXPECTED; - SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, + String msgTxt = CommonMessages.MSG_ERROR_UNEXPECTED; + SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, ICommonMessageIds.MSG_ERROR_UNEXPECTED, IStatus.ERROR, msgTxt, exc); @@ -899,7 +946,7 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste // ((SystemDialogPageMessageLine)msgLine).internalSetErrorMessage(message); } - /** + /** * ISystemMessageLine method.
* If the message line currently displays an error, * the message is stored and will be shown after a call to clearErrorMessage @@ -923,6 +970,6 @@ class RemoteExportWizardPage1 extends WizardExportResourcesPage implements Liste if (msgLine != null) msgLine.setMessage(message); // super.setMessage(message); // if (msgLine!=null) - // ((SystemDialogPageMessageLine)msgLine).internalSetMessage(message); + // ((SystemDialogPageMessageLine)msgLine).internalSetMessage(message); } } diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteFileExportActionDelegate.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteFileExportActionDelegate.java index 09dfd07eae4..832d73aa6c8 100644 --- a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteFileExportActionDelegate.java +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteFileExportActionDelegate.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2009 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 @@ -11,10 +11,10 @@ * David McKnight (IBM) - [216252] [api][nls] Resource Strings specific to subsystems should be moved from rse.ui into files.ui / shells.ui / processes.ui where possible * David McKnight (IBM) - [216252] MessageFormat.format -> NLS.bind * David McKnight (IBM) - [220547] [api][breaking] SimpleSystemMessage needs to specify a message id and some messages should be shared + * Takuya Miyamoto - [185925] Integrate Platform/Team Synchronization *******************************************************************************/ package org.eclipse.rse.internal.importexport.files; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; @@ -26,18 +26,16 @@ import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.IAction; import org.eclipse.osgi.util.NLS; -import org.eclipse.rse.internal.importexport.IRemoteImportExportConstants; import org.eclipse.rse.internal.importexport.RemoteImportExportPlugin; import org.eclipse.rse.internal.importexport.RemoteImportExportProblemDialog; import org.eclipse.rse.internal.importexport.RemoteImportExportResources; -import org.eclipse.rse.services.clientserver.messages.SimpleSystemMessage; -import org.eclipse.rse.services.clientserver.messages.SystemMessage; -import org.eclipse.rse.ui.SystemBasePlugin; -import org.eclipse.rse.ui.messages.SystemMessageDialog; -import org.eclipse.ui.PlatformUI; +import org.eclipse.rse.internal.synchronize.SynchronizeData; +import org.eclipse.rse.internal.synchronize.provisional.ISynchronizeOperation; +import org.eclipse.rse.internal.synchronize.provisional.SynchronizeOperation; +import org.eclipse.rse.internal.synchronize.provisional.Synchronizer; /** - * This class is a remote file export action. + * This class is a remote file export action. */ public class RemoteFileExportActionDelegate extends RemoteFileImportExportActionDelegate { /** @@ -50,7 +48,7 @@ public class RemoteFileExportActionDelegate extends RemoteFileImportExportAction if (length < 1) { return; } - // create read multi status + // create read multi status String message; if (length > 1) { message = RemoteImportExportResources.IMPORT_EXPORT_ERROR_CREATE_FILES_FAILED; @@ -127,30 +125,38 @@ public class RemoteFileExportActionDelegate extends RemoteFileImportExportAction } private IStatus export(RemoteFileExportData[] exportDatas) { - IStatus status = null; - for (int i = 0; i < exportDatas.length; i++) { - RemoteFileExportOperation op = new RemoteFileExportOperation(exportDatas[i], new RemoteFileOverwriteQuery()); - try { - PlatformUI.getWorkbench().getProgressService().run(true, true, op); - status = op.getStatus(); - } catch (InvocationTargetException e) { - SystemBasePlugin.logError("Error occured trying to export", e); //$NON-NLS-1$ - status = new Status(IStatus.ERROR, RemoteImportExportPlugin.getDefault().getBundle().getSymbolicName(), 0, "", e); //$NON-NLS-1$ - } catch (InterruptedException e) { - SystemBasePlugin.logError("Error occured trying to export", e); //$NON-NLS-1$ - status = new Status(IStatus.OK, RemoteImportExportPlugin.getDefault().getBundle().getSymbolicName(), 0, "", e); //$NON-NLS-1$ - } - if (!status.isOK()) { - String msgTxt = NLS.bind(RemoteImportExportResources.FILEMSG_EXPORT_FAILED, status); - - SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, - IRemoteImportExportConstants.FILEMSG_EXPORT_FAILED, - IStatus.ERROR, msgTxt); +// IStatus status = null; +// for (int i = 0; i < exportDatas.length; i++) { +// RemoteFileExportOperation op = new RemoteFileExportOperation(exportDatas[i], new RemoteFileOverwriteQuery()); +// try { +// PlatformUI.getWorkbench().getProgressService().run(true, true, op); +// status = op.getStatus(); +// } catch (InvocationTargetException e) { +// SystemBasePlugin.logError("Error occured trying to export", e); //$NON-NLS-1$ +// status = new Status(IStatus.ERROR, RemoteImportExportPlugin.getDefault().getBundle().getSymbolicName(), 0, "", e); //$NON-NLS-1$ +// } catch (InterruptedException e) { +// SystemBasePlugin.logError("Error occured trying to export", e); //$NON-NLS-1$ +// status = new Status(IStatus.OK, RemoteImportExportPlugin.getDefault().getBundle().getSymbolicName(), 0, "", e); //$NON-NLS-1$ +// } +// if (!status.isOK()) { +// String msgTxt = NLS.bind(RemoteImportExportResources.FILEMSG_EXPORT_FAILED, status); +// +// SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, +// IRemoteImportExportConstants.FILEMSG_EXPORT_FAILED, +// IStatus.ERROR, msgTxt); +// +// SystemMessageDialog dlg = new SystemMessageDialog(getShell(), msg); +// dlg.openWithDetails(); +// return null; +// } +// } +// return null; - SystemMessageDialog dlg = new SystemMessageDialog(getShell(), msg); - dlg.openWithDetails(); - return null; - } + // Add re-running synchronize operation + for (int i = 0; i < exportDatas.length; i++) { + SynchronizeData data = new SynchronizeData(exportDatas[i]); + data.setSynchronizeType(ISynchronizeOperation.SYNC_MODE_UI_REVIEW); + new Synchronizer(data).run(new SynchronizeOperation()); } return null; } diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteFileImportActionDelegate.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteFileImportActionDelegate.java index eb7cfdc8b3f..1abb83c4bdb 100644 --- a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteFileImportActionDelegate.java +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteFileImportActionDelegate.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2009 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 @@ -11,10 +11,10 @@ * David McKnight (IBM) - [216252] [api][nls] Resource Strings specific to subsystems should be moved from rse.ui into files.ui / shells.ui / processes.ui where possible * David McKnight (IBM) - [216252] MessageFormat.format -> NLS.bind * David McKnight (IBM) - [220547] [api][breaking] SimpleSystemMessage needs to specify a message id and some messages should be shared + * Takuya Miyamoto - [185925] Integrate Platform/Team Synchronization *******************************************************************************/ package org.eclipse.rse.internal.importexport.files; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; @@ -26,18 +26,17 @@ import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.IAction; import org.eclipse.osgi.util.NLS; -import org.eclipse.rse.internal.importexport.IRemoteImportExportConstants; import org.eclipse.rse.internal.importexport.RemoteImportExportPlugin; import org.eclipse.rse.internal.importexport.RemoteImportExportProblemDialog; import org.eclipse.rse.internal.importexport.RemoteImportExportResources; -import org.eclipse.rse.services.clientserver.messages.SimpleSystemMessage; -import org.eclipse.rse.services.clientserver.messages.SystemMessage; -import org.eclipse.rse.ui.SystemBasePlugin; -import org.eclipse.rse.ui.messages.SystemMessageDialog; -import org.eclipse.ui.PlatformUI; +import org.eclipse.rse.internal.synchronize.SynchronizeData; +import org.eclipse.rse.internal.synchronize.provisional.ISynchronizeOperation; +import org.eclipse.rse.internal.synchronize.provisional.SynchronizeOperation; +import org.eclipse.rse.internal.synchronize.provisional.Synchronizer; +import org.eclipse.rse.services.clientserver.messages.SystemMessageException; /** - * This class is a remote file import action. + * This class is a remote file import action. */ public class RemoteFileImportActionDelegate extends RemoteFileImportExportActionDelegate { /** @@ -50,7 +49,7 @@ public class RemoteFileImportActionDelegate extends RemoteFileImportExportAction if (length < 1) { return; } - // create read multi status + // create read multi status String message; if (length > 1) { message = RemoteImportExportResources.IMPORT_EXPORT_ERROR_CREATE_FILES_FAILED; @@ -127,36 +126,51 @@ public class RemoteFileImportActionDelegate extends RemoteFileImportExportAction } private IStatus importFiles(RemoteFileImportData[] importDatas) { - IStatus status = null; +// IStatus status = null; +// for (int i = 0; i < importDatas.length; i++) { +// RemoteFileImportOperation op = new RemoteFileImportOperation(importDatas[i], FileSystemStructureProvider.INSTANCE, new RemoteFileOverwriteQuery()); +// try { +// PlatformUI.getWorkbench().getProgressService().run(true, true, op); +// status = op.getStatus(); +// } catch (InvocationTargetException e) { +// SystemBasePlugin.logError("Error occured trying to import", e); //$NON-NLS-1$ +// status = new Status(IStatus.ERROR, RemoteImportExportPlugin.getDefault().getBundle().getSymbolicName(), 0, "", e); //$NON-NLS-1$ +// } catch (InterruptedException e) { +// SystemBasePlugin.logError("Error occured trying to import", e); //$NON-NLS-1$ +// status = new Status(IStatus.OK, RemoteImportExportPlugin.getDefault().getBundle().getSymbolicName(), 0, "", e); //$NON-NLS-1$ +// } +// if (!status.isOK()) { +// String msgTxt = NLS.bind(RemoteImportExportResources.FILEMSG_IMPORT_FAILED, status); +// Throwable e = status.getException(); +// SystemMessage msg = null; +// if (e != null){ +// msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, +// IRemoteImportExportConstants.FILEMSG_IMPORT_FAILED, +// IStatus.ERROR, msgTxt, e); +// } else { +// msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, +// IRemoteImportExportConstants.FILEMSG_IMPORT_FAILED, +// IStatus.ERROR, msgTxt); +// } +// +// SystemMessageDialog dlg = new SystemMessageDialog(getShell(), msg); +// dlg.openWithDetails(); +// return null; +// } +// } +// return null; + for (int i = 0; i < importDatas.length; i++) { - RemoteFileImportOperation op = new RemoteFileImportOperation(importDatas[i], FileSystemStructureProvider.INSTANCE, new RemoteFileOverwriteQuery()); try { - PlatformUI.getWorkbench().getProgressService().run(true, true, op); - status = op.getStatus(); - } catch (InvocationTargetException e) { - SystemBasePlugin.logError("Error occured trying to import", e); //$NON-NLS-1$ - status = new Status(IStatus.ERROR, RemoteImportExportPlugin.getDefault().getBundle().getSymbolicName(), 0, "", e); //$NON-NLS-1$ - } catch (InterruptedException e) { - SystemBasePlugin.logError("Error occured trying to import", e); //$NON-NLS-1$ - status = new Status(IStatus.OK, RemoteImportExportPlugin.getDefault().getBundle().getSymbolicName(), 0, "", e); //$NON-NLS-1$ - } - if (!status.isOK()) { - String msgTxt = NLS.bind(RemoteImportExportResources.FILEMSG_IMPORT_FAILED, status); - Throwable e = status.getException(); - SystemMessage msg = null; - if (e != null){ - msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, - IRemoteImportExportConstants.FILEMSG_IMPORT_FAILED, - IStatus.ERROR, msgTxt, e); - } else { - msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, - IRemoteImportExportConstants.FILEMSG_IMPORT_FAILED, - IStatus.ERROR, msgTxt); - } - - SystemMessageDialog dlg = new SystemMessageDialog(getShell(), msg); - dlg.openWithDetails(); - return null; + SynchronizeData data = new SynchronizeData(importDatas[i]); + data.setSynchronizeType(ISynchronizeOperation.SYNC_MODE_UI_REVIEW); + new Synchronizer(data).run(new SynchronizeOperation()); + } catch (SystemMessageException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (CoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } } return null; diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteImportWizardPage1.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteImportWizardPage1.java index 63a066e6c62..82bf433f3e1 100644 --- a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteImportWizardPage1.java +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/RemoteImportWizardPage1.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2009 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 @@ -14,10 +14,12 @@ * David McKnight (IBM) - [219792] use background query when doing import * David McKnight (IBM) - [220547] [api][breaking] SimpleSystemMessage needs to specify a message id and some messages should be shared * David McKnight (IBM) - [219792][importexport][ftp] RSE hangs on FTP import + * Takuya Miyamoto - [185925] Integrate Platform/Team Synchronization *******************************************************************************/ package org.eclipse.rse.internal.importexport.files; import java.io.File; +import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; @@ -31,6 +33,7 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -56,10 +59,16 @@ import org.eclipse.rse.internal.importexport.RemoteImportExportPlugin; import org.eclipse.rse.internal.importexport.RemoteImportExportResources; import org.eclipse.rse.internal.importexport.RemoteImportExportUtil; import org.eclipse.rse.internal.importexport.SystemImportExportResources; +import org.eclipse.rse.internal.synchronize.RSESyncUtils; +import org.eclipse.rse.internal.synchronize.SynchronizeData; +import org.eclipse.rse.internal.synchronize.provisional.ISynchronizeOperation; +import org.eclipse.rse.internal.synchronize.provisional.SynchronizeOperation; +import org.eclipse.rse.internal.synchronize.provisional.Synchronizer; import org.eclipse.rse.services.clientserver.messages.CommonMessages; import org.eclipse.rse.services.clientserver.messages.ICommonMessageIds; import org.eclipse.rse.services.clientserver.messages.SimpleSystemMessage; import org.eclipse.rse.services.clientserver.messages.SystemMessage; +import org.eclipse.rse.services.clientserver.messages.SystemMessageException; import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile; import org.eclipse.rse.ui.SystemBasePlugin; import org.eclipse.rse.ui.SystemWidgetHelpers; @@ -97,13 +106,13 @@ import org.eclipse.ui.model.WorkbenchContentProvider; * Page 1 of the base resource import-from-file-system Wizard */ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listener, ISystemWizardPage { - + private class DummyProvider implements ISelectionProvider { public void addSelectionChangedListener( ISelectionChangedListener listener) { // TODO Auto-generated method stub - + } public ISelection getSelection() { @@ -114,15 +123,15 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen public void removeSelectionChangedListener( ISelectionChangedListener listener) { // TODO Auto-generated method stub - + } public void setSelection(ISelection selection) { // TODO Auto-generated method stub - - } + + } } - + private class QueryAllJob extends Job { private Object _fileSystemObject; @@ -137,7 +146,7 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen _element = element; } - + public IStatus run(IProgressMonitor monitor){ _isActive = true; query(_fileSystemObject, _element, monitor); @@ -150,33 +159,33 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen }); return Status.OK_STATUS; } - + public boolean isActive() { return _isActive; } - - + + private void query(Object parent, MinimizedFileSystemElement element, IProgressMonitor monitor){ - + if (monitor.isCanceled()){ return; } - + List children = _provider.getChildren(parent); if (children == null) children = new ArrayList(1); Iterator childrenEnum = children.iterator(); - + List resultsToQuery = new ArrayList(); - + while (childrenEnum.hasNext()) { Object child = childrenEnum.next(); String elementLabel = _provider.getLabel(child); //Create one level below MinimizedFileSystemElement result = new MinimizedFileSystemElement(elementLabel, element, _provider.isFolder(child)); result.setFileSystemObject(child); - + if (child instanceof UniFilePlus){ if (((UniFilePlus)child).isDirectory()){ resultsToQuery.add(result); @@ -189,31 +198,31 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen Display.getDefault().asyncExec(new Runnable(){ public void run(){ DummyProvider provider = new DummyProvider(); - + ISelection sel1 = new StructuredSelection(_element.getParent()); SelectionChangedEvent evt1 = new SelectionChangedEvent(provider, sel1); selectionGroup.selectionChanged(evt1); - - ISelection sel2 = new StructuredSelection(_element); + + ISelection sel2 = new StructuredSelection(_element); SelectionChangedEvent evt2 = new SelectionChangedEvent(provider, sel2); selectionGroup.selectionChanged(evt2); } }); } - + for (int i = 0; i < resultsToQuery.size(); i++) { MinimizedFileSystemElement celement = (MinimizedFileSystemElement)resultsToQuery.get(i); query(celement.getFileSystemObject(), celement, monitor); celement.setPopulated(true); } - + element.setPopulated(true); } - + } - - - + + + private Object sourceDirectory = null; private String helpId; private Composite parentComposite; @@ -222,6 +231,7 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen private String pendingString, pendingErrorString; protected Composite sourceComposite; protected Combo sourceNameField; + protected Button reviewSynchronizeCheckbox; protected Button overwriteExistingResourcesCheckbox; protected Button createContainerStructureButton; protected Button createOnlySelectedButton; @@ -235,10 +245,10 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen protected Button deselectAllButton; // a boolean to indicate if the user has typed anything private boolean entryChanged = false; - + private QueryAllJob _queryAllJob; private MinimizedFileSystemElement _fileSystemTree; - + // input object protected Object inputObject = null; // flag to indicate whether initial selection was used to set source field @@ -285,14 +295,14 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen * including button presses and registers * default buttons with its shell. * The button id is stored as the buttons client data. - * Note that the parent's layout is assumed to be a GridLayout and + * Note that the parent's layout is assumed to be a GridLayout and * the number of columns in this layout is incremented. * Subclasses may override. *

* * @param parent the parent composite * @param id the id of the button (see - * IDialogConstants.*_ID constants + * IDialogConstants.*_ID constants * for standard dialog button ids) * @param label the label from the button * @param defaultButton true if the button is to be the @@ -396,13 +406,13 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen // SystemWidgetHelpers.setWizardPageMnemonics((Composite)c); // parentComposite = (Composite)c; // if (helpId != null) - // SystemWidgetHelpers.setHelp(parentComposite, helpId); + // SystemWidgetHelpers.setHelp(parentComposite, helpId); // } // else if (c instanceof Button) // { // Mnemonics ms = new Mnemonics(); // ms.setMnemonic((Button)c); - // } + // } // configureMessageLine(); } @@ -410,6 +420,9 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen * Create the import options specification widgets. */ protected void createOptionsGroupButtons(Group optionsGroup) { + reviewSynchronizeCheckbox = SystemWidgetHelpers.createCheckBox(optionsGroup, 1, null, SystemImportExportResources.RESID_FILEIMPORT_REVIEW_LABEL, + SystemImportExportResources.RESID_FILEIMPORT_REVIEW_TOOLTIP); + reviewSynchronizeCheckbox.addListener(SWT.Selection, this); overwriteExistingResourcesCheckbox = SystemWidgetHelpers.createCheckBox(optionsGroup, 1, null, SystemImportExportResources.RESID_FILEIMPORT_OPTION_OVERWRITE_LABEL, SystemImportExportResources.RESID_FILEIMPORT_OPTION_OVERWRITE_TOOLTIP); createContainerStructureButton = SystemWidgetHelpers.createRadioButton(optionsGroup, null, SystemImportExportResources.RESID_FILEIMPORT_OPTION_CREATEALL_LABEL, @@ -516,24 +529,24 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen protected MinimizedFileSystemElement createRootElement(Object fileSystemObject, IImportStructureProvider provider) { boolean isContainer = provider.isFolder(fileSystemObject); String elementLabel = provider.getLabel(fileSystemObject); - + // Use an empty label so that display of the element's full name // doesn't include a confusing label MinimizedFileSystemElement dummyParent = new MinimizedFileSystemElement("", null, true); //$NON-NLS-1$ MinimizedFileSystemElement result = new MinimizedFileSystemElement(elementLabel, dummyParent, isContainer); result.setFileSystemObject(fileSystemObject); - + if (_queryAllJob == null){ _queryAllJob = new QueryAllJob(fileSystemObject, provider, result); _queryAllJob.schedule(); } - + ////Get the files for the element so as to build the first level //result.getFiles(provider); return dummyParent; } - + /** * Create the import source specification widgets @@ -562,8 +575,8 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen if (((File) sourceDirectory).isDirectory()) return true; String msgTxt = RemoteImportExportResources.FILEMSG_FOLDER_IS_FILE; String msgDetails = NLS.bind(RemoteImportExportResources.FILEMSG_FOLDER_IS_FILE_DETAILS, ((File)sourceDirectory).getAbsolutePath()); - - SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, + + SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, IRemoteImportExportConstants.FILEMSG_FOLDER_IS_FILE, IStatus.ERROR, msgTxt, msgDetails); setErrorMessage(msg); @@ -586,18 +599,18 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen IStatus status = op.getStatus(); if (!status.isOK()) { String msgTxt = NLS.bind(RemoteImportExportResources.FILEMSG_IMPORT_FAILED, status); - + SystemMessage msg = null; if (status.getException() != null){ - msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, + msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, IRemoteImportExportConstants.FILEMSG_IMPORT_FAILED, IStatus.ERROR, msgTxt, status.getException()); } else { - msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, + msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, IRemoteImportExportConstants.FILEMSG_IMPORT_FAILED, IStatus.ERROR, msgTxt); } - + SystemMessageDialog dlg = new SystemMessageDialog(getContainer().getShell(), msg); dlg.openWithDetails(); return false; @@ -642,13 +655,53 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen data.setCreateSelectionOnly(createOnlySelectedButton.getSelection()); data.setSaveSettings(saveSettingsButton.getSelection()); data.setDescriptionFilePath(getDescriptionLocation()); - boolean ret = executeImportOperation(new RemoteFileImportOperation(data, FileSystemStructureProvider.INSTANCE, this)); - return ret; + + if (!reviewSynchronizeCheckbox.getSelection()) { + boolean ret = executeImportOperation(new RemoteFileImportOperation(data, FileSystemStructureProvider.INSTANCE, this)); + return ret; + } else { + // run synchronization + SynchronizeData data2 = null; + try { + data2 = new SynchronizeData(data); + } catch (SystemMessageException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (CoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + if (reviewSynchronizeCheckbox.getSelection()) { + data2.setSynchronizeType(ISynchronizeOperation.SYNC_MODE_UI_REVIEW_INITIAL); + } + + boolean ret = false; + + try { + ret = new Synchronizer(data2).run(new SynchronizeOperation()); + } catch (Exception e) { + e.printStackTrace(); + } + + // save description after synchronize operation + try { + if (data.isSaveSettings()) { + RSESyncUtils.saveDescription(data); + } + } catch (CoreException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + return ret; + } } String msgTxt = RemoteImportExportResources.FILEMSG_IMPORT_NONE_SELECTED; String msgDetails = RemoteImportExportResources.FILEMSG_IMPORT_NONE_SELECTED_DETAILS; - - SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, + + SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, IRemoteImportExportConstants.FILEMSG_IMPORT_NONE_SELECTED, IStatus.ERROR, msgTxt, msgDetails); setErrorMessage(msg); @@ -657,9 +710,9 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen - + /** - * Returns a content provider for FileSystemElements that returns + * Returns a content provider for FileSystemElements that returns * only files as children. */ protected ITreeContentProvider getFileProvider() { @@ -693,7 +746,7 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen protected MinimizedFileSystemElement getFileSystemTree() { File sourceDirectory = getSourceDirectory(); if (sourceDirectory == null) return null; - + if (_fileSystemTree == null){ _fileSystemTree = selectFiles(sourceDirectory, FileSystemStructureProvider.INSTANCE); } @@ -701,7 +754,7 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen } /** - * Returns a content provider for FileSystemElements that returns + * Returns a content provider for FileSystemElements that returns * only folders as children. */ protected ITreeContentProvider getFolderProvider() { @@ -740,13 +793,13 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen } /** - * Returns this page's collection of currently-specified resources to be - * imported. This is the primary resource selection facility accessor for + * Returns this page's collection of currently-specified resources to be + * imported. This is the primary resource selection facility accessor for * subclasses. * * Added here to allow access for inner classes. * - * @return a collection of resources currently selected + * @return a collection of resources currently selected * for export (element type: IResource) */ protected List getSelectedResources() { @@ -839,7 +892,7 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen action.setShowNewConnectionPrompt(true); action.setShowPropertySheet(true, false); action.setFoldersOnly(true); - action.run(); + action.run(); IRemoteFile folder = action.getSelectedFolder(); if (folder != null) { clearErrorMessage(); @@ -946,7 +999,7 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen RemoteImportWizard parentWizard = (RemoteImportWizard) getWizard(); boolean isInitializingFromImportData = parentWizard.getInitializeFromImportData(); if (!isInitializingFromImportData) { - // radio buttons and checkboxes + // radio buttons and checkboxes overwriteExistingResourcesCheckbox.setSelection(settings.getBoolean(STORE_OVERWRITE_EXISTING_RESOURCES_ID)); boolean createStructure = settings.getBoolean(STORE_CREATE_CONTAINER_STRUCTURE_ID); createContainerStructureButton.setSelection(createStructure); @@ -1013,7 +1066,7 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen if (sourceNames == null) sourceNames = new String[0]; sourceNames = addToHistory(sourceNames, getSourceDirectoryName()); settings.put(STORE_SOURCE_NAMES_ID, sourceNames); - // radio buttons and checkboxes + // radio buttons and checkboxes settings.put(STORE_OVERWRITE_EXISTING_RESOURCES_ID, overwriteExistingResourcesCheckbox.getSelection()); settings.put(STORE_CREATE_CONTAINER_STRUCTURE_ID, createContainerStructureButton.getSelection()); settings.put(STORE_CREATE_DESCRIPTION_FILE_ID, isSaveSettings()); @@ -1131,7 +1184,7 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen }; IRunnableWithProgress runnable = new IRunnableWithProgress() { public void run(final IProgressMonitor monitor) throws InterruptedException { - + String msg = RemoteImportExportResources.FILEMSG_IMPORT_FILTERING; monitor.beginTask(msg, IProgressMonitor.UNKNOWN); getSelectedResources(filter, monitor); @@ -1147,13 +1200,13 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen //Got interrupted. Do nothing. return; } - // make sure that all paint operations caused by closing the progress - // dialog get flushed, otherwise extra pixels will remain on the screen until + // make sure that all paint operations caused by closing the progress + // dialog get flushed, otherwise extra pixels will remain on the screen until // updateSelections is completed getShell().update(); // The updateSelections method accesses SWT widgets so cannot be executed // as part of the above progress dialog operation since the operation forks - // a new process. + // a new process. updateSelections(selectionMap); } @@ -1219,13 +1272,13 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen //Got interrupted. Do nothing. return; } - // make sure that all paint operations caused by closing the progress - // dialog get flushed, otherwise extra pixels will remain on the screen until + // make sure that all paint operations caused by closing the progress + // dialog get flushed, otherwise extra pixels will remain on the screen until // updateSelections is completed getShell().update(); // The updateSelections method accesses SWT widgets so cannot be executed // as part of the above progress dialog operation since the operation forks - // a new process. + // a new process. updateSelections(selectionMap); } @@ -1270,6 +1323,12 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen descFilePathField.setEnabled(isSaveSettings); descFileBrowseButton.setEnabled(isSaveSettings); } + + // if review is selected, the other options are grayed out without save settings + boolean isReview = reviewSynchronizeCheckbox.getSelection(); + overwriteExistingResourcesCheckbox.setEnabled(!isReview); + createContainerStructureButton.setEnabled(!isReview); + createOnlySelectedButton.setEnabled(!isReview); // this calls to determine whether page can be completed super.updateWidgetEnablements(); } @@ -1371,7 +1430,7 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen * Returns whether the source location conflicts * with the destination resource. This will occur if * the source is already under the destination. - * + * * @param sourcePath the path to check * @return true if there is a conflict, false if not */ @@ -1403,14 +1462,14 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen public boolean performFinish() { return finish(); } - + public void cancel() { if (_queryAllJob != null && _queryAllJob.isActive()){ _queryAllJob.cancel(); } } - - + + /* (non-Javadoc) * @see com.ibm.etools.systems.core.ui.wizards.ISystemWizardPage#setHelp(java.lang.String) @@ -1429,14 +1488,14 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen // ---------------- // INTERNAL METHODS - // ---------------- + // ---------------- /** * Internal method
* Configure the message line */ - // private void configureMessageLine() + // private void configureMessageLine() // { - // msgLine = SystemDialogPageMessageLine.createWizardMsgLine(this); + // msgLine = SystemDialogPageMessageLine.createWizardMsgLine(this); // if (msgLine!=null) // { // if (pendingMessage!=null) @@ -1444,7 +1503,7 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen // if (pendingErrorMessage!=null) // setErrorMessage(pendingErrorMessage); // } - // } + // } // ----------------------------- // ISystemMessageLine methods... // ----------------------------- @@ -1502,10 +1561,10 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen if (msgLine != null) msgLine.setErrorMessage(exc); else { - - SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, + + SystemMessage msg = new SimpleSystemMessage(RemoteImportExportPlugin.PLUGIN_ID, ICommonMessageIds.MSG_ERROR_UNEXPECTED, - IStatus.ERROR, + IStatus.ERROR, CommonMessages.MSG_ERROR_UNEXPECTED, exc); pendingErrorMessage = msg; } @@ -1528,7 +1587,7 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen } } - /** + /** * ISystemMessageLine method.
* If the message line currently displays an error, * the message is stored and will be shown after a call to clearErrorMessage @@ -1553,7 +1612,7 @@ class RemoteImportWizardPage1 extends WizardResourceImportPage implements Listen pendingString = message; } } - + public boolean determinePageCompletion(){ if (_queryAllJob != null && _queryAllJob.isActive()){ return false; diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/UniFilePlus.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/UniFilePlus.java index 06491a25aa2..31060eaa111 100644 --- a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/UniFilePlus.java +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/importexport/files/UniFilePlus.java @@ -1,16 +1,17 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2009 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 * Martin Oberhuber (Wind River) - [186128] Move IProgressMonitor last in all API * Martin Oberhuber (Wind River) - [183824] Forward SystemMessageException from IRemoteFileSubsystem * David McKnight (IBM) - [207178] changing list APIs for file service and subsystems * David Dykstal (IBM) [230821] fix IRemoteFileSubSystem API to be consistent with IFileService + * Takuya Miyamoto - [185925] Integrate Platform/Team Synchronization *******************************************************************************/ package org.eclipse.rse.internal.importexport.files; @@ -18,6 +19,7 @@ import java.io.File; import java.io.FileFilter; import java.io.FilenameFilter; import java.io.IOException; +import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.Vector; @@ -32,7 +34,7 @@ import org.eclipse.rse.ui.SystemBasePlugin; public class UniFilePlus extends File { /** - * + * */ private static final long serialVersionUID = -1717648997950319457L; public IRemoteFile remoteFile = null; @@ -147,11 +149,11 @@ public class UniFilePlus extends File { return remoteFile.getParentPath(); } - public File getParentFile() { - IRemoteFile parent = remoteFile.getParentRemoteFile(); - if (parent != null) { - return new File(parent.getAbsolutePath()); - //return parent.getFileWrapper(); + public UniFilePlus getParentFile() { + IRemoteFile parentFolder = this.remoteFile.getParentRemoteFileSubSystem().getParentFolder(this.remoteFile, null); + + if (parentFolder != null) { + return new UniFilePlus(parentFolder); } else return null; } @@ -220,6 +222,31 @@ public class UniFilePlus extends File { return null; } + public File[] listFiles() { + IRemoteFile[] files = null; + + try { + files = remoteFile.getParentRemoteFileSubSystem().list(this.remoteFile, null); + } catch (SystemMessageException e) { + e.printStackTrace(); + SystemBasePlugin.logError("unexpected exception", e); //$NON-NLS-1$ + } + if (files != null) { + Vector children = new Vector(); + for (int i = 0; i < files.length; i++) { + // fileName = files[idx].getName(); + UniFilePlus fileObj = new UniFilePlus(files[i]); + children.addElement(fileObj); + } + UniFilePlus[] fileObjs = new UniFilePlus[children.size()]; + // for (int i = 0; i < children.size(); i++) + // fileObjs[i] = (UniFilePlus) children.elementAt(i); + // return fileObjs; + return children.toArray(fileObjs); + } else + return null; + } + public String[] list(FilenameFilter filter) { IRemoteFile[] files = null; try { @@ -306,7 +333,7 @@ public class UniFilePlus extends File { public boolean mkdirs() { IRemoteFile dir = null; try { - if (!remoteFile.exists()) dir = remoteFile.getParentRemoteFileSubSystem().createFolder(remoteFile, new NullProgressMonitor()); + if (!remoteFile.exists()) dir = remoteFile.getParentRemoteFileSubSystem().createFolders(remoteFile, new NullProgressMonitor()); } catch (RemoteFileException exc) { Exception e = exc.getRemoteException(); if ((e != null) && (e instanceof SecurityException)) throw (SecurityException) e; @@ -384,4 +411,13 @@ public class UniFilePlus extends File { IProgressMonitor result = new NullProgressMonitor(); return result; } + + public IRemoteFile getRemoteFile() { + return remoteFile; + } + + public InputStream getInputStream() throws SystemMessageException { + return this.remoteFile.getParentRemoteFileSubSystem().getInputStream(this.remoteFile.getParentPath(), this.remoteFile.getName(), this.remoteFile.isBinary(), null); + } + } diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/ISynchronizeData.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/ISynchronizeData.java new file mode 100644 index 00000000000..063cb770e93 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/ISynchronizeData.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2008 Takuya Miyamoto 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: + * Takuya Miyamoto - initial API and implementation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize; + +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; + +/** + * Store synchronize information. This class is needed per each synchronize + * operation. + * + */ +public interface ISynchronizeData { + /** + * Return the descriptionFile path that store synchronize information. + * + * @return + */ + public IFile getDescriptionFile(); + + /** + * Return the remote path. + * + * @return + */ + public String getDestination(); + + /** + * Set destination path + * + * @param destinationPath + */ + public void setDestination(String destination); + + /** + * Return the synchronize type of this operation. + * + * @return + */ + public int getSynchronizeType(); + + public void setSynchronizeType(int synchronizeType); + + /** + * Return the element list that are synchronized in this operation. + * + * @return + */ + public List getElements(); + + public void setElements(List elements); + + /** + * Return if synchronize information is saved or not. + * + * @return + */ + public boolean isSaveSettings(); + + public void setSaveSettings(boolean saveSettings); + + /** + * Return if overwrite existing files or not. + * + * @return + */ + public boolean isOverWriteExistingFiles(); + + public void setOverWriteExistingFiles(boolean overWriteExistingFiles); + + /** + * Return if create directory structure or not. + * + * @return + */ + public boolean isCreateDirectoryStructure(); + + public void setCreateDirectoryStructure(boolean createDirectoryStructure); + + /** + * Return the description file path. + * + * @return + */ + public String getDescriptionFilePath(); + + public void setDescriptionFilePath(String descriptionFilePath); + + /** + * Return if create selection only or not. + * + * @return + */ + public boolean isCreateSelectionOnly(); + + public void setCreateSelectionOnly(boolean createSelectionOnly); + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/RSEResourceVariantComparator.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/RSEResourceVariantComparator.java new file mode 100644 index 00000000000..0016daf87a9 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/RSEResourceVariantComparator.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2008 Takuya Miyamoto 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: + * Takuya Miyamoto - initial API and implementation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize; + +import org.eclipse.core.resources.IResource; +import org.eclipse.rse.internal.synchronize.filesystem.subscriber.FileSystemResourceVariant; +import org.eclipse.team.core.variants.IResourceVariant; +import org.eclipse.team.core.variants.ThreeWayResourceComparator; +import org.eclipse.team.core.variants.ThreeWaySynchronizer; + +public class RSEResourceVariantComparator extends ThreeWayResourceComparator { + public RSEResourceVariantComparator(ThreeWaySynchronizer synchronizer){ + super(synchronizer); + } + + public boolean compare(IResource local, IResourceVariant remote) { + return super.compare(local, remote) && equalSize(local, remote); + } + + /** + * Return if the size of local and remote file are the same. + * @param local + * @param remote + * @return + */ + private boolean equalSize(IResource local, IResourceVariant remote){ + long localSize = local.getLocation().toFile().length(); + long remoteSize = 0; + if(remote instanceof FileSystemResourceVariant){ + remoteSize = ((FileSystemResourceVariant)remote).getFile().length(); + } + return localSize == remoteSize; + } +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/RSESyncUtils.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/RSESyncUtils.java new file mode 100644 index 00000000000..1f9233f2604 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/RSESyncUtils.java @@ -0,0 +1,285 @@ +/******************************************************************************* + * Copyright (c) 2008 Takuya Miyamoto 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: + * Takuya Miyamoto - initial API and implementation + *******************************************************************************/ + +package org.eclipse.rse.internal.synchronize; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.List; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +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.rse.internal.importexport.RemoteImportExportPlugin; +import org.eclipse.rse.internal.importexport.RemoteImportExportUtil; +import org.eclipse.rse.internal.importexport.files.IRemoteFileExportDescriptionWriter; +import org.eclipse.rse.internal.importexport.files.IRemoteFileImportDescriptionWriter; +import org.eclipse.rse.internal.importexport.files.RemoteFileExportData; +import org.eclipse.rse.internal.importexport.files.RemoteFileImportData; +import org.eclipse.rse.internal.synchronize.filesystem.FileSystemProvider; +import org.eclipse.rse.internal.synchronize.provisional.ISynchronizeFilter; +import org.eclipse.rse.services.clientserver.messages.SystemMessageException; +import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile; +import org.eclipse.rse.ui.SystemBasePlugin; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; + +public class RSESyncUtils { + + /** + * Convenience method to get the currently active workbench page. Note that + * the active page may not be the one that the user perceives as active in + * some situations so this method of obtaining the active page should only + * be used if no other method is available. + * + * @return the active workbench page + */ + public static IWorkbenchPage getActivePage() { + IWorkbenchWindow window = RemoteImportExportPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow(); + if (window == null) + return null; + return window.getActivePage(); + } + + /** + * Helper method for export operation. + * Calculate the synchronized elements in local side by using ISynchornizeFilter. + * The filter contains paths of synchronized elements in local side. + * The calculated resources are added in the resources. + * + * @param local root handle in local side. + * @param filter + * @param resources calculated resources + * @throws CoreException + */ + public static void getSynchronizeResources(IResource local, ISynchronizeFilter filter, List resources) throws CoreException{ + if(!filter.isExcluded(local.getFullPath())){ + resources.add(local); + } + if(local.getType() != IResource.FILE){ + for (IResource resource : ((IContainer)local).members()) { + getSynchronizeResources(resource, filter, resources); + } + } + } + + /** + * Helper method for import operation. + * Calculate the synchronize elements in local side by using ISynchronizeFilter. + * The filter contains paths of synchronized elements in remote side. + * The calculated resources are added in the resources. + * + * @param localRoot root handle in local side + * @param remote current element in remote side + * @param remoteRoot root handle in remote side + * @param filter + * @param resources calculated resources + * @throws SystemMessageException + * @throws CoreException + */ + public static void getSynchronizeResources(IResource localRoot, IRemoteFile remote, IRemoteFile remoteRoot, ISynchronizeFilter filter, List resources) throws SystemMessageException, CoreException{ + + if(!filter.isExcluded(new Path(remote.getAbsolutePathPlusConnection()))){ + String relativePath = remote.getAbsolutePath().replace(remoteRoot.getAbsolutePath(), ""); + if(remote.isFile()){ +// IFile file = ((IProject)localRoot).getFile(relativePath); +// IPath filePath = file.getProjectRelativePath(); + resources.add(((IProject)localRoot).getFile(relativePath)); + }else{ +// IFolder folder = ((IProject)localRoot).getFolder(relativePath); +// IPath folderPath = folder.getProjectRelativePath(); + resources.add(((IProject)localRoot).getFolder(relativePath)); + } + + } + if(!remote.isFile()){ + for (IRemoteFile remoteFile : remote.getParentRemoteFileSubSystem().list(remote, null)) { + getSynchronizeResources(localRoot, remoteFile, remoteRoot, filter, resources); + } + } + } + + // + /** + * Saves a description file for the export. + * + * @throws CoreException + * if an unexpected exception occurs. + * @throws IOException + * if an I/O error occurs. + */ + public static void saveDescription(RemoteFileExportData exportData) throws CoreException, IOException { + ByteArrayOutputStream objectStreamOutput = new ByteArrayOutputStream(); + IRemoteFileExportDescriptionWriter writer = exportData.createExportDescriptionWriter(objectStreamOutput); + ByteArrayInputStream fileInput = null; + try { + writer.write(exportData); + fileInput = new ByteArrayInputStream(objectStreamOutput.toByteArray()); + IFile descriptionFile = exportData.getDescriptionFile(); + // check if resource exists + if (descriptionFile.isAccessible()) { + descriptionFile.setContents(fileInput, true, true, null); + } + // if resource does not exist + else { + // now have to check if a variant of this file exists (i.e. + // whether a file exists + // that has the same path with a different case. For case + // insensitive file systems + // such as Windows, this is needed since we can't simply create + // a file with a different + // case. Note that isAccessible() above does not check for file + // paths with different case, + // so we have to check it explicitly). + IResource variant = RemoteImportExportUtil.getInstance().findExistingResourceVariant(descriptionFile.getFullPath()); + // if a variant was not found, create the new file + if (variant == null) { + // check if a variant of the parent exists + // we need to do this because at this point we know that the + // file path does not + // exist, and neither does its variant. However, it is + // possible that the parent path + // has a variant, in which case calling create on the + // description file with + // the path as it is given will fail. We need to get the + // variant path of the parent, + // append the name of the file to the variant path, and + // create a file with that path. + // get parent + IResource parent = descriptionFile.getParent(); + if (parent != null) { + // get parent path + IResource parentVariant = RemoteImportExportUtil.getInstance().findExistingResourceVariant(parent.getFullPath()); + // no parent variant (i.e. in a case sensitive file + // system) + if (parentVariant == null) { + descriptionFile.create(fileInput, true, null); + } + // parent variant found (might be same as original + // parent path) + else { + IPath newPath = parentVariant.getFullPath().append(descriptionFile.getName()); + IFile newDescriptionFile = SystemBasePlugin.getWorkspace().getRoot().getFile(newPath); + newDescriptionFile.create(fileInput, true, null); + } + } + } + // otherwise, simply set the contents of the variant file + else { + if (variant instanceof IFile) { + ((IFile) variant).setContents(fileInput, true, true, null); + } + } + } + } finally { + if (fileInput != null) { + fileInput.close(); + } + if (writer != null) { + writer.close(); + } + } + } + // + + // + /** + * Saves a description file for the export. + * + * @throws CoreException + * if an unexpected exception occurs. + * @throws IOException + * if an I/O error occurs. + */ + public static void saveDescription(RemoteFileImportData importData) throws CoreException, IOException { + ByteArrayOutputStream objectStreamOutput = new ByteArrayOutputStream(); + IRemoteFileImportDescriptionWriter writer = importData.createImportDescriptionWriter(objectStreamOutput); + ByteArrayInputStream fileInput = null; + try { + writer.write(importData); + fileInput = new ByteArrayInputStream(objectStreamOutput.toByteArray()); + IFile descriptionFile = importData.getDescriptionFile(); + // check if resource exists + if (descriptionFile.isAccessible()) { + descriptionFile.setContents(fileInput, true, true, null); + } + // if resource does not exist + else { + // now have to check if a variant of this file exists (i.e. + // whether a file exists + // that has the same path with a different case. For case + // insensitive file systems + // such as Windows, this is needed since we can't simply create + // a file with a different + // case. Note that isAccessible() above does not check for file + // paths with different case, + // so we have to check it explicitly). + IResource variant = RemoteImportExportUtil.getInstance().findExistingResourceVariant(descriptionFile.getFullPath()); + // if a variant was not found, create the new file + if (variant == null) { + // check if a variant of the parent exists + // we need to do this because at this point we know that the + // file path does not + // exist, and neither does its variant. However, it is + // possible that the parent path + // has a variant, in which case calling create on the + // description file with + // the path as it is given will fail. We need to get the + // variant path of the parent, + // append the name of the file to the variant path, and + // create a file with that path. + // get parent + IResource parent = descriptionFile.getParent(); + if (parent != null) { + // get parent path + IResource parentVariant = RemoteImportExportUtil.getInstance().findExistingResourceVariant(parent.getFullPath()); + // no parent variant (i.e. in a case sensitive file + // system) + if (parentVariant == null) { + descriptionFile.create(fileInput, true, null); + } + // parent variant found (might be same as original + // parent path) + else { + IPath newPath = parentVariant.getFullPath().append(descriptionFile.getName()); + IFile newDescriptionFile = SystemBasePlugin.getWorkspace().getRoot().getFile(newPath); + newDescriptionFile.create(fileInput, true, null); + } + } + } + // otherwise, simply set the contents of the variant file + else { + if (variant instanceof IFile) { + ((IFile) variant).setContents(fileInput, true, true, null); + } + } + } + } finally { + if (fileInput != null) { + fileInput.close(); + } + if (writer != null) { + writer.close(); + } + } + } + // + + public static final String PLUGIN_ID = "org.eclipse.rse.internal.synchronize"; //$NON-NLS-1$ + // Repository provider name + public static final String PROVIDER_ID = FileSystemProvider.class.getName(); + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/SynchronizeData.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/SynchronizeData.java new file mode 100644 index 00000000000..a33302a3491 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/SynchronizeData.java @@ -0,0 +1,190 @@ +/******************************************************************************* + * Copyright (c) 2008 Takuya Miyamoto 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: + * Takuya Miyamoto - initial API and implementation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.rse.internal.importexport.files.RemoteFileExportData; +import org.eclipse.rse.internal.importexport.files.RemoteFileImportData; +import org.eclipse.rse.internal.importexport.files.UniFilePlus; +import org.eclipse.rse.internal.synchronize.provisional.ISynchronizeOperation; +import org.eclipse.rse.internal.synchronize.provisional.SynchronizeFilter; +import org.eclipse.rse.services.clientserver.messages.SystemMessageException; +import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile; +import org.eclipse.rse.ui.SystemBasePlugin; + +public class SynchronizeData implements ISynchronizeData { + private String descriptionFilePath; + private String destination; + private List elements; + private int synchronizeType; + private boolean saveSettings; + private boolean createSelectionOnly; + private boolean createDirectoryStructure; + private boolean overWriteExistingFiles; + private boolean reviewSynchronzie; + + public SynchronizeData() { + setDescriptionFilePath(null); + setDestination(null); + setElements(null); + setSynchronizeType(0); + setSaveSettings(false); + setCreateDirectoryStructure(false); + setCreateSelectionOnly(false); + setOverWriteExistingFiles(false); + } + + public SynchronizeData(RemoteFileExportData data) { + setDescriptionFilePath(data.getDescriptionFilePath()); + setDestination(data.getDestination()); + setElements(data.getElements()); + setSynchronizeType(ISynchronizeOperation.SYNC_MODE_OVERRIDE_DEST); + setSaveSettings(data.isSaveSettings()); + setCreateDirectoryStructure(data.isCreateDirectoryStructure()); + setCreateSelectionOnly(data.isCreateSelectionOnly()); + setOverWriteExistingFiles(data.isOverWriteExistingFiles()); + } + + public SynchronizeData(RemoteFileImportData data) throws SystemMessageException, CoreException{ + IRemoteFile remoteRoot = ((UniFilePlus)data.getSource()).getRemoteFile(); + + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IContainer localRoot = (IContainer)workspace.getRoot().findMember(data.getContainerPath()); + + ArrayList paths = new ArrayList(); + List resources = data.getElements(); + for (UniFilePlus uniFilePlus : resources) { + paths.add(new Path(uniFilePlus.getRemoteFile().getAbsolutePathPlusConnection())); + } + SynchronizeFilter filter = new SynchronizeFilter(paths); + ArrayList localResource = new ArrayList(); + + RSESyncUtils.getSynchronizeResources(localRoot, remoteRoot, remoteRoot, filter, localResource); + + setDescriptionFilePath(data.getDescriptionFilePath()); + setDestination(((UniFilePlus)data.getSource()).getRemoteFile().getAbsolutePathPlusConnection()); + setElements(localResource); + setSynchronizeType(ISynchronizeOperation.SYNC_MODE_OVERRIDE_SOURCE); + setSaveSettings(data.isSaveSettings()); + setCreateDirectoryStructure(data.isCreateDirectoryStructure()); + setCreateSelectionOnly(data.isCreateSelectionOnly()); + setOverWriteExistingFiles(data.isOverWriteExistingFiles()); + } + + public IFile getDescriptionFile() { + String pathString = getDescriptionFilePath(); + if (pathString == null) { + return null; + } + IPath path = new Path(pathString); + if (path.isValidPath(path.toString()) && path.segmentCount() >= 2) { + return SystemBasePlugin.getWorkspace().getRoot().getFile(path); + } else { + return null; + } + } + + public String getDescriptionFilePath() { + return descriptionFilePath; + } + + public void setDescriptionFilePath(String descriptionFilePath) { + this.descriptionFilePath = descriptionFilePath; + } + + public String getDestination() { + return destination; + } + + public void setDestination(String destination) { + this.destination = destination; + } + + public List getElements() { + return elements; + } + + public void setElements(List elements) { + this.elements = elements; + } + + public int getSynchronizeType() { + return synchronizeType; + } + + public void setSynchronizeType(int synchronizeType) { + this.synchronizeType = synchronizeType; + } + + public boolean isSaveSettings() { + return saveSettings; + } + + public void setSaveSettings(boolean saveSettings) { + this.saveSettings = saveSettings; + } + + public boolean isCreateSelectionOnly() { + return createSelectionOnly; + } + + public void setCreateSelectionOnly(boolean createSelectionOnly) { + this.createSelectionOnly = createSelectionOnly; + } + + public boolean isOverWriteExistingFiles() { + return overWriteExistingFiles; + } + + public void setOverWriteExistingFiles(boolean overWriteExistingFiles) { + this.overWriteExistingFiles = overWriteExistingFiles; + } + + public boolean isCreateDirectoryStructure() { + return createDirectoryStructure; + } + + public void setCreateDirectoryStructure(boolean createDirectoryStructure) { + this.createDirectoryStructure = createDirectoryStructure; + } + + public boolean isReviewSynchronzie() { + return reviewSynchronzie; + } + + public void setReviewSynchronzie(boolean reviewSynchronzie) { + this.reviewSynchronzie = reviewSynchronzie; + } + + public RemoteFileExportData getExportData() { + RemoteFileExportData data = new RemoteFileExportData(); + data.setElements(getElements()); + data.setCreateDirectoryStructure(isCreateDirectoryStructure()); + data.setCreateSelectionOnly(isCreateSelectionOnly()); + data.setOverWriteExistingFiles(isOverWriteExistingFiles()); + data.setSaveSettings(isSaveSettings()); + data.setDescriptionFilePath(getDescriptionFilePath()); + data.setDestination(getDestination()); + + return data; + } + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/FileModificationValidator.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/FileModificationValidator.java new file mode 100644 index 00000000000..94225c6d2eb --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/FileModificationValidator.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.rse.importexport / FileModificationValidator + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem; + +import java.util.ArrayList; +import java.util.Collection; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.team.FileModificationValidationContext; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.rse.internal.synchronize.RSESyncUtils; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.TeamException; + +/** + * This class models a sentry that verifies whether resources are available for + * editing or overwriting. This has been made a separate class for illustration + * purposes. It may have been more appropriate to have FileSystemProvider + * implement IFileModificationValidator itself since the interface only has two + * methods and their implementation is straight forward. + */ +public final class FileModificationValidator extends org.eclipse.core.resources.team.FileModificationValidator { + + private FileSystemOperations operations; + + /** + * Constructor for FileModificationValidator. + */ + public FileModificationValidator(RepositoryProvider provider) { + operations = ((FileSystemProvider) provider).getOperations(); + } + + /** + * This method will convert any exceptions thrown by the + * SimpleAccessOperations.checkout() to a Status. + * + * @param resources + * the resources that are to be checked out + * @return IStatus a status indicator that reports whether the operation + * went smoothly or not. + */ + private IStatus checkout(IResource[] resources) { + try { + operations.checkout(resources, IResource.DEPTH_INFINITE, null); + } catch (TeamException e) { + // return new Status(IStatus.ERROR, FileSystemPlugin.ID, 0, + // e.getLocalizedMessage(), e); + return new Status(IStatus.ERROR, RSESyncUtils.PLUGIN_ID, 0, e.getLocalizedMessage(), e); + } + return Status.OK_STATUS; + } + + /** + * This method will be called by the workbench/editor before it tries to + * edit one or more files. The idea is to prevent anyone from accidentally + * working on a file that they won't be able to check in changes to. + * + * @see + * org.eclipse.core.resources.IFileModificationValidator#validateEdit(IFile + * [], Object) + */ + @Override + public IStatus validateEdit(IFile[] files, FileModificationValidationContext context) { + Collection toBeCheckedOut = new ArrayList(); + + // Make a list of all the files that need to be checked out: + for (int i = 0; i < files.length; i++) { + if (!operations.isCheckedOut(files[i])) { + toBeCheckedOut.add(files[i]); + } + } + + return checkout((IResource[]) toBeCheckedOut.toArray(new IResource[toBeCheckedOut.size()])); + } + + /** + * This method will be called by the workbench before it tries to save a + * file. It should not attempt to save any files that don't receive an OK + * status here. + * + * @see + * org.eclipse.core.resources.IFileModificationValidator#validateSave(IFile + * ) + */ + @Override + public IStatus validateSave(IFile file) { + if (file.isReadOnly()) { + return checkout(new IResource[] { file }); + } + return Status.OK_STATUS; + } + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/FileSystemOperations.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/FileSystemOperations.java new file mode 100644 index 00000000000..5cfd7f68622 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/FileSystemOperations.java @@ -0,0 +1,534 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Andreas Voss - Bug 181141 [Examples] Team: filesystem provider example can not handle deletions + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / FileSystemOperations + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem; + +import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +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.resources.IResourceVisitor; +import org.eclipse.core.resources.mapping.ResourceTraversal; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.rse.internal.importexport.files.UniFilePlus; +import org.eclipse.rse.internal.synchronize.filesystem.subscriber.FileSystemResourceVariant; +import org.eclipse.rse.internal.synchronize.filesystem.subscriber.FileSystemSubscriber; +import org.eclipse.rse.services.clientserver.messages.SystemMessageException; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.variants.IResourceVariant; +import org.eclipse.team.core.variants.IResourceVariantComparator; +import org.eclipse.team.core.variants.ThreeWaySynchronizer; +import org.eclipse.ui.dialogs.ContainerGenerator; + +/** + * The get and put operations for the file system provider. + */ +public class FileSystemOperations { + // A reference to the provider + // private FileSystemProvider provider; + + FileSystemOperations(FileSystemProvider provider) { + // this.provider = provider; + } + + private FileSystemProvider getProvider(IResource resource) { + return (FileSystemProvider) RepositoryProvider.getProvider(resource.getProject()); + } + + /** + * Make the local state of the project match the remote state by getting any + * out-of-sync resources. The overrideOutgoing flag is used to indicate + * whether locally modified files should also be replaced or left alone. + * + * @param resources + * the resources to get + * @param depth + * the depth of the operation + * @param overrideOutgoing + * whether locally modified resources should be replaced + * @param progress + * a progress monitor + * @throws TeamException + */ + public void get(IResource[] resources, int depth, boolean overrideOutgoing, IProgressMonitor progress) throws TeamException { + try { + // ensure the progress monitor is not null + progress = Policy.monitorFor(progress); + progress.beginTask(Policy.bind("GetAction.working"), 100); //$NON-NLS-1$ + // Refresh the subscriber so we have the latest remote state + FileSystemSubscriber.getInstance().refresh(resources, depth, new SubProgressMonitor(progress, 30)); + internalGet(resources, depth, overrideOutgoing, new SubProgressMonitor(progress, 70)); + } finally { + progress.done(); + } + } + + /** + * Make the local state of the traversals match the remote state by getting + * any out-of-sync resources. The overrideOutgoing flag is used to indicate + * whether locally modified files should also be replaced or left alone. + * + * @param traversals + * the traversals that cover the resources to get + * @param overrideOutgoing + * whether locally modified resources should be replaced + * @param progress + * a progress monitor + * @throws TeamException + */ + public void get(ResourceTraversal[] traversals, boolean overrideOutgoing, IProgressMonitor monitor) throws TeamException { + try { + // ensure the progress monitor is not null + monitor = Policy.monitorFor(monitor); + monitor.beginTask(null, 100 * traversals.length); + for (int i = 0; i < traversals.length; i++) { + ResourceTraversal traversal = traversals[i]; + get(traversal.getResources(), traversal.getDepth(), overrideOutgoing, new SubProgressMonitor(monitor, 100)); + } + } finally { + monitor.done(); + } + } + + /** + * Checkout the given resources to the given depth by setting any files to + * writable (i.e set read-only to false. + * + * @param resources + * the resources to be checked out + * @param depth + * the depth of the checkout + * @param progress + * a progress monitor + * @throws TeamException + */ + public void checkout(IResource[] resources, int depth, IProgressMonitor progress) throws TeamException { + try { + progress = Policy.monitorFor(progress); + progress.beginTask(Policy.bind("FileSystemSimpleAccessOperations.1"), resources.length); //$NON-NLS-1$ + for (int i = 0; i < resources.length; i++) { + Policy.checkCanceled(progress); + resources[i].accept(new IResourceVisitor() { + public boolean visit(IResource resource) throws CoreException { + if (resource.getType() == IResource.FILE) { + // TODO: lock the file on the' server'. + resource.getResourceAttributes().setReadOnly(false); + } + return true; + } + }, depth, false /* include phantoms */); + progress.worked(1); + } + } catch (CoreException e) { + throw TeamException.asTeamException(e); + } finally { + progress.done(); + } + } + + /** + * Check-in the given resources to the given depth by replacing the remote + * (i.e. file system) contents with the local workspace contents. + * + * @param resources + * the resources + * @param depth + * the depth of the operation + * @param overrideIncoming + * indicate whether incoming remote changes should be replaced + * @param progress + * a progress monitor + * @throws TeamException + */ + public void checkin(IResource[] resources, int depth, boolean overrideIncoming, IProgressMonitor progress) throws TeamException { + try { + // ensure the progress monitor is not null + progress = Policy.monitorFor(progress); + progress.beginTask(Policy.bind("PutAction.working"), 100); //$NON-NLS-1$ + // Refresh the subscriber so we have the latest remote state + FileSystemSubscriber.getInstance().refresh(resources, depth, new SubProgressMonitor(progress, 30)); + internalPut(resources, depth, overrideIncoming, new SubProgressMonitor(progress, 70)); + } finally { + progress.done(); + } + } + + /** + * Check-in the given resources to the given depth by replacing the remote + * (i.e. file system) contents with the local workspace contents. + * + * @param traversals + * the traversals that cover the resources to check in + * @param overrideIncoming + * indicate whether incoming remote changes should be replaced + * @param progress + * a progress monitor + * @throws TeamException + */ + public void checkin(ResourceTraversal[] traversals, boolean overrideIncoming, IProgressMonitor monitor) throws TeamException { + try { + // ensure the progress monitor is not null + monitor = Policy.monitorFor(monitor); + monitor.beginTask(null, 100 * traversals.length); + for (int i = 0; i < traversals.length; i++) { + ResourceTraversal traversal = traversals[i]; + checkin(traversal.getResources(), traversal.getDepth(), overrideIncoming, new SubProgressMonitor(monitor, 100)); + // update to the latest state + FileSystemSubscriber.getInstance().refresh(traversal.getResources(), traversal.getDepth(), null); + } + } finally { + monitor.done(); + } + } + + /** + * Return whether the local resource is checked out. A resource is checked + * out if it is a file that is not read-only. Folders are always checked + * out. + * + * @param resource + * the resource + * @return whether the resource is checked out and can be modified + */ + public boolean isCheckedOut(IResource resource) { + if (resource.getType() != IResource.FILE) { + return true; + } + return !resource.getResourceAttributes().isReadOnly(); + // return !resource.isReadOnly(); + } + + /* + * Get the resource variant for the given resource. + */ + private FileSystemResourceVariant getExportResourceVariant(IResource resource) { + // return + // (FileSystemResourceVariant)provider.getResourceVariant(resource); + return (FileSystemResourceVariant) getProvider(resource).getExportResourceVariant(resource); + } + + private FileSystemResourceVariant getImportResourceVariant(IResource resource){ + return (FileSystemResourceVariant) getProvider(resource).getImportResourcevariant(resource); + } + + private void internalGet(IResource[] resources, int depth, boolean overrideOutgoing, IProgressMonitor progress) throws TeamException { + // Traverse the resources and get any that are out-of-sync + // System.out.println("get operation"); + progress.beginTask(Policy.bind("GetAction.working"), IProgressMonitor.UNKNOWN); //$NON-NLS-1$ + for (int i = 0; i < resources.length; i++) { + Policy.checkCanceled(progress); + if (resources[i].getType() == IResource.FILE) { + internalGet((IFile) resources[i], overrideOutgoing, progress); + } else if (depth != IResource.DEPTH_ZERO) { + internalGet((IContainer) resources[i], depth, overrideOutgoing, progress); + } + progress.worked(1); + } + } + + /* + * Get the folder and its children to the depth specified. + */ + private void internalGet(IContainer container, int depth, boolean overrideOutgoing, IProgressMonitor progress) throws TeamException { + try { + ThreeWaySynchronizer synchronizer = FileSystemSubscriber.getInstance().getSynchronizer(); + // Make the local folder state match the remote folder state + List toDelete = new ArrayList(); + if (container.getType() == IResource.FOLDER) { + IFolder folder = (IFolder) container; +// FileSystemResourceVariant remote = getExportResourceVariant(container); + FileSystemResourceVariant remote = getImportResourceVariant(container); + if (!folder.exists() && remote != null) { + // Create the local folder +// folder.create(false, true, progress); + folder.create(true, true, progress); + folder.getResourceAttributes().setReadOnly(false); + synchronizer.setBaseBytes(folder, remote.asBytes()); + } else if (folder.exists() && remote == null) { + // Schedule the folder for removal but delay in + // case the folder contains outgoing changes + toDelete.add(folder); + } + } + + // Get the children + IResource[] children = synchronizer.members(container); + if (children.length > 0) { + internalGet(children, depth == IResource.DEPTH_INFINITE ? IResource.DEPTH_INFINITE : IResource.DEPTH_ZERO, overrideOutgoing, progress); + } + + // Remove any empty folders + for (Iterator iter = toDelete.iterator(); iter.hasNext();) { + IFolder folder = (IFolder) iter.next(); + if (folder.members().length == 0) { + folder.delete(false, true, progress); + synchronizer.flush(folder, IResource.DEPTH_INFINITE); + } + } + } catch (CoreException e) { + throw TeamException.asTeamException(e); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /* + * Get the file if it is out-of-sync. + */ + private void internalGet(IFile localFile, boolean overrideOutgoing, IProgressMonitor progress) throws TeamException { + ThreeWaySynchronizer synchronizer = FileSystemSubscriber.getInstance().getSynchronizer(); + IResourceVariantComparator comparator = FileSystemSubscriber.getInstance().getResourceComparator(); +// FileSystemResourceVariant remote = getExportResourceVariant(localFile); + FileSystemResourceVariant remote = getImportResourceVariant(localFile); + byte[] baseBytes = synchronizer.getBaseBytes(localFile); + FileSystemProvider provider = getProvider(localFile); + IResourceVariant base = provider.getResourceVariant(localFile, baseBytes); +// +// if (!synchronizer.hasSyncBytes(localFile) || (isLocallyModified(localFile) && !overrideOutgoing)) { +// // Do not overwrite the local modification +// return; +// } + if (base != null && remote == null) { + // The remote no longer exists so remove the local + try { + localFile.delete(false, true, progress); + synchronizer.flush(localFile, IResource.DEPTH_ZERO); + return; + } catch (CoreException e) { + throw TeamException.asTeamException(e); + } + } + if (!synchronizer.isLocallyModified(localFile) && base != null && remote != null && comparator.compare(base, remote)) { + // The base and remote are the same and there's no local changes + // so nothing needs to be done + return; + } + try { +// UniFilePlus remoteFile = (UniFilePlus) provider.getExportFile(localFile); + UniFilePlus remoteFile = (UniFilePlus) provider.getImportFile(localFile); + if(!remoteFile.exists()){ + localFile.delete(true, null); + synchronizer.flush(localFile, IResource.DEPTH_ZERO); + }else{ + if(localFile.exists()){ + localFile.delete(true, null); + } + try { + // Copy from the remote file to the local file: + +// if(!localFile.getParent().exists()){ +// IPath parentPath = localFile.getFullPath().removeLastSegments(1); +// ContainerGenerator generator = new ContainerGenerator(parentPath); +// IContainer container = generator.generateContainer(null); +// container.getResourceAttributes().setReadOnly(false); +// } + createParentFolderRecursively(localFile); + remoteFile.getRemoteFile().getParentRemoteFileSubSystem().download(remoteFile.getRemoteFile(), localFile.getLocation().toOSString(), localFile.getCharset(), progress); +// remoteFile.getRemoteFile().getParentRemoteFileSubSystem().download(remoteFile.getRemoteFile(), parent.getLocation().toOSString(), localFile.getCharset(), progress); + + // Mark as read-only to force a checkout before editing + //System.out.println(localFile.getLocation() + " : accessible = " + localFile.isAccessible()+", existing = "+localFile.exists()); + if(localFile.isAccessible()){ + localFile.getResourceAttributes().setReadOnly(true); + } + // update sync status + synchronizer.setBaseBytes(localFile, remote.asBytes()); + } catch (SystemMessageException e) { + e.printStackTrace(); + } + } + } catch (CoreException e) { + throw FileSystemPlugin.wrapException(e); + } + } + + // actual put operation for files + private void internalPut(IResource[] resources, int depth, boolean overrideIncoming, IProgressMonitor progress) throws TeamException { + try { + // ensure the progress monitor is not null + progress = Policy.monitorFor(progress); + progress.beginTask(Policy.bind("PutAction.working"), IProgressMonitor.UNKNOWN); //$NON-NLS-1$ + for (int i = 0; i < resources.length; i++) { + Policy.checkCanceled(progress); + if (resources[i].getType() == IResource.FILE) { + internalPut((IFile) resources[i], overrideIncoming, progress); + } else if (depth > 0) { // Assume that resources are either + // files or containers. + internalPut((IContainer) resources[i], depth, overrideIncoming, progress); + } + progress.worked(1); + } + progress.done(); + } catch (TeamException e) { + throw e; + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Put the file if the sync state allows it. + * + * @param localFile + * the local file + * @param overrideIncoming + * whether incoming changes should be overwritten + * @param progress + * a progress monitor + * @return whether the put succeeded (i.e. the local matches the remote) + * @throws TeamException + */ + private boolean internalPut(IFile localFile, boolean overrideIncoming, IProgressMonitor progress) throws TeamException { + ThreeWaySynchronizer synchronizer = FileSystemSubscriber.getInstance().getSynchronizer(); + IResourceVariantComparator comparator = FileSystemSubscriber.getInstance().getResourceComparator(); + FileSystemResourceVariant remote = getExportResourceVariant(localFile); + byte[] baseBytes = synchronizer.getBaseBytes(localFile); + FileSystemProvider provider = getProvider(localFile); + IResourceVariant base = provider.getResourceVariant(localFile, baseBytes); + + // Check whether we are overriding a remote change + if (base == null && remote != null && !overrideIncoming) { + // The remote is an incoming (or conflicting) addition. + // Do not replace unless we are overriding + return false; + } else if (base != null && remote == null) { + // The remote is an incoming deletion + if (!localFile.exists()) { + // Conflicting deletion. Clear the synchronizer. + synchronizer.flush(localFile, IResource.DEPTH_ZERO); + } else if (!overrideIncoming) { + // Do not override the incoming deletion + return false; + } + } else if (base != null && remote != null) { + boolean same = comparator.compare(base, remote); + if (!isLocallyModified(localFile) && same) { + // The base and remote are the same and there's no local changes + // so nothing needs to be done + return true; + } + if (!same && !overrideIncoming) { + // The remote has changed. Only override if specified + return false; + } + } + + // Handle an outgoing deletion + UniFilePlus remoteFile = (UniFilePlus) provider.getExportFile(localFile); + if (!localFile.exists()) { + remoteFile.delete(); + synchronizer.flush(localFile, IResource.DEPTH_ZERO); + } else { + // Otherwise, upload the contents + try { + // Copy from the local file to the remote file: + try { + if (!remoteFile.getParentFile().exists()) { + remoteFile.getParentFile().mkdirs(); + } + remoteFile.getRemoteFile().getParentRemoteFileSubSystem().upload(localFile.getLocation().toOSString(), remoteFile.getRemoteFile(), localFile.getCharset(), progress); + // Mark the file as read-only to require another checkout + localFile.getResourceAttributes().setReadOnly(true); + } catch (Exception e) { + e.printStackTrace(); + } + // Update the synchronizer base bytes + remote = getExportResourceVariant(localFile); + synchronizer.setBaseBytes(localFile, remote.asBytes()); + } catch (CoreException e) { + throw FileSystemPlugin.wrapException(e); + } catch (Exception e) { + e.printStackTrace(); + } + } + return true; + } + + private boolean isLocallyModified(IFile localFile) throws TeamException { + ThreeWaySynchronizer synchronizer = FileSystemSubscriber.getInstance().getSynchronizer(); + if (!localFile.exists()) { + // Extra check for bug 141415 + return synchronizer.getBaseBytes(localFile) != null; + } + return synchronizer.isLocallyModified(localFile); + } + + /* + * Get the folder and its children to the depth specified. + */ + private void internalPut(IContainer container, int depth, boolean overrideIncoming, IProgressMonitor progress) throws TeamException { + try { + ThreeWaySynchronizer synchronizer = FileSystemSubscriber.getInstance().getSynchronizer(); + FileSystemProvider provider = getProvider(container); + // Make the local folder state match the remote folder state + List toDelete = new ArrayList(); + if (container.getType() == IResource.FOLDER) { + IFolder folder = (IFolder) container; + UniFilePlus diskFile = (UniFilePlus) provider.getExportFile(container); + FileSystemResourceVariant remote = getExportResourceVariant(container); + if (!folder.exists() && remote != null) { + // Schedule the folder for removal but delay in + // case the folder contains incoming changes + toDelete.add(diskFile); + } else if (folder.exists() && remote == null) { + // Create the remote directory and sync up the local + diskFile.mkdir(); + synchronizer.setBaseBytes(folder, provider.getExportResourceVariant(folder).asBytes()); + } + } else if (container.getType() == IResource.PROJECT) { + IProject project = (IProject) container; + UniFilePlus remoteProjectFolder = (UniFilePlus) provider.getExportFile(project); + FileSystemResourceVariant remoteResourceVariant = getExportResourceVariant(container); + if (project.exists() && remoteResourceVariant == null) { + remoteProjectFolder.mkdir(); + synchronizer.setBaseBytes(project, provider.getExportResourceVariant(project).asBytes()); + } + } + + // Get the children + IResource[] children = synchronizer.members(container); + if (children.length > 0) { + internalPut(children, depth == IResource.DEPTH_INFINITE ? IResource.DEPTH_INFINITE : IResource.DEPTH_ZERO, overrideIncoming, progress); + } + + // Remove any empty folders + for (Iterator iter = toDelete.iterator(); iter.hasNext();) { + File diskFile = (File) iter.next(); + if (diskFile.listFiles().length == 0) { + diskFile.delete(); + synchronizer.flush(container, IResource.DEPTH_INFINITE); + } + } + } catch (CoreException e) { + throw TeamException.asTeamException(e); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void createParentFolderRecursively(IResource resource) throws CoreException{ + if(!resource.getParent().exists()){ + ContainerGenerator generator = new ContainerGenerator(resource.getParent().getFullPath()); + IContainer parent = generator.generateContainer(null); + createParentFolderRecursively(parent); + } + } +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/FileSystemPlugin.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/FileSystemPlugin.java new file mode 100644 index 00000000000..9708405bc9f --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/FileSystemPlugin.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / FileSystemPlugin + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem; + +import java.io.IOException; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPluginDescriptor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.rse.internal.synchronize.RSESyncUtils; +import org.eclipse.swt.widgets.Display; +import org.eclipse.team.core.TeamException; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * This is the plugin class for the file system examples. It provides the + * following: + * + *
    + *
  1. public fields for the plugin and provider IDs as defined in the + * plugin.xml + *
  2. initialization on startup of Policy class that provides + * internationalization of strings + *
  3. helper methods for outputing IStatus objects to the log + *
  4. helper methods for converting CoreExceptions and IOExceptions to + * TeamExceptions + *
+ */ +public class FileSystemPlugin extends AbstractUIPlugin { + + /** + * This is the ID of the plugin as defined in the plugin.xml + */ + /** + * This is the provider ID of the plugin as defined in the plugin.xml + */ + // This static field will hold the singleton instance of the plugin class + private static FileSystemPlugin plugin; + + /** + * Override the standard plugin constructor. + * + * @param descriptor + * the plugin descriptor + */ + public FileSystemPlugin(IPluginDescriptor descriptor) { + super(descriptor); + // record this instance as the singleton + plugin = this; + } + + /** + * Return the singlton instance of the plugin class to allow other classes + * in the plugin access to plugin instance methods such as those for logging + * errors, etc. + */ + public static FileSystemPlugin getPlugin() { + return plugin; + } + + /** + * Helper method to convert a CoreException into a TeamException. We do this + * to maintain the core status and code. This type of mapping may not be + * appropriate in more complicated exception handling situations. + * + * @param e + * the CoreException + */ + public static TeamException wrapException(CoreException e) { + return new TeamException(e.getStatus()); + } + + /** + * Helper method to convert an IOException into a TeamException. This type + * of mapping may not be appropriate in more complicated exception handling + * situations. + * + * @param e + * the CoreException + */ + public static TeamException wrapException(IOException e) { + return new TeamException(new Status(IStatus.ERROR, + RSESyncUtils.PLUGIN_ID, TeamException.IO_FAILED, e + .getMessage(), e)); + } + + /** + * Helper method to log an exception status. + * + * @param status + * the status to be logged + */ + public static void log(IStatus status) { + plugin.getLog().log(status); + } + + /** + * Returns the standard display to be used. The method first checks, if the + * thread calling this method has an associated display. If so, this display + * is returned. Otherwise the method returns the default display. + */ + public static Display getStandardDisplay() { + Display display = Display.getCurrent(); + if (display == null) { + display = Display.getDefault(); + } + return display; + } + + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + } + + @Override + public void stop(BundleContext context) throws Exception { + super.stop(context); + } + + public static void log(CoreException e) { + log(new Status(e.getStatus().getSeverity(), + RSESyncUtils.PLUGIN_ID, 0, e.getMessage(), e)); + } +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/FileSystemProvider.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/FileSystemProvider.java new file mode 100644 index 00000000000..f8bbf3966ec --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/FileSystemProvider.java @@ -0,0 +1,380 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / FileSystemProvider + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem; + +import java.io.File; + +import org.eclipse.core.resources.IFileModificationValidator; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceRuleFactory; +import org.eclipse.core.resources.team.FileModificationValidator; +import org.eclipse.core.resources.team.ResourceRuleFactory; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.rse.core.IRSESystemType; +import org.eclipse.rse.core.model.IHost; +import org.eclipse.rse.internal.importexport.files.UniFilePlus; +import org.eclipse.rse.internal.importexport.files.Utilities; +import org.eclipse.rse.internal.synchronize.RSESyncUtils; +import org.eclipse.rse.internal.synchronize.filesystem.subscriber.FileSystemResourceVariant; +import org.eclipse.rse.internal.synchronize.filesystem.subscriber.FileSystemSubscriber; +import org.eclipse.rse.services.clientserver.messages.SystemMessageException; +import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.history.IFileHistoryProvider; +import org.eclipse.team.core.variants.IResourceVariant; + +/** + * This example illustrates how to create a concrete implementation of a + * RepositoryProvider that uses the file system to act as the + * repository. See the plugin.xml file for the xml required to register this + * provider with the Team extension point + * org.eclipse.team.core.repository. The plugin.xml file also + * contains examples of how to filter menu items using a repository provider's + * ID. + * + *

+ * This example provider illustrates the following: + *

    + *
  1. simple working implementation of RepositoyProvider + *
  2. storage of a persistent property with the project (which provides the + * target location for the provider) + *
  3. access to an instance of SimpleAccessOperations for + * performing simple file operations + *
+ * + *

+ * Additional functionality that will be illustrated in the future include: + *

    + *
  1. Validate Save/Validate Edit + *
  2. Move/Delete Hook + *
  3. Project Sets + *
  4. Use of the workspace synchronizer (ISynchronizOperation) + *
  5. Use of decorators + *
  6. combining streams and progress monitors to get responsive UI + *
+ * + */ +public class FileSystemProvider extends RepositoryProvider { + + /* + * Create a custom rule factory to allow more optimistic concurrency + */ + private static final ResourceRuleFactory RESOURCE_RULE_FACTORY = new ResourceRuleFactory() { + // Just need a subclass to instantiate + }; + + // The location of the folder on file system where the repository is stored. + private IPath rootPath; + private UniFilePlus remoteRoot; + + // The QualifiedName that is used to persist the location across workspace + // as a persistent property on a resource + private static QualifiedName FILESYSTEM_REPO_LOC = new QualifiedName(RSESyncUtils.PLUGIN_ID, "disk_location"); //$NON-NLS-1$ + + /** + * Create a new FileSystemProvider. + */ + public FileSystemProvider() { + super(); + } + + /** + * This method is invoked when the provider is mapped to a project. Although + * we have access to the project at this point (using + * getProject(), we don't know the root location so there is + * nothing we can do yet. + * + * @see org.eclipse.team.core.RepositoryProvider#configureProject() + */ + @Override + public void configureProject() throws CoreException { + FileSystemSubscriber.getInstance().handleRootChanged(getProject(), true /* added */); + } + + /** + * This method is invoked when the provider is unmapped from its project. + * + * @see org.eclipse.core.resources.IProjectNature#deconfigure() + */ + public void deconfigure() throws CoreException { + // Clear the persistant property containing the location + getProject().setPersistentProperty(FILESYSTEM_REPO_LOC, null); + FileSystemSubscriber.getInstance().handleRootChanged(getProject(), false /* removed */); + } + + /** + * Return the provider ID as specified in the plugin.xml + * + * @see RepositoryProvider#getID() + */ + @Override + public String getID() { + return RSESyncUtils.PROVIDER_ID; + } + + /** + * Set the file system location for the provider. This mist be invoked after + * the provider is mapped and configured but before the provider is used to + * perform any operations. + * + * @param location + * the path representing the location where the project contents will + * be stored. + * @throws TeamException + */ + public void setTargetLocation(String location) throws TeamException { + // location = transformRSEtoNormal(location); + + // set the instance variable to the provided path + rootPath = new Path(location); + + // ensure that the location is a folder (if it exists) + File file = new File(location); + if (file.exists() && !file.isDirectory()) { + throw new TeamException(Policy.bind("FileSystemProvider.mustBeFolder", location)); //$NON-NLS-1$ + } + + // record the location as a persistent property so it will be remembered + // across platform invocations + try { + getProject().setPersistentProperty(FILESYSTEM_REPO_LOC, location); + } catch (CoreException e) { + throw FileSystemPlugin.wrapException(e); + } + } + + /** + * Returns the folder in the file system to which the provider is connected. + * Return null if there is no location or there was a problem + * determining it. + * + * @return IPath The path to the root of the repository. + */ + public IPath getRoot() { + if (rootPath == null) { + try { + String location = getProject().getPersistentProperty(FILESYSTEM_REPO_LOC); + if (location == null) { + return null; + } + rootPath = new Path(location); + } catch (CoreException e) { + // log the problem and carry on + FileSystemPlugin.log(e); + return null; + } + } + // System.out.println(root); + return rootPath; + } + + /** + * Return an object that provides the operations for transferring data to + * and from the provider's location. + */ + public FileSystemOperations getOperations() { + return new FileSystemOperations(this); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.RepositoryProvider#getFileModificationValidator() + */ + @Override + public IFileModificationValidator getFileModificationValidator() { + return getFileModificationValidator2(); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.RepositoryProvider#getFileModificationValidator2() + */ + @Override + public FileModificationValidator getFileModificationValidator2() { + return new org.eclipse.rse.internal.synchronize.filesystem.FileModificationValidator(this); + } + + /** + * Return the resource variant for the local resource using the bytes to + * identify the variant. + * + * @param resource + * the resource + * @param bytes + * the bytes that identify the resource variant + * @return the resource variant handle + */ + public IResourceVariant getResourceVariant(IResource resource, byte[] bytes) { + // Takuya: it's important if resource exist or not. + if (bytes == null) + return null; + UniFilePlus file = (UniFilePlus) getExportFile(resource); + if (file == null) + return null; + return new FileSystemResourceVariant(file, bytes); + } + + /** + * Return the resource variant for the local resource. + * + * @param resource + * the resource + * @return the resource variant + */ + public IResourceVariant getExportResourceVariant(IResource resource) { + // Takuya: it's important if resource exist or not. + UniFilePlus file = (UniFilePlus) getExportFile(resource); + if (file == null || !file.exists()) + return null; + return new FileSystemResourceVariant(file); + } + + public IResourceVariant getImportResourcevariant(IResource resource){ + UniFilePlus file = (UniFilePlus) getImportFile(resource); + if (file == null || !file.exists()) + return null; + return new FileSystemResourceVariant(file); + } + + /** + * Return the java.io.File that the given resource maps to. + * Return null if the resource is not a child of this + * provider's project. + * The path of return file is targetRootPath/project/relativePath. + * + * @param resource + * the resource + * @return the file that the resource maps to. + */ + public File getExportFile(IResource resource) { + UniFilePlus file = null; + try { + if (resource.getProject().equals(getProject())) { + UniFilePlus root = getRemoteRootFolder(); + String relativePath = transformInDependency(root.getRemoteFile().getHost(), resource.getFullPath().toString()); + // MOB BUGBUG//IRemoteFile remoteFile = + // root.getRemoteFile().getParentRemoteFileSubSystem + // ().getRemoteFileObject(root.getRemoteFile(),relativePath, + // null); + IRemoteFile remoteFile = root.getRemoteFile().getParentRemoteFileSubSystem().getRemoteFileObject(root.getRemoteFile().getAbsolutePath() + relativePath, null); + file = new UniFilePlus(remoteFile); + + } + } catch (SystemMessageException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return file; + } + + public File getImportFile(IResource resource){ + UniFilePlus file = null; + try { + if (resource.getProject().equals(getProject())) { + UniFilePlus root = getRemoteRootFolder(); + String relativePath = transformInDependency(root.getRemoteFile().getHost(), IPath.SEPARATOR + resource.getProjectRelativePath().toString()); + IRemoteFile remoteFile = root.getRemoteFile().getParentRemoteFileSubSystem().getRemoteFileObject(root.getRemoteFile().getAbsolutePath() + relativePath, null); + file = new UniFilePlus(remoteFile); + + } + } catch (SystemMessageException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return file; + } + + + /** + * return whether the resource is file or not + * + * @param resource + * @return + */ + private boolean isFile(IResource resource) { + return new File(this.transformRSEtoNormal(resource.getLocation().toString())).isFile(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.team.core.RepositoryProvider#getRuleFactory() + */ + @Override + public IResourceRuleFactory getRuleFactory() { + return RESOURCE_RULE_FACTORY; + } + + @Override + public IFileHistoryProvider getFileHistoryProvider() { + return null; + } + + private String transformRSEtoNormal(String original) { + if (original.indexOf(":") == -1) { + return original; + } + + String transformed = ""; + String[] str = original.split(":"); + + // Windows + if (str.length > 2) { + transformed += str[1] + ":" + str[2]; + } + // Linux + else { + transformed += str[1]; + } + + return transformed; + + } + + /** + * get the handle fo remote root directory which is specified by IHost and + * absolute path as the member value of this class. + * + * @return + */ + public UniFilePlus getRemoteRootFolder() { + if (remoteRoot == null) { + IPath remoteRootDir = getRoot(); + String remoteRootDirString = transformRSEtoNormal(remoteRootDir.toString()); + IHost conn = Utilities.parseForSystemConnection(remoteRootDir.toString()); + String absolutePath = transformInDependency(conn, remoteRootDirString); + return /* remoteRoot = */new UniFilePlus(Utilities.getIRemoteFile(conn, absolutePath)); + } + + return remoteRoot; + } + + private String transformInDependency(IHost host, String original) { + String ret = ""; + IRSESystemType type = host.getSystemType(); + if (host.getSystemType().isWindows()) { + ret = original.replace("/", "\\"); + } else { + ret = original.replace("\\", "/"); + } + return ret; + } + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/FileSystemProviderType.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/FileSystemProviderType.java new file mode 100644 index 00000000000..f72431fc410 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/FileSystemProviderType.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / FileSystemProviderType + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem; + +import org.eclipse.team.core.ProjectSetCapability; +import org.eclipse.team.core.RepositoryProviderType; + +/** + * The file system repository provider types + */ +public class FileSystemProviderType extends RepositoryProviderType { + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.RepositoryProviderType#getProjectSetCapability() + */ + @Override + public ProjectSetCapability getProjectSetCapability() { + // Create an empty project set capability to test backwards + // compatibility + return new ProjectSetCapability() { + }; + } + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/Policy.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/Policy.java new file mode 100644 index 00000000000..babc51217c1 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/Policy.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / Policy + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; + +/** + * This class is a clone of the Policy classes many Eclipse plugin use to + * provide NLSing of strings and aid in proper progress monitoring. + */ +public class Policy { + + private static ResourceBundle bundle = null; + //private static final String bundleName = "org.eclipse.rse.internal.synchronize.filesystem.messages"; //$NON-NLS-1$ + private static final String bundleName = Policy.class.getPackage().getName() + ".messages"; + + /* + * Returns a resource bundle, creating one if it none is available. + */ + private static ResourceBundle getResourceBundle() { + // thread safety + ResourceBundle tmpBundle = bundle; + if (tmpBundle != null) + return tmpBundle; + // always create a new classloader to be passed in + // in order to prevent ResourceBundle caching + return bundle = ResourceBundle.getBundle(bundleName); + // return bundle = ResourceBundle.getBundle(""); + } + + /** + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given string. + */ + public static String bind(String id, String binding) { + return bind(id, new String[] { binding }); + } + + /** + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given strings. + */ + public static String bind(String id, String binding1, String binding2) { + return bind(id, new String[] { binding1, binding2 }); + } + + /** + * Gets a string from the resource bundle. We don't want to crash because of + * a missing String. Returns the key if not found. + */ + public static String bind(String key) { + try { + return getResourceBundle().getString(key); + } catch (MissingResourceException e) { + return key; + } catch (NullPointerException e) { + return "!" + key + "!"; //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + /** + * Gets a string from the resource bundle and binds it with the given + * arguments. If the key is not found, return the key. + */ + public static String bind(String key, Object[] args) { + try { + return MessageFormat.format(bind(key), args); + } catch (MissingResourceException e) { + return key; + } catch (NullPointerException e) { + return "!" + key + "!"; //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + /** + * Progress monitor helpers + */ + public static void checkCanceled(IProgressMonitor monitor) { + if (monitor.isCanceled()) + throw new OperationCanceledException(); + } + + public static IProgressMonitor monitorFor(IProgressMonitor monitor) { + if (monitor == null) + return new NullProgressMonitor(); + return monitor; + } +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/messages.properties b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/messages.properties new file mode 100644 index 00000000000..14e6d00cced --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/messages.properties @@ -0,0 +1,42 @@ +############################################################################### +# Copyright (c) 2000, 2008 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 +# Takuya Miyamoto - Adapted from org.eclipse.rse.team.example / messages.properties +############################################################################### +fileSystem.propertyLocation=Location: + +FileSystemMainPage.location=Location: +FileSystemMainPage.browseDir=&Browse... +FileSystemMainPage.notValidLocation=Location must be an existing directory + +fsMainPage.name=Select a file system location +fsMainPage.description=This location will be used to share resources with a team + +ConfigurationWizard.errorTitle=Error configuring the provider. +ConfigurationWizard.error=File System provider could not be created + +ConfigurationWizard.name=File System Repository +ConfigurationWizard.description=File System Repository Properties + +DisconnectAction.errorTitle=Error Disconnecting + +PutAction.working=Putting resources... +PutAction.problemMessage=A problem occured putting the resources. + +GetAction.working=Getting resources... +GetAction.problemMessage=A problem occured getting the resources. + +ReplaceAction.working=Replacing resources... +ReplaceAction.problemMessage=A problem occured replacing the resources. + +FileSystemProvider.mustBeFolder=Target location ''{0}'' is a file and must be a folder. +RemoteResource.mustBeFolder=Resource ''{0}'' is a file so it cannot have entries +FileSystemRemoteResource.0=This resource is a container so it cannot have data. +FileSystemSimpleAccessOperations.1=Checking resources out... +FileSystemSimpleAccessOperations.3=Re-locking resources... diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/subscriber/FileSystemMergeContext.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/subscriber/FileSystemMergeContext.java new file mode 100644 index 00000000000..14975a566d4 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/subscriber/FileSystemMergeContext.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2006, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / FileSystemMergeContext + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem.subscriber; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.rse.internal.synchronize.RSESyncUtils; +import org.eclipse.team.core.diff.IDiff; +import org.eclipse.team.core.diff.IThreeWayDiff; +import org.eclipse.team.core.mapping.ISynchronizationScopeManager; +import org.eclipse.team.core.mapping.provider.MergeStatus; +import org.eclipse.team.core.mapping.provider.ResourceDiffTree; +import org.eclipse.team.core.subscribers.SubscriberMergeContext; + +/** + * A merge context for merging file system changes. + */ +public class FileSystemMergeContext extends SubscriberMergeContext { + + /** + * Create the file system merge context for the given scope manager. + * + * @param manager + * the scope manager + */ + public FileSystemMergeContext(ISynchronizationScopeManager manager) { + super(FileSystemSubscriber.getInstance(), manager); + initialize(); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.mapping.provider.MergeContext#makeInSync(org.eclipse + * .team.core.diff.IDiff, org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + protected void makeInSync(IDiff diff, IProgressMonitor monitor) throws CoreException { + IResource resource = ResourceDiffTree.getResourceFor(diff); + FileSystemSubscriber.getInstance().makeInSync(resource); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.mapping.IMergeContext#markAsMerged(org.eclipse. + * team.core.diff.IDiff, boolean, org.eclipse.core.runtime.IProgressMonitor) + */ + public void markAsMerged(IDiff diff, boolean inSyncHint, IProgressMonitor monitor) throws CoreException { + // TODO if inSyncHint is true, we should test to see if the contents + // match + IResource resource = ResourceDiffTree.getResourceFor(diff); + FileSystemSubscriber.getInstance().markAsMerged(resource, monitor); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.mapping.IMergeContext#reject(org.eclipse.team.core + * .diff.IDiff, org.eclipse.core.runtime.IProgressMonitor) + */ + public void reject(IDiff diff, IProgressMonitor monitor) throws CoreException { + markAsMerged(diff, false, monitor); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.mapping.provider.MergeContext#getMergeRule(org. + * eclipse.team.core.diff.IDiff) + */ + @Override + public ISchedulingRule getMergeRule(IDiff node) { + return ResourceDiffTree.getResourceFor(node).getProject(); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.mapping.provider.MergeContext#merge(org.eclipse + * .team.core.diff.IDiff, boolean, + * org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + public IStatus merge(IDiff diff, boolean ignoreLocalChanges, IProgressMonitor monitor) throws CoreException { + // Only attempt the merge for non-conflicts. The reason we do this + // is because the file system provider doesn't really have the proper + // base + // so merging conflicts doesn't work properly + if (!ignoreLocalChanges) { + IResource resource = ResourceDiffTree.getResourceFor(diff); + if (diff instanceof IThreeWayDiff && resource instanceof IFile) { + IThreeWayDiff twd = (IThreeWayDiff) diff; + if (twd.getDirection() == IThreeWayDiff.CONFLICTING) { + // return new MergeStatus(FileSystemPlugin.ID, + // "Cannot merge conflicting files", new IFile[] { + // (IFile)resource }); + return new MergeStatus(RSESyncUtils.PLUGIN_ID, "Cannot merge conflicting files", new IFile[] { (IFile) resource }); + } + } + } + return super.merge(diff, ignoreLocalChanges, monitor); + } + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/subscriber/FileSystemRemoteTree.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/subscriber/FileSystemRemoteTree.java new file mode 100644 index 00000000000..c87aed48f7d --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/subscriber/FileSystemRemoteTree.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / FileSystemRemoteTree + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem.subscriber; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.rse.internal.synchronize.RSESyncUtils; +import org.eclipse.rse.internal.synchronize.filesystem.FileSystemProvider; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.variants.IResourceVariant; +import org.eclipse.team.core.variants.ThreeWayRemoteTree; + +/** + * The file system three-way remote resource variant tree that provides the + * ability to traverse the file system for the creation of resource variants. + */ +public class FileSystemRemoteTree extends ThreeWayRemoteTree { + + /** + * Create the file system remote resource variant tree + * + * @param subscriber + * the file system subscriber + */ + public FileSystemRemoteTree(FileSystemSubscriber subscriber) { + super(subscriber); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.variants.AbstractResourceVariantTree#fetchMembers + * (org.eclipse.team.core.variants.IResourceVariant, + * org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + protected IResourceVariant[] fetchMembers(IResourceVariant variant, IProgressMonitor progress) throws TeamException { + return ((FileSystemResourceVariant) variant).members(); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.variants.AbstractResourceVariantTree#fetchVariant + * (org.eclipse.core.resources.IResource, int, + * org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + protected IResourceVariant fetchVariant(IResource resource, int depth, IProgressMonitor monitor) throws TeamException { + try { + RepositoryProvider provider = RepositoryProvider.getProvider(resource.getProject(), RSESyncUtils.PROVIDER_ID); + if (provider != null) { + return ((FileSystemProvider) provider).getExportResourceVariant(resource); + } + } catch (RuntimeException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/subscriber/FileSystemResourceVariant.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/subscriber/FileSystemResourceVariant.java new file mode 100644 index 00000000000..07e8195517a --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/subscriber/FileSystemResourceVariant.java @@ -0,0 +1,174 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / FileSystemResourceVariant + *******************************************************************************/ + +package org.eclipse.rse.internal.synchronize.filesystem.subscriber; + +import java.io.InputStream; +import java.util.Date; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.rse.internal.importexport.files.UniFilePlus; +import org.eclipse.rse.internal.synchronize.RSESyncUtils; +import org.eclipse.rse.services.clientserver.messages.SystemMessageException; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.variants.CachedResourceVariant; + +public class FileSystemResourceVariant extends CachedResourceVariant { + + private UniFilePlus ioFile; + private byte[] bytes; + + /** + * Create a resource variant for the given file. The bytes will be + * calculated when they are accessed. + * + * @param file + * the file + */ + public FileSystemResourceVariant(UniFilePlus file) { + this.ioFile = file; + } + + /** + * Create a resource variant for the given file and sync bytes. + * + * @param file + * the file + * @param bytes + * the timestamp bytes + */ + public FileSystemResourceVariant(UniFilePlus file, byte[] bytes) { + this.ioFile = file; + this.bytes = bytes; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.variants.CachedResourceVariant#fetchContents(org + * .eclipse.core.runtime.IProgressMonitor) + */ + @Override + protected void fetchContents(IProgressMonitor monitor) throws TeamException { + setContents(getContents(), monitor); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.team.core.variants.CachedResourceVariant#getCachePath() + */ + @Override + protected String getCachePath() { + // append the timestamp to the file path to give each variant a unique + // path + return getFilePath() + " " + ioFile.lastModified(); //$NON-NLS-1$ + } + + private String getFilePath() { + return ioFile.getCanonicalPath(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.team.core.variants.CachedResourceVariant#getCacheId() + */ + @Override + protected String getCacheId() { + // return FileSystemPlugin.ID; + return RSESyncUtils.PLUGIN_ID; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.team.core.variants.IResourceVariant#getName() + */ + public String getName() { + return ioFile.getName(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.team.core.variants.IResourceVariant#isContainer() + */ + public boolean isContainer() { + return ioFile.isDirectory(); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.variants.IResourceVariant#getContentIdentifier() + */ + public String getContentIdentifier() { + // Use the modification timestamp as the content identifier + return new Date(ioFile.lastModified()).toString(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.team.core.variants.IResourceVariant#asBytes() + */ + // TODO By using byte[] which this method return, ResourceComparator run + // comparison. + // so, this method provide how to compare with which value. + public byte[] asBytes() { + if (bytes == null) { + // For simplicity, convert the timestamp to it's string + // representation. + // A more optimal storage format would be the 8 bytes that make up + // the long. + bytes = Long.toString(ioFile.lastModified()).getBytes(); + } + return bytes; + } + + /** + * Return the files contained by the file of this resource variant. + * + * @return the files contained by the file of this resource variant. + */ + public FileSystemResourceVariant[] members() { + if (isContainer()) { + UniFilePlus[] members = (UniFilePlus[]) ioFile.listFiles(); + FileSystemResourceVariant[] result = new FileSystemResourceVariant[members.length]; + for (int i = 0; i < members.length; i++) { + result[i] = new FileSystemResourceVariant(members[i]); + } + return result; + } + return new FileSystemResourceVariant[0]; + } + + /** + * @return + */ + public InputStream getContents() throws TeamException { + // Takuya: modified for managing remote resource + try { + return ioFile.getInputStream(); + } catch (SystemMessageException e) { + throw new TeamException("Failed to fetch contents for " + getFilePath(), e); //$NON-NLS-1$ + } + } + + public UniFilePlus getFile() { + return ioFile; + } + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/subscriber/FileSystemSubscriber.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/subscriber/FileSystemSubscriber.java new file mode 100644 index 00000000000..ad5b1e17883 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/subscriber/FileSystemSubscriber.java @@ -0,0 +1,193 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / FileSystemSubscriber + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem.subscriber; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.rse.internal.synchronize.RSEResourceVariantComparator; +import org.eclipse.rse.internal.synchronize.RSESyncUtils; +import org.eclipse.rse.internal.synchronize.filesystem.FileSystemProvider; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.synchronize.SyncInfo; +import org.eclipse.team.core.variants.IResourceVariant; +import org.eclipse.team.core.variants.ThreeWayRemoteTree; +import org.eclipse.team.core.variants.ThreeWaySubscriber; +import org.eclipse.team.core.variants.ThreeWaySynchronizer; + +/** + * This is an example file system subscriber that overrides ThreeWaySubscriber. + * It uses a repository provider (FileSystemProvider) to determine + * and manage the roots and to create resource variants. It also makes use of a + * file system specific remote tree (FileSystemRemoteTree) for + * provided the remote tree access and refresh. + * + * @see ThreeWaySubscriber + * @see ThreeWaySynchronizer + * @see FileSystemProvider + * @see FileSystemRemoteTree + */ +public class FileSystemSubscriber extends ThreeWaySubscriber { + + private static FileSystemSubscriber instance; + + /** + * Return the file system subscriber singleton. + * + * @return the file system subscriber singleton. + */ + public static synchronized FileSystemSubscriber getInstance() { + if (instance == null) { + instance = new FileSystemSubscriber(); + } + return instance; + } + + /** + * Create the file system subscriber. + */ + private FileSystemSubscriber() { + super(new ThreeWaySynchronizer(new QualifiedName(RSESyncUtils.PLUGIN_ID, "workpsace-sync"))); //$NON-NLS-1$ + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.variants.ThreeWaySubscriber#getResourceVariant( + * org.eclipse.core.resources.IResource, byte[]) + */ + @Override + public IResourceVariant getResourceVariant(IResource resource, byte[] bytes) throws TeamException { + RepositoryProvider provider = RepositoryProvider.getProvider(resource.getProject(), RSESyncUtils.PROVIDER_ID); + if (provider != null) { + return ((FileSystemProvider) provider).getResourceVariant(resource, bytes); + } + return null; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.team.core.variants.ThreeWaySubscriber#createRemoteTree() + */ + @Override + protected ThreeWayRemoteTree createRemoteTree() { + return new FileSystemRemoteTree(this); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.team.core.subscribers.Subscriber#getName() + */ + @Override + public String getName() { + return "Synchronize"; //$NON-NLS-1$ + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.team.core.subscribers.Subscriber#roots() + */ + @Override + public IResource[] roots() { + List result = new ArrayList(); + IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); + for (int i = 0; i < projects.length; i++) { + IProject project = projects[i]; + if (project.isAccessible()) { + RepositoryProvider provider = RepositoryProvider.getProvider(project, RSESyncUtils.PROVIDER_ID); + if (provider != null) { + result.add(project); + } + } + } + return (IProject[]) result.toArray(new IProject[result.size()]); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.variants.ThreeWaySubscriber#handleRootChanged(org + * .eclipse.core.resources.IResource, boolean) + */ + @Override + public void handleRootChanged(IResource resource, boolean added) { + // Override to allow FileSystemProvider to signal the addition and + // removal of roots + super.handleRootChanged(resource, added); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.variants.ResourceVariantTreeSubscriber#getSyncInfo + * (org.eclipse.core.resources.IResource, + * org.eclipse.team.core.variants.IResourceVariant, + * org.eclipse.team.core.variants.IResourceVariant) + */ + @Override + protected SyncInfo getSyncInfo(IResource local, IResourceVariant base, IResourceVariant remote) throws TeamException { + // Override to use a custom sync info +// FileSystemSyncInfo info = new FileSystemSyncInfo(local, base, remote, this.getResourceComparator()); + FileSystemSyncInfo info = new FileSystemSyncInfo(local, base, remote, new RSEResourceVariantComparator(getSynchronizer())); + info.init(); + return info; + } + + /** + * Make the resource in-sync. + * + * @param resource + * the resource + * @throws TeamException + */ + public void makeInSync(IResource resource) throws TeamException { + ThreeWaySynchronizer synchronizer = getSynchronizer(); + byte[] remoteBytes = synchronizer.getRemoteBytes(resource); + if (remoteBytes == null) { + if (!resource.exists()) + synchronizer.flush(resource, IResource.DEPTH_ZERO); + } else { + synchronizer.setBaseBytes(resource, remoteBytes); + } + } + + /** + * Make the change an outgoing change + * + * @param resource + * @throws TeamException + */ + public void markAsMerged(IResource resource, IProgressMonitor monitor) throws TeamException { + makeInSync(resource); + try { + resource.touch(monitor); + } catch (CoreException e) { + throw TeamException.asTeamException(e); + } + } + + + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/subscriber/FileSystemSyncInfo.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/subscriber/FileSystemSyncInfo.java new file mode 100644 index 00000000000..f23fdde8a6a --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/subscriber/FileSystemSyncInfo.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / FileSystemSyncInfo + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem.subscriber; + +import org.eclipse.core.resources.IResource; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.synchronize.SyncInfo; +import org.eclipse.team.core.variants.IResourceVariant; +import org.eclipse.team.core.variants.IResourceVariantComparator; + +/** + * Provide a custom sync info that will report files that exist both locally and + * remotely as in-sync and will return a null base if there is an incoming + * change. + */ +public class FileSystemSyncInfo extends SyncInfo { + + public FileSystemSyncInfo(IResource local, IResourceVariant base, IResourceVariant remote, IResourceVariantComparator comparator) { + super(local, base, remote, comparator); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.core.subscribers.SyncInfo#calculateKind(org.eclipse. + * core.runtime.IProgressMonitor) + */ + @Override + protected int calculateKind() throws TeamException { + if (getLocal().getType() != IResource.FILE) { + if (getLocal().exists() && getRemote() != null) { + return IN_SYNC; + } + } + return super.calculateKind(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.team.core.synchronize.SyncInfo#getBase() + */ + @Override + public IResourceVariant getBase() { + // If the kind has been set and there is an incoming change + // return null as the base since the server does not keep the + // base contents + // if ((getKind() & INCOMING) > 0) { + // return null; + // } + return super.getBase(); + } +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/CompoundResourceTraversal.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/CompoundResourceTraversal.java new file mode 100644 index 00000000000..f1ee6a50df4 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/CompoundResourceTraversal.java @@ -0,0 +1,291 @@ +/******************************************************************************* + * Copyright (c) 2006, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / CompoundResourceTraversal + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem.ui; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.mapping.ResourceTraversal; +import org.eclipse.core.runtime.IPath; + +/** + * Helper class that accumulates several traversals in order to generate a final + * set of traversals and to perform certain queries on a set of traversals. + * + * TODO: This class was copied from the Team Core plugin since it was an + * internal class. It should probably be made API at some point. + */ +public class CompoundResourceTraversal { + + private Set deepFolders = new HashSet(); + private Set shallowFolders = new HashSet(); + private Set zeroFolders = new HashSet(); + private Set files = new HashSet(); + + public void addTraversals(ResourceTraversal[] traversals) { + for (int i = 0; i < traversals.length; i++) { + ResourceTraversal traversal = traversals[i]; + addTraversal(traversal); + } + } + + public void addTraversal(ResourceTraversal traversal) { + IResource[] resources = traversal.getResources(); + for (int i = 0; i < resources.length; i++) { + IResource resource = resources[i]; + addResource(resource, traversal.getDepth()); + } + } + + public void addResource(IResource resource, int depth) { + if (resource.getType() == IResource.FILE) { + if (!isCovered(resource, IResource.DEPTH_ZERO)) + files.add(resource); + } + switch (depth) { + case IResource.DEPTH_INFINITE: + addDeepFolder(resource); + break; + case IResource.DEPTH_ONE: + addShallowFolder(resource); + break; + case IResource.DEPTH_ZERO: + addZeroFolder(resource); + break; + } + } + + private void addShallowFolder(IResource resource) { + if (!isCovered(resource, IResource.DEPTH_ONE)) { + shallowFolders.add(resource); + removeDescendants(resource, IResource.DEPTH_ONE); + } + } + + public boolean isCovered(IResource resource, int depth) { + IPath fullPath = resource.getFullPath(); + // Regardless of the depth, look for a deep folder that covers the + // resource + for (Iterator iter = deepFolders.iterator(); iter.hasNext();) { + IResource deepFolder = (IResource) iter.next(); + if (deepFolder.getFullPath().isPrefixOf(fullPath)) { + return true; + } + } + // For files, look in the shallow folders and files + if (resource.getType() == IResource.FILE) { + return (shallowFolders.contains(resource.getParent()) || files.contains(resource)); + } + // For folders, look in appropriate sets + switch (depth) { + case IResource.DEPTH_ONE: + return (shallowFolders.contains(resource)); + case IResource.DEPTH_ZERO: + return (shallowFolders.contains(resource.getParent()) || zeroFolders.contains(resource)); + } + return false; + } + + private void addZeroFolder(IResource resource) { + if (!isCovered(resource, IResource.DEPTH_ZERO)) + zeroFolders.add(resource); + } + + private void addDeepFolder(IResource resource) { + if (!isCovered(resource, IResource.DEPTH_INFINITE)) { + deepFolders.add(resource); + removeDescendants(resource, IResource.DEPTH_INFINITE); + } + } + + private void removeDescendants(IResource resource, int depth) { + IPath fullPath = resource.getFullPath(); + // First, remove any files that are now covered + for (Iterator iter = files.iterator(); iter.hasNext();) { + IResource child = (IResource) iter.next(); + switch (depth) { + case IResource.DEPTH_INFINITE: + if (fullPath.isPrefixOf(child.getFullPath())) { + iter.remove(); + } + break; + case IResource.DEPTH_ONE: + if (fullPath.equals(child.getFullPath().removeLastSegments(1))) { + iter.remove(); + } + break; + } + } + // Now, remove any shallow folders + if (depth == IResource.DEPTH_INFINITE) { + for (Iterator iter = shallowFolders.iterator(); iter.hasNext();) { + IResource child = (IResource) iter.next(); + if (fullPath.isPrefixOf(child.getFullPath())) { + iter.remove(); + } + } + } + // Finally, remove any zero folders + for (Iterator iter = zeroFolders.iterator(); iter.hasNext();) { + IResource child = (IResource) iter.next(); + switch (depth) { + case IResource.DEPTH_INFINITE: + if (fullPath.isPrefixOf(child.getFullPath())) { + iter.remove(); + } + break; + case IResource.DEPTH_ONE: + // TODO: Is a zero folder covered by a shallow folder? + if (fullPath.equals(child.getFullPath().removeLastSegments(1))) { + iter.remove(); + } + break; + } + } + } + + public void add(CompoundResourceTraversal compoundTraversal) { + addResources((IResource[]) compoundTraversal.deepFolders.toArray(new IResource[compoundTraversal.deepFolders.size()]), IResource.DEPTH_INFINITE); + addResources((IResource[]) compoundTraversal.shallowFolders.toArray(new IResource[compoundTraversal.shallowFolders.size()]), IResource.DEPTH_ONE); + addResources((IResource[]) compoundTraversal.zeroFolders.toArray(new IResource[compoundTraversal.zeroFolders.size()]), IResource.DEPTH_ZERO); + addResources((IResource[]) compoundTraversal.files.toArray(new IResource[compoundTraversal.files.size()]), IResource.DEPTH_ZERO); + } + + public void addResources(IResource[] resources, int depth) { + for (int i = 0; i < resources.length; i++) { + IResource resource = resources[i]; + addResource(resource, depth); + } + + } + + /** + * Return the resources contained in the given traversals that are not + * covered by this traversal + * + * @param traversals + * the traversals being testes + * @return the resources contained in the given traversals that are not + * covered by this traversal + */ + public IResource[] getUncoveredResources(ResourceTraversal[] traversals) { + CompoundResourceTraversal newTraversals = new CompoundResourceTraversal(); + newTraversals.addTraversals(traversals); + return getUncoveredResources(newTraversals); + } + + /* + * Return any resources in the other traversal that are not covered by this + * traversal + */ + private IResource[] getUncoveredResources(CompoundResourceTraversal otherTraversal) { + Set result = new HashSet(); + for (Iterator iter = otherTraversal.files.iterator(); iter.hasNext();) { + IResource resource = (IResource) iter.next(); + if (!isCovered(resource, IResource.DEPTH_ZERO)) { + result.add(resource); + } + } + for (Iterator iter = otherTraversal.zeroFolders.iterator(); iter.hasNext();) { + IResource resource = (IResource) iter.next(); + if (!isCovered(resource, IResource.DEPTH_ZERO)) { + result.add(resource); + } + } + for (Iterator iter = otherTraversal.shallowFolders.iterator(); iter.hasNext();) { + IResource resource = (IResource) iter.next(); + if (!isCovered(resource, IResource.DEPTH_ONE)) { + result.add(resource); + } + } + for (Iterator iter = otherTraversal.deepFolders.iterator(); iter.hasNext();) { + IResource resource = (IResource) iter.next(); + if (!isCovered(resource, IResource.DEPTH_INFINITE)) { + result.add(resource); + } + } + return (IResource[]) result.toArray(new IResource[result.size()]); + } + + public ResourceTraversal[] asTraversals() { + List result = new ArrayList(); + if (!files.isEmpty() || !zeroFolders.isEmpty()) { + Set combined = new HashSet(); + combined.addAll(files); + combined.addAll(zeroFolders); + result.add(new ResourceTraversal((IResource[]) combined.toArray(new IResource[combined.size()]), IResource.DEPTH_ZERO, IResource.NONE)); + } + if (!shallowFolders.isEmpty()) { + result.add(new ResourceTraversal((IResource[]) shallowFolders.toArray(new IResource[shallowFolders.size()]), IResource.DEPTH_ONE, IResource.NONE)); + } + if (!deepFolders.isEmpty()) { + result.add(new ResourceTraversal((IResource[]) deepFolders.toArray(new IResource[deepFolders.size()]), IResource.DEPTH_INFINITE, IResource.NONE)); + } + return (ResourceTraversal[]) result.toArray(new ResourceTraversal[result.size()]); + } + + public IResource[] getRoots() { + List result = new ArrayList(); + result.addAll(files); + result.addAll(zeroFolders); + result.addAll(shallowFolders); + result.addAll(deepFolders); + return (IResource[]) result.toArray(new IResource[result.size()]); + } + + public ResourceTraversal[] getUncoveredTraversals(ResourceTraversal[] traversals) { + CompoundResourceTraversal other = new CompoundResourceTraversal(); + other.addTraversals(traversals); + return getUncoveredTraversals(other); + } + + public ResourceTraversal[] getUncoveredTraversals(CompoundResourceTraversal otherTraversal) { + CompoundResourceTraversal uncovered = new CompoundResourceTraversal(); + for (Iterator iter = otherTraversal.files.iterator(); iter.hasNext();) { + IResource resource = (IResource) iter.next(); + if (!isCovered(resource, IResource.DEPTH_ZERO)) { + uncovered.addResource(resource, IResource.DEPTH_ZERO); + } + } + for (Iterator iter = otherTraversal.zeroFolders.iterator(); iter.hasNext();) { + IResource resource = (IResource) iter.next(); + if (!isCovered(resource, IResource.DEPTH_ZERO)) { + uncovered.addResource(resource, IResource.DEPTH_ZERO); + } + } + for (Iterator iter = otherTraversal.shallowFolders.iterator(); iter.hasNext();) { + IResource resource = (IResource) iter.next(); + if (!isCovered(resource, IResource.DEPTH_ONE)) { + uncovered.addResource(resource, IResource.DEPTH_ONE); + } + } + for (Iterator iter = otherTraversal.deepFolders.iterator(); iter.hasNext();) { + IResource resource = (IResource) iter.next(); + if (!isCovered(resource, IResource.DEPTH_INFINITE)) { + uncovered.addResource(resource, IResource.DEPTH_INFINITE); + } + } + return uncovered.asTraversals(); + } + + public void clear() { + deepFolders.clear(); + shallowFolders.clear(); + zeroFolders.clear(); + files.clear(); + } + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/FileSystemOperation.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/FileSystemOperation.java new file mode 100644 index 00000000000..f3ccfeaa66a --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/FileSystemOperation.java @@ -0,0 +1,181 @@ +/******************************************************************************* + * Copyright (c) 2006, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / FileSystemOperation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem.ui; + +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.mapping.ResourceMapping; +import org.eclipse.core.resources.mapping.ResourceTraversal; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.rse.internal.synchronize.RSESyncUtils; +import org.eclipse.rse.internal.synchronize.filesystem.FileSystemProvider; +import org.eclipse.rse.internal.synchronize.filesystem.subscriber.FileSystemSubscriber; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.mapping.ISynchronizationScope; +import org.eclipse.team.core.subscribers.SubscriberScopeManager; +import org.eclipse.team.ui.synchronize.ModelOperation; +import org.eclipse.ui.IWorkbenchPart; + +public abstract class FileSystemOperation extends ModelOperation { + + /** + * Create a scope manager for the file system example. + * + * @param name + * the name of the manager + * @param inputMappings + * the input mappings + * @return a scope manager + */ + public static SubscriberScopeManager createScopeManager(String name, ResourceMapping[] inputMappings) { + return new SubscriberScopeManager(name, inputMappings, FileSystemSubscriber.getInstance(), true); + } + + /** + * Create a file system operation. + * + * @param part + * the part from which the operation was launched + * @param manager + * the scope manager that provides the input to the operation + */ + protected FileSystemOperation(IWorkbenchPart part, SubscriberScopeManager manager) { + super(part, manager); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.ui.synchronize.ModelOperation#execute(org.eclipse.core + * .runtime.IProgressMonitor) + */ + @Override + protected void execute(IProgressMonitor monitor) throws InvocationTargetException { + try { + Map providerToTraversals = getProviderToTraversalsMap(); + monitor.beginTask(getTaskName(), providerToTraversals.size() * 100); + monitor.setTaskName(getTaskName()); + for (Iterator iter = providerToTraversals.keySet().iterator(); iter.hasNext();) { + FileSystemProvider provider = (FileSystemProvider) iter.next(); + ResourceTraversal[] traversals = getTraversals(providerToTraversals, provider); + execute(provider, traversals, new SubProgressMonitor(monitor, 100)); + } + } catch (CoreException e) { + throw new InvocationTargetException(e); + } finally { + monitor.done(); + } + } + + /** + * Return a map of FileSystemProvider to ResourceTraversals. + * + * @return a map of FileSystemProvider to ResourceTraversals + */ + private Map getProviderToTraversalsMap() { + HashMap result = new HashMap(); + ISynchronizationScope scope = getScope(); + ResourceMapping[] mappings = scope.getMappings(); + for (int i = 0; i < mappings.length; i++) { + ResourceMapping mapping = mappings[i]; + ResourceTraversal[] traversals = scope.getTraversals(mapping); + for (int j = 0; j < traversals.length; j++) { + ResourceTraversal traversal = traversals[j]; + IResource[] resources = traversal.getResources(); + for (int k = 0; k < resources.length; k++) { + IResource resource = resources[k]; + recordResourceAndDepth(result, resource, traversal.getDepth()); + } + } + } + return result; + } + + /** + * Return the file system provider associated with the given project or + * null if the project is not mapped to the file system + * provider. + * + * @param project + * the project + * @return the file system provider associated with the given project + */ + protected FileSystemProvider getProviderFor(IProject project) { + return (FileSystemProvider) RepositoryProvider.getProvider(project, RSESyncUtils.PROVIDER_ID); + } + + private void recordResourceAndDepth(HashMap providerToTraversals, IResource resource, int depth) { + FileSystemProvider provider = getProviderFor(resource.getProject()); + if (provider != null) { + CompoundResourceTraversal traversal = (CompoundResourceTraversal) providerToTraversals.get(provider); + if (traversal == null) { + traversal = new CompoundResourceTraversal(); + providerToTraversals.put(provider, traversal); + } + traversal.addResource(resource, depth); + } + } + + /** + * Return the traversals that were accumulated for the given provider by the + * {@link #getProviderToTraversalsMap()} method. + * + * @param providerToTraversals + * the provider to traversals map + * @param provider + * the provider + * @return the traversals for the given provider + */ + private ResourceTraversal[] getTraversals(Map providerToTraversals, FileSystemProvider provider) { + CompoundResourceTraversal traversal = (CompoundResourceTraversal) providerToTraversals.get(provider); + return traversal.asTraversals(); + } + + /** + * Execute the operation for the given provider and traversals. + * + * @param provider + * the provider + * @param traversals + * the traversals to be operated on + * @param monitor + * a progress monitor + * @throws CoreException + */ + protected abstract void execute(FileSystemProvider provider, ResourceTraversal[] traversals, IProgressMonitor monitor) throws CoreException; + + /** + * Return the task name for this operation. + * + * @return the task name for this operation + */ + protected abstract String getTaskName(); + + /* + * (non-Javadoc) + * + * @see org.eclipse.team.ui.TeamOperation#canRunAsJob() + */ + @Override + protected boolean canRunAsJob() { + return true; + } + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/FileSystemSynchronizeParticipant.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/FileSystemSynchronizeParticipant.java new file mode 100644 index 00000000000..a3977ca0f31 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/FileSystemSynchronizeParticipant.java @@ -0,0 +1,274 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / FileSystemSynchronizeParticipant + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem.ui; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.mapping.ResourceMapping; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.viewers.ILabelDecorator; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.rse.internal.synchronize.filesystem.FileSystemPlugin; +import org.eclipse.rse.internal.synchronize.filesystem.subscriber.FileSystemMergeContext; +import org.eclipse.rse.internal.synchronize.filesystem.subscriber.FileSystemSubscriber; +import org.eclipse.swt.graphics.Image; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.mapping.ISynchronizationScopeManager; +import org.eclipse.team.core.mapping.provider.MergeContext; +import org.eclipse.team.core.mapping.provider.SynchronizationContext; +import org.eclipse.team.core.synchronize.SyncInfo; +import org.eclipse.team.core.variants.IResourceVariant; +import org.eclipse.team.internal.ui.TeamUIPlugin; +import org.eclipse.team.internal.ui.Utils; +import org.eclipse.team.ui.TeamUI; +import org.eclipse.team.ui.synchronize.ISynchronizeModelElement; +import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; +import org.eclipse.team.ui.synchronize.ModelSynchronizeParticipant; +import org.eclipse.team.ui.synchronize.ModelSynchronizeParticipantActionGroup; + +/** + * This is an example synchronize participant for the file system provider. It + * will allow showing synchronization state for local resources mapped to a + * remote file system location. + * + * @since 3.0 + */ +public class FileSystemSynchronizeParticipant extends ModelSynchronizeParticipant { + + /** + * The participant id for the org.eclipse.team.ui.synchronizeParticipant + * extension point. + */ + public static final String ID = "org.eclipse.rse.internal.synchronize.filesystem.participant"; //$NON-NLS-1$ + + /** + * The viewer id for the org.eclipse.ui.navigator.viewer extension point. + */ + public static final String VIEWER_ID = "org.eclipse.rse.internal.synchronize.filesystem.syncViewer"; //$NON-NLS-1$ + + /** + * Custom menu groups included in the viewer definition in the plugin.xml. + */ + public static final String CONTEXT_MENU_PUT_GROUP_1 = "put"; //$NON-NLS-1$ + public static final String CONTEXT_MENU_GET_GROUP_1 = "get"; //$NON-NLS-1$ + public static final String CONTEXT_MENU_OVERWRITE_GROUP_1 = "overwrite"; //$NON-NLS-1$ + + /** + * A custom label decorator that will show the remote mapped path for each + * file. + */ + public class FileSystemParticipantLabelDecorator extends LabelProvider implements ILabelDecorator { + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.ILabelDecorator#decorateImage(org.eclipse + * .swt.graphics.Image, java.lang.Object) + */ + public Image decorateImage(Image image, Object element) { + return image; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.jface.viewers.ILabelDecorator#decorateText(java.lang. + * String, java.lang.Object) + */ + public String decorateText(String text, Object element) { + try { + if (element instanceof ISynchronizeModelElement) { + IResource resource = ((ISynchronizeModelElement) element).getResource(); + if (resource != null && resource.getType() == IResource.FILE) { + SyncInfo info = FileSystemSubscriber.getInstance().getSyncInfo(resource); + IResourceVariant variant = info.getRemote(); + if (variant != null) { + return text + " (" + variant.getContentIdentifier() + ")"; + } + } + } + } catch (TeamException e) { + FileSystemPlugin.log(e); + } + return null; + } + } + + /** + * Action group that contributes the get an put menus to the context menu in + * the synchronize view + */ + public class FileSystemParticipantActionGroup extends ModelSynchronizeParticipantActionGroup { + private ModelPutAction putAction; + private ModelGetAction getAction; + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.ui.synchronize.SynchronizePageActionGroup#initialize + * (org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration) + */ + @Override + public void initialize(ISynchronizePageConfiguration configuration) { + super.initialize(configuration); + putAction = new ModelPutAction("", configuration); + getAction = new ModelGetAction("", configuration); + } + + + + @Override + public void fillContextMenu(IMenuManager menu) { + //menu.remove(CONTEXT_MENU_GET_GROUP_1); + //menu.remove(CONTEXT_MENU_PUT_GROUP_1); + + try { + //super.fillContextMenu(menu); + TreeSelection selection = (TreeSelection)getConfiguration().getSite().getSelectionProvider().getSelection(); + boolean hasOutgoingChange = false; + boolean hasIncomingChange = false; + boolean hasSingleResource = selection.size() == 1?true:false; + + List resources = new ArrayList(); + for (Iterator iterator = selection.iterator(); iterator.hasNext();) { + resources.add(Utils.getResource(iterator.next())); + } + + for (Iterator iterator = resources.iterator(); iterator.hasNext();) { + + IResource resource = (IResource) iterator.next(); + SyncInfo info = FileSystemSubscriber.getInstance().getSyncInfo(resource); + + if(SyncInfo.getDirection(info.getKind()) == SyncInfo.OUTGOING){ + hasOutgoingChange = true; + } else if (SyncInfo.getDirection(info.getKind()) == SyncInfo.INCOMING){ + hasIncomingChange = true; + } + } + + if(hasOutgoingChange){ + if(hasSingleResource){ + putAction.setText("Put"); + }else{ + putAction.setText("Put All"); + } + appendToGroup(ISynchronizePageConfiguration.P_CONTEXT_MENU, CONTEXT_MENU_PUT_GROUP_1, putAction); + menu.appendToGroup(CONTEXT_MENU_PUT_GROUP_1, putAction); + } + + if(hasIncomingChange){ + if(hasSingleResource){ + getAction.setText("Get"); + }else{ + getAction.setText("Get All"); + } + appendToGroup(ISynchronizePageConfiguration.P_CONTEXT_MENU, CONTEXT_MENU_GET_GROUP_1, getAction); + menu.appendToGroup(CONTEXT_MENU_GET_GROUP_1, getAction); + } + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + } + /** + * Create a file system participant. This method is invoked by the + * Synchronize view when a persisted participant is being restored. + * Participants that are persisted must override the {@link + * #restoreContext(ISynchronizationScopeManager)} method to recreate the + * context and may also need to override the {@link + * #createScopeManager(ResourceMapping[])} method if they require a custom + * scope manager. + */ + public FileSystemSynchronizeParticipant() { + super(); + } + + /** + * Create the participant for the given context. This method is used by the + * file system plugin to create a participant and then add it to the sync + * view (or show it is some other container). + * + * @param context + * the synchronization context + */ + public FileSystemSynchronizeParticipant(SynchronizationContext context) { + super(context); + try { + setInitializationData(TeamUI.getSynchronizeManager().getParticipantDescriptor(ID)); + } catch (CoreException e) { + TeamUIPlugin.log(e); + } + setSecondaryId(Long.toString(System.currentTimeMillis())); + } + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.team.ui.synchronize.subscribers.SubscriberParticipant# + * initializeConfiguration + * (org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration) + */ + @Override + protected void initializeConfiguration(ISynchronizePageConfiguration configuration) { + super.initializeConfiguration(configuration); + configuration.setProperty(ISynchronizePageConfiguration.P_VIEWER_ID, VIEWER_ID); + + // Add the label decorator + configuration.addLabelDecorator(new FileSystemParticipantLabelDecorator()); + + } + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.team.ui.synchronize.ModelSynchronizeParticipant# + * createMergeActionGroup() + */ + @Override + protected ModelSynchronizeParticipantActionGroup createMergeActionGroup() { + return new FileSystemParticipantActionGroup(); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.team.ui.synchronize.ModelSynchronizeParticipant#restoreContext + * (org.eclipse.team.core.mapping.ISynchronizationScopeManager) + */ + @Override + protected MergeContext restoreContext(ISynchronizationScopeManager manager) { + return new FileSystemMergeContext(manager); + } + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.team.ui.synchronize.ModelSynchronizeParticipant# + * createScopeManager(org.eclipse.core.resources.mapping.ResourceMapping[]) + */ + @Override + protected ISynchronizationScopeManager createScopeManager(ResourceMapping[] mappings) { + return FileSystemOperation.createScopeManager(getName(), mappings); + } +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/GetOperation.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/GetOperation.java new file mode 100644 index 00000000000..3a5583837ee --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/GetOperation.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / GetOperation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem.ui; + +import org.eclipse.core.resources.mapping.ResourceTraversal; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.rse.internal.synchronize.filesystem.FileSystemProvider; +import org.eclipse.rse.internal.synchronize.filesystem.Policy; +import org.eclipse.rse.internal.synchronize.filesystem.subscriber.FileSystemSubscriber; +import org.eclipse.team.core.TeamException; +import org.eclipse.team.core.diff.IDiff; +import org.eclipse.team.core.diff.IDiffVisitor; +import org.eclipse.team.core.diff.IThreeWayDiff; +import org.eclipse.team.core.subscribers.SubscriberScopeManager; +import org.eclipse.ui.IWorkbenchPart; + +/** + * Operation for getting the contents of the selected resources + */ +public class GetOperation extends FileSystemOperation { + + private boolean overwriteOutgoing; + + public GetOperation(IWorkbenchPart part, SubscriberScopeManager manager) { + super(part, manager); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.rse.internal.synchronize.provisional.filesystem.ui.FileSystemOperation#execute + * (org.eclipse.rse.internal.synchronize.provisional.filesystem.FileSystemProvider, + * org.eclipse.core.resources.mapping.ResourceTraversal[], + * org.eclipse.core.runtime.SubProgressMonitor) + */ + @Override + protected void execute(FileSystemProvider provider, ResourceTraversal[] traversals, IProgressMonitor monitor) throws CoreException { + try { + provider.getOperations().get(traversals, isOverwriteOutgoing(), monitor); + if (!isOverwriteOutgoing() && hasIncomingChanges(traversals)) { + throw new TeamException("Could not get all changes due to conflicts."); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + private boolean hasIncomingChanges(ResourceTraversal[] traversals) throws CoreException { + final RuntimeException found = new RuntimeException(); + try { + FileSystemSubscriber.getInstance().accept(traversals, new IDiffVisitor() { + public boolean visit(IDiff diff) { + if (diff instanceof IThreeWayDiff) { + IThreeWayDiff twd = (IThreeWayDiff) diff; + if (twd.getDirection() == IThreeWayDiff.INCOMING || twd.getDirection() == IThreeWayDiff.CONFLICTING) { + throw found; + } + } + return false; + } + }); + } catch (RuntimeException e) { + if (e == found) + return true; + throw e; + } + return false; + } + + /** + * Indicate whether the operation should overwrite outgoing changes. By + * default, the get operation does not override local modifications. + * + * @return whether the operation should overwrite outgoing changes. + */ + protected boolean isOverwriteOutgoing() { + return overwriteOutgoing; + } + + /** + * Set whether the operation should overwrite outgoing changes. + * + * @param overwriteOutgoing + * whether the operation should overwrite outgoing changes + */ + public void setOverwriteOutgoing(boolean overwriteOutgoing) { + this.overwriteOutgoing = overwriteOutgoing; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.rse.internal.synchronize.provisional.filesystem.ui.FileSystemOperation#getTaskName + * () + */ + @Override + protected String getTaskName() { + return Policy.bind("GetAction.working"); //$NON-NLS-1$ + } + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/ModelGetAction.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/ModelGetAction.java new file mode 100644 index 00000000000..77a3b7ba907 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/ModelGetAction.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2006, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / ModelPutAction + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem.ui; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.resources.mapping.ResourceMapping; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.rse.internal.synchronize.RSESyncUtils; +import org.eclipse.team.core.subscribers.SubscriberScopeManager; +import org.eclipse.team.internal.ui.Utils; +import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; +import org.eclipse.team.ui.synchronize.ModelParticipantAction; + +public class ModelGetAction extends ModelParticipantAction{ + public static final String GET_ACTION_ID = "org.eclipse.rse.internal.synchronize.getAction"; + + public ModelGetAction(String text, ISynchronizePageConfiguration configuration){ + super(text, configuration); + setId(GET_ACTION_ID); + } + + @Override + protected boolean isEnabledForSelection(IStructuredSelection selection) { + // Only enable the put in outgoing or both modes + int mode = getConfiguration().getMode(); + if (mode == ISynchronizePageConfiguration.OUTGOING_MODE || mode == ISynchronizePageConfiguration.BOTH_MODE) { + return getResourceMappings(selection).length > 0; + } + return false; + } + + private ResourceMapping[] getResourceMappings(IStructuredSelection selection) { + List mappings = new ArrayList(); + for (Iterator iter = selection.iterator(); iter.hasNext();) { + Object element = iter.next(); + ResourceMapping mapping = Utils.getResourceMapping(element); + if (mapping != null) + mappings.add(mapping); + } + return (ResourceMapping[]) mappings.toArray(new ResourceMapping[mappings.size()]); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.action.Action#run() + */ + @Override + public void run() { + ResourceMapping[] resourceMappings = getResourceMappings(getStructuredSelection()); + SubscriberScopeManager manager = FileSystemOperation.createScopeManager("Get", resourceMappings); + try { + new GetOperation(getConfiguration().getSite().getPart(), manager).run(); + } catch (InvocationTargetException e) { + IStatus status = getStatus(e); + ErrorDialog.openError(getConfiguration().getSite().getShell(), null, null, status); + } catch (InterruptedException e) { + // Ignore + } + } + + private IStatus getStatus(Throwable throwable) { + if (throwable instanceof InvocationTargetException) { + return getStatus(((InvocationTargetException) throwable).getCause()); + } + return new Status(IStatus.ERROR, RSESyncUtils.PLUGIN_ID, 0, "An error occurred during the put.", throwable); + } + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/ModelPutAction.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/ModelPutAction.java new file mode 100644 index 00000000000..18a8c33d4dd --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/ModelPutAction.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2006, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / ModelPutAction + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem.ui; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.resources.mapping.ResourceMapping; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.rse.internal.synchronize.RSESyncUtils; +import org.eclipse.team.core.subscribers.SubscriberScopeManager; +import org.eclipse.team.internal.ui.Utils; +import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; +import org.eclipse.team.ui.synchronize.ModelParticipantAction; + +/** + * A put action for use in the file system synchronize participant. + */ +public class ModelPutAction extends ModelParticipantAction { + public static final String PUT_ACTION_ID = "org.eclipse.rse.internal.synchronize.putAction"; + + public ModelPutAction(String text, ISynchronizePageConfiguration configuration) { + super(text, configuration); + setId(PUT_ACTION_ID); + } + + @Override + protected boolean isEnabledForSelection(IStructuredSelection selection) { + // Only enable the put in outgoing or both modes + int mode = getConfiguration().getMode(); + if (mode == ISynchronizePageConfiguration.OUTGOING_MODE || mode == ISynchronizePageConfiguration.BOTH_MODE) { + return getResourceMappings(selection).length > 0; + } + return false; + } + + private ResourceMapping[] getResourceMappings(IStructuredSelection selection) { + List mappings = new ArrayList(); + for (Iterator iter = selection.iterator(); iter.hasNext();) { + Object element = iter.next(); + ResourceMapping mapping = Utils.getResourceMapping(element); + if (mapping != null) + mappings.add(mapping); + } + return (ResourceMapping[]) mappings.toArray(new ResourceMapping[mappings.size()]); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.action.Action#run() + */ + @Override + public void run() { + ResourceMapping[] resourceMappings = getResourceMappings(getStructuredSelection()); + SubscriberScopeManager manager = FileSystemOperation.createScopeManager("Put", resourceMappings); + try { + new PutOperation(getConfiguration().getSite().getPart(), manager).run(); + } catch (InvocationTargetException e) { + IStatus status = getStatus(e); + ErrorDialog.openError(getConfiguration().getSite().getShell(), null, null, status); + } catch (InterruptedException e) { + // Ignore + } + } + + private IStatus getStatus(Throwable throwable) { + if (throwable instanceof InvocationTargetException) { + return getStatus(((InvocationTargetException) throwable).getCause()); + } + return new Status(IStatus.ERROR, RSESyncUtils.PLUGIN_ID, 0, "An error occurred during the put.", throwable); + } +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/PutOperation.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/PutOperation.java new file mode 100644 index 00000000000..b2a3b932b70 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/filesystem/ui/PutOperation.java @@ -0,0 +1,118 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 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 + * Takuya Miyamoto - Adapted from org.eclipse.team.examples.filesystem / PutOperation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.filesystem.ui; + +import org.eclipse.core.resources.mapping.ResourceTraversal; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.rse.internal.synchronize.filesystem.FileSystemProvider; +import org.eclipse.rse.internal.synchronize.filesystem.Policy; +import org.eclipse.rse.internal.synchronize.filesystem.subscriber.FileSystemSubscriber; +import org.eclipse.team.core.diff.IDiff; +import org.eclipse.team.core.diff.IDiffVisitor; +import org.eclipse.team.core.diff.IThreeWayDiff; +import org.eclipse.team.core.subscribers.SubscriberScopeManager; +import org.eclipse.ui.IWorkbenchPart; + +/** + * Operation for copying the selected resources to the file system location + */ +public class PutOperation extends FileSystemOperation { + + private boolean overwriteIncoming; + + /** + * Create the put operation + * + * @param part + * the originating part + * @param manager + * the scope manager + */ + protected PutOperation(IWorkbenchPart part, SubscriberScopeManager manager) { + super(part, manager); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.rse.internal.synchronize.provisional.filesystem.ui.FileSystemOperation#execute + * (org.eclipse.rse.internal.synchronize.provisional.filesystem.FileSystemProvider, + * org.eclipse.core.resources.mapping.ResourceTraversal[], + * org.eclipse.core.runtime.SubProgressMonitor) + */ + @Override + protected void execute(FileSystemProvider provider, ResourceTraversal[] traversals, IProgressMonitor monitor) throws CoreException { + provider.getOperations().checkin(traversals, isOverwriteIncoming(), monitor); + // if (!isOverwriteIncoming() && hasOutgoingChanges(traversals)) { + // throw new + // TeamException("Could not put all changes due to conflicts."); + // } + + } + + private boolean hasOutgoingChanges(ResourceTraversal[] traversals) throws CoreException { + final RuntimeException found = new RuntimeException(); + try { + FileSystemSubscriber.getInstance().accept(traversals, new IDiffVisitor() { + public boolean visit(IDiff diff) { + if (diff instanceof IThreeWayDiff) { + IThreeWayDiff twd = (IThreeWayDiff) diff; + if (twd.getDirection() == IThreeWayDiff.OUTGOING || twd.getDirection() == IThreeWayDiff.CONFLICTING) { + throw found; + } + } + return false; + } + }); + } catch (RuntimeException e) { + e.printStackTrace(); + if (e == found) + return true; + throw e; + } + return false; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.rse.internal.synchronize.provisional.filesystem.ui.FileSystemOperation#getTaskName + * () + */ + @Override + protected String getTaskName() { + return Policy.bind("PutAction.working"); //$NON-NLS-1$ + } + + /** + * Return whether incoming changes should be overwritten. + * + * @return whether incoming changes should be overwritten + */ + public boolean isOverwriteIncoming() { + return overwriteIncoming; + } + + /** + * Set whether incoming changes should be overwritten. + * + * @param overwriteIncoming + * whether incoming changes should be overwritten + */ + public void setOverwriteIncoming(boolean overwriteIncoming) { + this.overwriteIncoming = overwriteIncoming; + } + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizeByteCalculator.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizeByteCalculator.java new file mode 100644 index 00000000000..b9d9bb10f74 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizeByteCalculator.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2008 Takuya Miyamoto 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: + * Takuya Miyamoto - initial API and implementation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.provisional; + +import org.eclipse.core.resources.IResource; +import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile; + +/** + * Helper class to calculate byte array for synchronization in some algorithm. + * This interface is used in comparison of resource and resourceVariant. In the + * comparison, it's necessary to calculate byte array associated with them. + * + */ +public interface ISynchronizeByteCalculator { + /** + * Timestamp: The last modification time is used for comparison + */ + public static final int DIFF_TYPE_TIMESTAMP = 0; + /** + * MD5: The message digest 5 is used for comparison + */ + public static final int DIFF_TYPE_MD5 = 1; + + /** + * Return byte array for comparison used in synchronization. The criterion + * is specified by option. + * + * @param local + * @param option + * @return + */ + public byte[] cacByte(IResource local, int option); + + /** + * Return byte array for comparison used in synchronization. The criterion + * is specified by option. + * + * @param remote + * @param option + * @return + */ + public byte[] calcByte(IRemoteFile remote, int option); + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizeConnectionManager.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizeConnectionManager.java new file mode 100644 index 00000000000..fe910514011 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizeConnectionManager.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2008 Takuya Miyamoto 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: + * Takuya Miyamoto - initial API and implementation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.provisional; + +import org.eclipse.core.resources.IProject; +import org.eclipse.team.core.TeamException; + +public interface ISynchronizeConnectionManager { + /** + * Return if the project is already shared or not. + * + * @param project + * @return + */ + public boolean isConnected(IProject project); + + /** + * Share the project. Sharing project is necessary for synchronization. + * + * @param project + * @throws TeamException + */ + public void connect(IProject project) throws TeamException; + + /** + * Finish sharing the project. When sharing finished, re-synchronization no + * longer runs. + * + * @param project + * @throws TeamException + */ + public void disconnect(IProject project) throws TeamException; + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizeFilter.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizeFilter.java new file mode 100644 index 00000000000..9f1ec7ca2da --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizeFilter.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2008 Takuya Miyamoto 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: + * Takuya Miyamoto - initial API and implementation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.provisional; + +import org.eclipse.core.runtime.IPath; + +/** + * Captures the filter that a user sets up in the import/export wizard, in order + * to exclude certain files or directories from synchronization. All file system + * paths are relative to the synchronization root. + */ +public interface ISynchronizeFilter { + /** + * Return if the resource specified by relativePath is excluded or not. + * + * @param relativePath + * @return + */ + public boolean isExcluded(IPath relativePath); +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizeOperation.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizeOperation.java new file mode 100644 index 00000000000..3d969d91d0b --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizeOperation.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2008 Takuya Miyamoto 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: + * Takuya Miyamoto - initial API and implementation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.provisional; + +import java.util.Calendar; +import java.util.List; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile; + +/** + * Utility class to synchronize local and remote resources. IResource is used as + * local resources. IRemoteFile is used as remote resources. There are some + * kinds of synchronization, such as Import, Export, Synchronize, or Manual + * Synchronize. + */ +public interface ISynchronizeOperation { + /** + * the mode of synchronization is not defined + */ + public static final int SYNC_MODE_NON = 0; + /** + * "Import": Always override source with destination + */ + public static final int SYNC_MODE_OVERRIDE_SOURCE = 1; + /** + * "Export": Always override destination with source. + */ + public static final int SYNC_MODE_OVERRIDE_DEST = 2; + /** + * "Re-Synchronize": Always override older files with newer ones + */ + public static final int SYNC_MODE_OVERRIDE_OLDER = 3; + /** + * "Manual Re-Synchronize":Review sync in UI + */ + public static final int SYNC_MODE_UI_REVIEW = 4; + + /** + * TODO This will be removed because initial synchronize will be import or + * export. "Initial Manual Synchronize":Review sync in UI. + */ + public static final int SYNC_MODE_UI_REVIEW_INITIAL = 5; + + /** + * Synchronize local with remote, using the given filter. Both local and + * remote are folder. If lastSyncDate != null, it is the timestamp of last + * synchronization (for 3-way synchronization). The filter is always applied + * to the all kinds of synchronize operation. In initial export operation, + * filter is applied to the exported local resources. In initial import + * operation, filter is applied to the imported remote resources. In + * synchronization, filter is applied to the synchronized resources. throws + * CoreException if any error occurs. When SYNC_MODE_UI_REVIEW is requested + * option, the method returns as soon as the Synchronize View has been + * filled with contents according to the request. + * + * @param local + * @param remote + * @param filter + * @param lastSyncDate + * @param options + * @throws CoreException + */ + // TODO currently lastSyncDate is unnecessary + public void synchronize(List local, IRemoteFile remote, ISynchronizeFilter filter, Calendar lastSyncDate, int options) throws CoreException; + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizePerspectiveSelector.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizePerspectiveSelector.java new file mode 100644 index 00000000000..1c2e5b0bf35 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizePerspectiveSelector.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2008 Takuya Miyamoto 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: + * Takuya Miyamoto - initial API and implementation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.provisional; + +import java.util.List; + +import org.eclipse.core.resources.IResource; + +/** + * + * Switch to the team synchronization perspective + * + */ +public interface ISynchronizePerspectiveSelector { + + /** + * Open synchronize perspective + * + * @param synchronizeElement + */ + public void openSynchronizePerspective(List synchronizeElement); +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizer.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizer.java new file mode 100644 index 00000000000..dfbb4082c90 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/ISynchronizer.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2008 Takuya Miyamoto 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: + * Takuya Miyamoto - initial API and implementation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.provisional; + +/** + * + * This class manage the start point of actual synchronize operation. The class + * that implement this interface must have necessary informations for + * synchronization. + * + */ +public interface ISynchronizer { + + /** + * Run the SynchronizeOperation. Preparing for the synchronization and + * invoke ISyncronizeOperation#synchronize() as an actual synchronize + * operation. Preparing is mapping the project to RepositoryProvider, and if + * needed, unmap for new synchronization. This method is called directory + * from GUI. + * + * @param operation + * @return + */ + public boolean run(ISynchronizeOperation operation); + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/SynchronizeConnectionManager.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/SynchronizeConnectionManager.java new file mode 100644 index 00000000000..65fdf72fb02 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/SynchronizeConnectionManager.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2008 Takuya Miyamoto 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: + * Takuya Miyamoto - initial API and implementation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.provisional; + +import org.eclipse.core.resources.IProject; +import org.eclipse.rse.internal.synchronize.RSESyncUtils; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.TeamException; + +public class SynchronizeConnectionManager implements ISynchronizeConnectionManager { + public void connect(IProject project) throws TeamException { + RepositoryProvider.map(project, RSESyncUtils.PROVIDER_ID); + } + + public void disconnect(IProject project) throws TeamException { + if (isConnected(project)) { + RepositoryProvider.unmap(project); + } + } + + public boolean isConnected(IProject project) { + return RepositoryProvider.isShared(project); + } + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/SynchronizeFilter.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/SynchronizeFilter.java new file mode 100644 index 00000000000..c0ed026b387 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/SynchronizeFilter.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2008 Takuya Miyamoto 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: + * Takuya Miyamoto - initial API and implementation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.provisional; + +import java.util.List; + +import org.eclipse.core.runtime.IPath; + +public class SynchronizeFilter implements ISynchronizeFilter { + /** + * the paths of synchronize elements + */ + private List paths; + + public SynchronizeFilter(List sycnhronizeRelativePaths) { + super(); + this.paths = sycnhronizeRelativePaths; + } + + public boolean isExcluded(IPath relativePath) { + if(paths.contains(relativePath)){ + return false; + }else{ + return true; + } + } + +} \ No newline at end of file diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/SynchronizeOperation.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/SynchronizeOperation.java new file mode 100644 index 00000000000..bdb2870c852 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/SynchronizeOperation.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2008 Takuya Miyamoto 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: + * Takuya Miyamoto - initial API and implementation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.provisional; + +import java.util.Calendar; +import java.util.List; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.rse.internal.synchronize.filesystem.FileSystemOperations; +import org.eclipse.rse.internal.synchronize.filesystem.FileSystemProvider; +import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.TeamException; + +public class SynchronizeOperation implements ISynchronizeOperation { + private ISynchronizePerspectiveSelector switcher; + + public SynchronizeOperation() { + this.switcher = new SynchronizePerspectiveSelector(); + } + + public void synchronize(List local, IRemoteFile remote, ISynchronizeFilter filter, Calendar lastSyncDate, int options) throws CoreException { + + switch (options) { + case SYNC_MODE_OVERRIDE_DEST: + exportTo(local, remote, filter); + break; + case SYNC_MODE_OVERRIDE_SOURCE: + importFrom(local, remote, filter); + break; + case SYNC_MODE_OVERRIDE_OLDER: + synchronizeWith(local, remote, filter, lastSyncDate); + break; + case SYNC_MODE_UI_REVIEW: + synchronizeManually(local, remote, filter, lastSyncDate); + break; + case SYNC_MODE_UI_REVIEW_INITIAL: + initialSynchronizeManually(local, remote, filter, lastSyncDate); + break; + } + + } + + private void importFrom(List local, IRemoteFile remote, ISynchronizeFilter filter) throws TeamException{ + for (IResource resource : local) { + FileSystemProvider provider = (FileSystemProvider) RepositoryProvider.getProvider(resource.getProject()); + FileSystemOperations operations = provider.getOperations(); + operations.get(new IResource[] { resource }, IResource.DEPTH_INFINITE, true, null); + } + } + + + private void exportTo(List local, IRemoteFile remote, ISynchronizeFilter filter) throws TeamException { + for (IResource resource : local) { + FileSystemProvider provider = (FileSystemProvider) RepositoryProvider.getProvider(resource.getProject()); + FileSystemOperations operations = provider.getOperations(); + operations.checkin(new IResource[] { resource }, IResource.DEPTH_INFINITE, false, null); + } + } + + private void synchronizeWith(List local, IRemoteFile remote, ISynchronizeFilter filter, Calendar lastSyncDate) { + + } + + private void synchronizeManually(List local, IRemoteFile remote, ISynchronizeFilter filter, Calendar lastSyncDate) { + switcher.openSynchronizePerspective(local); + } + + private void initialSynchronizeManually(List local, IRemoteFile remote, ISynchronizeFilter filter, Calendar lastSyncDate) { + switcher.openSynchronizePerspective(local); + } + +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/SynchronizePerspectiveSelector.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/SynchronizePerspectiveSelector.java new file mode 100644 index 00000000000..805271f1090 --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/SynchronizePerspectiveSelector.java @@ -0,0 +1,161 @@ +/******************************************************************************* + * Copyright (c) 2008 Takuya Miyamoto 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: + * Takuya Miyamoto - initial API and implementation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.provisional; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.mapping.ResourceMapping; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.Platform; +import org.eclipse.rse.internal.synchronize.RSESyncUtils; +import org.eclipse.rse.internal.synchronize.filesystem.subscriber.FileSystemMergeContext; +import org.eclipse.rse.internal.synchronize.filesystem.subscriber.FileSystemSubscriber; +import org.eclipse.rse.internal.synchronize.filesystem.ui.FileSystemOperation; +import org.eclipse.rse.internal.synchronize.filesystem.ui.FileSystemSynchronizeParticipant; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.subscribers.SubscriberScopeManager; +import org.eclipse.team.ui.TeamUI; +import org.eclipse.team.ui.synchronize.ISynchronizeParticipant; +import org.eclipse.ui.IContributorResourceAdapter; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.ide.IContributorResourceAdapter2; + +public class SynchronizePerspectiveSelector implements ISynchronizePerspectiveSelector { + private IWorkbenchPart targetPart; + + /** + * Open Synchronize Perspective + */ + // + public void openSynchronizePerspective(List synchronizeElement) { + // Get resource mapping which is prepared the previous step. + ResourceMapping[] mappings = getSelectedResourceMappings(RSESyncUtils.PROVIDER_ID, synchronizeElement); + if (mappings.length == 0) { + return; + } + SubscriberScopeManager manager = FileSystemOperation.createScopeManager(FileSystemSubscriber.getInstance().getName(), mappings); + FileSystemMergeContext context = new FileSystemMergeContext(manager); + FileSystemSynchronizeParticipant participant = new FileSystemSynchronizeParticipant(context); + TeamUI.getSynchronizeManager().addSynchronizeParticipants(new ISynchronizeParticipant[] { participant }); + participant.run(getTargetPart()); + } + + // + + // + /** + * Return the selected resource mappins that contain resources in projects + * that are associated with a repository of the given id. + * + * @param providerId + * the repository provider id + * @return the resource mappings that contain resources associated with the + * given provider + */ + protected ResourceMapping[] getSelectedResourceMappings(String providerId, List synchronizeResources) { + Object[] elements = synchronizeResources.toArray(); + ArrayList providerMappings = new ArrayList(); + for (int i = 0; i < elements.length; i++) { + Object object = elements[i]; + Object adapted = getResourceMapping(object); + if (adapted instanceof ResourceMapping) { + ResourceMapping mapping = (ResourceMapping) adapted; + if (providerId == null || isMappedToProvider(mapping, providerId)) { + providerMappings.add(mapping); + } + } + } + return (ResourceMapping[]) providerMappings.toArray(new ResourceMapping[providerMappings.size()]); + } + + // + + /** + * return if the element is mapped to providerId in the RepositoryProvider + * + * @param element + * @param providerId + * @return + */ + // + private boolean isMappedToProvider(ResourceMapping element, String providerId) { + IProject[] projects = element.getProjects(); + for (int k = 0; k < projects.length; k++) { + IProject project = projects[k]; + RepositoryProvider provider = RepositoryProvider.getProvider(project); + if (provider != null && provider.getID().equals(providerId)) { + return true; + } + } + return false; + } + + // + + /** + * + * @param object + * @return + */ + // + private Object getResourceMapping(Object object) { + // if object is already ResourceMapping + if (object instanceof ResourceMapping) { + return object; + } + + // + if (object instanceof IAdaptable) { + IAdaptable adaptable = (IAdaptable) object; + Object adapted = adaptable.getAdapter(ResourceMapping.class); + if (adapted instanceof ResourceMapping) { + return adapted; + } + adapted = adaptable.getAdapter(IContributorResourceAdapter.class); + if (adapted instanceof IContributorResourceAdapter2) { + IContributorResourceAdapter2 cra = (IContributorResourceAdapter2) adapted; + return cra.getAdaptedResourceMapping(adaptable); + } + } else { + Object adapted = Platform.getAdapterManager().getAdapter(object, ResourceMapping.class); + if (adapted instanceof ResourceMapping) { + return adapted; + } + } + return null; + // + } + + // + + /** + * + * @return + */ + // + protected IWorkbenchPart getTargetPart() { + if (targetPart == null) { + IWorkbenchPage page = RSESyncUtils.getActivePage(); + if (page != null) { + targetPart = page.getActivePart(); + } + } + return targetPart; + + } + // +} diff --git a/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/Synchronizer.java b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/Synchronizer.java new file mode 100644 index 00000000000..84afa326b7c --- /dev/null +++ b/rse/plugins/org.eclipse.rse.importexport/src/org/eclipse/rse/internal/synchronize/provisional/Synchronizer.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2008 Takuya Miyamoto 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: + * Takuya Miyamoto - initial API and implementation + *******************************************************************************/ +package org.eclipse.rse.internal.synchronize.provisional; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.rse.internal.importexport.files.UniFilePlus; +import org.eclipse.rse.internal.synchronize.ISynchronizeData; +import org.eclipse.rse.internal.synchronize.filesystem.FileSystemProvider; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.TeamException; + +public class Synchronizer implements ISynchronizer { + private ISynchronizeData data; + private ISynchronizeConnectionManager connector; + + /** + * TODO in the future, remoteRoot is probably needed for import or export + */ + private UniFilePlus remoteRoot; + + public Synchronizer(ISynchronizeData data) { + this.data = data; + this.connector = new SynchronizeConnectionManager(); + } + + public boolean run(ISynchronizeOperation operation) { + IProject[] projects = null; + List elements = data.getElements(); + Set projectSet = new HashSet(); + + for (IResource resource : elements) { + projectSet.add(resource.getProject()); + } + + // get resources to synchronize in the type of Array. + projects = projectSet.toArray(new IProject[projectSet.size()]); + + try { + // if user request new synchronization, previous mapping are + // removed. + if (data.getSynchronizeType() == ISynchronizeOperation.SYNC_MODE_OVERRIDE_DEST || + data.getSynchronizeType() == ISynchronizeOperation.SYNC_MODE_OVERRIDE_SOURCE || + data.getSynchronizeType() == ISynchronizeOperation.SYNC_MODE_UI_REVIEW_INITIAL) { + for (int i = 0; i < projects.length; i++) { + connector.disconnect(projects[i]); + } + + } + + // create new connection for each project + for (int i = 0; i < projects.length; i++) { + IProject project = projects[i]; + connector.connect(project); + FileSystemProvider provider = (FileSystemProvider) RepositoryProvider.getProvider(project); + String destination = data.getDestination(); + provider.setTargetLocation(data.getDestination()); + this.remoteRoot = provider.getRemoteRootFolder(); + } + + // run actual synchronize operation. + // TODO currently, not support last synchronization date. + operation.synchronize(data.getElements(), remoteRoot.remoteFile, null, null, data.getSynchronizeType()); + } catch (TeamException e1) { + e1.printStackTrace(); + } catch (CoreException e) { + e.printStackTrace(); + } + + return true; + } +}