| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.hdt.dfs.ui; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.apache.hdt.ui.ImageLibrary; |
| import org.apache.hdt.dfs.ui.DFSActions; |
| import org.apache.hdt.dfs.core.DFSFile; |
| import org.apache.hdt.dfs.core.DFSFolder; |
| import org.apache.hdt.dfs.core.DFSLocation; |
| import org.apache.hdt.dfs.core.DFSLocationsRoot; |
| import org.apache.hdt.dfs.core.DFSPath; |
| import org.eclipse.core.resources.IStorage; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.PlatformObject; |
| import org.eclipse.jface.action.IAction; |
| import org.eclipse.jface.dialogs.InputDialog; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.widgets.DirectoryDialog; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.FileDialog; |
| import org.eclipse.ui.IObjectActionDelegate; |
| import org.eclipse.ui.IPersistableElement; |
| import org.eclipse.ui.IStorageEditorInput; |
| import org.eclipse.ui.IWorkbenchPart; |
| import org.eclipse.ui.PartInitException; |
| import org.eclipse.ui.PlatformUI; |
| |
| /** |
| * Actual implementation of DFS actions |
| */ |
| public class DFSActionImpl implements IObjectActionDelegate { |
| |
| private ISelection selection; |
| |
| private IWorkbenchPart targetPart; |
| |
| /* @inheritDoc */ |
| public void setActivePart(IAction action, IWorkbenchPart targetPart) { |
| this.targetPart = targetPart; |
| } |
| |
| /* @inheritDoc */ |
| public void run(IAction action) { |
| |
| // Ignore non structured selections |
| if (!(this.selection instanceof IStructuredSelection)) |
| return; |
| |
| // operate on the DFS asynchronously to prevent blocking the main UI |
| final IStructuredSelection ss = (IStructuredSelection) selection; |
| final String actionId = action.getActionDefinitionId(); |
| Display.getDefault().asyncExec(new Runnable() { |
| public void run() { |
| try { |
| switch (DFSActions.getById(actionId)) { |
| case DELETE: { |
| delete(ss); |
| break; |
| } |
| case OPEN: { |
| open(ss); |
| break; |
| } |
| case MKDIR: { |
| mkdir(ss); |
| break; |
| } |
| case UPLOAD_FILES: { |
| uploadFilesToDFS(ss); |
| break; |
| } |
| case UPLOAD_DIR: { |
| uploadDirectoryToDFS(ss); |
| break; |
| } |
| case REFRESH: { |
| refresh(ss); |
| break; |
| } |
| case DOWNLOAD: { |
| downloadFromDFS(ss); |
| break; |
| } |
| case RECONNECT: { |
| reconnect(ss); |
| break; |
| } |
| case DISCONNECT: { |
| disconnect(ss); |
| break; |
| } |
| default: { |
| System.err.printf("Unhandled DFS Action: " + actionId); |
| break; |
| } |
| } |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| MessageDialog.openError(Display.getDefault().getActiveShell(), |
| "DFS Action error", |
| "An error occurred while performing DFS operation: " |
| + e.getMessage()); |
| } |
| } |
| }); |
| } |
| |
| /** |
| * Create a new sub-folder into an existing directory |
| * |
| * @param selection |
| */ |
| private void mkdir(IStructuredSelection selection) { |
| List<DFSFolder> folders = filterSelection(DFSFolder.class, selection); |
| if (folders.size() >= 1) { |
| DFSFolder folder = folders.get(0); |
| InputDialog dialog = |
| new InputDialog(Display.getCurrent().getActiveShell(), |
| "Create subfolder", "Enter the name of the subfolder", "", |
| null); |
| if (dialog.open() == InputDialog.OK) |
| folder.mkdir(dialog.getValue()); |
| } |
| } |
| |
| /** |
| * Implement the import action (upload files from the current machine to |
| * HDFS) |
| * |
| * @param object |
| * @throws SftpException |
| * @throws JSchException |
| * @throws InvocationTargetException |
| * @throws InterruptedException |
| */ |
| private void uploadFilesToDFS(IStructuredSelection selection) |
| throws InvocationTargetException, InterruptedException { |
| |
| // Ask the user which files to upload |
| FileDialog dialog = |
| new FileDialog(Display.getCurrent().getActiveShell(), SWT.OPEN |
| | SWT.MULTI); |
| dialog.setText("Select the local files to upload"); |
| dialog.open(); |
| |
| List<File> files = new ArrayList<File>(); |
| for (String fname : dialog.getFileNames()) |
| files.add(new File(dialog.getFilterPath() + File.separator + fname)); |
| |
| // TODO enable upload command only when selection is exactly one folder |
| List<DFSFolder> folders = filterSelection(DFSFolder.class, selection); |
| if (folders.size() >= 1) |
| uploadToDFS(folders.get(0), files); |
| } |
| |
| /** |
| * Implement the import action (upload directory from the current machine |
| * to HDFS) |
| * |
| * @param object |
| * @throws SftpException |
| * @throws JSchException |
| * @throws InvocationTargetException |
| * @throws InterruptedException |
| */ |
| private void uploadDirectoryToDFS(IStructuredSelection selection) |
| throws InvocationTargetException, InterruptedException { |
| |
| // Ask the user which local directory to upload |
| DirectoryDialog dialog = |
| new DirectoryDialog(Display.getCurrent().getActiveShell(), SWT.OPEN |
| | SWT.MULTI); |
| dialog.setText("Select the local file or directory to upload"); |
| |
| String dirName = dialog.open(); |
| final File dir = new File(dirName); |
| List<File> files = new ArrayList<File>(); |
| files.add(dir); |
| |
| // TODO enable upload command only when selection is exactly one folder |
| final List<DFSFolder> folders = |
| filterSelection(DFSFolder.class, selection); |
| if (folders.size() >= 1) |
| uploadToDFS(folders.get(0), files); |
| |
| } |
| |
| private void uploadToDFS(final DFSFolder folder, final List<File> files) |
| throws InvocationTargetException, InterruptedException { |
| |
| PlatformUI.getWorkbench().getProgressService().busyCursorWhile( |
| new IRunnableWithProgress() { |
| public void run(IProgressMonitor monitor) |
| throws InvocationTargetException { |
| |
| int work = 0; |
| for (File file : files) |
| work += computeUploadWork(file); |
| |
| monitor.beginTask("Uploading files to distributed file system", |
| work); |
| |
| for (File file : files) { |
| try { |
| folder.upload(monitor, file); |
| |
| } catch (IOException ioe) { |
| ioe.printStackTrace(); |
| MessageDialog.openError(null, |
| "Upload files to distributed file system", |
| "Upload failed.\n" + ioe); |
| } |
| } |
| |
| monitor.done(); |
| |
| // Update the UI |
| folder.doRefresh(); |
| } |
| }); |
| } |
| |
| private void reconnect(IStructuredSelection selection) { |
| for (DFSLocation location : filterSelection(DFSLocation.class, selection)) |
| location.reconnect(); |
| } |
| |
| private void disconnect(IStructuredSelection selection) { |
| if (selection.size() != 1) |
| return; |
| |
| Object first = selection.getFirstElement(); |
| if (!(first instanceof DFSLocationsRoot)) |
| return; |
| |
| DFSLocationsRoot root = (DFSLocationsRoot) first; |
| root.disconnect(); |
| root.refresh(); |
| } |
| |
| /** |
| * Implements the Download action from HDFS to the current machine |
| * |
| * @param object |
| * @throws SftpException |
| * @throws JSchException |
| * @throws InterruptedException |
| * @throws InvocationTargetException |
| */ |
| private void downloadFromDFS(IStructuredSelection selection) |
| throws InvocationTargetException, InterruptedException { |
| |
| // Ask the user where to put the downloaded files |
| DirectoryDialog dialog = |
| new DirectoryDialog(Display.getCurrent().getActiveShell()); |
| dialog.setText("Copy to local directory"); |
| dialog.setMessage("Copy the selected files and directories from the " |
| + "distributed filesystem to a local directory"); |
| String directory = dialog.open(); |
| |
| if (directory == null) |
| return; |
| |
| final File dir = new File(directory); |
| if (!dir.exists()) |
| dir.mkdirs(); |
| |
| if (!dir.isDirectory()) { |
| MessageDialog.openError(null, "Download to local file system", |
| "Invalid directory location: \"" + dir + "\""); |
| return; |
| } |
| |
| final List<DFSPath> paths = filterSelection(DFSPath.class, selection); |
| |
| PlatformUI.getWorkbench().getProgressService().busyCursorWhile( |
| new IRunnableWithProgress() { |
| public void run(IProgressMonitor monitor) |
| throws InvocationTargetException { |
| |
| int work = 0; |
| for (DFSPath path : paths) |
| work += path.computeDownloadWork(); |
| |
| monitor |
| .beginTask("Downloading files to local file system", work); |
| |
| for (DFSPath path : paths) { |
| if (monitor.isCanceled()) |
| return; |
| try { |
| path.downloadToLocalDirectory(monitor, dir); |
| } catch (Exception e) { |
| // nothing we want to do here |
| e.printStackTrace(); |
| } |
| } |
| |
| monitor.done(); |
| } |
| }); |
| } |
| |
| /** |
| * Open the selected DfsPath in the editor window |
| * |
| * @param selection |
| * @throws JSchException |
| * @throws IOException |
| * @throws PartInitException |
| * @throws InvocationTargetException |
| * @throws InterruptedException |
| */ |
| private void open(IStructuredSelection selection) throws IOException, |
| PartInitException, InvocationTargetException, InterruptedException { |
| |
| for (DFSFile file : filterSelection(DFSFile.class, selection)) { |
| |
| IStorageEditorInput editorInput = new DFSFileEditorInput(file); |
| targetPart.getSite().getWorkbenchWindow().getActivePage().openEditor( |
| editorInput, "org.eclipse.ui.DefaultTextEditor"); |
| } |
| } |
| |
| /** |
| * @param selection |
| * @throws JSchException |
| */ |
| private void refresh(IStructuredSelection selection) { |
| for (DFSPath path : filterSelection(DFSPath.class, selection)) |
| path.refresh(); |
| |
| } |
| |
| private void delete(IStructuredSelection selection) { |
| List<DFSPath> list = filterSelection(DFSPath.class, selection); |
| if (list.isEmpty()) |
| return; |
| |
| StringBuffer msg = new StringBuffer(); |
| msg.append("Are you sure you want to delete " |
| + "the following files from the distributed file system?\n"); |
| for (DFSPath path : list) |
| msg.append(path.getPath()).append("\n"); |
| |
| if (MessageDialog.openConfirm(null, "Confirm Delete from DFS", msg |
| .toString())) { |
| |
| Set<DFSPath> toRefresh = new HashSet<DFSPath>(); |
| for (DFSPath path : list) { |
| path.delete(); |
| toRefresh.add(path.getParent()); |
| } |
| |
| for (DFSPath path : toRefresh) { |
| path.refresh(); |
| } |
| } |
| } |
| |
| /* @inheritDoc */ |
| public void selectionChanged(IAction action, ISelection selection) { |
| this.selection = selection; |
| } |
| |
| /** |
| * Extract the list of <T> from the structured selection |
| * |
| * @param clazz the class T |
| * @param selection the structured selection |
| * @return the list of <T> it contains |
| */ |
| private static <T> List<T> filterSelection(Class<T> clazz, |
| IStructuredSelection selection) { |
| List<T> list = new ArrayList<T>(); |
| for (Object obj : selection.toList()) { |
| if (clazz.isAssignableFrom(obj.getClass())) { |
| list.add((T) obj); |
| } |
| } |
| return list; |
| } |
| |
| private static int computeUploadWork(File file) { |
| if (file.isDirectory()) { |
| int contentWork = 1; |
| for (File child : file.listFiles()) |
| contentWork += computeUploadWork(child); |
| return contentWork; |
| |
| } else if (file.isFile()) { |
| return 1 + (int) (file.length() / 1024); |
| |
| } else { |
| return 0; |
| } |
| } |
| |
| } |
| |
| /** |
| * Adapter to allow the viewing of a DfsFile in the Editor window |
| */ |
| class DFSFileEditorInput extends PlatformObject implements |
| IStorageEditorInput { |
| |
| private DFSFile file; |
| |
| /** |
| * Constructor |
| * |
| * @param file |
| */ |
| DFSFileEditorInput(DFSFile file) { |
| this.file = file; |
| } |
| |
| /* @inheritDoc */ |
| public String getToolTipText() { |
| return file.toDetailedString(); |
| } |
| |
| /* @inheritDoc */ |
| public IPersistableElement getPersistable() { |
| return null; |
| } |
| |
| /* @inheritDoc */ |
| public String getName() { |
| return file.toString(); |
| } |
| |
| /* @inheritDoc */ |
| public ImageDescriptor getImageDescriptor() { |
| return ImageLibrary.get("dfs.file.editor"); |
| } |
| |
| /* @inheritDoc */ |
| public boolean exists() { |
| return true; |
| } |
| |
| /* @inheritDoc */ |
| public IStorage getStorage() throws CoreException { |
| return file.getIStorage(); |
| } |
| }; |