1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ddmuilib.handler; 18 19 import com.android.ddmlib.ClientData.IHprofDumpHandler; 20 import com.android.ddmlib.ClientData.IMethodProfilingHandler; 21 import com.android.ddmlib.SyncException; 22 import com.android.ddmlib.SyncService; 23 import com.android.ddmlib.SyncService.ISyncProgressMonitor; 24 import com.android.ddmlib.TimeoutException; 25 import com.android.ddmuilib.SyncProgressHelper; 26 import com.android.ddmuilib.SyncProgressHelper.SyncRunnable; 27 28 import org.eclipse.jface.dialogs.MessageDialog; 29 import org.eclipse.swt.SWT; 30 import org.eclipse.swt.widgets.Display; 31 import org.eclipse.swt.widgets.FileDialog; 32 import org.eclipse.swt.widgets.Shell; 33 34 import java.io.File; 35 import java.io.FileOutputStream; 36 import java.io.IOException; 37 import java.lang.reflect.InvocationTargetException; 38 39 /** 40 * Base handler class for handler dealing with files located on a device. 41 * 42 * @see IHprofDumpHandler 43 * @see IMethodProfilingHandler 44 */ 45 public abstract class BaseFileHandler { 46 47 protected final Shell mParentShell; 48 BaseFileHandler(Shell parentShell)49 public BaseFileHandler(Shell parentShell) { 50 mParentShell = parentShell; 51 } 52 getDialogTitle()53 protected abstract String getDialogTitle(); 54 55 /** 56 * Prompts the user for a save location and pulls the remote files into this location. 57 * <p/>This <strong>must</strong> be called from the UI Thread. 58 * @param sync the {@link SyncService} to use to pull the file from the device 59 * @param localFileName The default local name 60 * @param remoteFilePath The name of the file to pull off of the device 61 * @param title The title of the File Save dialog. 62 * @return The result of the pull as a {@link SyncResult} object, or null if the sync 63 * didn't happen (canceled by the user). 64 * @throws InvocationTargetException 65 * @throws InterruptedException 66 * @throws SyncException if an error happens during the push of the package on the device. 67 * @throws IOException 68 */ promptAndPull(final SyncService sync, String localFileName, final String remoteFilePath, String title)69 protected void promptAndPull(final SyncService sync, 70 String localFileName, final String remoteFilePath, String title) 71 throws InvocationTargetException, InterruptedException, SyncException, TimeoutException, 72 IOException { 73 FileDialog fileDialog = new FileDialog(mParentShell, SWT.SAVE); 74 75 fileDialog.setText(title); 76 fileDialog.setFileName(localFileName); 77 78 final String localFilePath = fileDialog.open(); 79 if (localFilePath != null) { 80 SyncProgressHelper.run(new SyncRunnable() { 81 @Override 82 public void run(ISyncProgressMonitor monitor) throws SyncException, IOException, 83 TimeoutException { 84 sync.pullFile(remoteFilePath, localFilePath, monitor); 85 } 86 87 @Override 88 public void close() { 89 sync.close(); 90 } 91 }, 92 String.format("Pulling %1$s from the device", remoteFilePath), mParentShell); 93 } 94 } 95 96 /** 97 * Prompts the user for a save location and copies a temp file into it. 98 * <p/>This <strong>must</strong> be called from the UI Thread. 99 * @param localFileName The default local name 100 * @param tempFilePath The name of the temp file to copy. 101 * @param title The title of the File Save dialog. 102 * @return true if success, false on error or cancel. 103 */ promptAndSave(String localFileName, byte[] data, String title)104 protected boolean promptAndSave(String localFileName, byte[] data, String title) { 105 FileDialog fileDialog = new FileDialog(mParentShell, SWT.SAVE); 106 107 fileDialog.setText(title); 108 fileDialog.setFileName(localFileName); 109 110 String localFilePath = fileDialog.open(); 111 if (localFilePath != null) { 112 try { 113 saveFile(data, new File(localFilePath)); 114 return true; 115 } catch (IOException e) { 116 String errorMsg = e.getMessage(); 117 displayErrorInUiThread( 118 "Failed to save file '%1$s'%2$s", 119 localFilePath, 120 errorMsg != null ? ":\n" + errorMsg : "."); 121 } 122 } 123 124 return false; 125 } 126 127 /** 128 * Display an error message. 129 * <p/>This will call about to {@link Display} to run this in an async {@link Runnable} in the 130 * UI Thread. This is safe to be called from a non-UI Thread. 131 * @param format the string to display 132 * @param args the string arguments 133 */ displayErrorInUiThread(final String format, final Object... args)134 protected void displayErrorInUiThread(final String format, final Object... args) { 135 mParentShell.getDisplay().asyncExec(new Runnable() { 136 @Override 137 public void run() { 138 MessageDialog.openError(mParentShell, getDialogTitle(), 139 String.format(format, args)); 140 } 141 }); 142 } 143 144 /** 145 * Display an error message. 146 * This must be called from the UI Thread. 147 * @param format the string to display 148 * @param args the string arguments 149 */ displayErrorFromUiThread(final String format, final Object... args)150 protected void displayErrorFromUiThread(final String format, final Object... args) { 151 MessageDialog.openError(mParentShell, getDialogTitle(), 152 String.format(format, args)); 153 } 154 155 /** 156 * Saves a given data into a temp file and returns its corresponding {@link File} object. 157 * @param data the data to save 158 * @return the File into which the data was written or null if it failed. 159 * @throws IOException 160 */ saveTempFile(byte[] data, String extension)161 protected File saveTempFile(byte[] data, String extension) throws IOException { 162 File f = File.createTempFile("ddms", extension); 163 saveFile(data, f); 164 return f; 165 } 166 167 /** 168 * Saves some data into a given File. 169 * @param data the data to save 170 * @param output the file into the data is saved. 171 * @throws IOException 172 */ saveFile(byte[] data, File output)173 protected void saveFile(byte[] data, File output) throws IOException { 174 FileOutputStream fos = null; 175 try { 176 fos = new FileOutputStream(output); 177 fos.write(data); 178 } finally { 179 if (fos != null) { 180 fos.close(); 181 } 182 } 183 } 184 } 185