1 /*
2  * This file is part of the LibreOffice project.
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  *
8  * This file incorporates work covered by the following license notice:
9  *
10  *   Licensed to the Apache Software Foundation (ASF) under one or more
11  *   contributor license agreements. See the NOTICE file distributed
12  *   with this work for additional information regarding copyright
13  *   ownership. The ASF licenses this file to you under the Apache
14  *   License, Version 2.0 (the "License"); you may not use this file
15  *   except in compliance with the License. You may obtain a copy of
16  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
17  */
18 
19  package complex.loadAllDocuments;
20 
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.fail;
23 import helper.URLHelper;
24 
25 import java.io.File;
26 import java.io.InputStreamReader;
27 import java.util.ArrayList;
28 import java.util.Iterator;
29 import java.util.List;
30 
31 import org.junit.After;
32 import org.junit.AfterClass;
33 import org.junit.Before;
34 import org.junit.BeforeClass;
35 import org.junit.Test;
36 import org.openoffice.test.OfficeConnection;
37 import org.openoffice.test.OfficeFileUrl;
38 
39 import com.sun.star.beans.PropertyValue;
40 import com.sun.star.frame.FrameSearchFlag;
41 import com.sun.star.frame.XComponentLoader;
42 import com.sun.star.frame.XFrame;
43 import com.sun.star.frame.XStorable;
44 import com.sun.star.io.XInputStream;
45 import com.sun.star.lang.XComponent;
46 import com.sun.star.lang.XMultiServiceFactory;
47 import com.sun.star.ucb.XSimpleFileAccess;
48 import com.sun.star.uno.UnoRuntime;
49 import com.sun.star.util.XCloseable;
50 
51 
52 /** @short  Check the interface method XComponentLoader.loadComponentFromURL()
53 
54     @descr  A prerequisite for this test is a server which allows access to files
55             that will be loaded via three different access methods:
56             <ul>
57                 <li>1. nfs (mounted directory / mapped network drive)</li>
58                 <li>2. ftp</li>
59                 <li>3. http</li>
60             </ul>
61             <p>
62             The test will look for a list of files from the <i>TestDocumentPath</i>
63             on and load these files from the mounted directory, via ftp and http.
64             The parameters for this have to be "ftp_access" and "http_access".
65             If they are not given, tests for ftp and http will fail.
66 
67     @todo   We need a further test for accessing UNC paths on windows!
68  */
69 public class CheckXComponentLoader
70 {
71 
72     // some const
73 
74     /** used to classify the result of a loadComponentFromURL() request. */
75     private static final int RESULT_VALID_DOC                = 1;
76     private static final int RESULT_EMPTY_DOC                = 2;
77     private static final int RESULT_ILLEGALARGUMENTEXCEPTION = 3;
78     private static final int RESULT_IOEXCEPTION              = 4;
79     private static final int RESULT_RUNTIMEEXCEPTION         = 5;
80     private static final int RESULT_EXCEPTION                = 6;
81 
82     /** used for testing password protected files. */
83     private static final String SUFFIX_PASSWORD_TEMPFILE = "password_";
84     private static final String PREFIX_PASSWORD_TEMPFILE = ".sxw";
85     private static final String DEFAULT_PASSWORD         = "DefaultPasswordForComponentLoaderTest";
86 
87 
88     // member
89 
90     /** provides XComponentLoader interface too. */
91     private XFrame m_xFrame = null;
92 
93     /** will be set to xDesktop OR xFrame. */
94     private XComponentLoader m_xLoader = null;
95 
96     /** can be used to open local files as stream. */
97     private XSimpleFileAccess m_xStreamProvider = null;
98 
99     /** directory for creating temp. files. */
100     private String m_sTempPath = null;
101 
102     /** directory for searching files to load */
103     private String m_sTestDocPath = null;
104 
105     /** files of m_sTestDocPath to test. */
106     private static ArrayList<String> m_lTestFiles = null;
107 
108 
109     // test environment
110 
111 
112     /** @short  Create the environment for following tests.
113 
114         @descr  Use either a component loader from desktop or
115                 from frame
116      */
before()117     @Before public void before() throws Exception
118     {
119         // get uno service manager from global test environment
120         /* points to the global uno service manager. */
121         XMultiServiceFactory xMSF = getMSF();
122 
123         // create stream provider
124         m_xStreamProvider = UnoRuntime.queryInterface(XSimpleFileAccess.class, xMSF.createInstance("com.sun.star.ucb.SimpleFileAccess"));
125 
126         // create desktop instance
127         /* provides XComponentLoader interface. */
128         XFrame xDesktop = UnoRuntime.queryInterface(XFrame.class, xMSF.createInstance("com.sun.star.frame.Desktop"));
129 
130         // create frame instance
131         m_xFrame = xDesktop.findFrame("testFrame_componentLoader",
132                                         FrameSearchFlag.TASKS | FrameSearchFlag.CREATE);
133         assertNotNull("Couldn't create test frame.", m_xFrame);
134 
135         // define default loader for testing
136         // TODO think about using of bot loader instances!
137         m_xLoader = UnoRuntime.queryInterface(XComponentLoader.class, xDesktop);
138         assertNotNull("Desktop service doesn't support needed component loader interface.", m_xLoader);
139 
140         // get temp path for this environment
141         final String tempDirURL = util.utils.getOfficeTemp/*Dir*/(getMSF());
142         m_sTempPath = graphical.FileHelper.getSystemPathFromFileURL(tempDirURL);
143         // m_sTempPath = "."+fs_sys;
144 
145         // get all files from the given directory
146         // TODO URLHelper should ignore directories!
147         m_lTestFiles = new ArrayList<String>();
148         final String sTestDocURL = OfficeFileUrl.getAbsolute(new File("testdocuments"));
149         m_sTestDocPath = graphical.FileHelper.getSystemPathFromFileURL(sTestDocURL);
150         File           aBaseDir        = new File(m_sTestDocPath);
151         List<File>     lDirContent     = URLHelper.getSystemFilesFromDir(aBaseDir.getPath());
152         Iterator<File> lList           = lDirContent.iterator();
153         int            nBasePathLength = m_sTestDocPath.length();
154         while(lList.hasNext())
155         {
156             File aFile = lList.next();
157 
158             // ignore broken links and directories at all
159             if (
160                 (!aFile.exists()) ||
161                 (!aFile.isFile())
162                )
163             {
164                 continue;
165             }
166 
167             String sCompletePath = aFile.getAbsolutePath();
168             String sSubPath      = sCompletePath.substring(nBasePathLength);
169 
170             m_lTestFiles.add(sSubPath);
171         }
172     }
173 
174 
175     /** @short  close the environment.
176      */
after()177     @After public void after() throws Exception
178     {
179         XCloseable xClose = UnoRuntime.queryInterface(XCloseable.class, m_xFrame);
180         xClose.close(false);
181 
182         m_xFrame  = null;
183         m_xLoader = null;
184     }
185 
186 
187     /** @short  Look for files in the given directory for loading.
188      */
checkUsingOfMediaDescriptor()189     @Test public void checkUsingOfMediaDescriptor()
190     {
191         InteractionHandler xHandler   = new InteractionHandler();
192         StatusIndicator    xIndicator = new StatusIndicator();
193 
194         PropertyValue[] lProps = new PropertyValue[3];
195 
196         lProps[0] = new PropertyValue();
197         lProps[0].Name  = "Hidden";
198         lProps[0].Value = Boolean.TRUE;
199 
200         lProps[1] = new PropertyValue();
201         lProps[1].Name  = "InteractionHandler";
202         lProps[1].Value = xHandler;
203 
204         lProps[2] = new PropertyValue();
205         lProps[2].Name  = "StatusIndicator";
206         lProps[2].Value = xIndicator;
207 
208         Iterator<String> aSnapshot = m_lTestFiles.iterator();
209         while (aSnapshot.hasNext())
210         {
211             File   aSysFile = new File(m_sTestDocPath, aSnapshot.next());
212             String sURL     = URLHelper.getFileURLFromSystemPath(aSysFile);
213 
214             loadURL(m_xLoader, RESULT_VALID_DOC, sURL, "_blank", 0, lProps);
215             // It's not needed to reset this using states!
216             // Its done internally ...
217             if (!xIndicator.wasUsed())
218             {
219                 System.out.println("External progress was not used for loading.");
220             }
221             if (xHandler.wasUsed())
222             {
223                 System.out.println("External interaction handler was not used for loading.");
224             }
225         }
226     }
227 
228 
229     /** TODO document me and move this method to a more global helper! */
impl_getTempFileName(String sTempPath, String sSuffix , String sPrefix )230     private String impl_getTempFileName(String sTempPath,
231                                         String sSuffix  ,
232                                         String sPrefix  )
233     {
234         File aDir = new File(sTempPath);
235         aDir.mkdirs();
236 
237     // TODO: create a temp file which not exist!
238         for (int i=0; i<999999; ++i)
239         {
240             File aTempFile = new File(aDir, sSuffix+i+sPrefix);
241             if (!aTempFile.exists())
242             {
243                 return aTempFile.getAbsolutePath();
244             }
245         }
246 
247         fail("Seems that all temp file names are currently in use!");
248         return null;
249     }
250 
251 
252     /** TODO document me and move this method to a more global helper! */
impl_createTempOfficeDocument(XComponentLoader xLoader , String sSourceURL, String sTargetURL, String sFilter , String sPassword )253     private void impl_createTempOfficeDocument(XComponentLoader xLoader   ,
254                                                String           sSourceURL,
255                                                String           sTargetURL,
256                                                String           sFilter   ,
257                                                String           sPassword ) throws Exception
258     {
259         PropertyValue[] lLoadProps = new PropertyValue[1];
260 
261         lLoadProps[0] = new PropertyValue();
262         lLoadProps[0].Name = "Hidden";
263         lLoadProps[0].Value = Boolean.TRUE;
264 
265         PropertyValue[] lSaveProps = new PropertyValue[3];
266 
267         lSaveProps[0] = new PropertyValue();
268         lSaveProps[0].Name = "FilterName";
269         lSaveProps[0].Value = sFilter;
270 
271         lSaveProps[1] = new PropertyValue();
272         lSaveProps[1].Name = "PassWord";
273         lSaveProps[1].Value = sPassword;
274 
275         lSaveProps[2] = new PropertyValue();
276         lSaveProps[2].Name = "Overwrite";
277         lSaveProps[2].Value = Boolean.TRUE;
278 
279         XComponent xDoc = null;
280         // load it
281         xDoc = xLoader.loadComponentFromURL(sSourceURL, "_blank", 0, lLoadProps);
282         assertNotNull("Could create office document, which should be saved as temp one.", xDoc);
283 
284         // save it as temp file
285         XStorable xStore = UnoRuntime.queryInterface(XStorable.class, xDoc);
286         xStore.storeAsURL(sTargetURL, lSaveProps);
287 
288         // Don't forget to close this file. Otherwise the temp file is locked!
289         XCloseable xClose = UnoRuntime.queryInterface(XCloseable.class, xDoc);
290         xClose.close(false);
291     }
292 
293 
294     /** @short  Check the password handling.
295 
296         @descr  The used password is the one given
297                 as password for the ftp connection,
298                 or - if none given a default one.
299      */
checkLoadingWithPassword()300     @Test public void checkLoadingWithPassword() throws Exception
301     {
302         String sTempFile = impl_getTempFileName(m_sTempPath, SUFFIX_PASSWORD_TEMPFILE, PREFIX_PASSWORD_TEMPFILE);
303         File   aTestFile = new File(sTempFile);
304         String sTestURL  = URLHelper.getFileURLFromSystemPath(aTestFile);
305 
306         impl_createTempOfficeDocument(m_xLoader, "private:factory/swriter", sTestURL, "StarOffice XML (Writer)", DEFAULT_PASSWORD);
307 
308         PropertyValue[] lArgs1 = new PropertyValue[2];
309 
310         lArgs1[0] = new PropertyValue();
311         lArgs1[0].Name  = "Hidden";
312         lArgs1[0].Value = Boolean.TRUE;
313 
314         lArgs1[1] = new PropertyValue();
315         lArgs1[1].Name  = "Password";
316         lArgs1[1].Value = DEFAULT_PASSWORD;
317 
318         PropertyValue[] lArgs2 = new PropertyValue[1];
319 
320         lArgs2[0] = new PropertyValue();
321         lArgs2[0].Name  = "Hidden";
322         lArgs2[0].Value = Boolean.TRUE;
323 
324         loadURL(m_xLoader, RESULT_VALID_DOC, sTestURL, "_blank", 0, lArgs1);
325 // TODO: wrong?        loadURL(m_xLoader, RESULT_EMPTY_DOC, sTestURL, "_blank", 0, lArgs2);
326     }
327 
328     /**
329      * Check URL encoding. The first filename that matches "*.sxw"
330      * is used as source for several encodings.
331      */
checkURLEncoding()332     @Test public void checkURLEncoding() throws Exception {
333         PropertyValue[] lProps = new PropertyValue[1];
334 
335         lProps[0] = new PropertyValue();
336         lProps[0].Name = "Hidden";
337         lProps[0].Value = Boolean.TRUE;
338 
339         // first get encoding of this system
340         InputStreamReader in = new InputStreamReader(System.in);
341         String sSystemEncoding = in.getEncoding();
342 
343         System.out.println("This system's encoding: " + sSystemEncoding);
344 
345         assertNotNull("Found an empty directory. There are no files for testing.", m_lTestFiles);
346 
347 
348         // get a file name as byte array
349         Iterator<String> aSnapshot = m_lTestFiles.iterator();
350         byte[] baURL = null;
351 
352         while (aSnapshot.hasNext()) {
353             File aFile = new File(m_sTestDocPath, aSnapshot.next());
354             String sFile = URLHelper.getFileURLFromSystemPath(aFile);
355 
356             // take the first sxw file as stream
357             if (sFile.endsWith(".sxw")) {
358                 baURL = sFile.getBytes();
359 
360                 break;
361             }
362         }
363 
364         assertNotNull("Found no file to load. Cannot test.", baURL);
365 
366         //construct several different encoded strings
367         String[] sEncoding = new String[] {
368             "US-ASCII", "TRUE", // us ascii encoding
369             "ISO-8859-1", "TRUE", // iso encoding
370             "UTF-8", "TRUE", // 8 bit utf encoding
371             "UTF-16BE", "FALSE", // 16 bit big endian utf
372             "UTF-16LE", "FALSE", // 16 bit little endian utf
373             "UTF-16", "FALSE" // 16 bit, order specified by byte order mark
374 
375         };
376 
377         for (int i = 0; i < sEncoding.length; i = i + 2) {
378             String encURL = new String(baURL, sEncoding[i]);
379             System.out.println("ENC[" + sEncoding[i] + "]");
380 
381             if (sEncoding[i + 1].equals("TRUE")) {
382                 loadURL(m_xLoader, RESULT_VALID_DOC, encURL, "_blank", 0,
383                         lProps);
384             } else {
385                 //with cws_loadenv01 changed to IllegalArgumentException
386                 loadURL(m_xLoader, RESULT_ILLEGALARGUMENTEXCEPTION, encURL, "_blank", 0,
387                         lProps);
388             }
389         }
390     }
391 
392     /** TODo document me
393      */
checkStreamLoading()394     @Test public void checkStreamLoading() throws Exception
395     {
396         PropertyValue[] lProps = new PropertyValue[2];
397 
398         lProps[0] = new PropertyValue();
399         lProps[0].Name = "Hidden";
400         lProps[0].Value = Boolean.TRUE;
401 
402         lProps[1] = new PropertyValue();
403         lProps[1].Name = "InputStream";
404 
405         Iterator<String> aSnapshot = m_lTestFiles.iterator();
406         while (aSnapshot.hasNext())
407         {
408             File   aFile = new File(m_sTestDocPath, aSnapshot.next());
409             String sURL  = URLHelper.getFileURLFromSystemPath(aFile);
410 
411             XInputStream xStream = m_xStreamProvider.openFileRead(sURL);
412             lProps[1].Value = xStream;
413 
414             // check different version of "private:stream" URL!
415             loadURL(m_xLoader, RESULT_VALID_DOC, "private:stream" , "_blank", 0, lProps);
416         }
417     }
418 
419     /**
420      * Loads one URL with the given parameters using the method
421      * loadComponentFromURL(). Further it's possible to specify, which result is
422      * required and we check internally if it was reached. Logging of errors
423      * and success stories is done inside this method too. Of course we catch
424      * all possible exceptions and try to leave the office without any forgotten
425      * but opened documents.
426      */
loadURL(XComponentLoader xLoader, int nRequiredResult, String sURL, String sTarget, int nFlags, PropertyValue[] lProps)427     private void loadURL(XComponentLoader xLoader, int nRequiredResult,
428                          String sURL, String sTarget, int nFlags,
429                          PropertyValue[] lProps) {
430         int nResult = RESULT_EMPTY_DOC;
431         XComponent xDoc = null;
432 
433         try {
434             xDoc = xLoader.loadComponentFromURL(sURL, sTarget, nFlags,
435                                                      lProps);
436 
437             if (xDoc != null) {
438                 nResult = RESULT_VALID_DOC;
439             } else {
440                 nResult = RESULT_EMPTY_DOC;
441             }
442         } catch (com.sun.star.lang.IllegalArgumentException exArgument) {
443             nResult = RESULT_ILLEGALARGUMENTEXCEPTION;
444         } catch (com.sun.star.io.IOException exIO) {
445             nResult = RESULT_IOEXCEPTION;
446         } catch (com.sun.star.uno.RuntimeException exRuntime) {
447             nResult = RESULT_RUNTIMEEXCEPTION;
448         } catch (Exception e) {
449             nResult = RESULT_EXCEPTION;
450         }
451 
452         try {
453             if (xDoc != null) {
454                 xDoc.dispose();
455                 xDoc = null;
456             }
457         } catch (com.sun.star.uno.RuntimeException exClosing) {
458             System.out.println("exception during disposing of a document found!" +
459                         " Doesn't influence test - but should be checked.");
460         }
461 
462         String sMessage = "URL[\"" + sURL + "\"]";
463 
464         if (nResult == nRequiredResult) {
465             System.out.println(sMessage + " expected result [" +
466                         convertResult2String(nResult) + "] ");
467         } else {
468             fail(sMessage + " unexpected result [" +
469                    convertResult2String(nResult) + "] " +
470                    "\nrequired was [" +
471                    convertResult2String(nRequiredResult) + "]" +
472                    "\nwe got       [" + convertResult2String(nResult) + "]"
473                    );
474         }
475     }
476 
477     /**
478      * it match the int result value to a string, which can be used for logging
479      */
convertResult2String(int nResult)480     private static String convertResult2String(int nResult) {
481         switch (nResult) {
482         case RESULT_VALID_DOC:
483             return "VALID_DOC";
484 
485         case RESULT_EMPTY_DOC:
486             return "EMPTY_DOC";
487 
488         case RESULT_ILLEGALARGUMENTEXCEPTION:
489             return "ILLEGALARGUMENTEXCEPTION";
490 
491         case RESULT_IOEXCEPTION:
492             return "IOEXCEPTION";
493 
494         case RESULT_RUNTIMEEXCEPTION:
495             return "RUNTIMEEXCEPTION";
496 
497         case RESULT_EXCEPTION:
498             return "ALLOTHEREXCEPTION";
499         }
500 
501         return "unknown!";
502     }
503 
getMSF()504     private XMultiServiceFactory getMSF()
505     {
506         return UnoRuntime.queryInterface(XMultiServiceFactory.class, connection.getComponentContext().getServiceManager());
507     }
508 
509     // setup and close connections
510     @BeforeClass
setUpConnection()511     public static void setUpConnection() throws Exception
512     {
513         System.out.println("setUpConnection()");
514         connection.setUp();
515     }
516 
517     @AfterClass
tearDownConnection()518     public static void tearDownConnection()
519             throws InterruptedException, com.sun.star.uno.Exception
520     {
521         System.out.println("tearDownConnection()");
522         connection.tearDown();
523     }
524     private static final OfficeConnection connection = new OfficeConnection();
525 
526 }
527