]> git.argeo.org Git - gpl/argeo-slc.git/blob - org.argeo.slc.client.ui.dist/src/org/argeo/slc/client/ui/dist/editors/BundleDetailPage.java
Adapt to changes in BND.
[gpl/argeo-slc.git] / org.argeo.slc.client.ui.dist / src / org / argeo / slc / client / ui / dist / editors / BundleDetailPage.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.argeo.slc.client.ui.dist.editors;
17
18 import java.net.URL;
19
20 import javax.jcr.Node;
21 import javax.jcr.RepositoryException;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.argeo.slc.SlcException;
26 import org.argeo.slc.SlcNames;
27 import org.argeo.slc.build.License;
28 import org.argeo.slc.client.ui.dist.DistConstants;
29 import org.argeo.slc.client.ui.dist.utils.HyperlinkAdapter;
30 import org.argeo.slc.repo.RepoConstants;
31 import org.argeo.slc.repo.RepoUtils;
32 import org.eclipse.jface.dialogs.IMessageProvider;
33 import org.eclipse.swt.SWT;
34 import org.eclipse.swt.layout.GridData;
35 import org.eclipse.swt.layout.GridLayout;
36 import org.eclipse.swt.layout.RowLayout;
37 import org.eclipse.swt.widgets.Composite;
38 import org.eclipse.swt.widgets.Label;
39 import org.eclipse.swt.widgets.Text;
40 import org.eclipse.ui.PlatformUI;
41 import org.eclipse.ui.browser.IWebBrowser;
42 import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
43 import org.eclipse.ui.forms.IManagedForm;
44 import org.eclipse.ui.forms.editor.FormEditor;
45 import org.eclipse.ui.forms.editor.FormPage;
46 import org.eclipse.ui.forms.events.HyperlinkEvent;
47 import org.eclipse.ui.forms.widgets.FormToolkit;
48 import org.eclipse.ui.forms.widgets.Hyperlink;
49 import org.eclipse.ui.forms.widgets.ScrolledForm;
50 import org.eclipse.ui.forms.widgets.Section;
51
52 /** Show details for a given bundle. */
53 public class BundleDetailPage extends FormPage implements SlcNames {
54 private final static Log log = LogFactory.getLog(BundleDetailPage.class);
55
56 final static String PAGE_ID = "BundleDetailPage";
57
58 // Business Objects
59 private Node bundle;
60
61 // This page widgets
62 private FormToolkit tk;
63
64 public BundleDetailPage(FormEditor formEditor, String title, Node bundle) {
65 super(formEditor, PAGE_ID, title);
66 this.bundle = bundle;
67 }
68
69 @Override
70 protected void createFormContent(IManagedForm managedForm) {
71 // General settings for this page
72 ScrolledForm form = managedForm.getForm();
73 tk = managedForm.getToolkit();
74 Composite body = form.getBody();
75
76 GridLayout layout = new GridLayout(1, false);
77 layout.marginWidth = 5;
78 layout.marginRight = 15;
79 layout.verticalSpacing = 0;
80 body.setLayout(layout);
81 try {
82 form.setText(bundle.hasProperty(SlcNames.SLC_SYMBOLIC_NAME) ? bundle
83 .getProperty(SlcNames.SLC_SYMBOLIC_NAME).getString() : "");
84 form.setMessage(bundle
85 .hasProperty(DistConstants.SLC_BUNDLE_DESCRIPTION) ? bundle
86 .getProperty(DistConstants.SLC_BUNDLE_DESCRIPTION)
87 .getString() : "", IMessageProvider.NONE);
88 } catch (RepositoryException re) {
89 throw new SlcException("Unable to get bundle name for node "
90 + bundle, re);
91 }
92
93 // Main layout
94 Composite header = tk.createComposite(body);
95 header.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
96 populateHeaderPart(header);
97
98 Composite mavenSnipet = tk.createComposite(body);
99 mavenSnipet.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
100 populateMavenSnippetPart(mavenSnipet);
101 }
102
103 private void populateHeaderPart(Composite parent) {
104 GridLayout layout = new GridLayout(6, false);
105 // layout.marginWidth = layout.horizontalSpacing = layout.marginHeight =
106 // 0;
107 layout.horizontalSpacing = 10;
108 parent.setLayout(layout);
109 try {
110 // 1st Line: Category, name version
111 createLT(parent, "Category",
112 bundle.hasProperty(SlcNames.SLC_GROUP_ID) ? bundle
113 .getProperty(SlcNames.SLC_GROUP_ID).getString()
114 : "");
115 createLT(parent, "Name",
116 bundle.hasProperty(SlcNames.SLC_ARTIFACT_ID) ? bundle
117 .getProperty(SlcNames.SLC_ARTIFACT_ID).getString()
118 : "");
119 createLT(parent, "Version",
120 bundle.hasProperty(SlcNames.SLC_ARTIFACT_VERSION) ? bundle
121 .getProperty(SlcNames.SLC_ARTIFACT_VERSION)
122 .getString() : "");
123
124 // 3rd Line: Vendor, licence, sources
125 createLT(
126 parent,
127 "Vendor",
128 bundle.hasProperty(DistConstants.SLC_BUNDLE_VENDOR) ? bundle
129 .getProperty(DistConstants.SLC_BUNDLE_VENDOR)
130 .getString() : "N/A");
131
132 createLicencesLink(parent, "Licence",
133 DistConstants.SLC_BUNDLE_LICENCE);
134 addSourceLink(parent);
135
136 // 2nd Line: The Jar itself and the Manifest
137 createJarLink(parent);
138 createManifestLink(parent);
139
140 // Last line
141 createPomLink(parent);
142
143 } catch (RepositoryException re) {
144 throw new SlcException("Unable to get bundle name for node "
145 + bundle, re);
146 }
147
148 }
149
150 private void populateMavenSnippetPart(Composite parent) {
151 GridLayout layout = new GridLayout(1, false);
152 layout.marginWidth = layout.horizontalSpacing = layout.horizontalSpacing = layout.marginHeight = 0;
153 parent.setLayout(layout);
154
155 Section section = tk.createSection(parent, Section.TITLE_BAR
156 | Section.DESCRIPTION);
157 section.setText("Maven");
158 section.setDescription("Add the below tag to your Artifact pom dependencies");
159 section.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
160 Text snippetTxt = createMavenSnippet(section);
161 section.setClient(snippetTxt);
162 }
163
164 // /////////////////////
165 // HELPERS
166
167 private Text createLT(Composite parent, String labelValue, String textValue) {
168 Label label = tk.createLabel(parent, labelValue, SWT.RIGHT);
169 // label.setFont(EclipseUiUtils.getBoldFont(parent));
170 label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
171 // Add a trailing space to workaround a display glitch in RAP 1.3
172 Text text = new Text(parent, SWT.LEFT);
173 text.setText(textValue + " ");
174 text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
175 text.setEditable(false);
176 return text;
177 }
178
179 private void createLicencesLink(Composite parent, String label,
180 String jcrPropName) throws RepositoryException {
181 tk.createLabel(parent, label, SWT.NONE);
182 if (bundle.hasProperty(jcrPropName)) {
183
184 String licenceLinkVal = bundle.getProperty(jcrPropName).getString();
185
186 // FIXME Hack until license generation is done cleanly
187 // Problem is with description that contains a "," like
188 // "Apache License, Version 2"
189 String[] licenceVals;
190 if (licenceLinkVal.contains("description="))
191 licenceVals = new String[] { licenceLinkVal };
192 else
193 // multiple license, form non-regenerated manifests
194 licenceVals = licenceLinkVal.split(", ");
195
196 Composite body = tk.createComposite(parent);
197 body.setLayout(new RowLayout(SWT.WRAP));
198
199 for (final String value : licenceVals) {
200 final License currLicense = parseLicenseString(value);
201
202 Hyperlink link = tk.createHyperlink(body,
203 currLicense.getName(), SWT.NONE);
204 link.addHyperlinkListener(new HyperlinkAdapter() {
205 @Override
206 public void linkActivated(HyperlinkEvent e) {
207 try {
208 IWorkbenchBrowserSupport browserSupport = PlatformUI
209 .getWorkbench().getBrowserSupport();
210 IWebBrowser browser = browserSupport
211 .createBrowser(
212 IWorkbenchBrowserSupport.LOCATION_BAR
213 | IWorkbenchBrowserSupport.NAVIGATION_BAR,
214 "SLC Distribution browser",
215 "SLC Distribution browser",
216 "A tool tip");
217 browser.openURL(new URL(currLicense.getUri()));
218 } catch (Exception ex) {
219 throw new SlcException("error opening browser", ex); //$NON-NLS-1$
220 }
221 }
222 });
223 }
224 } else
225 tk.createLabel(parent, "N/A", SWT.NONE);
226 }
227
228 // TODO this must be moved to a better place once the standard has been
229 // defined
230 // Enable licence encoding in a single JCR Value
231 private final static String LICENSE_SEPARATOR = ";";
232 // The human readable name of the licence
233 private final static String LICENSE_NAME = "description";
234 // A link on the internet with some more info on this licence
235 private final static String LICENSE_LINK = "link";
236
237 private License parseLicenseString(String licenseStr) {
238 String uri = null, name = null, link = null, text = null;
239 // TODO enhance this
240 String[] values = licenseStr.split(LICENSE_SEPARATOR);
241 for (String value : values) {
242 if (value.startsWith(LICENSE_NAME))
243 name = value.substring(LICENSE_NAME.length() + 1); // +1 for the
244 // '='
245 else if (value.startsWith(LICENSE_LINK))
246 link = value.substring(LICENSE_LINK.length() + 1);
247 else if (uri == null)
248 uri = value;
249 // TODO manage text
250 }
251 return new SimpleLicense(name, uri, link, text);
252 }
253
254 class SimpleLicense implements License {
255 private final String name;
256 private final String uri;
257 private final String link;
258 private final String text;
259
260 public SimpleLicense(String name, String uri, String link, String text) {
261 if (uri == null)
262 throw new SlcException(
263 "Cannot manage a licence with a null URI ");
264 this.uri = uri;
265
266 this.name = name;
267 this.link = link;
268 this.text = text;
269 }
270
271 public String getUri() {
272 return uri;
273 }
274
275 public String getText() {
276 return text;
277 }
278
279 public String getName() {
280 return name != null ? name : uri;
281 }
282
283 public String getLink() {
284 return link;
285 }
286 }
287
288 private void createJarLink(Composite parent) throws RepositoryException {
289 Label label = tk.createLabel(parent, "Jar", SWT.RIGHT);
290 label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
291
292 Composite body = tk.createComposite(parent);
293 RowLayout rl = new RowLayout(SWT.HORIZONTAL);
294 rl.spacing = 6;
295 body.setLayout(rl);
296 body.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
297
298 Hyperlink jarLink = tk
299 .createHyperlink(body, bundle.getName(), SWT.NONE);
300 jarLink.addHyperlinkListener(new OpenFileLinkListener(bundle.getPath()));
301
302 // Corresponding check sums
303
304 String name = bundle.getName() + ".md5";
305 if (bundle.getParent().hasNode(name)) {
306 Node md5 = bundle.getParent().getNode(name);
307 Hyperlink md5Link = tk.createHyperlink(body, "MD5", SWT.NONE);
308 md5Link.addHyperlinkListener(new OpenFileLinkListener(md5.getPath()));
309 }
310
311 name = bundle.getName() + ".sha1";
312 if (bundle.getParent().hasNode(name)) {
313 Node sha1 = bundle.getParent().getNode(name);
314 Hyperlink sha1Link = tk.createHyperlink(body, "SHA1", SWT.NONE);
315 sha1Link.addHyperlinkListener(new OpenFileLinkListener(sha1
316 .getPath()));
317 }
318 }
319
320 private void createPomLink(Composite parent) throws RepositoryException {
321 Label label = tk.createLabel(parent, "Pom", SWT.RIGHT);
322 label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
323
324 String name = bundle.getName().substring(0,
325 bundle.getName().length() - "jar".length())
326 + "pom";
327
328 if (bundle.getParent().hasNode(name)) {
329 Node pom = bundle.getParent().getNode(name);
330
331 Composite body = tk.createComposite(parent);
332 RowLayout rl = new RowLayout(SWT.HORIZONTAL);
333 rl.spacing = 6;
334 body.setLayout(rl);
335 body.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
336 3, 1));
337
338 Hyperlink pomLink = tk.createHyperlink(body, "pom.xml", SWT.NONE);
339 pomLink.addHyperlinkListener(new OpenFileLinkListener(pom.getPath()));
340
341 // Corresponding check sums
342 name = pom.getName() + ".md5";
343 if (pom.getParent().hasNode(name)) {
344 Node md5 = pom.getParent().getNode(name);
345 Hyperlink md5Link = tk.createHyperlink(body, "MD5", SWT.NONE);
346 md5Link.addHyperlinkListener(new OpenFileLinkListener(md5
347 .getPath()));
348 }
349
350 name = pom.getName() + ".sha1";
351 if (pom.getParent().hasNode(name)) {
352 Node sha1 = pom.getParent().getNode(name);
353 Hyperlink sha1Link = tk.createHyperlink(body, "SHA1", SWT.NONE);
354 sha1Link.addHyperlinkListener(new OpenFileLinkListener(sha1
355 .getPath()));
356 }
357 } else
358 tk.createLabel(parent, "N/A", SWT.NONE);
359 }
360
361 private void createManifestLink(Composite parent)
362 throws RepositoryException {
363 tk.createLabel(parent, "Manifest", SWT.NONE);
364 // Hyperlink link =
365 // TODO fix this when file download has been implemented for the
366 // manifest
367 tk.createHyperlink(parent, "MANIFEST.MF", SWT.NONE);
368 // link.addHyperlinkListener(new
369 // OpenFileLinkListener(bundle.getPath()));
370 }
371
372 // private void createHyperlink(Composite parent, String label,
373 // String jcrPropName) throws RepositoryException {
374 // tk.createLabel(parent, label, SWT.NONE);
375 // if (bundle.hasProperty(jcrPropName)) {
376 // final Hyperlink link = tk.createHyperlink(parent, bundle
377 // .getProperty(jcrPropName).getString(), SWT.NONE);
378 // link.addHyperlinkListener(new AbstractHyperlinkListener() {
379 // @Override
380 // public void linkActivated(HyperlinkEvent e) {
381 // try {
382 // IWorkbenchBrowserSupport browserSupport = PlatformUI
383 // .getWorkbench().getBrowserSupport();
384 // IWebBrowser browser = browserSupport
385 // .createBrowser(
386 // IWorkbenchBrowserSupport.LOCATION_BAR
387 // | IWorkbenchBrowserSupport.NAVIGATION_BAR,
388 // "SLC Distribution browser",
389 // "SLC Distribution browser",
390 // "A tool tip");
391 // browser.openURL(new URL(link.getText()));
392 // } catch (Exception ex) {
393 // throw new SlcException("error opening browser", ex); //$NON-NLS-1$
394 // }
395 // }
396 // });
397 // } else
398 // tk.createLabel(parent, "N/A", SWT.NONE);
399 // }
400
401 // helper to check if sources are available
402 private void addSourceLink(Composite parent) {
403 try {
404 String srcPath = RepoUtils.relatedPdeSourcePath(
405 RepoConstants.DEFAULT_ARTIFACTS_BASE_PATH, bundle);
406 if (!bundle.getSession().nodeExists(srcPath)) {
407 createLT(parent, "Sources", "N/A");
408 } else {
409 final Node sourcesNode = bundle.getSession().getNode(srcPath);
410
411 String srcName = null;
412 if (sourcesNode.hasProperty(SlcNames.SLC_SYMBOLIC_NAME))
413 srcName = sourcesNode.getProperty(
414 SlcNames.SLC_SYMBOLIC_NAME).getString();
415 else
416 srcName = sourcesNode.getName();
417 Label label = tk.createLabel(parent, "Sources", SWT.RIGHT);
418 label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false,
419 false));
420 final Hyperlink link = tk.createHyperlink(parent, srcName,
421 SWT.NONE);
422 link.addHyperlinkListener(new OpenFileLinkListener(sourcesNode
423 .getPath()));
424
425 // {
426 // @Override
427 // public void linkActivated(HyperlinkEvent e) {
428 // try {
429 // ModuleEditorInput editorInput = (ModuleEditorInput)
430 // getEditorInput();
431 // Map<String, String> params = new HashMap<String, String>();
432 // params.put(OpenJcrFile.PARAM_REPO_NODE_PATH,
433 // editorInput.getRepoNodePath());
434 // params.put(OpenJcrFile.PARAM_REPO_URI,
435 // editorInput.getUri());
436 // params.put(OpenJcrFile.PARAM_WORKSPACE_NAME,
437 // editorInput.getWorkspaceName());
438 // params.put(OpenJcrFile.PARAM_FILE_PATH,
439 // );
440 // CommandUtils.callCommand(OpenJcrFile.ID, params);
441 // } catch (Exception ex) {
442 // throw new SlcException("error opening browser", ex); //$NON-NLS-1$
443 // }
444 // }
445 // });
446
447 }
448 } catch (RepositoryException e) {
449 throw new SlcException("Unable to configure sources link for "
450 + bundle, e);
451 }
452 }
453
454 private class OpenFileLinkListener extends HyperlinkAdapter {
455 final private String path;
456
457 public OpenFileLinkListener(String path) {
458 this.path = path;
459 }
460
461 @Override
462 public void linkActivated(HyperlinkEvent e) {
463 log.warn("File download must be implemented. Cannot provide access to "
464 + path);
465
466 // try {
467 // ModuleEditorInput editorInput = (ModuleEditorInput)
468 // getEditorInput();
469 // Map<String, String> params = new HashMap<String, String>();
470 // params.put(OpenJcrFile.PARAM_REPO_NODE_PATH,
471 // editorInput.getRepoNodePath());
472 // params.put(OpenJcrFile.PARAM_REPO_URI, editorInput.getUri());
473 // params.put(OpenJcrFile.PARAM_WORKSPACE_NAME,
474 // editorInput.getWorkspaceName());
475 // params.put(OpenJcrFile.PARAM_FILE_PATH, path);
476 //
477 // String cmdId = (new OpenJcrFileCmdId()).getCmdId();
478 // if (log.isTraceEnabled())
479 // log.debug("Retrieved openFile Cmd ID: " + cmdId);
480 // CommandUtils.callCommand(cmdId, params);
481 // } catch (Exception ex) {
482 // throw new SlcException("error opening browser", ex); //$NON-NLS-1$
483 // }
484 }
485 }
486
487 /** Creates a text area with corresponding maven snippet */
488 private Text createMavenSnippet(Composite parent) {
489 Text mavenSnippet = new Text(parent, SWT.MULTI | SWT.WRAP);
490 GridData gd = new GridData(GridData.FILL_HORIZONTAL);
491 gd.grabExcessHorizontalSpace = true;
492 gd.heightHint = 100;
493 mavenSnippet.setLayoutData(gd);
494 mavenSnippet.setText(generateXmlSnippet());
495 return mavenSnippet;
496 }
497
498 private String generateXmlSnippet() {
499 try {
500 StringBuffer sb = new StringBuffer();
501 sb.append("<dependency>\n");
502 sb.append("\t<groupId>");
503 sb.append(bundle.getProperty(SLC_GROUP_ID).getString());
504 sb.append("</groupId>\n");
505 sb.append("\t<artifactId>");
506 sb.append(bundle.getProperty(SLC_ARTIFACT_ID).getString());
507 sb.append("</artifactId>\n");
508 sb.append("\t<version>");
509 sb.append(bundle.getProperty(SLC_ARTIFACT_VERSION).getString());
510 sb.append("</version>\n");
511 sb.append("</dependency>");
512 return sb.toString();
513 } catch (RepositoryException re) {
514 throw new SlcException(
515 "unexpected error while generating maven snippet");
516 }
517 }
518 }