1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package com.sun.star.xml.security.uno;
25 
26 import javax.xml.parsers.DocumentBuilder;
27 import javax.xml.parsers.DocumentBuilderFactory;
28 import javax.xml.parsers.ParserConfigurationException;
29 
30 import java.io.File;
31 import java.io.IOException;
32 import java.io.FileOutputStream;
33 import java.io.FileInputStream;
34 import java.io.InputStream;
35 import java.io.ByteArrayInputStream;
36 import java.io.UnsupportedEncodingException;
37 
38 import org.w3c.dom.Document;
39 import org.w3c.dom.Node;
40 import org.w3c.dom.NodeList;
41 
42 /* Basic GUI components */
43 import javax.swing.JFrame;
44 import javax.swing.JPanel;
45 import javax.swing.JScrollPane;
46 import javax.swing.JTree;
47 import javax.swing.JButton;
48 import javax.swing.JCheckBox;
49 import javax.swing.JTextArea;
50 import javax.swing.JTextField;
51 import javax.swing.JFileChooser;
52 import javax.swing.ToolTipManager;
53 import javax.swing.JTable;
54 import javax.swing.JLabel;
55 import javax.swing.BorderFactory;
56 
57 /* GUI components for right-hand side */
58 import javax.swing.JSplitPane;
59 import javax.swing.JOptionPane;
60 import javax.swing.JTabbedPane;
61 
62 
63 /* GUI support classes */
64 import java.awt.BorderLayout;
65 import java.awt.Dimension;
66 import java.awt.Container;
67 import java.awt.Toolkit;
68 import java.awt.event.WindowEvent;
69 import java.awt.event.WindowAdapter;
70 import java.awt.event.ActionEvent;
71 import java.awt.event.ActionListener;
72 
73 /* For creating borders */
74 import javax.swing.border.EmptyBorder;
75 import javax.swing.border.BevelBorder;
76 import javax.swing.border.CompoundBorder;
77 
78 /* For creating a TreeModel */
79 import javax.swing.tree.TreePath;
80 import java.util.Vector;
81 
82 /* UNO classes */
83 import com.sun.star.uno.UnoRuntime;
84 import com.sun.star.bridge.XUnoUrlResolver;
85 import com.sun.star.lang.XMultiComponentFactory;
86 import com.sun.star.beans.XPropertySet;
87 import com.sun.star.uno.XComponentContext;
88 import com.sun.star.xml.sax.XDocumentHandler;
89 
90 import com.sun.star.xml.crypto.*;
91 import com.sun.star.xml.crypto.sax.*;
92 
93 public class TestTool extends JFrame implements ActionListener
94 {
95 	/*
96 	 * xml security framewrok component names
97 	 */
98 	public static String SIGNATURECREATOR_COMPONENT = "com.sun.star.xml.crypto.sax.SignatureCreator";
99 	public static String SIGNATUREVERIFIER_COMPONENT = "com.sun.star.xml.crypto.sax.SignatureVerifier";
100 	public static String ENCRYPTOR_COMPONENT = "com.sun.star.xml.crypto.sax.Encryptor";
101 	public static String DECRYPTOR_COMPONENT = "com.sun.star.xml.crypto.sax.Decryptor";
102 	public static String SAXEVENTKEEPER_COMPONENT = "com.sun.star.xml.crypto.sax.SAXEventKeeper";
103 
104 	/*
105 	 * Java-based component names
106 	 */
107 	public static String SEINITIALIZER_COMPONENT_JAVA = "com.sun.star.xml.security.bridge.jxsec.SEInitializer_JxsecImpl";
108 	public static String XMLSIGNATURE_COMPONENT_JAVA = "com.sun.star.xml.security.bridge.jxsec.XMLSignature_JxsecImpl";
109 	public static String XMLENCRYPTION_COMPONENT_JAVA = "com.sun.star.xml.security.bridge.jxsec.XMLEncryption_JxsecImpl";
110 	public static String XMLDOCUMENTWRAPPER_COMPONENT_JAVA = "com.sun.star.xml.security.bridge.jxsec.XMLDocumentWrapper_JxsecImpl";
111 
112 	/*
113 	 * C-based component names
114 	 */
115 	public static String SEINITIALIZER_COMPONENT_C = "com.sun.star.xml.crypto.SEInitializer";
116 	public static String XMLSIGNATURE_COMPONENT_C = "com.sun.star.xml.crypto.XMLSignature";
117 	public static String XMLENCRYPTION_COMPONENT_C = "com.sun.star.xml.crypto.XMLEncryption";
118 	public static String XMLDOCUMENTWRAPPER_COMPONENT_C = "com.sun.star.xml.wrapper.XMLDocumentWrapper";
119 
120 	/* url resolver name */
121 	public static String UNOURLRESOLVER = "com.sun.star.bridge.UnoUrlResolver";
122 
123 	/*
124 	 * connection URL
125 	 */
126 	private String m_unoURL = "uno:socket,host=localhost,port=2002;urp;StarOffice.ServiceManager";
127 
128 	/* key file */
129 	private String m_javaTokenFile = null;
130 	private String m_nssTokenPath = null;
131 
132 	/* User Interfaces */
133 	private JButton m_goButton;
134 	private JButton m_stepButton;
135 	private JButton m_startButton;
136 	private JButton m_openButton;
137 	private JCheckBox m_isExportingButton;
138 	private JCheckBox m_isJavaComponentButton;
139 	private JButton m_saveButton;
140 	private JButton m_batchButton;
141 	private JTree m_leftTree;
142 	private JTextArea m_leftTextArea;
143 	private JTree m_middleTree;
144 	private JTree m_rightTree;
145 	private JTabbedPane m_leftTabPane;
146 	private JTextArea m_bufferNodeTextArea;
147 	private JLabel m_saxChainLabel;
148 	private JTextField m_saxEventText;
149 	private JTable m_unsolvedReferenceTable;
150 
151 	/*
152 	 * whether a batch file is running,
153 	 * if so, no message box is popped up
154 	 */
155 	private boolean m_bIsBatchRunning = false;
156 
157 	/*
158 	 * whether the UI needs to be updated.
159 	 * when user click the "go" button, the UI needs
160 	 * not to be updated step by step for performance
161 	 * reason
162 	 */
163 	private boolean m_bIsUIUpdateSuppressed = false;
164 
165 	/*
166 	 * three DOM tree adapter
167 	 */
168 	private DomToTreeModelAdapter m_leftTreeModelAdapter;
169 	private DomToTreeModelAdapter m_middleTreeModelAdapter;
170 	private DomToTreeModelAdapter m_rightTreeModelAdapter;
171 
172 	/*
173 	 * the current directory, which reserves the default
174 	 * location when user open/save a file.
175 	 */
176 	private File m_currentDirectory = null;
177 
178 	/*
179 	 * the log file
180 	 */
181 	private FileOutputStream m_logFileOutputStream = null;
182 
183 	/*
184 	 * the thread which is parsing the current XML
185 	 * file
186 	 */
187 	private ParsingThread m_parsingThread;
188 
189 	/*
190 	 * whether is exporting or importing
191 	 */
192 	private boolean m_bIsExporting;
193 
194 	/*
195 	 * whether java based component or c based component
196 	 * is used now
197 	 */
198 	private boolean m_bIsJavaBased;
199 
200 	/*
201 	 * XML security component interface
202 	 */
203 	private XComponentContext m_xRemoteContext = null;
204 	private XMultiComponentFactory m_xRemoteServiceManager = null;
205 	private XXMLSecurityContext m_xXMLSecurityContext = null;
206 	private XXMLSignature m_xXMLSignature = null;
207 	private XXMLEncryption m_xXMLEncryption = null;
208 	private XSEInitializer m_xSEInitializer = null;
209 
210 	/*
211 	 * SAX event collector for the middle tree and the right tree
212 	 */
213 	private SAXEventCollector m_rightTreeEventCollector = null;
214 	private SAXEventCollector m_middleTreeEventCollector = null;
215 
216 	/*
217 	 * security framework controller
218 	 */
219 	private XMLSecurityFrameworkController m_xmlSecurityFrameworkController = null;
220 
221 	/* org.w3c.dom.Document */
222 	private Document m_document;
223 
224 	/* represents whether "Go" or "Step" */
225 	private boolean stepMode = true;
226 
227 /**************************************************************************************
228  * private methods
229  **************************************************************************************/
230 
231 
232 	/******************************************************************************
233 	 * UI related methods
234 	 ******************************************************************************/
235 
236 	/*
237 	 * initalizes the UI.
238 	 */
239 	private void initUI()
240 	{
241 		m_leftTreeModelAdapter = new DomToTreeModelAdapter(m_document);
242 		m_middleTreeModelAdapter = new DomToTreeModelAdapter(m_document);
243 		m_rightTreeModelAdapter = new DomToTreeModelAdapter(m_document);
244 
245 		m_parsingThread = null;
246 
247 		m_leftTree.setModel(m_leftTreeModelAdapter);
248 		m_middleTree.setModel(m_middleTreeModelAdapter);
249 		m_rightTree.setModel(m_rightTreeModelAdapter);
250 	}
251 
252 	/*
253 	 * constructs the user interface.
254 	 */
255 	private Container buildUI(int width, int height)
256 	{
257 		JPanel mainPanel = new JPanel();
258 
259 		int frameHeight = height-40;
260 		int leftWindowWidth = (width-40)/3;
261 		int middleWindowWidth = leftWindowWidth;
262 		int rightWindowWidth = leftWindowWidth;
263 		int leftPaneWidth = leftWindowWidth+middleWindowWidth;
264 		int frameWidth = leftPaneWidth + rightWindowWidth;
265 
266 		/* Make a nice border */
267 		EmptyBorder emptyBorder = new EmptyBorder(5,5,5,5);
268 		BevelBorder bevelBorder = new BevelBorder(BevelBorder.LOWERED);
269 		CompoundBorder compoundBorder = new CompoundBorder(emptyBorder,bevelBorder);
270 		mainPanel.setBorder(new CompoundBorder(compoundBorder,emptyBorder));
271 
272 		/* Set up the tree */
273 		m_leftTreeModelAdapter = new DomToTreeModelAdapter(m_document);
274 		m_middleTreeModelAdapter = new DomToTreeModelAdapter(m_document);
275 		m_rightTreeModelAdapter = new DomToTreeModelAdapter(m_document);
276 
277 		m_leftTree = new JTree(m_leftTreeModelAdapter);
278 		m_leftTextArea = new JTextArea();
279 		m_middleTree = new JTree(m_middleTreeModelAdapter);
280 		m_rightTree = new JTree(m_rightTreeModelAdapter);
281 
282 		ToolTipManager.sharedInstance().registerComponent(m_leftTree);
283 		ToolTipManager.sharedInstance().registerComponent(m_middleTree);
284 		ToolTipManager.sharedInstance().registerComponent(m_rightTree);
285 
286 		/* Builds left tab pane */
287 		JScrollPane leftTreePane = new JScrollPane(m_leftTree);
288 		JScrollPane leftTextPane = new JScrollPane(m_leftTextArea);
289 		m_leftTabPane= new JTabbedPane();
290 		m_leftTabPane.add("Tree View",leftTreePane);
291 		m_leftTabPane.add("Text View",leftTextPane);
292 
293 		/* Builds middle tree pane */
294 		JScrollPane middleTreePane = new JScrollPane(m_middleTree);
295 
296 		/* Builds right tree pane */
297 		JScrollPane rightTreePane = new JScrollPane(m_rightTree);
298 		rightTreePane.setBorder(BorderFactory.createCompoundBorder(
299                         BorderFactory.createTitledBorder("Result"),
300                         BorderFactory.createEmptyBorder(8,8,8,8)));
301 
302 		m_leftTabPane.setPreferredSize(
303 			new Dimension( leftWindowWidth, frameHeight ));
304 		middleTreePane.setPreferredSize(
305 			new Dimension( middleWindowWidth, frameHeight ));
306 		rightTreePane.setPreferredSize(
307 			new Dimension( rightWindowWidth, frameHeight ));
308 
309 		/* Builds the SAX event text box */
310 		m_saxEventText = new JTextField();
311 
312 		/* Builds the unsolved reference table */
313 		m_unsolvedReferenceTable = new JTable(
314 				new UnsolvedReferenceTableModel(this));
315 
316 		/* Builds the BufferNode information text area */
317 		m_bufferNodeTextArea = new JTextArea();
318 
319 		/* Builds the SAX chain information label */
320 		m_saxChainLabel = new JLabel();
321 
322 		/* Builds the left pane */
323 		JPanel tabPaneWithSaxEventPane = new JPanel();
324 		tabPaneWithSaxEventPane.setLayout(new BorderLayout());
325 		tabPaneWithSaxEventPane.add("Center",m_leftTabPane);
326 		tabPaneWithSaxEventPane.add("South",new JScrollPane(m_saxEventText));
327 
328 		JSplitPane leftPane =
329 			new JSplitPane( JSplitPane.VERTICAL_SPLIT,
330 				tabPaneWithSaxEventPane,
331 				new JScrollPane(m_unsolvedReferenceTable));
332 		leftPane.setBorder(BorderFactory.createCompoundBorder(
333                         BorderFactory.createTitledBorder("Original"),
334                         BorderFactory.createEmptyBorder(8,8,8,8)));
335 
336 		leftPane.setContinuousLayout( true );
337 		leftPane.setDividerLocation( frameHeight*2/3 );
338 		leftPane.setPreferredSize(
339 			new Dimension( leftWindowWidth, frameHeight ));
340 
341 		/* Builds the middle pane */
342 		JPanel bufferNodeWithSaxChainPane = new JPanel();
343 		bufferNodeWithSaxChainPane.setLayout(new BorderLayout());
344 		bufferNodeWithSaxChainPane.add("Center",m_bufferNodeTextArea);
345 		bufferNodeWithSaxChainPane.add("South",new JScrollPane(m_saxChainLabel));
346 
347 		JSplitPane middlePane =
348 			new JSplitPane( JSplitPane.VERTICAL_SPLIT,
349 				middleTreePane,
350 				new JScrollPane(bufferNodeWithSaxChainPane));
351 
352 		middlePane.setBorder(BorderFactory.createCompoundBorder(
353                         BorderFactory.createTitledBorder("Insight SAXEventKeeper"),
354                         BorderFactory.createEmptyBorder(8,8,8,8)));
355 
356 		middlePane.setContinuousLayout( true );
357 		middlePane.setDividerLocation( frameHeight/2+5 );
358 		middlePane.setPreferredSize(
359 			new Dimension( middleWindowWidth, frameHeight ));
360 
361 		/* Builds the whole frame pane */
362 		JSplitPane leftWithMiddlePane =
363 			new JSplitPane( JSplitPane.HORIZONTAL_SPLIT,
364 				leftPane,
365 				middlePane );
366 		leftWithMiddlePane.setContinuousLayout( true );
367 		leftWithMiddlePane.setDividerLocation( leftWindowWidth );
368 		leftWithMiddlePane.setPreferredSize(
369 			new Dimension( leftPaneWidth + 10, frameHeight+10 ));
370 
371 		JSplitPane framePane =
372 			new JSplitPane( JSplitPane.HORIZONTAL_SPLIT,
373 				leftWithMiddlePane,
374 				rightTreePane );
375 
376 
377 		framePane.setContinuousLayout( true );
378 		framePane.setDividerLocation(leftPaneWidth+10 );
379 		framePane.setPreferredSize(
380 			new Dimension( frameWidth + 20, frameHeight+10 ));
381 
382 		/* Adds all GUI components to the main panel */
383 		mainPanel.setLayout(new BorderLayout());
384 		mainPanel.add("Center", framePane );
385 
386 		m_openButton = new JButton("Open...");
387 		m_openButton.addActionListener(this);
388 
389 		m_goButton = new JButton("Go!");
390 		m_goButton.addActionListener(this);
391 
392 		m_stepButton = new JButton("Step");
393 		m_stepButton.addActionListener(this);
394 
395 		m_startButton = new JButton("Start");
396 		m_startButton.addActionListener(this);
397 		m_startButton.setEnabled(false);
398 
399 		m_isExportingButton = new JCheckBox("export, not import", true);
400 		m_isJavaComponentButton = new JCheckBox("use java component", false);
401 
402 		m_saveButton = new JButton("Save...");
403 		m_saveButton.addActionListener(this);
404 
405 		m_batchButton = new JButton("Batch...");
406 		m_batchButton.addActionListener(this);
407 
408 		JPanel buttonPanel = new JPanel();
409 		buttonPanel.add(m_batchButton);
410 		buttonPanel.add(m_openButton);
411 		buttonPanel.add(m_startButton);
412 		buttonPanel.add(m_goButton);
413 		buttonPanel.add(m_stepButton);
414 		buttonPanel.add(m_isExportingButton);
415 		buttonPanel.add(m_isJavaComponentButton);
416 		buttonPanel.add(m_saveButton);
417 
418 		mainPanel.add("South", buttonPanel);
419 
420 		enableGoButton(false);
421 
422 		return mainPanel;
423 	}
424 
425 	/*
426 	 * enables/disables the Go(and Step) button.
427 	 */
428 	private void enableGoButton(boolean enabled)
429 	{
430 		m_goButton.setEnabled(enabled);
431 		m_stepButton.setEnabled(enabled);
432 	}
433 
434 	/*
435 	 * updates the unsolved reference information.
436 	 */
437 	private void updatesUnsolvedReferencesInformation()
438 	{
439 		m_unsolvedReferenceTable.setModel(new UnsolvedReferenceTableModel(this));
440 	}
441 
442 	/*
443 	 * adjusts the view of the tree in order to make the
444 	 * particular Node into the focus tree leaf.
445 	 */
446 	private void updatesTree(Node node, JTree tree)
447 	{
448 		int i=0;
449 		int currentLine = 0;
450 
451 		while (i<tree.getRowCount())
452 		{
453 			TreePath treePath = tree.getPathForRow(i);
454 			tree.expandPath(treePath);
455 
456 			AdapterNode adapterNode = (AdapterNode)treePath.getLastPathComponent();
457 
458 			if (node == adapterNode.getNode())
459 			{
460 				tree.addSelectionPath(treePath);
461 				currentLine = i;
462 			}
463 
464 			++i;
465 		}
466 
467 		tree.setCellRenderer(new XMLTreeCellRanderer(node));
468 		tree.scrollRowToVisible(currentLine);
469 	}
470 
471 	/******************************************************************************
472 	 * action listener related methods.
473 	 ******************************************************************************/
474 
475 	/*
476 	 * reads in a document, either the document is a file or
477 	 * is a text paragraph.
478 	 */
479 	private void openDocument()
480 	{
481 		if (m_leftTabPane.getSelectedIndex() == 0)
482 		{
483 			File f = openFile();
484 			if (f != null)
485 			{
486 				parseFile(f);
487 			}
488 		}
489 		else
490 		{
491 			String text = m_leftTextArea.getText();
492 
493 			try
494 			{
495 				parseStream(new ByteArrayInputStream(text.getBytes("UTF-8")));
496 			}
497 			catch(UnsupportedEncodingException e)
498 			{
499 				e.printStackTrace();
500 			}
501 
502 			m_leftTabPane.setSelectedIndex(0);
503 		}
504 	}
505 
506 	/*
507 	 * save the result tree to a file.
508 	 */
509 	private void saveResult()
510 	{
511 		saveFile();
512 	}
513 
514 	/*
515 	 * selects a batch file to excute.
516 	 */
517 	private void openBatch()
518 	{
519 		File f = openFile();
520 		if (f != null)
521 		{
522 			runBatch(f);
523 		}
524 	}
525 
526 	/*
527 	 * makes the current operation to an end.
528 	 */
529 	private void endMission()
530 	{
531 		enableGoButton(false);
532 		m_parsingThread = null;
533 
534 		if (m_xmlSecurityFrameworkController != null)
535 		{
536 			m_xmlSecurityFrameworkController.endMission();
537 		}
538 
539 		updatesUIs();
540 
541 		m_xmlSecurityFrameworkController = null;
542 		freeComponents();
543 
544 		System.gc();
545 	}
546 
547 
548 	/******************************************************************************
549 	 * UNO component related methods
550 	 ******************************************************************************/
551 
552 	/*
553 	 * connects the SO server.
554 	 */
555 	private void connectSO(String unoUrlString)
556 	{
557 		if (unoUrlString != null)
558 		{
559 			m_unoURL = new String(unoUrlString);
560 		}
561 
562 		try
563 		{
564 			m_xRemoteServiceManager = getRemoteServiceManager(m_unoURL);
565 		}
566 		catch(Exception e)
567 		{
568 			e.printStackTrace();
569 		}
570 	}
571 
572 	/*
573 	 * creates UNO components.
574 	 */
575 	private boolean createComponents()
576 	{
577 		try
578 		{
579 			String SEInitializer_comp;
580 			String XMLSignature_comp;
581 			String XMLEncryption_comp;
582 			String tokenPath;
583 
584 			if (m_bIsJavaBased)
585 			{
586 				SEInitializer_comp = SEINITIALIZER_COMPONENT_JAVA;
587 				XMLSignature_comp = XMLSIGNATURE_COMPONENT_JAVA;
588 				XMLEncryption_comp = XMLENCRYPTION_COMPONENT_JAVA;
589 				tokenPath = m_javaTokenFile;
590 			}
591 			else
592 			{
593 				SEInitializer_comp = SEINITIALIZER_COMPONENT_C;
594 				XMLSignature_comp = XMLSIGNATURE_COMPONENT_C;
595 				XMLEncryption_comp = XMLENCRYPTION_COMPONENT_C;
596 				tokenPath = m_nssTokenPath;
597 			}
598 
599 			Object seInitializerObj = m_xRemoteServiceManager.createInstanceWithContext(
600 				SEInitializer_comp, m_xRemoteContext);
601 
602 			if (seInitializerObj == null)
603 			{
604 				freeComponents();
605 				return false;
606 			}
607 
608 			m_xSEInitializer = (XSEInitializer)UnoRuntime.queryInterface(
609 						XSEInitializer.class, seInitializerObj);
610 
611 			m_xXMLSecurityContext = m_xSEInitializer.createSecurityContext(tokenPath);
612 
613 			Object xmlSignatureObj = m_xRemoteServiceManager.createInstanceWithContext(
614 				XMLSignature_comp, m_xRemoteContext);
615 
616 			if (xmlSignatureObj == null)
617 			{
618 				freeComponents();
619 				return false;
620 			}
621 
622 			m_xXMLSignature = (XXMLSignature)UnoRuntime.queryInterface(
623 						XXMLSignature.class, xmlSignatureObj);
624 
625 			Object xmlEncryptionObj = m_xRemoteServiceManager.createInstanceWithContext(
626 				XMLEncryption_comp, m_xRemoteContext);
627 
628 			if (xmlEncryptionObj == null)
629 			{
630 				freeComponents();
631 				return false;
632 			}
633 
634 			m_xXMLEncryption = (XXMLEncryption)UnoRuntime.queryInterface(
635 						XXMLEncryption.class, xmlEncryptionObj);
636 
637 			return true;
638 		}
639 		catch(Exception e)
640 		{
641 			freeComponents();
642 			e.printStackTrace();
643 			return false;
644 		}
645 	}
646 
647         /*
648          * frees UNO components.
649          */
650 	private void freeComponents()
651 	{
652 		try
653 		{
654 			if (m_xXMLSecurityContext != null)
655 			{
656 				m_xSEInitializer.freeSecurityContext(m_xXMLSecurityContext);
657 				m_xXMLSecurityContext = null;
658 			}
659 
660 			m_xXMLSignature = null;
661 			m_xXMLEncryption = null;
662 			m_xSEInitializer = null;
663 		}
664 		catch(Exception e)
665 		{
666 			e.printStackTrace();
667 		}
668 	}
669 
670 	/*
671 	 * getRemoteServiceManager
672 	 */
673 	private XMultiComponentFactory getRemoteServiceManager(String unoUrl) throws java.lang.Exception
674 	{
675 		if (m_xRemoteContext == null)
676 		{
677 			/*
678 			 * First step: create local component context, get local servicemanager and
679 			 * ask it to create a UnoUrlResolver object with an XUnoUrlResolver interface
680 			 */
681 			XComponentContext xLocalContext =
682 				com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(null);
683 			XMultiComponentFactory xLocalServiceManager = xLocalContext.getServiceManager();
684 			Object urlResolver = xLocalServiceManager.createInstanceWithContext(
685 				UNOURLRESOLVER, xLocalContext );
686 			/*
687 			 * query XUnoUrlResolver interface from urlResolver object
688 			 */
689 			XUnoUrlResolver xUnoUrlResolver = (XUnoUrlResolver) UnoRuntime.queryInterface(
690 				XUnoUrlResolver.class, urlResolver );
691 
692 			/*
693 			 * Second step: use xUrlResolver interface to import the remote StarOffice.ServiceManager,
694 			 * retrieve its property DefaultContext and get the remote servicemanager
695 			 */
696 			Object initialObject = xUnoUrlResolver.resolve( unoUrl );
697 			XPropertySet xPropertySet = (XPropertySet)UnoRuntime.queryInterface(
698 			XPropertySet.class, initialObject);
699 			Object context = xPropertySet.getPropertyValue("DefaultContext");
700 			m_xRemoteContext = (XComponentContext)UnoRuntime.queryInterface(
701 				XComponentContext.class, context);
702 		}
703 		return m_xRemoteContext.getServiceManager();
704 	}
705 
706 
707 	/******************************************************************************
708 	 * XML related methods
709 	 ******************************************************************************/
710 
711 	/*
712 	 * removes all empty text node inside the particular element
713 	 */
714 	private void removeEmptyText(Node node)
715 	{
716 		int type = node.getNodeType();
717 		NodeList children;
718 		int i;
719 
720 		switch (type)
721 		{
722 		case Node.DOCUMENT_NODE:
723 		case Node.ELEMENT_NODE:
724 			Node child = node.getFirstChild();
725 			while (child!= null)
726 			{
727 				Node nextSibling = child.getNextSibling();
728 				int childType = child.getNodeType();
729 
730 				if (childType==Node.TEXT_NODE)
731 				{
732 					String message = child.getNodeValue().trim();
733 					if (message == null || message.length()<=0)
734 					{
735 						node.removeChild(child);
736 					}
737 				}
738 				else if (childType == Node.ELEMENT_NODE)
739 				{
740 					removeEmptyText(child);
741 				}
742 
743 				child = nextSibling;
744 			}
745 			break;
746 		}
747 	}
748 
749 	/*
750 	 * reads a stream, and parses it into the original tree.
751 	 */
752 	private void parseStream(InputStream is)
753 	{
754 		try
755 		{
756 			DocumentBuilderFactory factory =
757 				DocumentBuilderFactory.newInstance();
758 			m_document = null;
759 			m_startButton.setEnabled(false);
760 			initUI();
761 
762 			/* factory.setValidating(true); */
763 			/* factory.setNamespaceAware(true); */
764 
765 			try
766 			{
767 				DocumentBuilder builder = factory.newDocumentBuilder();
768 				m_document = builder.parse(is);
769 				m_startButton.setEnabled(true);
770 				initUI();
771 			}
772 			catch (ParserConfigurationException pce)
773 			{
774 				pce.printStackTrace();
775 			}
776 			catch (IOException ioe)
777 			{
778 				ioe.printStackTrace();
779 			}
780 		}
781 		catch(Exception exce)
782 		{
783 			System.out.println("input stream Exception");
784 		}
785 	}
786 
787 
788 	/******************************************************************************
789 	 * file operation related methods
790 	 ******************************************************************************/
791 
792 	/*
793 	 * opens a file, and parses it into the original tree.
794 	 */
795 	private void parseFile(File name)
796 	{
797 		try
798 		{
799 			FileInputStream fis = new FileInputStream(name);
800 			parseStream(fis);
801 			fis.close();
802 		}
803 		catch(Exception exce)
804 		{
805 			System.out.println("open file Exception");
806 		}
807 	}
808 
809 
810 	/*
811 	 * selects a file to open
812 	 */
813 	private File openFile()
814 	{
815 		File rc = null;
816 
817 		JFileChooser fileChooser= new JFileChooser();
818 
819 		fileChooser.setDialogTitle("Select File To Open");
820 		fileChooser.setDialogType(JFileChooser.OPEN_DIALOG);
821 
822 		fileChooser.setApproveButtonText("Ok");
823 
824 		if (m_currentDirectory == null)
825 		{
826 			fileChooser.rescanCurrentDirectory();
827 		}
828 		else
829 		{
830 			fileChooser.setCurrentDirectory(m_currentDirectory);
831 		}
832 
833 		fileChooser.setFileFilter(new XMLFileFilter());
834 
835 		int result = fileChooser.showDialog(this,null);
836 		if (result==fileChooser.APPROVE_OPTION)
837 		{
838 			m_currentDirectory = fileChooser.getCurrentDirectory();
839 			rc = fileChooser.getSelectedFile();
840 		}
841 
842 		return rc;
843 	}
844 
845 	private void saveFile()
846 	{
847 		JFileChooser fileChooser= new JFileChooser();
848 
849 		fileChooser.setDialogTitle("Select File To Save");
850 		fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
851 
852 		fileChooser.setApproveButtonText("Ok");
853 
854 		if (m_currentDirectory == null)
855 		{
856 			fileChooser.rescanCurrentDirectory();
857 		}
858 		else
859 		{
860 			fileChooser.setCurrentDirectory(m_currentDirectory);
861 		}
862 
863 		fileChooser.setFileFilter(new XMLFileFilter());
864 
865 		int result = fileChooser.showDialog(this,null);
866 		if (result==fileChooser.APPROVE_OPTION)
867 		{
868 			try
869 			{
870 				m_currentDirectory = fileChooser.getCurrentDirectory();
871 				saveFile(fileChooser.getSelectedFile());
872 			}
873 			catch(Exception exce)
874 			{
875 				System.out.println("save file Exception");
876 				exce.printStackTrace();
877 			}
878 		}
879 	}
880 
881 	/*
882 	 * excutes a batch file.
883 	 */
884 	private void runBatch(File f)
885 	{
886 		FileInputStream fis = null;
887 
888 		try
889 		{
890 			fis = new FileInputStream(f);
891 			StringBuffer commandBuffer = new StringBuffer();
892 
893 			m_logFileOutputStream = new FileOutputStream("TestTool-log.txt");
894 			m_bIsBatchRunning = true;
895 			int ch = 0;
896 
897 			while (ch != -1)
898 			{
899 				ch = fis.read();
900 
901 				if (ch != 0x0a && ch != -1)
902 				{
903 					if (ch != 0x0d)
904 					{
905 						commandBuffer.append((char)ch);
906 					}
907 				}
908 				else
909 				{
910 					String command = new String(commandBuffer);
911 					if (command.startsWith("Open "))
912 					{
913 						m_logFileOutputStream.write(("start \""+command+"\" ...\n").getBytes());
914 						String fileName = command.substring(5);
915 						parseFile(new File(fileName));
916 						m_logFileOutputStream.write("command end \n\n".getBytes());
917 					}
918 					else if (command.startsWith("Use Java Component"))
919 					{
920 						m_logFileOutputStream.write(("start \""+command+"\" ...\n").getBytes());
921 						m_isJavaComponentButton.setSelected(true);
922 						m_logFileOutputStream.write("command end \n\n".getBytes());
923 					}
924 					else if (command.startsWith("Use C++ Component"))
925 					{
926 						m_logFileOutputStream.write(("start \""+command+"\" ...\n").getBytes());
927 						m_isJavaComponentButton.setSelected(false);
928 						m_logFileOutputStream.write("command end \n\n".getBytes());
929 					}
930 					else if (command.startsWith("Go "))
931 					{
932 						m_logFileOutputStream.write(("start \""+command+"\" ...\n").getBytes());
933 						String opera = command.substring(3);
934 						if (opera.equals("Sign") || opera.equals("Encrypt"))
935 						{
936 							m_isExportingButton.setSelected(true);
937 						}
938 						else
939 						{
940 							m_isExportingButton.setSelected(false);
941 						}
942 
943 						startsUp();
944 						if (m_parsingThread != null)
945 						{
946 							m_bIsUIUpdateSuppressed = true;
947 							try{
948 								while (m_parsingThread.nextStep());
949 								endMission();
950 							}
951 							catch(Exception e)
952 							{
953 								System.out.println("exception happen during batch:"+e);
954 								e.printStackTrace();
955 							}
956 
957 							m_bIsUIUpdateSuppressed = false;
958 							updatesUIs();
959 						}
960 						m_logFileOutputStream.write("command end \n\n".getBytes());
961 					}
962 					else if (command.startsWith("Save "))
963 					{
964 						m_logFileOutputStream.write(("start \""+command+"\" ...\n").getBytes());
965 						String fileName = command.substring(5);
966 						saveFile(new File(fileName));
967 						m_logFileOutputStream.write("command end \n\n".getBytes());
968 					}
969 
970 					commandBuffer = new StringBuffer();
971 				}
972 			}
973 
974 			m_bIsBatchRunning = false;
975 			m_logFileOutputStream.close();
976 			m_logFileOutputStream = null;
977 
978 			fis.close();
979 			fis = null;
980 		}
981 		catch(java.io.IOException e)
982 		{
983 			e.printStackTrace();
984 		}
985 	}
986 
987 	/*
988 	 * save the current result tree to a particular file.
989 	 */
990 	private void saveFile(File f)
991 	{
992 		try{
993 			FileOutputStream fos = new FileOutputStream(f);
994 			SAXEventPrinter.display((Document)m_rightTreeEventCollector.getDocument(),
995 				0,fos,false);
996 			fos.close();
997 		}catch(Exception e)
998 		{
999 			e.printStackTrace();
1000 		}
1001 	}
1002 
1003 	/******************************************************************************
1004 	 * others
1005 	 ******************************************************************************/
1006 
1007 	/*
1008 	 * starts up the operation.
1009 	 */
1010 	private void startsUp()
1011 	{
1012 		if (m_parsingThread != null)
1013 		{
1014 			m_parsingThread = null;
1015 		}
1016 
1017 		m_bIsExporting = m_isExportingButton.isSelected();
1018 		m_bIsJavaBased = m_isJavaComponentButton.isSelected();
1019 
1020 		if (createComponents())
1021 		{
1022 			m_rightTreeEventCollector = new SAXEventCollector(this);
1023 
1024 			m_parsingThread = new ParsingThread(
1025 				m_document,
1026 				null,
1027 				this);
1028 
1029 			m_xmlSecurityFrameworkController =
1030 				new XMLSecurityFrameworkController(
1031 					this,
1032 					m_bIsExporting,
1033 					m_bIsJavaBased,
1034 					m_rightTreeEventCollector,
1035 					m_parsingThread,
1036 					m_xXMLSecurityContext,
1037 					m_xXMLSignature,
1038 					m_xXMLEncryption,
1039 					m_xRemoteServiceManager,
1040 					m_xRemoteContext);
1041 
1042 			enableGoButton(true);
1043 		}
1044 		else
1045 		{
1046 			showMessage("Error in creating XML Security Components!");
1047 		}
1048 	}
1049 
1050 /**************************************************************************************
1051  * protected methods
1052  **************************************************************************************/
1053 
1054 	/******************************************************************************
1055 	 * UI related methods
1056 	 ******************************************************************************/
1057 
1058 	/*
1059 	 * updates the sax chain information.
1060 	 */
1061 	protected void updatesSAXChainInformation(String chainStr)
1062 	{
1063 		m_saxChainLabel.setText(chainStr);
1064 	}
1065 
1066 	/*
1067 	 * update the current SAX event information.
1068 	 */
1069 	protected void updatesCurrentSAXEventInformation(String event)
1070 	{
1071 		m_saxEventText.setText(event);
1072 	}
1073 
1074 	/*
1075 	 * updates all information in the UI.
1076 	 */
1077 	protected void updatesUIs()
1078 	{
1079 		if (!m_bIsUIUpdateSuppressed)
1080 		{
1081 			m_leftTree.clearSelection();
1082 			updatesTree(null, m_leftTree);
1083 
1084 			if (m_xmlSecurityFrameworkController != null)
1085 			{
1086 				String bufferNodeTreeText = m_xmlSecurityFrameworkController.getBufferNodeTreeInformation();
1087 				if (bufferNodeTreeText == null)
1088 				{
1089 					m_middleTree.setVisible(false);
1090 					m_bufferNodeTextArea.setText("No XML Security Related");
1091 				}
1092 				else
1093 				{
1094 					m_middleTreeEventCollector = new SAXEventCollector(null);
1095 					m_xmlSecurityFrameworkController.getDocument(m_middleTreeEventCollector);
1096 
1097 					m_middleTreeModelAdapter = new DomToTreeModelAdapter(m_middleTreeEventCollector.getDocument());
1098 					m_middleTree.setModel(m_middleTreeModelAdapter);
1099 					updatesTree(null, m_middleTree);
1100 					m_middleTree.setVisible(true);
1101 					m_bufferNodeTextArea.setText(bufferNodeTreeText);
1102 				}
1103 			}
1104 			else
1105 			{
1106 				m_middleTree.setVisible(false);
1107 				m_bufferNodeTextArea.setText("No XMLImporter/XMLExporter");
1108 			}
1109 
1110 			if (m_rightTreeEventCollector != null)
1111 			{
1112 				m_rightTreeModelAdapter = new DomToTreeModelAdapter((Document)m_rightTreeEventCollector.getDocument());
1113 				m_rightTree.setModel(m_rightTreeModelAdapter);
1114 				updatesTree((Node)m_rightTreeEventCollector.getCurrentElement(), m_rightTree);
1115 			}
1116 
1117 			updatesUnsolvedReferencesInformation();
1118 		}
1119 	}
1120 
1121 	/*
1122 	 * shows a message.
1123 	 */
1124 	protected void showMessage(String msg)
1125 	{
1126 		if (m_bIsBatchRunning)
1127 		{
1128 			try
1129 			{
1130 				if (!msg.startsWith("Message from : SAXEventKeeper"))
1131 				{
1132 					byte [] b = msg.getBytes();
1133 					m_logFileOutputStream.write("        ".getBytes());
1134 
1135 					for (int i=0; i<b.length; ++i)
1136 					{
1137 						m_logFileOutputStream.write(b[i]);
1138 						if (b[i] == '\n')
1139 						{
1140 							m_logFileOutputStream.write("        ".getBytes());
1141 						}
1142 					}
1143 					m_logFileOutputStream.write("\n        ==============================\n".getBytes());
1144 				}
1145 			}
1146 			catch(IOException e)
1147 			{
1148 				e.printStackTrace();
1149 			}
1150 		}
1151 		else
1152 		{
1153 			if (stepMode)
1154 			{
1155 				JOptionPane optionPane = new JOptionPane();
1156 				optionPane.showMessageDialog(this, msg, "TestTool Notification", JOptionPane.INFORMATION_MESSAGE);
1157 			}
1158 			else
1159 			{
1160 				Object[] options = { "OK", "Go back to step mode" };
1161 				if (1 == JOptionPane.showOptionDialog(this, msg, "TestTool Notification",
1162 					JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE,
1163 					null, options, options[0]))
1164 				{
1165 					stepMode = true;
1166 				}
1167 			}
1168 		}
1169 	}
1170 
1171 
1172 	/******************************************************************************
1173 	 * information retrieving
1174 	 ******************************************************************************/
1175 
1176 	/*
1177 	 * gets all unsolved reference ids.
1178 	 * a reference id is the value of the id attribute of an
1179 	 * referenced element.
1180 	 */
1181 	protected Vector getUnsolvedReferenceIds()
1182 	{
1183 		Vector rc;
1184 
1185 		if (m_xmlSecurityFrameworkController == null)
1186 		{
1187 			rc = new Vector();
1188 		}
1189 		else
1190 		{
1191 			rc = ((XMLSecurityFrameworkController)m_xmlSecurityFrameworkController).
1192 				getUnsolvedReferenceIds();
1193 		}
1194 
1195 		return rc;
1196 	}
1197 
1198 	/*
1199 	 * gets all unsolved reference keeper ids.
1200 	 * a reference keeper id is the id which the SAXEventKeeper uses
1201 	 * to identify the corresponding BufferNode.
1202 	 */
1203 	protected Vector getUnsolvedReferenceKeeperIds()
1204 	{
1205 		Vector rc;
1206 
1207 		if (m_xmlSecurityFrameworkController == null)
1208 		{
1209 			rc = new Vector();
1210 		}
1211 		else
1212 		{
1213 			rc = ((XMLSecurityFrameworkController)m_xmlSecurityFrameworkController).
1214 				getUnsolvedReferenceKeeperIds();
1215 		}
1216 
1217 		return rc;
1218 	}
1219 
1220 	/*
1221 	 * gets all unsolved references' remaining numbers.
1222 	 * a remaining number is that how many claims have not been found for
1223 	 * a unsolved reference.
1224 	 */
1225 	protected Vector getUnsolvedReferenceRefNum()
1226 	{
1227 		Vector rc;
1228 
1229 		if (m_xmlSecurityFrameworkController == null)
1230 		{
1231 			rc = new Vector();
1232 		}
1233 		else
1234 		{
1235 			rc = ((XMLSecurityFrameworkController)m_xmlSecurityFrameworkController).
1236 				getUnsolvedReferenceRefNum();
1237 		}
1238 
1239 		return rc;
1240 	}
1241 
1242 
1243 /**************************************************************************************
1244  * public methods
1245  **************************************************************************************/
1246 
1247 	/******************************************************************************
1248 	 * action listener related methods.
1249 	 ******************************************************************************/
1250 
1251 	/*
1252 	 * action listening method.
1253 	 */
1254 	public void actionPerformed(ActionEvent e)
1255 	{
1256 		if (e.getSource().equals(m_startButton))
1257 		{
1258 			endMission();
1259 			startsUp();
1260 		}
1261 		if (e.getSource().equals(m_goButton))
1262 		{
1263 			if (m_parsingThread != null)
1264 			{
1265 				stepMode = false;
1266 				boolean notOver;
1267 				while ( notOver = m_parsingThread.nextStep())
1268 				{
1269 					if (stepMode) break;
1270 				}
1271 
1272 				if (!notOver) endMission();
1273 			}
1274 		}
1275 		if (e.getSource().equals(m_stepButton))
1276 		{
1277 			if (m_parsingThread != null)
1278 			{
1279 				if (!m_parsingThread.nextStep())
1280 				{
1281 					endMission();
1282 				}
1283 			}
1284 		}
1285 		if (e.getSource().equals(m_openButton))
1286 		{
1287 			openDocument();
1288 		}
1289 		if (e.getSource().equals(m_saveButton))
1290 		{
1291 			saveResult();
1292 		}
1293 		if (e.getSource().equals(m_batchButton))
1294 		{
1295 			openBatch();
1296 		}
1297 	}
1298 
1299 	/*
1300 	 * void-consturctor method
1301 	 */
1302 	public TestTool()
1303 	{
1304 	        getRootPane().putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE);
1305 
1306         	try
1307         	{
1308         		m_currentDirectory = new File(System.getProperty("user.dir"));
1309 		}
1310 		catch(Exception e)
1311 		{
1312 			System.out.println("getProperty error :"+e);
1313 		}
1314 	}
1315 
1316 	/*
1317 	 * consturctor method with a specific connection URL
1318 	 */
1319 	public TestTool(String connecturl)
1320 	{
1321 		this();
1322 		m_unoURL = new String(connecturl);
1323 	}
1324 
1325 	public static void main(String argv[])
1326 	{
1327 		Dimension screenSize =
1328 			Toolkit.getDefaultToolkit().getScreenSize();
1329 
1330 		TestTool tt;
1331 
1332 		if (argv.length < 1)
1333 		{
1334 			System.out.println("Usage: java TestTool [javaTokenFile] [nssTokenPath] [xml file]?");
1335 			return;
1336 		}
1337 
1338 		boolean hasFile = false;
1339 		boolean hasBatch = false;
1340 		String fileName = null;
1341 
1342 		if (argv.length >= 3)
1343 		{
1344 			if (argv[2].startsWith("-b"))
1345 			{
1346 				fileName = argv[2].substring(2);
1347 				hasBatch = true;
1348 			}
1349 			else
1350 			{
1351 				fileName = argv[2];
1352 				hasFile = true;
1353 			}
1354 		}
1355 
1356 		tt = new TestTool();
1357 		tt.m_javaTokenFile = new String(argv[0]);
1358 		tt.m_nssTokenPath = new String(argv[1]);
1359 		tt.connectSO(null);
1360 
1361 		/* Set up a GUI framework */
1362 		JFrame myFrame = new JFrame("XML Security Components Tester");
1363 		myFrame.addWindowListener(
1364 			new WindowAdapter() {
1365 				public void windowClosing(WindowEvent e) {System.exit(0);}
1366 			}
1367 			);
1368 
1369 		myFrame.setContentPane(tt.buildUI(screenSize.width, screenSize.height));
1370 		myFrame.pack();
1371 		int w = screenSize.width-30;
1372 		int h = screenSize.height-30;
1373 		myFrame.setLocation(screenSize.width/2 - w/2,
1374 		screenSize.height/2 - h/2);
1375 		myFrame.setSize(w, h);
1376 		myFrame.setVisible(true);
1377 
1378 		if (hasFile)
1379 		{
1380 			tt.parseFile(new File(fileName));
1381 		}
1382 		else if (hasBatch)
1383 		{
1384 			tt.runBatch(new File(fileName));
1385 		}
1386 	}
1387 }
1388 
1389