package org.eparapher.rcp.properties; import java.io.File; import java.io.IOException; import org.apache.log4j.Logger; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.RTFTransfer; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.MenuAdapter; import org.eclipse.swt.events.MenuEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; 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.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.PropertyPage; import org.eparapher.core.crypto.EPDigestManager; import org.eparapher.core.tools.FileUtil; import org.eparapher.rcp.tools.GUIIcons; import org.eparapher.rcp.views.documents.SecuredDocumentsView; public class FileHashPropertyPage extends PropertyPage { private static final String ID = "org.eparapher.rcp.properties.filePropertyPage"; private static Logger log = Logger.getLogger(FileHashPropertyPage.class); private static final String COMPUTE_ALL_DIGESTS = "Compute all digests"; private static final String COMPUTE_SELECTED_DIGEST = "Compute selected digest"; private Button processAllHashes = null; private Button processSelectedHash = null; private Table hashTable = null; /** * Constructor for SamplePropertyPage. */ public FileHashPropertyPage() { super(); } private void addFirstSection(Composite parent) { Composite composite = createDefaultComposite(parent); processAllHashes = new Button(composite, SWT.PUSH); processAllHashes.setText(COMPUTE_ALL_DIGESTS); processAllHashes.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { processDigests(false); } }); processSelectedHash = new Button(composite, SWT.PUSH); processSelectedHash.setText(COMPUTE_SELECTED_DIGEST); processSelectedHash.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { processDigests(true); } }); } private void addSeparator(Composite parent) { Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); GridData gridData = new GridData(); gridData.horizontalAlignment = GridData.FILL; gridData.grabExcessHorizontalSpace = true; separator.setLayoutData(gridData); } private void addSecondSection(Composite parent) { Composite composite = createDefaultComposite(parent); hashTable = new Table(composite, SWT.BORDER | SWT.SINGLE ); hashTable.setLayoutData(new GridData(GridData.FILL_BOTH)); hashTable.setLinesVisible(true); hashTable.setHeaderVisible(true); TableColumn algColumn = new TableColumn(hashTable, SWT.NONE); algColumn.setWidth(80); algColumn.setText("Algorithm"); TableColumn hashValueColumn = new TableColumn(hashTable, SWT.NONE); hashValueColumn.setWidth(700); hashValueColumn.setText("Value"); //Empty table TableItem ti; for (int i = 0; i < EPDigestManager.DIGEST_ALGORITHMS.length; i++) { String alg = EPDigestManager.DIGEST_ALGORITHMS[i]; ti = new TableItem(hashTable,SWT.NONE); ti.setText(0, alg); //ti.setText(1, hash(alg)); } final Menu menu = new Menu(hashTable); hashTable.setMenu(menu); menu.addMenuListener(new MenuAdapter() { public void menuShown(MenuEvent e) { //empty menu items MenuItem[] items = menu.getItems(); for (int i = 0; i < items.length; i++) { items[i].dispose(); } //Create menu items int index = hashTable.getSelectionIndex(); if (index == -1) return; MenuItem copyHashItem = new MenuItem(menu, SWT.PUSH); copyHashItem.setText("Copy"); copyHashItem.setImage(GUIIcons.EDIT_COPY_ICON_IMAGE); copyHashItem.setAccelerator(SWT.CTRL + 'c'); copyHashItem.addListener( SWT.Selection ,new Listener() { public void handleEvent(Event event) { log.debug("Copy pressed in FileHashPropertyPage"); if (hashTable.getSelection()!=null) { Clipboard clipboard = new Clipboard(PlatformUI.getWorkbench().getDisplay()); String plainText = hashTable.getSelection()[0].getText(1); String rtfText = "{\\rtf1\\b "+plainText+"}"; clipboard.setContents(new String[]{plainText, rtfText}, new Transfer[]{TextTransfer.getInstance(), RTFTransfer.getInstance()}); clipboard.dispose(); } } }); MenuItem computeHashItem = new MenuItem(menu, SWT.PUSH); computeHashItem.setText("Compute this hash"); computeHashItem.setImage(GUIIcons.RUN_ICON_IMAGE); computeHashItem.setAccelerator(SWT.CTRL + 'e'); computeHashItem.addListener( SWT.Selection ,new Listener() { public void handleEvent(Event event) { log.debug("Compute "+hashTable.getItems()[hashTable.getSelectionIndex()].getText(0)+" digest of "+((SecuredDocumentsView.TreeObject) getElement()).getFilePath()); processDigests(true); } }); } }); } /** * @see PreferencePage#createContents(Composite) */ protected Control createContents(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(1,false); composite.setLayout(layout); //composite.setSize(800, 400); GridData data = new GridData(GridData.FILL); data.grabExcessHorizontalSpace = true; composite.setLayoutData(data); addFirstSection(composite); addSeparator(composite); addSecondSection(composite); //processDigests(); return composite; } private Composite createDefaultComposite(Composite parent) { Composite composite = new Composite(parent, SWT.NULL); GridLayout layout = new GridLayout(); layout.numColumns = 2; composite.setLayout(layout); GridData data = new GridData(); data.verticalAlignment = GridData.FILL; data.horizontalAlignment = GridData.FILL; composite.setLayoutData(data); return composite; } protected void performDefaults() { // Populate the owner text field with the default value //ownerText.setText(DEFAULT_OWNER); } public boolean performOk() { return true; } private void processDigests(boolean selected) { FileDigestJob job = new FileDigestJob(selected); job.setUser(true); job.schedule(); } class FileDigestJob extends Job { private String filePath; private String[] algs; private String[] values; private boolean selected; private int selectedIndex; protected FileDigestJob(boolean mselected) { super("Digests for " + ((SecuredDocumentsView.TreeObject) getElement()).getFilePath() ); // File Path filePath = ((SecuredDocumentsView.TreeObject) getElement()).getFilePath(); selected = mselected; // Get algs names from table TableItem[] items = hashTable.getItems(); algs = new String[items.length]; values = new String[items.length]; for (int i = 0; i < items.length; i++) { algs[i] = items[i].getText(0); values[i] = items[i].getText(1); } selectedIndex = hashTable.getSelectionIndex(); //End Job Listener this.addJobChangeListener(new JobChangeAdapter() { public void done(IJobChangeEvent event) { if (event.getResult().isOK()) { log.info("File digests job completed successfully"); //refreshTable(); } else log.warn("Calculating file digest failed"); } }); } @SuppressWarnings("unchecked") @Override public IStatus run(IProgressMonitor monitor) { //Check Free Memory : if more than file size, then load all file in memory //otherwise, use buffers if (FileUtil.isFileTooLargeForJVMFreeRAM(filePath)) { return loadFileAndProcessDigests( monitor, new File( filePath ) ); } else { log.info("Not enough free memory to load file in memory ( you can increase Xmx value in eParapher.ini )"); return processDigestsWithBuffering(monitor, new File( filePath )); } } private IStatus processDigestsWithBuffering(IProgressMonitor monitor, File file) { if (!selected) monitor.beginTask("Processing digests for " + file.getName(), algs.length); else monitor.beginTask("Processing "+algs[selectedIndex]+" digest for " + file.getName(), 1); long start = System.currentTimeMillis(); for (int i = 0; i < algs.length; i++) { if (!selected || (selected && selectedIndex==i)) { monitor.subTask("Processing " + algs[i] ); values[i] = EPDigestManager.getInstance().hashFileInHex(algs[i],filePath); refreshTable(); monitor.worked(1); } } monitor.done(); long stop = System.currentTimeMillis(); if (!selected) log.debug( (stop-start)+"ms for processing all digests on " + file.getName() + " ("+file.length()+"o)"); else log.debug( (stop-start)+"ms for processing "+algs[selectedIndex]+" digest on " + file.getName() + " ("+file.length()+"o)"); return Status.OK_STATUS; } private IStatus loadFileAndProcessDigests(IProgressMonitor monitor, File file) { if (!selected) monitor.beginTask("Processing digests for " + file.getName(), algs.length+1); else monitor.beginTask("Processing digest for " + file.getName(), 2); long start = System.currentTimeMillis(); monitor.subTask("Loading file to memory"); byte[] fcontent = null; try { fcontent = FileUtil.readFile(file.getAbsolutePath()); monitor.worked(1); } catch (IOException e) { log.error("Error while loading file : " + filePath, e); return Status.CANCEL_STATUS; } for (int i = 0; i < algs.length; i++) { if (!selected || (selected && selectedIndex==i)) { monitor.subTask("Processing " + algs[i] ); values[i] = EPDigestManager.getInstance().hashInHex(algs[i],fcontent); refreshTable(); monitor.worked(1); } } monitor.done(); long stop = System.currentTimeMillis(); if (!selected) log.debug( (stop-start)+"ms for processing all digests on " + file.getName() + " ("+file.length()+"o)"); else log.debug( (stop-start)+"ms for processing "+algs[selectedIndex]+" digest on " + file.getName() + " ("+file.length()+"o)"); return Status.OK_STATUS; } private void refreshTable() { Display.getDefault().asyncExec(new Runnable() { public void run() { for(int i = 0; i < hashTable.getItems().length; i++) hashTable.getItems()[i].setText(1, values[i]); } }); } } }