1 package complex.ofopxmlstorages;
2 
3 import com.sun.star.uno.UnoRuntime;
4 import com.sun.star.uno.XInterface;
5 import com.sun.star.uno.AnyConverter;
6 
7 import com.sun.star.lang.*;
8 import com.sun.star.embed.*;
9 import com.sun.star.packages.*;
10 import com.sun.star.io.*;
11 import com.sun.star.beans.*;
12 
13 import share.LogWriter;
14 
15 public class TestHelper  {
16 
17 	LogWriter m_aLogWriter;
18 	String m_sTestPrefix;
19 
20 	public TestHelper( LogWriter aLogWriter, String sTestPrefix )
21 	{
22 		m_aLogWriter = aLogWriter;
23 		m_sTestPrefix = sTestPrefix;
24 	}
25 
26 	public boolean WriteBytesToStream( XStream xStream,
27 										String sStreamName,
28 										String sMediaType,
29 										boolean bCompressed,
30 										byte[] pBytes,
31 										StringPair[][] aRelations )
32 	{
33 		// get output stream of substream
34 		XOutputStream xOutput = xStream.getOutputStream();
35 		if ( xOutput == null )
36 		{
37 			Error( "Can't get XOutputStream implementation from substream '" + sStreamName + "'!" );
38 			return false;
39 		}
40 
41 		// get XTrucate implementation from output stream
42 		XTruncate xTruncate = (XTruncate) UnoRuntime.queryInterface( XTruncate.class, xOutput );
43 		if ( xTruncate == null )
44 		{
45 			Error( "Can't get XTruncate implementation from substream '" + sStreamName + "'!" );
46 			return false;
47 		}
48 
49 		// write requested byte sequence
50 		try
51 		{
52 			xTruncate.truncate();
53 			xOutput.writeBytes( pBytes );
54 		}
55 		catch( Exception e )
56 		{
57 			Error( "Can't write to stream '" + sStreamName + "', exception: " + e );
58 			return false;
59 		}
60 
61 		// get access to the XPropertySet interface
62 		XPropertySet xPropSet = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, xStream );
63 		if ( xPropSet == null )
64 		{
65 			Error( "Can't get XPropertySet implementation from substream '" + sStreamName + "'!" );
66 			return false;
67 		}
68 
69 		// set properties to the stream
70 		try
71 		{
72 			xPropSet.setPropertyValue( "MediaType", sMediaType );
73 			xPropSet.setPropertyValue( "Compressed", new Boolean( bCompressed ) );
74 		}
75 		catch( Exception e )
76 		{
77 			Error( "Can't set properties to substream '" + sStreamName + "', exception: " + e );
78 			return false;
79 		}
80 
81 		// check size property of the stream
82 		try
83 		{
84 			int nSize = AnyConverter.toInt( xPropSet.getPropertyValue( "Size" ) );
85 			if ( nSize != pBytes.length )
86 			{
87 				Error( "The 'Size' property of substream '" + sStreamName + "' contains wrong value!" );
88 				return false;
89 			}
90 		}
91 		catch( Exception e )
92 		{
93 			Error( "Can't get 'Size' property from substream '" + sStreamName + "', exception: " + e );
94 			return false;
95 		}
96 
97 		// get access to the relationship information
98 		XRelationshipAccess xRelAccess = (XRelationshipAccess) UnoRuntime.queryInterface( XRelationshipAccess.class, xStream );
99 		if ( xRelAccess == null )
100 		{
101 			Error( "Can't get XRelationshipAccess implementation from substream '" + sStreamName + "'!" );
102 			return false;
103 		}
104 
105 		// set the relationship information
106 		try
107 		{
108 			xRelAccess.insertRelationships( aRelations, false );
109 		}
110 		catch( Exception e )
111 		{
112 			Error( "Can't set relationships to substream '" + sStreamName + "', exception: " + e );
113 			return false;
114 		}
115 
116 		// free the stream resources, garbage collector may remove the object too late
117 		if ( !disposeStream( xStream, sStreamName ) )
118 			return false;
119 
120 		return true;
121 	}
122 
123 	public boolean WriteBytesToSubstream( XStorage xStorage,
124 										  String sStreamName,
125 										  String sMediaType,
126 										  boolean bCompressed,
127 										  byte[] pBytes,
128 										  StringPair[][] aRelations )
129 	{
130 		// open substream element
131 		XStream xSubStream = null;
132 		try
133 		{
134 			Object oSubStream = xStorage.openStreamElement( sStreamName, ElementModes.WRITE );
135 			xSubStream = (XStream) UnoRuntime.queryInterface( XStream.class, oSubStream );
136 			if ( xSubStream == null )
137 			{
138 				Error( "Can't create substream '" + sStreamName + "'!" );
139 				return false;
140 			}
141 		}
142 		catch( Exception e )
143 		{
144 			Error( "Can't create substream '" + sStreamName + "', exception : " + e + "!" );
145 			return false;
146 		}
147 
148 		return WriteBytesToStream( xSubStream, sStreamName, sMediaType, bCompressed, pBytes, aRelations );
149 	}
150 
151 	public boolean setStorageTypeAndCheckProps( XStorage xStorage,
152 												boolean bIsRoot,
153 												int nMode,
154 												StringPair[][] aRelations )
155 	{
156 		boolean bOk = false;
157 
158 		// get access to the XPropertySet interface
159 		XPropertySet xPropSet = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, xStorage );
160 		if ( xPropSet != null )
161 		{
162 			try
163 			{
164 				// get "IsRoot" and "OpenMode" properties and control there values
165 				boolean bPropIsRoot = AnyConverter.toBoolean( xPropSet.getPropertyValue( "IsRoot" ) );
166 				int nPropMode = AnyConverter.toInt( xPropSet.getPropertyValue( "OpenMode" ) );
167 
168 				bOk = true;
169 				if ( bPropIsRoot != bIsRoot )
170 				{
171 					Error( "'IsRoot' property contains wrong value!" );
172 					bOk = false;
173 				}
174 
175 				if ( ( bIsRoot
176 				  && ( nPropMode | ElementModes.READ ) != ( nMode | ElementModes.READ ) )
177 				  || ( !bIsRoot && ( nPropMode & nMode ) != nMode ) )
178 				{
179 					Error( "'OpenMode' property contains wrong value, expected " + nMode + ", in reality " + nPropMode + "!" );
180 					bOk = false;
181 				}
182 			}
183 			catch( Exception e )
184 			{
185 				Error( "Can't control properties of substorage, exception: " + e );
186 			}
187 		}
188 		else
189 		{
190 			Error( "Can't get XPropertySet implementation from storage!" );
191 		}
192 
193 		// get access to the relationship information
194 		XRelationshipAccess xRelAccess = (XRelationshipAccess) UnoRuntime.queryInterface( XRelationshipAccess.class, xStorage );
195 
196 		if ( xRelAccess == null )
197 		{
198 			Error( "Can't get XRelationshipAccess implementation from the storage!" );
199 			return false;
200 		}
201 
202 		// set the relationship information
203 		try
204 		{
205 			xRelAccess.insertRelationships( aRelations, false );
206 		}
207 		catch( Exception e )
208 		{
209 			Error( "Can't set relationships to the storage, exception: " + e );
210 			return false;
211 		}
212 
213 
214 		return bOk;
215 	}
216 
217 	public boolean checkRelations( StringPair[][] aStorRels, StringPair[][] aTestRels )
218 	{
219 		// Message( "StorageRels:" );
220 		// PrintRelations( aStorRels );
221 		// Message( "TestRels:" );
222 		// PrintRelations( aTestRels );
223 
224 		if ( aStorRels.length != aTestRels.length )
225 		{
226 			Error( "The provided relations sequence has different size than the storage's one!" );
227 			return false;
228 		}
229 
230 		for ( int nStorInd = 0; nStorInd < aStorRels.length; nStorInd++ )
231 		{
232 			int nStorIDInd = -1;
233 			for ( int nStorTagInd = 0; nStorTagInd < aStorRels[nStorInd].length; nStorTagInd++ )
234 			{
235 				if ( aStorRels[nStorInd][nStorTagInd].First.equals( "Id" ) )
236 				{
237 					nStorIDInd = nStorTagInd;
238 					break;
239 				}
240 			}
241 
242 			if ( nStorIDInd == -1 )
243 			{
244 				Error( "One of the storage relations entries has no ID!" );
245 				return false;
246 			}
247 
248 			for ( int nInd = 0; nInd < aTestRels.length; nInd++ )
249 			{
250 				int nIDInd = -1;
251 				for ( int nTagInd = 0; nTagInd < aTestRels[nInd].length; nTagInd++ )
252 				{
253 					if ( aTestRels[nInd][nTagInd].First.equals( "Id" ) )
254 					{
255 						nIDInd = nTagInd;
256 						break;
257 					}
258 				}
259 
260 				if ( nIDInd == -1 )
261 				{
262 					Error( "One of the test hardcoded entries has no ID, num = " + nInd + ", length = " + aTestRels[nInd].length + ", global length = " + aTestRels.length + "!" );
263 					return false;
264 				}
265 
266 				if ( aStorRels[nStorInd][nStorIDInd].Second.equals( aTestRels[nInd][nIDInd].Second ) )
267 				{
268 					boolean[] pRelCheckMark = new boolean[ aTestRels[nInd].length ];
269 					for ( int nCheckInd = 0; nCheckInd < pRelCheckMark.length; nCheckInd++ )
270 					{
271 						pRelCheckMark[nCheckInd] = false;
272 					}
273 
274 					for ( int nStorTagInd = 0; nStorTagInd < aStorRels[nStorInd].length; nStorTagInd++ )
275 					{
276 						boolean bFound = false;
277 						for ( int nTagInd = 0; nTagInd < aTestRels[nInd].length; nTagInd++ )
278 						{
279 							if ( aTestRels[nInd][nTagInd].First.equals( aStorRels[nStorInd][nStorTagInd].First ) )
280 							{
281 								if ( !aTestRels[nInd][nTagInd].Second.equals( aStorRels[nStorInd][nStorTagInd].Second ) )
282 								{
283 									Error( "Test rel. num. " + nInd + " has different tag \"" + aTestRels[nInd][nTagInd].First + "\" value!" );
284 									return false;
285 								}
286 
287 								bFound = true;
288 								pRelCheckMark[nTagInd] = true;
289 								break;
290 							}
291 						}
292 
293 						if ( !bFound )
294 						{
295 							Error( "Stor rel. num. " + nStorInd + " has unexpected tag \"" + aStorRels[nStorInd][nStorTagInd].First + "\", ID = \"" + aStorRels[nStorInd][nStorIDInd].Second + "\"!" );
296 							return false;
297 						}
298 					}
299 
300 					for ( int nCheckInd = 0; nCheckInd < pRelCheckMark.length; nCheckInd++ )
301 					{
302 						if ( !pRelCheckMark[nCheckInd] && !aTestRels[nInd][nCheckInd].Second.equals( "" ) )
303 						{
304 							Error( "Test rel. num. " + nInd + " has unexpected tag \"" + aTestRels[nInd][nCheckInd].First + "\" with nonempty value!" );
305 							return false;
306 						}
307 					}
308 
309 					break;
310 				}
311 			}
312 		}
313 
314 		return true;
315 	}
316 
317 	public boolean checkStorageProperties( XStorage xStorage,
318 											boolean bIsRoot,
319 											int nMode,
320 											StringPair[][] aRelations )
321 	{
322 		boolean bOk = false;
323 
324 		// get access to the XPropertySet interface
325 		XPropertySet xPropSet = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, xStorage );
326 		if ( xPropSet != null )
327 		{
328 			try
329 			{
330 				// get "IsRoot" and "OpenMode" properties and control there values
331 				boolean bPropIsRoot = AnyConverter.toBoolean( xPropSet.getPropertyValue( "IsRoot" ) );
332 				int nPropMode = AnyConverter.toInt( xPropSet.getPropertyValue( "OpenMode" ) );
333 
334 				bOk = true;
335 				if ( bPropIsRoot != bIsRoot )
336 				{
337 					Error( "'IsRoot' property contains wrong value!" );
338 					bOk = false;
339 				}
340 
341 				if ( ( bIsRoot
342 				  && ( nPropMode | ElementModes.READ ) != ( nMode | ElementModes.READ ) )
343 				  || ( !bIsRoot && ( nPropMode & nMode ) != nMode ) )
344 				{
345 					Error( "'OpenMode' property contains wrong value, expected " + nMode + ", in reality " + nPropMode + "!" );
346 					bOk = false;
347 				}
348 			}
349 			catch( Exception e )
350 			{
351 				Error( "Can't get properties of substorage, exception: " + e );
352 			}
353 		}
354 		else
355 		{
356 			Error( "Can't get XPropertySet implementation from storage!" );
357 		}
358 
359 		// get access to the relationship information
360 		XRelationshipAccess xRelAccess = (XRelationshipAccess) UnoRuntime.queryInterface( XRelationshipAccess.class, xStorage );
361 
362 		if ( xRelAccess == null )
363 		{
364 			Error( "Can't get XRelationshipAccess implementation from the checked storage!" );
365 			return false;
366 		}
367 
368 		// get the relationship information
369 		StringPair[][] aStorRels;
370 		try
371 		{
372 			aStorRels = xRelAccess.getAllRelationships();
373 		}
374 		catch( Exception e )
375 		{
376 			Error( "Can't get relationships of the checked storage, exception: " + e );
377 			return false;
378 		}
379 
380 		if ( !checkRelations( aStorRels, aRelations ) )
381 		{
382 			Error( "StorageRelationsChecking has failed!" );
383 			return false;
384 		}
385 
386 		return bOk;
387 	}
388 
389 	public boolean InternalCheckStream( XStream xStream,
390 										String sName,
391 										String sMediaType,
392 										byte[] pBytes,
393 										StringPair[][] aRelations )
394 	{
395 		// get input stream of substream
396 		XInputStream xInput = xStream.getInputStream();
397 		if ( xInput == null )
398 		{
399 			Error( "Can't get XInputStream implementation from substream '" + sName + "'!" );
400 			return false;
401 		}
402 
403 		byte pContents[][] = new byte[1][]; // ???
404 
405 		// read contents
406 		try
407 		{
408 			xInput.readBytes( pContents, pBytes.length + 1 );
409 		}
410 		catch( Exception e )
411 		{
412 			Error( "Can't read from stream '" + sName + "', exception: " + e );
413 			return false;
414 		}
415 
416 		// check size of stream data
417 		if ( pContents.length == 0 )
418 		{
419 			Error( "SubStream '" + sName + "' reading produced disaster!"  );
420 			return false;
421 		}
422 
423 		if ( pBytes.length != pContents[0].length )
424 		{
425 			Error( "SubStream '" + sName + "' contains wrong amount of data! (" + pContents[0].length + "/" + pBytes.length + ")" );
426 			return false;
427 		}
428 
429 		// check stream data
430 		for ( int ind = 0; ind < pBytes.length; ind++ )
431 		{
432 			if ( pBytes[ind] != pContents[0][ind] )
433 			{
434 				Error( "SubStream '" + sName + "' contains wrong data! ( byte num. "
435 						+ ind + " should be" + pBytes[ind] + " but it is " + pContents[0][ind] + ")" );
436 				return false;
437 			}
438 		}
439 
440 		// check properties
441 		boolean bOk = false;
442 
443 		// get access to the XPropertySet interface
444 		XPropertySet xPropSet = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, xStream );
445 		if ( xPropSet != null )
446 		{
447 			try
448 			{
449 				// get "MediaType" and "Size" properties and control there values
450 				String sPropMediaType = AnyConverter.toString( xPropSet.getPropertyValue( "MediaType" ) );
451 				int nPropSize = AnyConverter.toInt( xPropSet.getPropertyValue( "Size" ) );
452 
453 				bOk = true;
454 				if ( !sPropMediaType.equals( sMediaType ) )
455 				{
456 					Error( "'MediaType' property contains wrong value for stream '" + sName + "',\nexpected: '"
457 							+ sMediaType + "', set: '" + sPropMediaType + "'!" );
458 					bOk = false;
459 				}
460 
461 				if ( nPropSize != pBytes.length )
462 				{
463 					Error( "'Size' property contains wrong value for stream'" + sName + "'!" );
464 					bOk = false;
465 				}
466 			}
467 			catch( Exception e )
468 			{
469 				Error( "Can't get properties of substream '" + sName + "', exception: " + e );
470 			}
471 		}
472 		else
473 		{
474 			Error( "Can't get XPropertySet implementation from stream '" + sName + "'!" );
475 		}
476 
477 
478 		// get access to the relationship information
479 		XRelationshipAccess xRelAccess = (XRelationshipAccess) UnoRuntime.queryInterface( XRelationshipAccess.class, xStream );
480 
481 		if ( xRelAccess == null )
482 		{
483 			Error( "Can't get XRelationshipAccess implementation from the stream\"" + sName + "\"!" );
484 			return false;
485 		}
486 
487 		// get the relationship information
488 		StringPair[][] aStorRels;
489 		try
490 		{
491 			aStorRels = xRelAccess.getAllRelationships();
492 		}
493 		catch( Exception e )
494 		{
495 			Error( "Can't get relationships of the substream '" + sName + "', exception: " + e );
496 			return false;
497 		}
498 
499 		if ( !checkRelations( aStorRels, aRelations ) )
500 		{
501 			Error( "Stream '" + sName + "' RelationsChecking has failed!" );
502 			return false;
503 		}
504 
505 		return bOk;
506 	}
507 
508 	public boolean checkStream( XStorage xParentStorage,
509 								String sName,
510 								String sMediaType,
511 								byte[] pBytes,
512 								StringPair[][] aRelations )
513 	{
514 		// open substream element first
515 		XStream xSubStream = null;
516 		try
517 		{
518 			Object oSubStream = xParentStorage.openStreamElement( sName, ElementModes.READ );
519 			xSubStream = (XStream) UnoRuntime.queryInterface( XStream.class, oSubStream );
520 			if ( xSubStream == null )
521 			{
522 				Error( "Can't open substream '" + sName + "'!" );
523 				return false;
524 			}
525 		}
526 		catch( Exception e )
527 		{
528 			Error( "Can't open substream '" + sName + "', exception : " + e + "!" );
529 			return false;
530 		}
531 
532 		boolean bResult = InternalCheckStream( xSubStream, sName, sMediaType, pBytes, aRelations );
533 
534 		// free the stream resources, garbage collector may remove the object too late
535 		if ( !disposeStream( xSubStream, sName ) )
536 			return false;
537 
538 		return bResult;
539 	}
540 
541 	public boolean copyStorage( XStorage xSourceStorage, XStorage xDestStorage )
542 	{
543 		// copy xSourceStorage to xDestStorage
544 		try
545 		{
546 			xSourceStorage.copyToStorage( xDestStorage );
547 		}
548 		catch( Exception e )
549 		{
550 			Error( "Storage copying failed, exception: " + e );
551 			return false;
552 		}
553 
554 		return true;
555 	}
556 
557 	public boolean commitStorage( XStorage xStorage )
558 	{
559 		// XTransactedObject must be supported by storages
560 		XTransactedObject xTransact = (XTransactedObject) UnoRuntime.queryInterface( XTransactedObject.class, xStorage );
561 		if ( xTransact == null )
562 		{
563 			Error( "Storage doesn't implement transacted access!" );
564 			return false;
565 		}
566 
567 		try
568 		{
569 			xTransact.commit();
570 		}
571 		catch( Exception e )
572 		{
573 			Error( "Storage commit failed, exception:" + e );
574 			return false;
575 		}
576 
577 		return true;
578 	}
579 
580 	public boolean disposeStream( XStream xStream, String sStreamName )
581 	{
582 		XComponent xComponent = (XComponent) UnoRuntime.queryInterface( XComponent.class, xStream );
583 		if ( xComponent == null )
584 		{
585 			Error( "Can't get XComponent implementation from substream '" + sStreamName + "'!" );
586 			return false;
587 		}
588 
589 		try
590 		{
591 			xComponent.dispose();
592 		}
593 		catch( Exception e )
594 		{
595 			Error( "Substream '" + sStreamName + "' disposing throws exception: " + e );
596 			return false;
597 		}
598 
599 		return true;
600 	}
601 
602 	public boolean disposeStorage( XStorage xStorage )
603 	{
604 		// dispose the storage
605 		XComponent xComponent = (XComponent) UnoRuntime.queryInterface( XComponent.class, xStorage );
606 		if ( xComponent == null )
607 		{
608 			Error( "Can't retrieve XComponent implementation from storage!" );
609 			return false;
610 		}
611 
612 		try
613 		{
614 			xComponent.dispose();
615 		}
616 		catch( Exception e )
617 		{
618 			Error( "Storage disposing failed!" );
619 			return false;
620 		}
621 
622 		return true;
623 	}
624 
625 	public XInputStream getInputStream( XStream xStream )
626 	{
627 		XInputStream xInTemp = null;
628 		try
629 		{
630 			xInTemp = xStream.getInputStream();
631 			if ( xInTemp == null )
632 				Error( "Can't get the input part of a stream!" );
633 		}
634 		catch ( Exception e )
635 		{
636 			Error( "Can't get the input part of a stream, exception :" + e );
637 		}
638 
639 		return xInTemp;
640 	}
641 
642 	public boolean closeOutput( XStream xStream )
643 	{
644 		XOutputStream xOutTemp = null;
645 		try
646 		{
647 			xOutTemp = xStream.getOutputStream();
648 			if ( xOutTemp == null )
649 			{
650 				Error( "Can't get the output part of a stream!" );
651 				return false;
652 			}
653 		}
654 		catch ( Exception e )
655 		{
656 			Error( "Can't get the output part of a stream, exception :" + e );
657 			return false;
658 		}
659 
660 		try
661 		{
662 			xOutTemp.closeOutput();
663 		}
664 		catch ( Exception e )
665 		{
666 			Error( "Can't close output part of a stream, exception :" + e );
667 			return false;
668 		}
669 
670 		return true;
671 	}
672 
673 	public XStorage openSubStorage( XStorage xStorage, String sName, int nMode )
674 	{
675 		// open existing substorage
676 		try
677 		{
678 			Object oSubStorage = xStorage.openStorageElement( sName, nMode );
679 			XStorage xSubStorage = (XStorage) UnoRuntime.queryInterface( XStorage.class, oSubStorage );
680 			return xSubStorage;
681 		}
682 		catch( Exception e )
683 		{
684 			Error( "Can't open substorage '" + sName + "', exception: " + e );
685 		}
686 
687 		return null;
688 	}
689 
690 	public XStream CreateTempFileStream( XMultiServiceFactory xMSF )
691 	{
692 		// try to get temporary file representation
693 		XStream xTempFileStream = null;
694 		try
695 		{
696 			Object oTempFile = xMSF.createInstance( "com.sun.star.io.TempFile" );
697 			xTempFileStream = (XStream)UnoRuntime.queryInterface( XStream.class, oTempFile );
698 		}
699 		catch( Exception e )
700 		{}
701 
702 		if ( xTempFileStream == null )
703 			Error( "Can't create temporary file!" );
704 
705 		return xTempFileStream;
706 	}
707 
708 	public String CreateTempFile( XMultiServiceFactory xMSF )
709 	{
710 		String sResult = null;
711 
712 		// try to get temporary file representation
713 		XPropertySet xTempFileProps = null;
714 		try
715 		{
716 			Object oTempFile = xMSF.createInstance( "com.sun.star.io.TempFile" );
717 			xTempFileProps = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, oTempFile );
718 		}
719 		catch( Exception e )
720 		{}
721 
722 		if ( xTempFileProps != null )
723 		{
724 			try
725 			{
726 				xTempFileProps.setPropertyValue( "RemoveFile", new Boolean( false ) );
727 				sResult = AnyConverter.toString( xTempFileProps.getPropertyValue( "Uri" ) );
728 			}
729 			catch( Exception e )
730 			{
731 				Error( "Can't control TempFile properties, exception: " + e );
732 			}
733 		}
734 		else
735 		{
736 			Error( "Can't create temporary file representation!" );
737 		}
738 
739 		// close temporary file explicitly
740 		try
741 		{
742 			XStream xStream = (XStream)UnoRuntime.queryInterface( XStream.class, xTempFileProps );
743 			if ( xStream != null )
744 			{
745 				XOutputStream xOut = xStream.getOutputStream();
746 				if ( xOut != null )
747 					xOut.closeOutput();
748 
749 				XInputStream xIn = xStream.getInputStream();
750 				if ( xIn != null )
751 					xIn.closeInput();
752 			}
753 			else
754 				Error( "Can't close TempFile!" );
755 		}
756 		catch( Exception e )
757 		{
758 			Error( "Can't close TempFile, exception: " + e );
759 		}
760 
761 		return sResult;
762 	}
763 
764 	public boolean copyElementTo( XStorage xSource, String sName, XStorage xDest )
765 	{
766 		// copy element with name sName from xSource to xDest
767 		try
768 		{
769 			xSource.copyElementTo( sName, xDest, sName );
770 		}
771 		catch( Exception e )
772 		{
773 			Error( "Element copying failed, exception: " + e );
774 			return false;
775 		}
776 
777 		return true;
778 	}
779 
780 	public boolean copyElementTo( XStorage xSource, String sName, XStorage xDest, String sTargetName )
781 	{
782 		// copy element with name sName from xSource to xDest
783 		try
784 		{
785 			xSource.copyElementTo( sName, xDest, sTargetName );
786 		}
787 		catch( Exception e )
788 		{
789 			Error( "Element copying failed, exception: " + e );
790 			return false;
791 		}
792 
793 		return true;
794 	}
795 
796 	public boolean moveElementTo( XStorage xSource, String sName, XStorage xDest )
797 	{
798 		// move element with name sName from xSource to xDest
799 		try
800 		{
801 			xSource.moveElementTo( sName, xDest, sName );
802 		}
803 		catch( Exception e )
804 		{
805 			Error( "Element moving failed, exception: " + e );
806 			return false;
807 		}
808 
809 		return true;
810 	}
811 
812 	public boolean renameElement( XStorage xStorage, String sOldName, String sNewName )
813 	{
814 		// rename element with name sOldName to sNewName
815 		try
816 		{
817 			xStorage.renameElement( sOldName, sNewName );
818 		}
819 		catch( Exception e )
820 		{
821 			Error( "Element renaming failed, exception: " + e );
822 			return false;
823 		}
824 
825 		return true;
826 	}
827 
828 	public boolean removeElement( XStorage xStorage, String sName )
829 	{
830 		// remove element with name sName
831 		try
832 		{
833 			xStorage.removeElement( sName );
834 		}
835 		catch( Exception e )
836 		{
837 			Error( "Element removing failed, exception: " + e );
838 			return false;
839 		}
840 
841 		return true;
842 	}
843 
844 	public XStream OpenStream( XStorage xStorage,
845 								String sStreamName,
846 								int nMode )
847 	{
848 		// open substream element
849 		XStream xSubStream = null;
850 		try
851 		{
852 			Object oSubStream = xStorage.openStreamElement( sStreamName, nMode );
853 			xSubStream = (XStream) UnoRuntime.queryInterface( XStream.class, oSubStream );
854 			if ( xSubStream == null )
855 				Error( "Can't create substream '" + sStreamName + "'!" );
856 		}
857 		catch( Exception e )
858 		{
859 			Error( "Can't create substream '" + sStreamName + "', exception : " + e + "!" );
860 		}
861 
862 		return xSubStream;
863 	}
864 
865 	public boolean cantOpenStorage( XStorage xStorage, String sName )
866 	{
867 		// try to open an opened substorage, open call must fail
868 		try
869 		{
870 			Object oDummyStorage = xStorage.openStorageElement( sName, ElementModes.READ );
871 			Error( "The trying to reopen opened substorage '" + sName + "' must fail!" );
872 		}
873 		catch( Exception e )
874 		{
875 			return true;
876 		}
877 
878 		return false;
879 	}
880 
881 	public boolean cantOpenStream( XStorage xStorage, String sName, int nMode )
882 	{
883 		// try to open the substream with specified mode must fail
884 		try
885 		{
886 			Object oDummyStream = xStorage.openStreamElement( sName, nMode );
887 			Error( "The trying to open substoream '" + sName + "' must fail!" );
888 		}
889 		catch( Exception e )
890 		{
891 			return true;
892 		}
893 
894 		return false;
895 	}
896 
897 	public XStorage createStorageFromURL(
898 								XSingleServiceFactory xFactory,
899 								String aURL,
900 								int nMode )
901 	{
902 		XStorage xResult = null;
903 
904 		try
905 		{
906 			PropertyValue[] aAddArgs = new PropertyValue[1];
907 			aAddArgs[0] = new PropertyValue();
908 			aAddArgs[0].Name = "StorageFormat";
909 			aAddArgs[0].Value = "OFOPXMLFormat";
910 
911 			Object pArgs[] = new Object[3];
912 			pArgs[0] = (Object) aURL;
913 			pArgs[1] = new Integer( nMode );
914 			pArgs[2] = (Object) aAddArgs;
915 
916 			Object oTempStorage = xFactory.createInstanceWithArguments( pArgs );
917 			xResult = (XStorage) UnoRuntime.queryInterface( XStorage.class, oTempStorage );
918 		}
919 		catch( Exception e )
920 		{
921 			Error( "Can't create storage from URL, exception: " + e );
922 			return null;
923 		}
924 
925 		if ( xResult == null )
926 			Error( "Can't create storage from URL!" );
927 
928 		return xResult;
929 	}
930 
931 	public XStorage createStorageFromStream(
932 								XSingleServiceFactory xFactory,
933 								XStream xStream,
934 								int nMode )
935 	{
936 		XStorage xResult = null;
937 
938 		try
939 		{
940 			PropertyValue[] aAddArgs = new PropertyValue[1];
941 			aAddArgs[0] = new PropertyValue();
942 			aAddArgs[0].Name = "StorageFormat";
943 			aAddArgs[0].Value = "OFOPXMLFormat";
944 
945 			Object pArgs[] = new Object[3];
946 			pArgs[0] = (Object) xStream;
947 			pArgs[1] = new Integer( nMode );
948 			pArgs[2] = (Object) aAddArgs;
949 
950 			Object oTempStorage = xFactory.createInstanceWithArguments( pArgs );
951 			xResult = (XStorage) UnoRuntime.queryInterface( XStorage.class, oTempStorage );
952 		}
953 		catch( Exception e )
954 		{
955 			Error( "Can't create storage from stream, exception: " + e );
956 			return null;
957 		}
958 
959 		if ( xResult == null )
960 			Error( "Can't create storage from stream!" );
961 
962 		return xResult;
963 	}
964 
965 	public XStorage createStorageFromInputStream(
966 								XSingleServiceFactory xFactory,
967 								XInputStream xInStream )
968 	{
969 		XStorage xResult = null;
970 
971 		try
972 		{
973 			PropertyValue[] aAddArgs = new PropertyValue[1];
974 			aAddArgs[0] = new PropertyValue();
975 			aAddArgs[0].Name = "StorageFormat";
976 			aAddArgs[0].Value = "OFOPXMLFormat";
977 
978 			Object pArgs[] = new Object[3];
979 			pArgs[0] = (Object) xInStream;
980 			pArgs[1] = new Integer( ElementModes.READ );
981 			pArgs[2] = (Object) aAddArgs;
982 
983 			Object oTempStorage = xFactory.createInstanceWithArguments( pArgs );
984 			xResult = (XStorage) UnoRuntime.queryInterface( XStorage.class, oTempStorage );
985 		}
986 		catch( Exception e )
987 		{
988 			Error( "Can't create storage from input stream, exception: " + e );
989 			return null;
990 		}
991 
992 		if ( xResult == null )
993 			Error( "Can't create storage from input stream!" );
994 
995 		return xResult;
996 	}
997 
998 	public XStorage createTempStorage( XMultiServiceFactory xMSF, XSingleServiceFactory xFactory )
999 	{
1000 		// create a temporary storage
1001 		XStorage xResult = null;
1002 		XStream xStream = CreateTempFileStream( xMSF );
1003 		if ( xStream == null )
1004 		{
1005 			Error( "Can't create temp file stream!" );
1006 			return null;
1007 		}
1008 
1009 		try
1010 		{
1011 			xResult = createStorageFromStream( xFactory, xStream, ElementModes.WRITE );
1012 		}
1013 		catch( Exception e )
1014 		{
1015 			Error( "Can't create temp storage, exception: " + e );
1016 		}
1017 
1018 		return xResult;
1019 	}
1020 
1021 	public XStorage cloneStorage( XMultiServiceFactory xMSF, XSingleServiceFactory xFactory, XStorage xStorage )
1022 	{
1023 		// create a copy of a last commited version of specified storage
1024 		XStorage xResult = null;
1025 		try
1026 		{
1027 			xResult = createTempStorage( xMSF, xFactory );
1028 			if ( xResult != null )
1029 				xStorage.copyLastCommitTo( xResult );
1030 		}
1031 		catch( Exception e )
1032 		{
1033 			Error( "Can't clone storage, exception: " + e );
1034 			return null;
1035 		}
1036 
1037 		return xResult;
1038 	}
1039 
1040 	public XStorage cloneSubStorage( XMultiServiceFactory xMSF, XSingleServiceFactory xFactory, XStorage xStorage, String sName )
1041 	{
1042 		// create a copy of a last commited version of specified substorage
1043 		XStorage xResult = null;
1044 		try
1045 		{
1046 			xResult = createTempStorage( xMSF, xFactory );
1047 			if ( xResult != null )
1048 				xStorage.copyStorageElementLastCommitTo( sName, xResult );
1049 		}
1050 		catch( Exception e )
1051 		{
1052 			Error( "Can't clone substorage '" + sName + "', exception: " + e );
1053 			return null;
1054 		}
1055 
1056 		return xResult;
1057 	}
1058 
1059 	public XStream cloneSubStream( XStorage xStorage, String sName )
1060 	{
1061 		// clone existing substream
1062 		try
1063 		{
1064 			XStream xStream = xStorage.cloneStreamElement( sName );
1065 			return xStream;
1066 		}
1067 		catch( Exception e )
1068 		{
1069 			Error( "Can't clone substream '" + sName + "', exception: " + e );
1070 		}
1071 
1072 		return null;
1073 	}
1074 
1075 	public void Error( String sError )
1076 	{
1077 		m_aLogWriter.println( m_sTestPrefix + "Error: " + sError );
1078 	}
1079 
1080 	public void Message( String sMessage )
1081 	{
1082 		m_aLogWriter.println( m_sTestPrefix + sMessage );
1083 	}
1084 
1085 	public void PrintRelations( StringPair[][] aRels )
1086 	{
1087 		m_aLogWriter.println( "========" );
1088 		for ( int nInd1 = 0; nInd1 < aRels.length; nInd1++ )
1089 		{
1090 			for ( int nInd2 = 0; nInd2 < aRels[nInd1].length; nInd2++ )
1091 			{
1092 				m_aLogWriter.println( "\"" + aRels[nInd1][nInd2].First + "\" = \"" + aRels[nInd1][nInd2].Second + "\", " );
1093 			}
1094 			m_aLogWriter.println( "========" );
1095 		}
1096 	}
1097 }
1098 
1099