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.SyncException; 20 import com.android.ddmlib.SyncService; 21 import com.android.ddmlib.TimeoutException; 22 import com.android.ddmlib.ClientData.IHprofDumpHandler; 23 import com.android.ddmlib.ClientData.IMethodProfilingHandler; 24 import com.android.ddmlib.SyncService.ISyncProgressMonitor; 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 public void run(ISyncProgressMonitor monitor) throws SyncException, IOException, 82 TimeoutException { 83 sync.pullFile(remoteFilePath, localFilePath, monitor); 84 } 85 86 public void close() { 87 sync.close(); 88 } 89 }, 90 String.format("Pulling %1$s from the device", remoteFilePath), mParentShell); 91 } 92 } 93 94 /** 95 * Prompts the user for a save location and copies a temp file into it. 96 * <p/>This <strong>must</strong> be called from the UI Thread. 97 * @param localFileName The default local name 98 * @param tempFilePath The name of the temp file to copy. 99 * @param title The title of the File Save dialog. 100 * @return true if success, false on error or cancel. 101 */ promptAndSave(String localFileName, byte[] data, String title)102 protected boolean promptAndSave(String localFileName, byte[] data, String title) { 103 FileDialog fileDialog = new FileDialog(mParentShell, SWT.SAVE); 104 105 fileDialog.setText(title); 106 fileDialog.setFileName(localFileName); 107 108 String localFilePath = fileDialog.open(); 109 if (localFilePath != null) { 110 try { 111 saveFile(data, new File(localFilePath)); 112 return true; 113 } catch (IOException e) { 114 String errorMsg = e.getMessage(); 115 displayErrorInUiThread( 116 "Failed to save file '%1$s'%2$s", 117 localFilePath, 118 errorMsg != null ? ":\n" + errorMsg : "."); 119 } 120 } 121 122 return false; 123 } 124 125 /** 126 * Display an error message. 127 * <p/>This will call about to {@link Display} to run this in an async {@link Runnable} in the 128 * UI Thread. This is safe to be called from a non-UI Thread. 129 * @param format the string to display 130 * @param args the string arguments 131 */ displayErrorInUiThread(final String format, final Object... args)132 protected void displayErrorInUiThread(final String format, final Object... args) { 133 mParentShell.getDisplay().asyncExec(new Runnable() { 134 public void run() { 135 MessageDialog.openError(mParentShell, getDialogTitle(), 136 String.format(format, args)); 137 } 138 }); 139 } 140 141 /** 142 * Display an error message. 143 * This must be called from the UI Thread. 144 * @param format the string to display 145 * @param args the string arguments 146 */ displayErrorFromUiThread(final String format, final Object... args)147 protected void displayErrorFromUiThread(final String format, final Object... args) { 148 MessageDialog.openError(mParentShell, getDialogTitle(), 149 String.format(format, args)); 150 } 151 152 /** 153 * Saves a given data into a temp file and returns its corresponding {@link File} object. 154 * @param data the data to save 155 * @return the File into which the data was written or null if it failed. 156 * @throws IOException 157 */ saveTempFile(byte[] data, String extension)158 protected File saveTempFile(byte[] data, String extension) throws IOException { 159 File f = File.createTempFile("ddms", extension); 160 saveFile(data, f); 161 return f; 162 } 163 164 /** 165 * Saves some data into a given File. 166 * @param data the data to save 167 * @param output the file into the data is saved. 168 * @throws IOException 169 */ saveFile(byte[] data, File output)170 protected void saveFile(byte[] data, File output) throws IOException { 171 FileOutputStream fos = null; 172 try { 173 fos = new FileOutputStream(output); 174 fos.write(data); 175 } finally { 176 if (fos != null) { 177 fos.close(); 178 } 179 } 180 } 181 } 182