This project has retired. For details please refer to its
Attic page.
ClientHelper xref
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.chemistry.opencmis.workbench;
20
21 import groovy.lang.Binding;
22 import groovy.ui.Console;
23 import groovy.util.GroovyScriptEngine;
24
25 import java.awt.Color;
26 import java.awt.Component;
27 import java.awt.Cursor;
28 import java.awt.Desktop;
29 import java.awt.Desktop.Action;
30 import java.awt.Toolkit;
31 import java.awt.Window;
32 import java.awt.datatransfer.Clipboard;
33 import java.awt.datatransfer.StringSelection;
34 import java.awt.datatransfer.Transferable;
35 import java.awt.event.ActionEvent;
36 import java.awt.event.ActionListener;
37 import java.io.BufferedOutputStream;
38 import java.io.BufferedReader;
39 import java.io.File;
40 import java.io.FileInputStream;
41 import java.io.FileOutputStream;
42 import java.io.FileReader;
43 import java.io.IOException;
44 import java.io.InputStream;
45 import java.io.InputStreamReader;
46 import java.io.OutputStream;
47 import java.io.PrintWriter;
48 import java.io.Writer;
49 import java.net.URI;
50 import java.net.URL;
51 import java.text.SimpleDateFormat;
52 import java.util.ArrayList;
53 import java.util.Collection;
54 import java.util.Collections;
55 import java.util.GregorianCalendar;
56 import java.util.List;
57 import java.util.Properties;
58
59 import javax.script.ScriptEngine;
60 import javax.script.ScriptEngineManager;
61 import javax.swing.AbstractAction;
62 import javax.swing.ImageIcon;
63 import javax.swing.InputMap;
64 import javax.swing.JComponent;
65 import javax.swing.JFileChooser;
66 import javax.swing.JMenu;
67 import javax.swing.JMenuItem;
68 import javax.swing.JOptionPane;
69 import javax.swing.JRootPane;
70 import javax.swing.JTable;
71 import javax.swing.KeyStroke;
72 import javax.swing.UIManager;
73 import javax.swing.text.DefaultEditorKit;
74
75 import org.apache.chemistry.opencmis.client.api.CmisObject;
76 import org.apache.chemistry.opencmis.client.api.Document;
77 import org.apache.chemistry.opencmis.client.api.ObjectId;
78 import org.apache.chemistry.opencmis.client.api.Rendition;
79 import org.apache.chemistry.opencmis.commons.data.ContentStream;
80 import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
81 import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
82 import org.apache.chemistry.opencmis.commons.impl.MimeTypes;
83 import org.apache.chemistry.opencmis.workbench.model.ClientModel;
84 import org.apache.commons.logging.Log;
85 import org.apache.commons.logging.LogFactory;
86
87 public class ClientHelper {
88
89 public static final Color LINK_COLOR = new Color(105, 29, 21);
90 public static final Color LINK_SELECTED_COLOR = new Color(255, 255, 255);
91
92 private static final Log log = LogFactory.getLog(ClientHelper.class);
93 private static final int BUFFER_SIZE = 64 * 1024;
94
95 private ClientHelper() {
96 }
97
98 public static void showError(Component parent, Exception ex) {
99 if (log.isErrorEnabled()) {
100 log.error(ex.getClass().getSimpleName() + ": " + ex.getMessage(), ex);
101
102 if (ex instanceof CmisBaseException) {
103 CmisBaseException cex = (CmisBaseException) ex;
104
105 if (cex.getCode() != null) {
106 log.error("Error code: " + cex.getCode());
107 }
108
109 if (cex.getErrorContent() != null) {
110 log.error("Error content: " + cex.getErrorContent());
111 }
112 }
113 }
114
115 String exceptionName = ex.getClass().getSimpleName();
116 if (ex instanceof CmisBaseException) {
117 exceptionName = ((CmisBaseException) ex).getExceptionName();
118 }
119
120 StringBuilder sb = new StringBuilder(ex.getMessage());
121
122 int width = 80;
123 while (sb.length() > width) {
124 int p = width;
125
126 int x = sb.indexOf(" ", p);
127 if (x < 0 || x > p + 10) {
128 x = sb.indexOf("/", p);
129 }
130 if (x < 0 || x > p + 10) {
131 x = sb.indexOf(":", p);
132 }
133 if (x < 0 || x > p + 10) {
134 x = p;
135 }
136
137 sb.insert(x, '\n');
138 width = x + 80;
139 }
140
141 JOptionPane.showMessageDialog(parent, exceptionName + ":\n" + sb, "Error", JOptionPane.ERROR_MESSAGE);
142 }
143
144 public static boolean isMacOSX() {
145 return System.getProperty("os.name").startsWith("Mac OS X");
146 }
147
148 public static void installKeyBindings() {
149 if (isMacOSX()) {
150 final KeyStroke copyKeyStroke = KeyStroke.getKeyStroke("meta pressed C");
151 final KeyStroke pasteKeyStroke = KeyStroke.getKeyStroke("meta pressed V");
152 final KeyStroke cutKeyStroke = KeyStroke.getKeyStroke("meta pressed X");
153 final KeyStroke allKeyStroke = KeyStroke.getKeyStroke("meta pressed A");
154
155 InputMap textFieldMap = (InputMap) UIManager.get("TextField.focusInputMap");
156 textFieldMap.put(copyKeyStroke, DefaultEditorKit.copyAction);
157 textFieldMap.put(pasteKeyStroke, DefaultEditorKit.pasteAction);
158 textFieldMap.put(cutKeyStroke, DefaultEditorKit.cutAction);
159 textFieldMap.put(allKeyStroke, DefaultEditorKit.selectAllAction);
160
161 InputMap formattedTextFieldMap = (InputMap) UIManager.get("FormattedTextField.focusInputMap");
162 formattedTextFieldMap.put(copyKeyStroke, DefaultEditorKit.copyAction);
163 formattedTextFieldMap.put(pasteKeyStroke, DefaultEditorKit.pasteAction);
164 formattedTextFieldMap.put(cutKeyStroke, DefaultEditorKit.cutAction);
165 formattedTextFieldMap.put(allKeyStroke, DefaultEditorKit.selectAllAction);
166
167 InputMap textAreaMap = (InputMap) UIManager.get("TextArea.focusInputMap");
168 textAreaMap.put(copyKeyStroke, DefaultEditorKit.copyAction);
169 textAreaMap.put(pasteKeyStroke, DefaultEditorKit.pasteAction);
170 textAreaMap.put(cutKeyStroke, DefaultEditorKit.cutAction);
171 textAreaMap.put(allKeyStroke, DefaultEditorKit.selectAllAction);
172
173 InputMap passwordFieldMap = (InputMap) UIManager.get("PasswordField.focusInputMap");
174 passwordFieldMap.put(pasteKeyStroke, DefaultEditorKit.pasteAction);
175 }
176 }
177
178 public static void installEscapeBinding(final Window window, final JRootPane rootPane, final boolean dispose) {
179 final KeyStroke stroke = KeyStroke.getKeyStroke("ESCAPE");
180 final InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
181 inputMap.put(stroke, "ESCAPE");
182 rootPane.getActionMap().put("ESCAPE", new AbstractAction() {
183 private static final long serialVersionUID = 1L;
184
185 @Override
186 public void actionPerformed(ActionEvent e) {
187 if (dispose) {
188 window.dispose();
189 } else {
190 window.setVisible(false);
191 }
192 }
193 });
194 }
195
196 public static ImageIcon getIcon(String name) {
197 URL imageURL = ClientHelper.class.getResource("/images/" + name);
198 if (imageURL != null) {
199 return new ImageIcon(imageURL);
200 }
201
202 return null;
203 }
204
205 public static String getDateString(GregorianCalendar cal) {
206 if (cal == null) {
207 return "";
208 }
209
210 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ZZZ");
211 return sdf.format(cal.getTime());
212 }
213
214 public static void download(Component component, CmisObject object, String streamId) {
215 ContentStream content = getContentStream(object, streamId);
216 if (content == null) {
217 return;
218 }
219
220 String filename = content.getFileName();
221 if (filename == null) {
222 if (object instanceof Document) {
223 filename = ((Document) object).getContentStreamFileName();
224 } else {
225 filename = object.getName();
226 }
227 }
228
229 JFileChooser fileChooser = new JFileChooser();
230 fileChooser.setSelectedFile(new File(filename));
231
232 int chooseResult = fileChooser.showDialog(component, "Download");
233 if (chooseResult == JFileChooser.APPROVE_OPTION) {
234 try {
235 storeStream(content.getStream(), fileChooser.getSelectedFile());
236 } catch (Exception e) {
237 showError(component, e);
238 }
239 }
240 }
241
242 public static void copy(Component component, File file) {
243 JFileChooser fileChooser = new JFileChooser();
244 fileChooser.setSelectedFile(new File(file.getName()));
245
246 int chooseResult = fileChooser.showDialog(component, "Download");
247 if (chooseResult == JFileChooser.APPROVE_OPTION) {
248 try {
249 storeStream(new FileInputStream(file), fileChooser.getSelectedFile());
250 } catch (Exception e) {
251 showError(component, e);
252 }
253 }
254 }
255
256 public static void open(Component component, CmisObject object, String streamId) {
257 if (!Desktop.isDesktopSupported()) {
258 download(component, object, streamId);
259 return;
260 }
261
262 Desktop desktop = Desktop.getDesktop();
263
264 if (!desktop.isSupported(Desktop.Action.OPEN)) {
265 download(component, object, streamId);
266 return;
267 }
268
269 File file = null;
270
271 try {
272 file = createTempFileFromDocument(object, streamId);
273 } catch (Exception e) {
274 showError(component, e);
275 return;
276 }
277
278 try {
279 desktop.open(file);
280 } catch (Exception e) {
281 if (e instanceof IOException) {
282 copy(component, file);
283 } else {
284 showError(component, e);
285 }
286 }
287 }
288
289 public static File createTempFile(String filename) {
290 String tempDir = System.getProperty("java.io.tmpdir");
291 File clientTempDir = new File(tempDir, "cmisworkbench");
292 if (!clientTempDir.exists()) {
293 clientTempDir.mkdirs();
294 }
295 clientTempDir.deleteOnExit();
296
297 File tempFile = new File(clientTempDir, filename);
298 tempFile.deleteOnExit();
299
300 return tempFile;
301 }
302
303 public static File createTempFileFromDocument(CmisObject object, String streamId) throws Exception {
304 ContentStream content = getContentStream(object, streamId);
305 if (content == null) {
306 throw new Exception("No content!");
307 }
308
309 String filename = content.getFileName();
310 if ((filename == null) || (filename.length() == 0)) {
311 if (object instanceof Document) {
312 filename = ((Document) object).getContentStreamFileName();
313 }
314 }
315 if ((filename == null) || (filename.length() == 0)) {
316 filename = object.getName();
317 }
318 if ((filename == null) || (filename.length() == 0)) {
319 filename = "content";
320 }
321
322 String ext = MimeTypes.getExtension(content.getMimeType());
323 if (ext.length() > 0 && !filename.endsWith(ext)) {
324 filename = filename + ext;
325 }
326
327 File tempFile = ClientHelper.createTempFile(filename);
328 try {
329 storeStream(content.getStream(), tempFile);
330 } catch (CmisConstraintException e) {
331
332 }
333
334 return tempFile;
335 }
336
337 private static void storeStream(InputStream in, File file) throws IOException {
338 OutputStream out = null;
339 try {
340 out = new BufferedOutputStream(new FileOutputStream(file), BUFFER_SIZE);
341
342 byte[] buffer = new byte[BUFFER_SIZE];
343 int b;
344 while ((b = in.read(buffer)) > -1) {
345 out.write(buffer, 0, b);
346 }
347
348 } finally {
349 if (in != null) {
350 try {
351 in.close();
352 } catch (Exception e) {
353 }
354 }
355 if (out != null) {
356 try {
357 out.close();
358 } catch (Exception e) {
359 }
360 }
361 }
362 }
363
364 private static ContentStream getContentStream(CmisObject object, String streamId) {
365 if (object == null) {
366 return null;
367 }
368
369 if (object instanceof Document) {
370 return ((Document) object).getContentStream(streamId);
371 } else {
372 if (streamId == null) {
373 return null;
374 }
375
376 List<Rendition> renditions = object.getRenditions();
377 if (renditions == null) {
378 return null;
379 }
380
381 for (Rendition rendition : renditions) {
382 if (streamId.equals(rendition.getStreamId())) {
383 return rendition.getContentStream();
384 }
385 }
386 }
387
388 return null;
389 }
390
391 public static void copyTableToClipboard(JTable table) {
392 final String newline = System.getProperty("line.separator");
393
394 final StringBuilder sb = new StringBuilder();
395 final int rows = table.getModel().getRowCount();
396 final int cols = table.getModel().getColumnCount();
397
398 for (int col = 0; col < cols; col++) {
399 if (col > 0) {
400 sb.append(",");
401 }
402
403 sb.append(formatCSVValue(table.getModel().getColumnName(col)));
404 }
405
406 sb.append(newline);
407
408 for (int row = 0; row < rows; row++) {
409 for (int col = 0; col < cols; col++) {
410 if (col > 0) {
411 sb.append(",");
412 }
413
414 Object value = table.getModel().getValueAt(row, col);
415 sb.append(formatCSVValue(value));
416 }
417 sb.append(newline);
418 }
419
420 Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
421 Transferable transferable = new StringSelection(sb.toString());
422 clipboard.setContents(transferable, null);
423 }
424
425 private static String formatCSVValue(Object value) {
426 if (value == null) {
427 return "";
428 } else if (value instanceof GregorianCalendar) {
429 return getDateString((GregorianCalendar) value);
430 } else if (value instanceof String) {
431 String s = value.toString();
432
433 StringBuffer sb = new StringBuffer();
434 sb.append('\"');
435
436 for (int i = 0; i < s.length(); i++) {
437 char c = s.charAt(i);
438 sb.append(c);
439 if (c == '\"') {
440 sb.append('\"');
441 }
442 }
443
444 sb.append('\"');
445
446 return sb.toString();
447 } else if (value instanceof Collection<?>) {
448 StringBuffer sb = new StringBuffer();
449 sb.append("[");
450
451 for (Object v : (Collection<?>) value) {
452 if (sb.length() > 1) {
453 sb.append(",");
454 }
455 sb.append(formatCSVValue(v));
456 }
457
458 sb.append("]");
459
460 return sb.toString();
461 } else if (value instanceof ObjectId) {
462 return formatCSVValue(((ObjectId) value).getId());
463 } else if (value instanceof ImageIcon) {
464 return "<icon>";
465 }
466
467 return value.toString();
468 }
469
470 public static String readFileAndRemoveHeader(String file) {
471 if (file == null) {
472 return "";
473 }
474
475 InputStream stream = ClientHelper.class.getResourceAsStream(file);
476 if (stream == null) {
477 return "";
478 } else {
479 try {
480 BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
481 StringBuilder sb = new StringBuilder();
482 String s;
483 boolean header = true;
484
485 while ((s = reader.readLine()) != null) {
486
487 if (header) {
488 String st = s.trim();
489 if (st.length() == 0) {
490 header = false;
491 continue;
492 }
493
494 char c = st.charAt(0);
495 header = (c == '/') || (c == '*') || (c == '#');
496 if (header) {
497 continue;
498 }
499 }
500
501 sb.append(s);
502 sb.append("\n");
503 }
504
505 reader.close();
506
507 return sb.toString();
508 } catch (Exception e) {
509 return "";
510 }
511 }
512 }
513
514 public static List<FileEntry> readFileProperties(String propertiesFile, String path) {
515 InputStream stream = ClientHelper.class.getResourceAsStream(propertiesFile);
516 if (stream == null) {
517 return null;
518 }
519
520 try {
521 Properties properties = new Properties();
522 properties.load(stream);
523 stream.close();
524
525 List<FileEntry> result = new ArrayList<FileEntry>();
526 for (String file : properties.stringPropertyNames()) {
527 result.add(new FileEntry(properties.getProperty(file), path + file));
528 }
529 Collections.sort(result);
530
531 return result;
532 } catch (IOException e) {
533 return null;
534 } finally {
535 try {
536 stream.close();
537 } catch (IOException ioe) {
538 }
539 }
540 }
541
542 public static Console openConsole(final Component parent, final ClientModel model, final String file) {
543 try {
544 parent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
545
546 Console console = new Console(parent.getClass().getClassLoader());
547 console.setVariable("session", model.getClientSession().getSession());
548 console.setVariable("binding", model.getClientSession().getSession().getBinding());
549
550 console.run();
551
552 JMenu cmisMenu = new JMenu("CMIS");
553 console.getFrame().getRootPane().getJMenuBar().add(cmisMenu);
554
555 addConsoleMenu(cmisMenu, "CMIS 1.0 Specification", new URI(
556 "http://docs.oasis-open.org/cmis/CMIS/v1.0/os/cmis-spec-v1.0.html"));
557 addConsoleMenu(cmisMenu, "OpenCMIS Documentation",
558 new URI("http://chemistry.apache.org/java/opencmis.html"));
559 addConsoleMenu(cmisMenu, "OpenCMIS Client API JavaDoc", new URI(
560 "http://chemistry.apache.org/java/0.7.0/maven/apidocs/"));
561
562 console.getInputArea().setText(ClientHelper.readFileAndRemoveHeader(file));
563
564 return console;
565 } catch (Exception ex) {
566 ClientHelper.showError(null, ex);
567 return null;
568 } finally {
569 parent.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
570 }
571 }
572
573 private static void addConsoleMenu(JMenu menu, String title, final URI url) {
574 if (!Desktop.isDesktopSupported() || !Desktop.getDesktop().isSupported(Action.BROWSE)) {
575 return;
576 }
577
578 JMenuItem menuItem = new JMenuItem(title);
579 menuItem.addActionListener(new ActionListener() {
580 @Override
581 public void actionPerformed(ActionEvent e) {
582 try {
583 Desktop.getDesktop().browse(url);
584 } catch (IOException e1) {
585 }
586 }
587 });
588
589 menu.add(menuItem);
590 }
591
592 public static void runGroovyScript(final Component parent, final ClientModel model, final File file,
593 final Writer out) {
594 try {
595 parent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
596
597 String[] roots = new String[] { file.getParentFile().getAbsolutePath() };
598 GroovyScriptEngine gse = new GroovyScriptEngine(roots, parent.getClass().getClassLoader());
599 Binding binding = new Binding();
600 binding.setVariable("session", model.getClientSession().getSession());
601 binding.setVariable("binding", model.getClientSession().getSession().getBinding());
602 binding.setVariable("out", out);
603 gse.run(file.getName(), binding);
604 } catch (Exception ex) {
605 ClientHelper.showError(null, ex);
606 } finally {
607 parent.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
608 }
609 }
610
611 public static void runJSR223Script(final Component parent, final ClientModel model, final File file,
612 final String ext, final Writer out) {
613 try {
614 parent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
615
616 ScriptEngineManager mgr = new ScriptEngineManager();
617 ScriptEngine engine = mgr.getEngineByExtension(ext);
618 engine.getContext().setWriter(out);
619 engine.getContext().setErrorWriter(out);
620 engine.put("session", model.getClientSession().getSession());
621 engine.put("binding", model.getClientSession().getSession().getBinding());
622 engine.put("out", new PrintWriter(out));
623 engine.eval(new FileReader(file));
624 } catch (Exception ex) {
625 ClientHelper.showError(null, ex);
626 } finally {
627 parent.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
628 }
629 }
630
631 public static class FileEntry implements Comparable<FileEntry> {
632 private final String name;
633 private final String file;
634
635 public FileEntry(String name, String file) {
636 this.name = name;
637 this.file = file;
638 }
639
640 public String getName() {
641 return name;
642 }
643
644 public String getFile() {
645 return file;
646 }
647
648 @Override
649 public String toString() {
650 return name;
651 }
652
653 @Override
654 public int compareTo(FileEntry o) {
655 return name.compareToIgnoreCase(o.getName());
656 }
657
658 @Override
659 public int hashCode() {
660 return name.hashCode();
661 }
662
663 @Override
664 public boolean equals(Object obj) {
665 if (!(obj instanceof FileEntry)) {
666 return false;
667 }
668
669 return name.equals(((FileEntry) obj).getName());
670 }
671 }
672 }