• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.SyncService;
20 import com.android.ddmlib.ClientData.IHprofDumpHandler;
21 import com.android.ddmlib.ClientData.IMethodProfilingHandler;
22 import com.android.ddmlib.SyncService.SyncResult;
23 import com.android.ddmuilib.SyncProgressMonitor;
24 
25 import org.eclipse.core.runtime.IProgressMonitor;
26 import org.eclipse.jface.dialogs.MessageDialog;
27 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
28 import org.eclipse.jface.operation.IRunnableWithProgress;
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      */
promptAndPull(SyncService sync, String localFileName, String remoteFilePath, String title)67     protected SyncResult promptAndPull(SyncService sync,
68             String localFileName, String remoteFilePath, String title)
69             throws InvocationTargetException, InterruptedException {
70         FileDialog fileDialog = new FileDialog(mParentShell, SWT.SAVE);
71 
72         fileDialog.setText(title);
73         fileDialog.setFileName(localFileName);
74 
75         String localFilePath = fileDialog.open();
76         if (localFilePath != null) {
77             return pull(sync, localFilePath, remoteFilePath);
78         }
79 
80         return null;
81     }
82 
83     /**
84      * Prompts the user for a save location and copies a temp file into it.
85      * <p/>This <strong>must</strong> be called from the UI Thread.
86      * @param localFileName The default local name
87      * @param tempFilePath The name of the temp file to copy.
88      * @param title The title of the File Save dialog.
89      * @return true if success, false on error or cancel.
90      */
promptAndSave(String localFileName, byte[] data, String title)91     protected boolean promptAndSave(String localFileName, byte[] data, String title) {
92         FileDialog fileDialog = new FileDialog(mParentShell, SWT.SAVE);
93 
94         fileDialog.setText(title);
95         fileDialog.setFileName(localFileName);
96 
97         String localFilePath = fileDialog.open();
98         if (localFilePath != null) {
99             try {
100                 saveFile(data, new File(localFilePath));
101                 return true;
102             } catch (IOException e) {
103                 String errorMsg = e.getMessage();
104                 displayErrorInUiThread(
105                         "Failed to save file '%1$s'%2$s",
106                         localFilePath,
107                         errorMsg != null ? ":\n" + errorMsg : ".");
108             }
109         }
110 
111         return false;
112     }
113 
114     /**
115      * Pulls a file off of a device. This displays a {@link ProgressMonitorDialog} and therefore
116      * must be run from the UI Thread.
117      * @param sync the {@link SyncService} to use to pull the file.
118      * @param localFilePath the path of the local file to create
119      * @param remoteFilePath the path of the remote file to pull
120      * @return the result of the sync as an instance of {@link SyncResult}
121      * @throws InvocationTargetException
122      * @throws InterruptedException
123      */
pull(final SyncService sync, final String localFilePath, final String remoteFilePath)124     protected SyncResult pull(final SyncService sync, final String localFilePath,
125             final String remoteFilePath)
126             throws InvocationTargetException, InterruptedException {
127         final SyncResult[] res = new SyncResult[1];
128         new ProgressMonitorDialog(mParentShell).run(true, true, new IRunnableWithProgress() {
129             public void run(IProgressMonitor monitor) {
130                 try {
131                     res[0] = sync.pullFile(remoteFilePath, localFilePath,
132                             new SyncProgressMonitor(monitor, String.format(
133                                     "Pulling %1$s from the device", remoteFilePath)));
134                 } finally {
135                     sync.close();
136                 }
137             }
138         });
139 
140         return res[0];
141     }
142 
143     /**
144      * Display an error message.
145      * <p/>This will call about to {@link Display} to run this in an async {@link Runnable} in the
146      * UI Thread. This is safe to be called from a non-UI Thread.
147      * @param format the string to display
148      * @param args the string arguments
149      */
displayErrorInUiThread(final String format, final Object... args)150     protected void displayErrorInUiThread(final String format, final Object... args) {
151         mParentShell.getDisplay().asyncExec(new Runnable() {
152             public void run() {
153                 MessageDialog.openError(mParentShell, getDialogTitle(),
154                         String.format(format, args));
155             }
156         });
157     }
158 
159     /**
160      * Display an error message.
161      * This must be called from the UI Thread.
162      * @param format the string to display
163      * @param args the string arguments
164      */
displayErrorFromUiThread(final String format, final Object... args)165     protected void displayErrorFromUiThread(final String format, final Object... args) {
166         MessageDialog.openError(mParentShell, getDialogTitle(),
167                 String.format(format, args));
168     }
169 
170     /**
171      * Saves a given data into a temp file and returns its corresponding {@link File} object.
172      * @param data the data to save
173      * @return the File into which the data was written or null if it failed.
174      * @throws IOException
175      */
saveTempFile(byte[] data)176     protected File saveTempFile(byte[] data) throws IOException {
177         File f = File.createTempFile("ddms", null);
178         saveFile(data, f);
179         return f;
180     }
181 
182     /**
183      * Saves some data into a given File.
184      * @param data the data to save
185      * @param output the file into the data is saved.
186      * @throws IOException
187      */
saveFile(byte[] data, File output)188     protected void saveFile(byte[] data, File output) throws IOException {
189         FileOutputStream fos = null;
190         try {
191             fos = new FileOutputStream(output);
192             fos.write(data);
193         } finally {
194             if (fos != null) {
195                 fos.close();
196             }
197         }
198     }
199 }
200