DeviceExplorerpublic class DeviceExplorer extends com.android.ddmuilib.Panel Device filesystem explorer class. |
Fields Summary |
---|
private static final String | TRACE_KEY_EXT | private static final String | TRACE_DATA_EXT | private static Pattern | mKeyFilePattern | private static Pattern | mDataFilePattern | public static String | COLUMN_NAME | public static String | COLUMN_SIZE | public static String | COLUMN_DATE | public static String | COLUMN_TIME | public static String | COLUMN_PERMISSIONS | public static String | COLUMN_INFO | private org.eclipse.swt.widgets.Composite | mParent | private org.eclipse.jface.viewers.TreeViewer | mTreeViewer | private org.eclipse.swt.widgets.Tree | mTree | private DeviceContentProvider | mContentProvider | private com.android.ddmuilib.actions.ICommonAction | mPushAction | private com.android.ddmuilib.actions.ICommonAction | mPullAction | private com.android.ddmuilib.actions.ICommonAction | mDeleteAction | private org.eclipse.swt.graphics.Image | mFileImage | private org.eclipse.swt.graphics.Image | mFolderImage | private org.eclipse.swt.graphics.Image | mPackageImage | private org.eclipse.swt.graphics.Image | mOtherImage | private com.android.ddmlib.Device | mCurrentDevice | private String | mDefaultSave |
Constructors Summary |
---|
public DeviceExplorer()
|
Methods Summary |
---|
protected org.eclipse.swt.widgets.Control | createControl(org.eclipse.swt.widgets.Composite parent)Creates a control capable of displaying some information. This is
called once, when the application is initializing, from the UI thread.
mParent = parent;
parent.setLayout(new FillLayout());
mTree = new Tree(parent, SWT.MULTI | SWT.FULL_SELECTION | SWT.VIRTUAL);
mTree.setHeaderVisible(true);
IPreferenceStore store = DdmUiPreferences.getStore();
// create columns
TableHelper.createTreeColumn(mTree, "Name", SWT.LEFT,
"0000drwxrwxrwx", COLUMN_NAME, store); //$NON-NLS-1$
TableHelper.createTreeColumn(mTree, "Size", SWT.RIGHT,
"000000", COLUMN_SIZE, store); //$NON-NLS-1$
TableHelper.createTreeColumn(mTree, "Date", SWT.LEFT,
"2007-08-14", COLUMN_DATE, store); //$NON-NLS-1$
TableHelper.createTreeColumn(mTree, "Time", SWT.LEFT,
"20:54", COLUMN_TIME, store); //$NON-NLS-1$
TableHelper.createTreeColumn(mTree, "Permissions", SWT.LEFT,
"drwxrwxrwx", COLUMN_PERMISSIONS, store); //$NON-NLS-1$
TableHelper.createTreeColumn(mTree, "Info", SWT.LEFT,
"drwxrwxrwx", COLUMN_INFO, store); //$NON-NLS-1$
// create the jface wrapper
mTreeViewer = new TreeViewer(mTree);
// setup data provider
mContentProvider = new DeviceContentProvider();
mTreeViewer.setContentProvider(mContentProvider);
mTreeViewer.setLabelProvider(new FileLabelProvider(mFileImage,
mFolderImage, mPackageImage, mOtherImage));
// setup a listener for selection
mTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
ISelection sel = event.getSelection();
if (sel.isEmpty()) {
mPullAction.setEnabled(false);
mPushAction.setEnabled(false);
mDeleteAction.setEnabled(false);
return;
}
if (sel instanceof IStructuredSelection) {
IStructuredSelection selection = (IStructuredSelection) sel;
Object element = selection.getFirstElement();
if (element == null)
return;
if (element instanceof FileEntry) {
mPullAction.setEnabled(true);
mPushAction.setEnabled(selection.size() == 1);
if (selection.size() == 1) {
setDeleteEnabledState((FileEntry)element);
} else {
mDeleteAction.setEnabled(false);
}
}
}
}
});
// add support for double click
mTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
ISelection sel = event.getSelection();
if (sel instanceof IStructuredSelection) {
IStructuredSelection selection = (IStructuredSelection) sel;
if (selection.size() == 1) {
FileEntry entry = (FileEntry)selection.getFirstElement();
String name = entry.getName();
FileEntry parentEntry = entry.getParent();
// can't really do anything with no parent
if (parentEntry == null) {
return;
}
// check this is a file like we want.
Matcher m = mKeyFilePattern.matcher(name);
if (m.matches()) {
// get the name w/o the extension
String baseName = m.group(1);
// add the data extension
String dataName = baseName + TRACE_DATA_EXT;
FileEntry dataEntry = parentEntry.findChild(dataName);
handleTraceDoubleClick(baseName, entry, dataEntry);
} else {
m = mDataFilePattern.matcher(name);
if (m.matches()) {
// get the name w/o the extension
String baseName = m.group(1);
// add the key extension
String keyName = baseName + TRACE_KEY_EXT;
FileEntry keyEntry = parentEntry.findChild(keyName);
handleTraceDoubleClick(baseName, keyEntry, entry);
}
}
}
}
}
});
// setup drop listener
mTreeViewer.addDropSupport(DND.DROP_COPY | DND.DROP_MOVE,
new Transfer[] { FileTransfer.getInstance() },
new ViewerDropAdapter(mTreeViewer) {
@Override
public boolean performDrop(Object data) {
// get the item on which we dropped the item(s)
FileEntry target = (FileEntry)getCurrentTarget();
// in case we drop at the same level as root
if (target == null) {
return false;
}
// if the target is not a directory, we get the parent directory
if (target.isDirectory() == false) {
target = target.getParent();
}
if (target == null) {
return false;
}
// get the list of files to drop
String[] files = (String[])data;
// do the drop
pushFiles(files, target);
// we need to finish with a refresh
refresh(target);
return true;
}
@Override
public boolean validateDrop(Object target, int operation, TransferData transferType) {
if (target == null) {
return false;
}
// convert to the real item
FileEntry targetEntry = (FileEntry)target;
// if the target is not a directory, we get the parent directory
if (targetEntry.isDirectory() == false) {
target = targetEntry.getParent();
}
if (target == null) {
return false;
}
return true;
}
});
// create and start the refresh thread
new Thread("Device Ls refresher") {
@Override
public void run() {
while (true) {
try {
sleep(FileListingService.REFRESH_RATE);
} catch (InterruptedException e) {
return;
}
if (mTree != null && mTree.isDisposed() == false) {
Display display = mTree.getDisplay();
if (display.isDisposed() == false) {
display.asyncExec(new Runnable() {
public void run() {
if (mTree.isDisposed() == false) {
mTreeViewer.refresh(true);
}
}
});
} else {
return;
}
} else {
return;
}
}
}
}.start();
return mTree;
| public void | deleteSelection()
// get the name of the object we're going to pull
TreeItem[] items = mTree.getSelection();
if (items.length != 1) {
return;
}
FileEntry entry = (FileEntry)items[0].getData();
final FileEntry parentEntry = entry.getParent();
// create the delete command
String command = "rm " + entry.getFullEscapedPath(); //$NON-NLS-1$
try {
mCurrentDevice.executeShellCommand(command, new IShellOutputReceiver() {
public void addOutput(byte[] data, int offset, int length) {
// pass
// TODO get output to display errors if any.
}
public void flush() {
mTreeViewer.refresh(parentEntry);
}
public boolean isCancelled() {
return false;
}
});
} catch (IOException e) {
// adb failed somehow, we do nothing. We should be displaying the error from the output
// of the shell command.
}
| private void | handleTraceDoubleClick(java.lang.String baseName, com.android.ddmlib.FileListingService.FileEntry keyEntry, com.android.ddmlib.FileListingService.FileEntry dataEntry)Processes a double click on a trace file
// first we need to download the files.
File keyFile;
File dataFile;
String path;
try {
// create a temp file for keyFile
File f = File.createTempFile(baseName, ".trace");
f.delete();
f.mkdir();
path = f.getAbsolutePath();
keyFile = new File(path + File.separator + keyEntry.getName());
dataFile = new File(path + File.separator + dataEntry.getName());
} catch (IOException e) {
return;
}
// download the files
SyncService sync = mCurrentDevice.getSyncService();
if (sync != null) {
ISyncProgressMonitor monitor = SyncService.getNullProgressMonitor();
SyncResult result = sync.pullFile(keyEntry, keyFile.getAbsolutePath(), monitor);
if (result.getCode() != SyncService.RESULT_OK) {
DdmConsole.printErrorToConsole(String.format(
"Failed to pull %1$s: %2$s", keyEntry.getName(), result.getMessage()));
return;
}
result = sync.pullFile(dataEntry, dataFile.getAbsolutePath(), monitor);
if (result.getCode() != SyncService.RESULT_OK) {
DdmConsole.printErrorToConsole(String.format(
"Failed to pull %1$s: %2$s", dataEntry.getName(), result.getMessage()));
return;
}
// now that we have the file, we need to launch traceview
String[] command = new String[2];
command[0] = DdmUiPreferences.getTraceview();
command[1] = path + File.separator + baseName;
try {
final Process p = Runtime.getRuntime().exec(command);
// create a thread for the output
new Thread("Traceview output") {
@Override
public void run() {
// create a buffer to read the stderr output
InputStreamReader is = new InputStreamReader(p.getErrorStream());
BufferedReader resultReader = new BufferedReader(is);
// read the lines as they come. if null is returned, it's
// because the process finished
try {
while (true) {
String line = resultReader.readLine();
if (line != null) {
DdmConsole.printErrorToConsole("Traceview: " + line);
} else {
break;
}
}
// get the return code from the process
p.waitFor();
} catch (IOException e) {
} catch (InterruptedException e) {
}
}
}.start();
} catch (IOException e) {
}
}
| protected void | postCreation()
| private void | pullFile(com.android.ddmlib.FileListingService.FileEntry remote, java.lang.String local)Pulls a file from a device.
final SyncService sync = mCurrentDevice.getSyncService();
if (sync != null) {
try {
new ProgressMonitorDialog(mParent.getShell()).run(true, true,
new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException,
InterruptedException {
SyncResult result = sync.pullFile(remote, local, new SyncProgressMonitor(
monitor, String.format("Pulling %1$s from the device",
remote.getName())));
if (result.getCode() != SyncService.RESULT_OK) {
DdmConsole.printErrorToConsole(String.format(
"Failed to pull %1$s: %2$s", remote, result.getMessage()));
}
sync.close();
}
});
} catch (InvocationTargetException e) {
DdmConsole.printErrorToConsole( "Failed to pull selection");
DdmConsole.printErrorToConsole(e.getMessage());
} catch (InterruptedException e) {
DdmConsole.printErrorToConsole("Failed to pull selection");
DdmConsole.printErrorToConsole(e.getMessage());
}
}
| private void | pullSelection(org.eclipse.swt.widgets.TreeItem[] items, java.lang.String localDirectory)Pulls the selection from a device.
final SyncService sync = mCurrentDevice.getSyncService();
if (sync != null) {
// make a list of the FileEntry.
ArrayList<FileEntry> entries = new ArrayList<FileEntry>();
for (TreeItem item : items) {
Object data = item.getData();
if (data instanceof FileEntry) {
entries.add((FileEntry)data);
}
}
final FileEntry[] entryArray = entries.toArray(
new FileEntry[entries.size()]);
// get a progressdialog
try {
new ProgressMonitorDialog(mParent.getShell()).run(true, true,
new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException,
InterruptedException {
// create a monitor wrapper around the jface monitor
SyncResult result = sync.pull(entryArray, localDirectory,
new SyncProgressMonitor(monitor,
"Pulling file(s) from the device"));
if (result.getCode() != SyncService.RESULT_OK) {
DdmConsole.printErrorToConsole(String.format(
"Failed to pull selection: %1$s", result.getMessage()));
}
sync.close();
}
});
} catch (InvocationTargetException e) {
DdmConsole.printErrorToConsole( "Failed to pull selection");
DdmConsole.printErrorToConsole(e.getMessage());
} catch (InterruptedException e) {
DdmConsole.printErrorToConsole("Failed to pull selection");
DdmConsole.printErrorToConsole(e.getMessage());
}
}
| public void | pullSelection()Pull the current selection on the local drive. This method displays
a dialog box to let the user select where to store the file(s) and
folder(s).
// get the selection
TreeItem[] items = mTree.getSelection();
// name of the single file pull, or null if we're pulling a directory
// or more than one object.
String filePullName = null;
FileEntry singleEntry = null;
// are we pulling a single file?
if (items.length == 1) {
singleEntry = (FileEntry)items[0].getData();
if (singleEntry.getType() == FileListingService.TYPE_FILE) {
filePullName = singleEntry.getName();
}
}
// where do we save by default?
String defaultPath = mDefaultSave;
if (defaultPath == null) {
defaultPath = System.getProperty("user.home"); //$NON-NLS-1$
}
if (filePullName != null) {
FileDialog fileDialog = new FileDialog(mParent.getShell(), SWT.SAVE);
fileDialog.setText("Get Device File");
fileDialog.setFileName(filePullName);
fileDialog.setFilterPath(defaultPath);
String fileName = fileDialog.open();
if (fileName != null) {
mDefaultSave = fileDialog.getFilterPath();
pullFile(singleEntry, fileName);
}
} else {
DirectoryDialog directoryDialog = new DirectoryDialog(mParent.getShell(), SWT.SAVE);
directoryDialog.setText("Get Device Files/Folders");
directoryDialog.setFilterPath(defaultPath);
String directoryName = directoryDialog.open();
if (directoryName != null) {
pullSelection(items, directoryName);
}
}
| private void | pushFile(java.lang.String local, java.lang.String remoteDirectory)Pushes a file on a device.
final SyncService sync = mCurrentDevice.getSyncService();
if (sync != null) {
try {
new ProgressMonitorDialog(mParent.getShell()).run(true, true,
new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException,
InterruptedException {
// get the file name
String[] segs = local.split(Pattern.quote(File.separator));
String name = segs[segs.length-1];
String remoteFile = remoteDirectory + FileListingService.FILE_SEPARATOR
+ name;
SyncResult result = sync.pushFile(local, remoteFile,
new SyncProgressMonitor(monitor,
String.format("Pushing %1$s to the device.", name)));
if (result.getCode() != SyncService.RESULT_OK) {
DdmConsole.printErrorToConsole(String.format(
"Failed to push %1$s on %2$s: %3$s",
name, mCurrentDevice.getSerialNumber(), result.getMessage()));
}
sync.close();
}
});
} catch (InvocationTargetException e) {
DdmConsole.printErrorToConsole("Failed to push the item(s).");
DdmConsole.printErrorToConsole(e.getMessage());
} catch (InterruptedException e) {
DdmConsole.printErrorToConsole("Failed to push the item(s).");
DdmConsole.printErrorToConsole(e.getMessage());
}
return;
}
| private void | pushFiles(java.lang.String[] localFiles, com.android.ddmlib.FileListingService.FileEntry remoteDirectory)Pushes several files and directory into a remote directory.
final SyncService sync = mCurrentDevice.getSyncService();
if (sync != null) {
try {
new ProgressMonitorDialog(mParent.getShell()).run(true, true,
new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException,
InterruptedException {
SyncResult result = sync.push(localFiles, remoteDirectory,
new SyncProgressMonitor(monitor,
"Pushing file(s) to the device"));
if (result.getCode() != SyncService.RESULT_OK) {
DdmConsole.printErrorToConsole(String.format(
"Failed to push the items: %1$s", result.getMessage()));
}
sync.close();
}
});
} catch (InvocationTargetException e) {
DdmConsole.printErrorToConsole("Failed to push the items");
DdmConsole.printErrorToConsole(e.getMessage());
} catch (InterruptedException e) {
DdmConsole.printErrorToConsole("Failed to push the items");
DdmConsole.printErrorToConsole(e.getMessage());
}
return;
}
| public void | pushIntoSelection()Push new file(s) and folder(s) into the current selection. Current
selection must be single item. If the current selection is not a
directory, the parent directory is used.
This method displays a dialog to let the user choose file to push to
the device.
// get the name of the object we're going to pull
TreeItem[] items = mTree.getSelection();
if (items.length == 0) {
return;
}
FileDialog dlg = new FileDialog(mParent.getShell(), SWT.OPEN);
String fileName;
dlg.setText("Put File on Device");
// There should be only one.
FileEntry entry = (FileEntry)items[0].getData();
dlg.setFileName(entry.getName());
String defaultPath = mDefaultSave;
if (defaultPath == null) {
defaultPath = System.getProperty("user.home"); //$NON-NLS-1$
}
dlg.setFilterPath(defaultPath);
fileName = dlg.open();
if (fileName != null) {
mDefaultSave = dlg.getFilterPath();
// we need to figure out the remote path based on the current selection type.
String remotePath;
FileEntry toRefresh = entry;
if (entry.isDirectory()) {
remotePath = entry.getFullPath();
} else {
toRefresh = entry.getParent();
remotePath = toRefresh.getFullPath();
}
pushFile(fileName, remotePath);
mTreeViewer.refresh(toRefresh);
}
| public void | refresh()Force a full refresh of the explorer.
mTreeViewer.refresh(true);
| private void | refresh(com.android.ddmlib.FileListingService.FileEntry entry)Refresh an entry from a non ui thread.
Display d = mTreeViewer.getTree().getDisplay();
d.asyncExec(new Runnable() {
public void run() {
mTreeViewer.refresh(entry);
}
});
| public void | setActions(com.android.ddmuilib.actions.ICommonAction pushAction, com.android.ddmuilib.actions.ICommonAction pullAction, com.android.ddmuilib.actions.ICommonAction deleteAction)Sets the actions so that the device explorer can enable/disable them based on the current
selection
mPushAction = pushAction;
mPullAction = pullAction;
mDeleteAction = deleteAction;
| protected void | setDeleteEnabledState(com.android.ddmlib.FileListingService.FileEntry element)Sets the enabled state based on a FileEntry properties
mDeleteAction.setEnabled(element.getType() == FileListingService.TYPE_FILE);
| public void | setFocus()Sets the focus to the proper control inside the panel.
mTree.setFocus();
| public void | setImages(org.eclipse.swt.graphics.Image fileImage, org.eclipse.swt.graphics.Image folderImage, org.eclipse.swt.graphics.Image packageImage, org.eclipse.swt.graphics.Image otherImage)Sets the images for the listview
mFileImage = fileImage;
mFolderImage = folderImage;
mPackageImage = packageImage;
mOtherImage = otherImage;
| public void | switchDevice(com.android.ddmlib.Device device)Sets the new device to explorer
if (device != mCurrentDevice) {
mCurrentDevice = device;
// now we change the input. but we need to do that in the
// ui thread.
if (mTree.isDisposed() == false) {
Display d = mTree.getDisplay();
d.asyncExec(new Runnable() {
public void run() {
if (mTree.isDisposed() == false) {
// new service
if (mCurrentDevice != null) {
FileListingService fls = mCurrentDevice.getFileListingService();
mContentProvider.setListingService(fls);
mTreeViewer.setInput(fls.getRoot());
}
}
}
});
}
}
|
|