001: /*******************************************************************************
002: * Copyright (c) 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: ******************************************************************************/package org.eclipse.ui.internal.dialogs;
011:
012: import java.io.IOException;
013: import java.text.DateFormat;
014: import java.util.ArrayList;
015: import java.util.Date;
016: import java.util.Iterator;
017: import java.util.List;
018: import java.util.Map;
019: import java.util.Properties;
020: import java.util.StringTokenizer;
021: import java.util.Map.Entry;
022:
023: import org.eclipse.core.runtime.IProgressMonitor;
024: import org.eclipse.core.runtime.IStatus;
025: import org.eclipse.core.runtime.OperationCanceledException;
026: import org.eclipse.core.runtime.Status;
027: import org.eclipse.core.runtime.jobs.Job;
028: import org.eclipse.jface.dialogs.Dialog;
029: import org.eclipse.jface.dialogs.DialogTray;
030: import org.eclipse.jface.dialogs.TrayDialog;
031: import org.eclipse.jface.resource.JFaceResources;
032: import org.eclipse.osgi.internal.provisional.verifier.CertificateChain;
033: import org.eclipse.osgi.internal.provisional.verifier.CertificateVerifier;
034: import org.eclipse.osgi.internal.provisional.verifier.CertificateVerifierFactory;
035: import org.eclipse.osgi.util.NLS;
036: import org.eclipse.swt.SWT;
037: import org.eclipse.swt.custom.StyledText;
038: import org.eclipse.swt.graphics.Color;
039: import org.eclipse.swt.graphics.GC;
040: import org.eclipse.swt.graphics.Point;
041: import org.eclipse.swt.layout.GridData;
042: import org.eclipse.swt.layout.GridLayout;
043: import org.eclipse.swt.widgets.Composite;
044: import org.eclipse.swt.widgets.Control;
045: import org.eclipse.swt.widgets.Display;
046: import org.eclipse.swt.widgets.Label;
047: import org.eclipse.swt.widgets.Shell;
048: import org.eclipse.swt.widgets.Text;
049: import org.eclipse.ui.internal.WorkbenchMessages;
050: import org.eclipse.ui.internal.WorkbenchPlugin;
051: import org.eclipse.ui.internal.about.AboutBundleData;
052: import org.eclipse.ui.statushandlers.StatusManager;
053: import org.osgi.framework.BundleContext;
054: import org.osgi.framework.ServiceReference;
055:
056: /**
057: * @since 3.3
058: *
059: */
060: public class BundleSigningTray extends DialogTray {
061:
062: private Text date;
063: private StyledText certificate;
064: private AboutBundleData data;
065: private TrayDialog dialog;
066:
067: /**
068: *
069: */
070: public BundleSigningTray(TrayDialog dialog) {
071: this .dialog = dialog;
072: }
073:
074: public void setData(AboutBundleData data) {
075: this .data = data;
076: startJobs();
077: }
078:
079: /* (non-Javadoc)
080: * @see org.eclipse.jface.dialogs.DialogTray#createContents(org.eclipse.swt.widgets.Composite)
081: */
082: protected Control createContents(Composite parent) {
083: Composite content = new Composite(parent, SWT.NONE);
084: content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
085: true));
086: GridLayout layout = new GridLayout(2, false);
087: content.setLayout(layout);
088: // date
089: Color backgroundColor = parent.getDisplay().getSystemColor(
090: SWT.COLOR_WIDGET_BACKGROUND);
091: {
092: Label label = new Label(content, SWT.NONE);
093: label
094: .setText(WorkbenchMessages.BundleSigningTray_Signing_Date);
095: GridData data = new GridData(SWT.FILL, SWT.BEGINNING, true,
096: false);
097: date = new Text(content, SWT.READ_ONLY);
098: GC gc = new GC(date);
099: gc.setFont(JFaceResources.getDialogFont());
100: Point size = gc.stringExtent(DateFormat
101: .getDateTimeInstance().format(new Date()));
102: data.widthHint = size.x;
103: gc.dispose();
104: date.setText(WorkbenchMessages.BundleSigningTray_Working);
105: date.setLayoutData(data);
106: date.setBackground(backgroundColor);
107: }
108: // signer
109: {
110: Label label = new Label(content, SWT.NONE);
111: label
112: .setText(WorkbenchMessages.BundleSigningTray_Signing_Certificate);
113: GridData data = new GridData(SWT.BEGINNING, SWT.BEGINNING,
114: true, false);
115: data.horizontalSpan = 2;
116: data = new GridData(SWT.FILL, SWT.FILL, true, true);
117: data.horizontalSpan = 2;
118: certificate = new StyledText(content, SWT.READ_ONLY
119: | SWT.MULTI | SWT.WRAP);
120: certificate
121: .setText(WorkbenchMessages.BundleSigningTray_Working);
122: certificate.setLayoutData(data);
123: }
124:
125: // problems
126: // {
127: // Label label = new Label(content, SWT.NONE);
128: // label.setText("Problems:"); //$NON-NLS-1$
129: //
130: // }
131: Dialog.applyDialogFont(content);
132:
133: startJobs(); // start the jobs that will prime the content
134:
135: return content;
136: }
137:
138: /**
139: *
140: */
141: private void startJobs() {
142: if (!isOpen())
143: return;
144: certificate
145: .setText(WorkbenchMessages.BundleSigningTray_Working);
146: date.setText(WorkbenchMessages.BundleSigningTray_Working);
147: final BundleContext bundleContext = WorkbenchPlugin
148: .getDefault().getBundleContext();
149: final ServiceReference certRef = bundleContext
150: .getServiceReference(CertificateVerifierFactory.class
151: .getName());
152: if (certRef == null) {
153: StatusManager
154: .getManager()
155: .handle(
156: new Status(
157: IStatus.WARNING,
158: WorkbenchPlugin.PI_WORKBENCH,
159: WorkbenchMessages.BundleSigningTray_Cant_Find_Service),
160: StatusManager.LOG);
161: return;
162: }
163:
164: final CertificateVerifierFactory certFactory = (CertificateVerifierFactory) bundleContext
165: .getService(certRef);
166: if (certFactory == null) {
167: StatusManager
168: .getManager()
169: .handle(
170: new Status(
171: IStatus.WARNING,
172: WorkbenchPlugin.PI_WORKBENCH,
173: WorkbenchMessages.BundleSigningTray_Cant_Find_Service),
174: StatusManager.LOG);
175: return;
176: }
177:
178: final AboutBundleData myData = data;
179: final Job signerJob = new Job(
180: NLS
181: .bind(
182: WorkbenchMessages.BundleSigningTray_Determine_Signer_For,
183: myData.getId())) {
184:
185: protected IStatus run(IProgressMonitor monitor) {
186: try {
187: if (myData != data)
188: return Status.OK_STATUS;
189: CertificateVerifier verifier = certFactory
190: .getVerifier(myData.getBundle());
191: if (myData != data)
192: return Status.OK_STATUS;
193: CertificateChain[] chains = verifier.getChains();
194: final String signerText, dateText;
195: final Shell dialogShell = dialog.getShell();
196: if (!isOpen()
197: && BundleSigningTray.this .data == myData)
198: return Status.OK_STATUS;
199:
200: if (chains.length == 0) {
201: signerText = WorkbenchMessages.BundleSigningTray_Unsigned;
202: dateText = WorkbenchMessages.BundleSigningTray_Unsigned;
203: } else {
204: Properties[] certs = parseCerts(chains[0]
205: .getChain());
206: if (certs.length == 0)
207: signerText = WorkbenchMessages.BundleSigningTray_Unknown;
208: else {
209: StringBuffer buffer = new StringBuffer();
210: for (Iterator i = certs[0].entrySet()
211: .iterator(); i.hasNext();) {
212: Map.Entry entry = (Entry) i.next();
213: buffer.append(entry.getKey());
214: buffer.append('=');
215: buffer.append(entry.getValue());
216: if (i.hasNext())
217: buffer.append('\n');
218: }
219: signerText = buffer.toString();
220: }
221:
222: Date signDate = chains[0].getSigningTime();
223: if (signDate != null)
224: dateText = DateFormat.getDateTimeInstance()
225: .format(signDate);
226: else
227: dateText = WorkbenchMessages.BundleSigningTray_Unknown;
228: }
229:
230: Display display = dialogShell.getDisplay();
231: display.asyncExec(new Runnable() {
232:
233: public void run() {
234: // check to see if the tray is still visible and if we're still looking at the same item
235: if (!isOpen()
236: && BundleSigningTray.this .data != myData)
237: return;
238: certificate.setText(signerText);
239: date.setText(dateText);
240: }
241: });
242:
243: } catch (IOException e) {
244: return new Status(IStatus.ERROR,
245: WorkbenchPlugin.PI_WORKBENCH, e
246: .getMessage(), e);
247: }
248: return Status.OK_STATUS;
249: }
250: };
251: signerJob.setSystem(true);
252: signerJob.belongsTo(signerJob);
253: signerJob.schedule();
254:
255: Job cleanup = new Job(
256: WorkbenchMessages.BundleSigningTray_Unget_Signing_Service) {
257:
258: protected IStatus run(IProgressMonitor monitor) {
259: try {
260: getJobManager().join(signerJob, monitor);
261: } catch (OperationCanceledException e) {
262: } catch (InterruptedException e) {
263: }
264: bundleContext.ungetService(certRef);
265: return Status.OK_STATUS;
266: }
267: };
268: cleanup.setSystem(true);
269: cleanup.schedule();
270:
271: }
272:
273: /**
274: *
275: */
276: private boolean isOpen() {
277: return certificate != null && !certificate.isDisposed();
278: }
279:
280: private Properties[] parseCerts(String certString) {
281: List certs = new ArrayList();
282: StringTokenizer toker = new StringTokenizer(certString, ";"); //$NON-NLS-1$
283:
284: while (toker.hasMoreTokens()) {
285: Map cert = parseCert(toker.nextToken());
286: if (cert != null)
287: certs.add(cert);
288: }
289: return (Properties[]) certs
290: .toArray(new Properties[certs.size()]);
291:
292: }
293:
294: /**
295: * @param certString
296: * @return
297: */
298: private Properties parseCert(String certString) {
299: StringTokenizer toker = new StringTokenizer(certString, ","); //$NON-NLS-1$
300: Properties cert = new Properties();
301: while (toker.hasMoreTokens()) {
302: String pair = toker.nextToken();
303: int idx = pair.indexOf('=');
304: if (idx > 0 && idx < pair.length() - 2) {
305: String key = pair.substring(0, idx).trim();
306: String value = pair.substring(idx + 1).trim();
307: if (value.length() > 2) {
308: if (value.charAt(0) == '\"')
309: value = value.substring(1);
310:
311: if (value.charAt(value.length() - 1) == '\"')
312: value = value.substring(0, value.length() - 1);
313: }
314: cert.setProperty(key, value);
315: }
316: }
317: return cert;
318: }
319:
320: }
|