/***************************************************************************** * Copyright (c) 2008 g-Eclipse Consortium * 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 * * Initial development of the original code was made for the * g-Eclipse project founded by European Union * project number: FP6-IST-034327 http://www.geclipse.eu/ * * Contributors: * Mathias Stuempert - initial API and implementation *****************************************************************************/ package eu.geclipse.ui.actions; import java.net.URI; import java.net.URISyntaxException; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileInfo; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.Action; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.widgets.Shell; import eu.geclipse.core.auth.AbstractAuthTokenProvider; import eu.geclipse.core.filesystem.GEclipseFileSystem; import eu.geclipse.core.filesystem.GEclipseURI; import eu.geclipse.core.model.GridModel; import eu.geclipse.core.model.IGridConnection; import eu.geclipse.core.model.IGridConnectionElement; import eu.geclipse.core.model.IGridContainer; import eu.geclipse.core.model.IGridPreferences; import eu.geclipse.core.model.IGridProject; import eu.geclipse.core.model.IMountable; import eu.geclipse.core.model.IVirtualOrganization; import eu.geclipse.core.model.IMountable.MountPoint; import eu.geclipse.core.model.IMountable.MountPointID; import eu.geclipse.core.reporting.IProblem; import eu.geclipse.core.reporting.ProblemException; import eu.geclipse.ui.dialogs.ProblemDialog; import eu.geclipse.ui.internal.Activator; import eu.geclipse.ui.internal.actions.Messages; import eu.geclipse.ui.problems.RemountSolution; import eu.geclipse.ui.wizards.ConnectionWizard; /** * Action used for mounting storage elements. * */ public class MountAction extends Action { private IMountable[] mountables; private MountPointID mountID; private Shell shell; private boolean mountAs; /** * Construct a new <code>MountAction</code> for the specified * {@link IMountable}s using the specified mount ID. * * @param shell A shell used to report errors. * @param mountables The {@link IMountable}s that should be mounted. * @param mountID The {@link MountPointID} that should be used. * @param mountAs Specifies if this is a mountAs operation. */ public MountAction( final Shell shell, final IMountable[] mountables, final MountPointID mountID, final boolean mountAs ) { super( mountID.getUID() ); this.shell = shell; this.mountables = mountables; this.mountID = mountID; this.mountAs = mountAs; } /* (non-Javadoc) * @see org.eclipse.jface.action.Action#run() */ @Override public void run() { Job mountJob = new Job( Messages.getString("MountAction.mount_job_name") ) { //$NON-NLS-1$ @Override protected IStatus run( final IProgressMonitor monitor ) { return mountOperation( monitor ); } }; mountJob.setUser( true ); mountJob.schedule(); } protected IStatus mountOperation( final IProgressMonitor monitor ) { SubMonitor sMonitor = SubMonitor.convert( monitor, Messages.getString("MountAction.monitor_title"), //$NON-NLS-1$ this.mountables.length ); for ( IMountable mountable : this.mountables ) { try { if ( sMonitor.isCanceled() ) { throw new OperationCanceledException(); } sMonitor.subTask( Messages.getString("MountAction.monitor_subtask_mounting") + mountable.getName() ); //$NON-NLS-1$ createMount( mountable, sMonitor.newChild( 1 ) ); } catch ( CoreException cExc ) { if ( ! AbstractAuthTokenProvider.isTokenRequestCanceledException( cExc ) ) { ProblemDialog.openProblem( this.shell, String.format( Messages.getString("MountAction.problem_dialog_title") ), //$NON-NLS-1$ String.format( Messages.getString("MountAction.failed_mount_info"), mountable.getName() ), //$NON-NLS-1$ cExc ); } } } sMonitor.done(); IStatus result = Status.OK_STATUS; return result; } /** * Create a mount file for the specified {@link IMountable}. The mount * file is created in the connections folder of the selected project. * * @param mountable The {@link IMountable} to be mounted. * @throws CoreException * @throws CoreException If the mount file count not be created. */ protected void createMount( final IMountable mountable, final IProgressMonitor monitor ) throws CoreException { boolean global = false; if ( mountable instanceof IGridConnectionElement ) { IGridContainer root = ( IGridConnectionElement ) mountable; while ( ! ( root instanceof IGridConnection ) && ( root != null ) ) { root = root.getParent(); } if ( ( root != null ) && ( root instanceof IGridConnection ) ) { global = ( ( IGridConnection ) root ).isGlobal(); } } MountPoint mountPoint = mountable.getMountPoint( this.mountID ); if ( mountPoint != null ) { String mountName = mountPoint.getName(); URI uri = mountPoint.getURI(); if ( this.mountAs ) { ConnectionWizard wizard = new ConnectionWizard( uri, mountName, global ); if ( ! global ) { IGridProject project = mountable.getProject(); IGridContainer mountFolder = project.getProjectFolder( IGridConnection.class ); wizard.init( null, new StructuredSelection( mountFolder.getResource() ) ); } final WizardDialog dialog = new WizardDialog( this.shell, wizard ); this.shell.getDisplay().asyncExec( new Runnable() { public void run() { dialog.open(); } } ); } else if ( global ) { createGlobalMount( uri, mountName, monitor ); } else { IGridProject project = mountable.getProject(); IGridContainer mountFolder = project.getProjectFolder( IGridConnection.class ); IPath path = mountFolder.getPath().append( mountName ); if ( ! checkExists( mountable, path ) ) { createLocalMount( uri, path, monitor ); } } } } /** * Static method for creating global connection. * * @param uri Location of the storage element that should be mounted. * @param name Name of the mount. * @param monitor Monitor used to present progress of the mount operation. * @throws CoreException Throws {@link CoreException} in case mount operation * fails. */ public static void createGlobalMount( final URI uri, final String name, final IProgressMonitor monitor ) throws CoreException { SubMonitor sMonitor = SubMonitor.convert( monitor, 10 ); try { sMonitor.subTask( String.format( Messages.getString("MountAction.monitor_subtask_preparing_resources"), name ) ); //$NON-NLS-1$ GEclipseURI geclURI = new GEclipseURI( uri ); isDirectory( geclURI ); sMonitor.worked( 4 ); if ( sMonitor.isCanceled() ) { throw new OperationCanceledException(); } sMonitor.subTask( Messages.getString("MountAction.monitor_subtask_creating_connection") ); //$NON-NLS-1$ IGridPreferences preferences = GridModel.getPreferences(); preferences.createGlobalConnection( name, geclURI.toMasterURI(), sMonitor.newChild( 6 ) ); } finally { sMonitor.done(); } } /** * Static method for creating local mounts. * * @param uri Location of the storage element that should be mounted. * @param path Local relative {@link IPath}, where link will be stored. * @param monitor Monitor used to present progress of the mount operation. * @throws CoreException Throws {@link CoreException} in case mount operation * fails. */ public static void createLocalMount( final URI uri, final IPath path, final IProgressMonitor monitor ) throws CoreException { SubMonitor sMonitor = SubMonitor.convert( monitor, 10 ); try { sMonitor.subTask( String.format( Messages.getString("MountAction.monitor_subtask_preparing_resources"), path.toString() ) ); //$NON-NLS-1$ String projectName = path.segment( 0 ); IGridProject project = ( IGridProject ) GridModel.getRoot().findChild( projectName ); IVirtualOrganization vo = project.getVO(); String voName = vo != null ? vo.getName() : null; URI newUri = processURI( voName, uri ); GEclipseURI geclURI = new GEclipseURI( newUri ); boolean isDirectory = isDirectory( geclURI ); sMonitor.worked( 4 ); if ( sMonitor.isCanceled() ) { throw new OperationCanceledException(); } sMonitor.subTask( Messages.getString("MountAction.monitor_subtask_creating_connection") ); //$NON-NLS-1$ if ( isDirectory ) { IFolder folder = ResourcesPlugin.getWorkspace().getRoot().getFolder( path ); folder.createLink( geclURI.toMasterURI(), IResource.ALLOW_MISSING_LOCAL, sMonitor.newChild( 6 ) ); } else { IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile( path ); file.createLink( geclURI.toMasterURI(), IResource.ALLOW_MISSING_LOCAL, sMonitor.newChild( 6 ) ); } } finally { sMonitor.done(); } } private static URI processURI( final String voName, final URI uri ) { URI result = uri; if ( voName != null && uri != null ) { //Default file store should not be processed if( !uri.getScheme().equals( "file" ) ) { //$NON-NLS-1$ try { String schemeSpecificPart = uri.getSchemeSpecificPart(); if( schemeSpecificPart.contains( "?" ) ) { //$NON-NLS-1$ schemeSpecificPart += "&vo=" + voName; //$NON-NLS-1$ } else { schemeSpecificPart += "?vo=" + voName; //$NON-NLS-1$ } result = new URI( uri.getScheme(), schemeSpecificPart, uri.getFragment() ); } catch( URISyntaxException e ) { //TODO Auto-generated catch block Activator.logException( e ); } } } return result; } private boolean checkExists( final IMountable mountable, final IPath target ) { boolean result = ResourcesPlugin.getWorkspace().getRoot().getFile( target ).exists() || ResourcesPlugin.getWorkspace().getRoot().getFolder( target ).exists(); if ( result ) { ProblemException problemExc = new ProblemException( "eu.geclipse.ui.problem.mountAlreadyExists", //$NON-NLS-1$ Activator.PLUGIN_ID ); IProblem problem = problemExc.getProblem(); if( this.mountID != null ) { problem.addSolution( new RemountSolution( mountable, this.mountID ) ); } ProblemDialog.openProblem( this.shell, Messages.getString("MountAction.resource_exists_problem"), //$NON-NLS-1$ String.format( Messages.getString("MountAction.resource_exists_info"), target.toString() ), //$NON-NLS-1$ problemExc ); } return result; } private static boolean isDirectory( final GEclipseURI uri ) throws CoreException, ProblemException { URI masterURI = uri.toMasterURI(); IFileStore fileStore = EFS.getStore( masterURI ); GEclipseFileSystem.assureFileStoreIsActive( fileStore ); IFileInfo fileInfo = null; try { fileInfo = fileStore.fetchInfo( EFS.NONE, new NullProgressMonitor() ); } catch ( CoreException coreExc ) { throw new ProblemException( "eu.geclipse.core.filesystem.serverCouldNotBeContacted", //$NON-NLS-1$ String.format( Messages.getString("MountAction.cannot_fetch_info_error"), //$NON-NLS-1$ uri.toSlaveURI() ), coreExc, Activator.PLUGIN_ID ); } // Check if the server could be really contacted if ( fileInfo == null || !fileInfo.exists() ) { throw new ProblemException( "eu.geclipse.core.filesystem.serverCouldNotBeContacted", //$NON-NLS-1$ String.format( Messages.getString("MountAction.server_not_responding_info"), //$NON-NLS-1$ uri.toSlaveURI() ), Activator.PLUGIN_ID ); } return fileInfo.isDirectory(); } }