Eclipse has a useful plugin/extension called Remote Systems Explorer (RSE) and can be used to browse files, folders, processes and start a shell for a remote server right within Eclipse IDE. They have tutorials to show how it can be extended further and one of them is to add a property page for local folders showing the no of files and the total size.
Rest of the file was generated by Eclipse to implement the abstract methods. Hope it works for you too.
But the tutorial does not work for Mars version of Eclipse and spent several hours trying to figure out on how to fix it.
One of the first error I encountered was ResourceBundle not found. That was easy one and moved the rseSamplesMessages.xml and rseSamplesResources.properties into src/ folder.
Second error was the missing message Id 1002. Figured out that 1002 needs to be added to the xml file having the message Processing as shown below.
<message id="1002" indicator="E"> <levelone>Sample message</levelone> <leveltwo>Processing...</leveltwo> </message>
Third error was to extend new class called FolderInfoPropertyPage from com.ibm.etools.systems.core.ui.propertypages.SystemAbstractRemoteFilePropertyPageExtensionAction but that class was not present in the Mars plugins. Figured out that I can extend FolderInfoPropertyPage from
org.eclipse.rse.ui.propertypages.SystemBasePropertyPage and copy the getRemoteFile() from the class org.eclipse.rse.internal.files.ui.propertypages.SystemFilePropertyPage. Had to do some trivial code changes but seems to be working.
org.eclipse.rse.ui.propertypages.SystemBasePropertyPage and copy the getRemoteFile() from the class org.eclipse.rse.internal.files.ui.propertypages.SystemFilePropertyPage. Had to do some trivial code changes but seems to be working.
package samples.ui.propertypages; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.rse.core.filters.ISystemFilter; import org.eclipse.rse.core.filters.ISystemFilterPool; import org.eclipse.rse.core.filters.ISystemFilterPoolReference; import org.eclipse.rse.core.filters.ISystemFilterPoolReferenceManager; import org.eclipse.rse.core.filters.ISystemFilterReference; import org.eclipse.rse.core.filters.ISystemFilterString; import org.eclipse.rse.core.model.IHost; import org.eclipse.rse.core.model.IPropertySet; import org.eclipse.rse.core.model.IPropertySetContainer; import org.eclipse.rse.core.model.IRSECallback; import org.eclipse.rse.core.model.IRSEPersistableContainer; import org.eclipse.rse.core.model.ISystemProfile; import org.eclipse.rse.core.subsystems.ICacheManager; import org.eclipse.rse.core.subsystems.IConnectorService; import org.eclipse.rse.core.subsystems.ISubSystem; import org.eclipse.rse.core.subsystems.ISubSystemConfiguration; import org.eclipse.rse.internal.files.ui.propertypages.*; import org.eclipse.rse.services.clientserver.messages.SystemMessageException; import org.eclipse.rse.services.search.IHostSearchResultConfiguration; import org.eclipse.rse.subsystems.files.core.ILanguageUtilityFactory; import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile; import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileContext; import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileSubSystem; import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileSubSystemConfiguration; import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteSearchResult; import org.eclipse.rse.ui.SystemBasePlugin; import org.eclipse.rse.ui.SystemWidgetHelpers; import org.eclipse.rse.ui.propertypages.SystemBasePropertyPage; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.dialogs.PropertyPage; import rsesamples.RSESamplesPlugin; /** * A sample property page for a remote object, which in this case is scoped via the * extension point xml to only apply to folder objects. * * com.ibm.etools.systems.core.ui.propertypages.SystemAbstractRemoteFilePropertyPageExtensionAction */ public class FolderInfoPropertyPage //extends SystemFilePropertyPage extends SystemBasePropertyPage implements SelectionListener, IRemoteFileSubSystem { // gui widgets... private Label sizeLabel, filesLabel, foldersLabel; private Button stopButton; // state... private int totalSize = 0; private int totalFolders = 0; private int totalFiles = 0; private boolean stopped = false; private Thread workerThread; private Runnable guiUpdater; /** * Constructor for FolderInfoPropertyPage. */ public FolderInfoPropertyPage() { super(); } // -------------------------- // Parent method overrides... // -------------------------- /* (non-Javadoc) * @see org.eclipse.rse.files.ui.propertypages.SystemAbstractRemoteFilePropertyPageExtensionAction#createContentArea(org.eclipse.swt.widgets.Composite) */ protected Control createContentArea(Composite parent) { Composite composite = SystemWidgetHelpers.createComposite(parent, 2); // draw the gui sizeLabel = SystemWidgetHelpers.createLabeledLabel(composite, RSESamplesPlugin.getResourceString("pp.size.label"), //$NON-NLS-1$ RSESamplesPlugin.getResourceString("pp.size.tooltip"), //$NON-NLS-1$ false); filesLabel = SystemWidgetHelpers.createLabeledLabel(composite, RSESamplesPlugin.getResourceString("pp.files.label"), //$NON-NLS-1$ RSESamplesPlugin.getResourceString("pp.files.tooltip"), //$NON-NLS-1$ false); foldersLabel = SystemWidgetHelpers.createLabeledLabel(composite, RSESamplesPlugin.getResourceString("pp.folders.label"), //$NON-NLS-1$ RSESamplesPlugin.getResourceString("pp.folders.tooltip"), //$NON-NLS-1$ false); stopButton = SystemWidgetHelpers.createPushButton(composite, null, RSESamplesPlugin.getResourceString("pp.stopButton.label"), //$NON-NLS-1$ RSESamplesPlugin.getResourceString("pp.stopButton.tooltip") //$NON-NLS-1$ ); stopButton.addSelectionListener(this); setValid(false); // Disable OK button until thread is done // show "Processing..." message setMessage(RSESamplesPlugin.getPluginMessage("RSSG1002")); //$NON-NLS-1$ // create instance of Runnable to allow asynchronous GUI updates from background thread guiUpdater = new RunnableGUIClass(); // spawn a thread to calculate the information workerThread = new RunnableClass(getRemoteFile()); workerThread.start(); return composite; } /** * Get the input remote file object. Copied from org.eclipse.rse.internal.files.ui.propertypages.SystemFilePropertyPage */ protected IRemoteFile getRemoteFile() { Object element = getElement(); IRemoteFile file = (IRemoteFile)element; return file; } /** * Intercept from PreferencePage. Called when user presses Cancel button. * We stop the background thread. * @see org.eclipse.jface.preference.PreferencePage#performCancel() */ public boolean performCancel() { killThread(); return true; } /** * Intercept from DialogPage. Called when dialog going away. * If the user presses the X to close this dialog, we * need to stop that background thread. */ public void dispose() { killThread(); super.dispose(); } /** * Private method to kill our background thread. * Control doesn't return until it ends. */ private void killThread() { if (!stopped && workerThread.isAlive()) { stopped = true; try { workerThread.join(); // wait for thread to end } catch (InterruptedException exc) {} } } // ------------------------------------------- // Methods from SelectionListener interface... // ------------------------------------------- /** * From SelectionListener * @see SelectionListener#widgetSelected(SelectionEvent) */ public void widgetSelected(SelectionEvent event) { if (event.getSource() == stopButton) { stopped = true; stopButton.setEnabled(false); } } /** * From SelectionListener * @see SelectionListener#widgetDefaultSelected(SelectionEvent) */ public void widgetDefaultSelected(SelectionEvent event) { } // ---------------- // Inner classes... // ---------------- /** * Inner class encapsulating the background work to be done, so it may be executed * in background thread. */ private class RunnableClass extends Thread { IRemoteFile inputFolder; RunnableClass(IRemoteFile inputFolder) { this.inputFolder = inputFolder; } public void run() { if (stopped) return; walkFolder(inputFolder); updateGUI(); if (!stopped) { stopped = true; updateGUI(); } } /** * Recursively walk a folder, updating the running tallies. * Update the GUI after processing each subfolder. */ private void walkFolder(IRemoteFile currFolder) { SystemBasePlugin.logInfo("walkFolder() currFolder="+currFolder.getName()); try { IRemoteFile[] folders = currFolder.getParentRemoteFileSubSystem().list( currFolder, null); if ((folders != null) && (folders.length>0)) { for (int idx=0; !stopped && (idx<folders .length="" a="" catch="" e="" else="" exception="+e); } } // end of walkFolder method } // end of inner class /** * Inner class encapsulating the GUI work to be done from the * background thread. */ private class RunnableGUIClass implements Runnable { public void run() { if (stopButton.isDisposed()) return; sizeLabel.setText(Integer.toString(totalSize)); filesLabel.setText(Integer.toString(totalFiles)); foldersLabel.setText(Integer.toString(totalFolders)); if (!stopped) { } else if (stopped) { setValid(true); // re-enable OK button stopButton.setEnabled(false); // disable Stop button //clearMessage(); // clear "Processing..." message } } }
Rest of the file was generated by Eclipse to implement the abstract methods. Hope it works for you too.