View Javadoc

1   package org.eparapher.rcp.actions;
2   
3   import java.io.File;
4   import java.util.ArrayList;
5   import java.util.Iterator;
6   
7   import org.apache.log4j.Logger;
8   import org.eclipse.core.runtime.IProgressMonitor;
9   import org.eclipse.core.runtime.IStatus;
10  import org.eclipse.core.runtime.Status;
11  import org.eclipse.core.runtime.jobs.IJobChangeEvent;
12  import org.eclipse.core.runtime.jobs.Job;
13  import org.eclipse.core.runtime.jobs.JobChangeAdapter;
14  import org.eclipse.jface.action.Action;
15  import org.eclipse.jface.viewers.ISelection;
16  import org.eclipse.jface.viewers.IStructuredSelection;
17  import org.eclipse.jface.viewers.TreeViewer;
18  import org.eclipse.jface.window.Window;
19  import org.eclipse.jface.wizard.WizardDialog;
20  import org.eclipse.swt.SWT;
21  import org.eclipse.swt.widgets.Display;
22  import org.eclipse.ui.IWorkbenchWindow;
23  import org.eclipse.ui.PlatformUI;
24  import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
25  import org.eparapher.core.crypto.EPKeystoreManager;
26  import org.eparapher.core.crypto.keystore.IUserKeystore;
27  import org.eparapher.core.signature.XMLSignatureParameters;
28  import org.eparapher.core.signature.XMLSigner;
29  import org.eparapher.rcp.tools.GUIIcons;
30  import org.eparapher.rcp.tools.eParapherTools;
31  import org.eparapher.rcp.views.documents.SecuredDocumentsView.TreeObject;
32  import org.eparapher.rcp.views.documents.SecuredDocumentsView.TreeParent;
33  import org.eparapher.rcp.wizards.XMLSigningWizard;
34  
35  public class XMLSignDocumentAction extends Action implements IWorkbenchAction {
36  
37  	private static Logger log = Logger.getLogger(ToPDFAndSignDocumentAction.class);
38  	
39  	private TreeViewer viewer;
40  	
41  	private boolean usewizard;
42  	private IWorkbenchWindow window;
43  
44  	public XMLSignDocumentAction() {
45  		this(null,true);
46  	}
47  
48  	public XMLSignDocumentAction(TreeViewer mviewer, boolean museWizard) {
49  		viewer = mviewer;
50  		usewizard = museWizard;
51  		window = null;
52  		this.setId("XMLSignDocumentAction");
53  		this.setImageDescriptor(GUIIcons.XML_ICON);
54  		if (!usewizard) {
55  			this.setText("XML DSig Signature");
56  			this.setToolTipText("Digitally sign XML file(s) with default parameters");
57  			this.setAccelerator(SWT.CTRL | 'J');
58  		} else {
59  			this.setText("XML DSig Signature (wizard)");
60  			this.setToolTipText("Digitally sign XML file(s) using a wizard");
61  			this.setAccelerator(SWT.CTRL | 'K');
62  		}
63  	}
64  
65  	public XMLSignDocumentAction(IWorkbenchWindow mwindow) {
66  		this();
67  		window=mwindow;
68  	}
69  
70  	public void run() {
71  		XMLSignJob job = new XMLSignJob();
72  		job.setUser(true);
73  		job.schedule();
74  	}
75  
76  	private XMLSignatureParameters getSignatureParameters() {
77  		
78  		XMLSignatureParameters xmlsignparams = new XMLSignatureParameters();
79  		xmlsignparams.setXMLSignatureParamsFromPreferences();
80  		if (viewer != null)
81  			xmlsignparams.setFileSelectiontoSign(getFileSelectionFromView());
82  
83  		if (usewizard) {
84  			//Launch Wizard to get PDF Signature Parameters
85  			XMLSigningWizard xmlWizard = new XMLSigningWizard(xmlsignparams);
86  			if (window==null)
87  				window=PlatformUI.getWorkbench().getActiveWorkbenchWindow();
88  			WizardDialog dialog = new WizardDialog(window.getShell(), xmlWizard );
89  			if ( dialog.open() != Window.OK ) {
90  				log.info("XML DSig signature options wizard cancelled");
91  				return null;
92  			}
93  			//recover params from wizard
94  			xmlsignparams = xmlWizard.getXMLSignatureParams();
95  		}
96  		return xmlsignparams;
97  	}
98  
99  	private File[] getFileSelectionFromView() {
100 
101 		ArrayList<File> fileList = new ArrayList<File>();
102 		
103 		if (viewer.getSelection()!=null && !viewer.getSelection().isEmpty()) {
104 			// Iterate over selected file in view
105 			ISelection selection = viewer.getSelection();
106 			IStructuredSelection structselection = (IStructuredSelection) selection;
107 			
108 			//Build File Array from Table Selection
109 			for (Iterator<Object> iterator = structselection.iterator(); iterator.hasNext();) {
110 				Object obj =  iterator.next();
111 				if (obj instanceof TreeParent)
112 					//TODO : sign all files in a directory (if confirm?)
113 					eParapherTools.debugMessage("Cannot sign a directory!");
114 				else {
115 					TreeObject to = (TreeObject) obj;
116 					File f = new File(to.getFilePath());
117 					if (!f.exists())
118 						log.error("file " + to.getFilePath() + " has been deleted");
119 					else
120 						fileList.add(f);
121 				}
122 			}
123 		}
124 		return fileList.toArray(new File[] {});
125 	}
126 
127 	public void dispose() {
128 	}
129 
130 	class XMLSignJob extends Job {
131 		
132 		private XMLSignatureParameters xmlsignatureparams;
133 		private XMLSigner xmlsigner;
134 
135 		private String originalAlias;
136 		protected boolean isSigningPrivateKeyLoaded;
137 
138 		protected XMLSignJob() {
139 			
140 			super("XML DSig Signer Job");
141 			
142 			// Use Wizard if needed for signature parameters
143 			xmlsignatureparams = getSignatureParameters();
144 			
145 			//Verify if algorithm is supported (Elliptic curve not supported yet)
146 			IUserKeystore uk = EPKeystoreManager.getInstance().getUserkeystore();
147 				
148 			if (xmlsignatureparams!=null) {
149 				
150 				// Set the alias keystore to use
151 				originalAlias = uk.getDefaultAlias();
152 				if (xmlsignatureparams.getSignatureAlias()!=null
153 					&& uk.containsAlias(xmlsignatureparams.getSignatureAlias()) )
154 					uk.setDefaultAlias(xmlsignatureparams.getSignatureAlias());
155 				
156 				//Ask PIN or Passphrase with CMSSigner Constructor
157 				isSigningPrivateKeyLoaded = EPKeystoreManager.getInstance().getUserkeystore().loadPrivateKey();
158 				
159 				if (isSigningPrivateKeyLoaded) {
160 					xmlsigner = new XMLSigner();
161 					
162 					//End Job Listener
163 					this.addJobChangeListener(new JobChangeAdapter() {
164 						public void done(IJobChangeEvent event) {
165 							if (event.getResult().isOK())
166 								log.info("XML DSig signing job completed successfully");
167 							else
168 								log.warn("XML DSig signing job did not complete successfully");
169 						}
170 					});
171 				}
172 			}
173 		}
174 
175 		@SuppressWarnings("unchecked")
176 		@Override
177 		protected IStatus run(IProgressMonitor monitor) {
178 			if (xmlsignatureparams!=null && isSigningPrivateKeyLoaded) {
179 
180 				monitor.beginTask("XML DSig Signer", xmlsignatureparams.getFileSelectiontoSign().length );
181 				
182 				File[] f2s = xmlsignatureparams.getFileSelectiontoSign();
183 				
184 				for (int i = 0; i < f2s.length; i++) {
185 					if (isXMLFile(f2s[i].getName().toLowerCase())) {
186 						monitor.subTask("Signing "+f2s[i].getName());
187 						xmlsigner.sign( f2s[i].getAbsolutePath(), xmlsignatureparams);
188 						monitor.worked(1);
189 					} else {
190 						log.warn("Cannot apply XML signature on : " + f2s[i].getAbsolutePath() );
191 					}
192 
193 					//refresh the view
194 					Display.getDefault().asyncExec(new Runnable() {
195 						public void run() {	viewer.refresh(); }
196 					});
197 				}
198 				monitor.done();
199 			}
200 			if (originalAlias!=null)
201 				EPKeystoreManager.getInstance().getUserkeystore().setDefaultAlias(originalAlias);
202 			return Status.OK_STATUS;
203 		}
204 
205 		private boolean isXMLFile(String lowerCaseFileName) {
206 			for (int i = 0; i < xmlsignatureparams.XMLExtentions.length; i++) {
207 				if (lowerCaseFileName.endsWith(xmlsignatureparams.XMLExtentions[i]))
208 					return true;
209 				break;
210 			}
211 			//TODO : XML Detection : read file Header to detect "<?xml ..."
212 			return false;
213 		}
214 
215 		private void refreshView() {
216 			Display.getDefault().asyncExec(
217 				new Runnable() {
218 					public void run() {	viewer.refresh(); }
219 				}
220 			);
221 		}
222 	}
223 
224 }