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 complex.sfx2;
25 
26 
27 import complex.sfx2.tools.TestDocument;
28 import com.sun.star.uno.UnoRuntime;
29 import com.sun.star.uno.XComponentContext;
30 import com.sun.star.lang.XInitialization;
31 
32 import com.sun.star.lang.XMultiServiceFactory;
33 import com.sun.star.lang.Locale;
34 import com.sun.star.lang.EventObject;
35 import com.sun.star.util.Date;
36 import com.sun.star.util.DateTime;
37 import com.sun.star.util.Time;
38 import com.sun.star.util.Duration;
39 import com.sun.star.util.XModifyListener;
40 import com.sun.star.util.XModifyBroadcaster;
41 import com.sun.star.beans.XPropertyContainer;
42 import com.sun.star.beans.XPropertySet;
43 import com.sun.star.beans.PropertyValue;
44 import com.sun.star.beans.NamedValue;
45 import com.sun.star.beans.PropertyAttribute;
46 import com.sun.star.beans.UnknownPropertyException;
47 import com.sun.star.beans.IllegalTypeException;
48 
49 import com.sun.star.document.XDocumentProperties;
50 
51 import org.junit.After;
52 import org.junit.AfterClass;
53 import org.junit.BeforeClass;
54 import org.junit.Test;
55 import org.openoffice.test.OfficeConnection;
56 import static org.junit.Assert.*;
57 
58 /**
59  * Test case for the service com.sun.star.document.DocumentProperties.
60  * Currently, this service is implemented in
61  * sfx2/source/doc/SfxDocumentMetaData.cxx.
62  *
63  * @author mst
64  */
65 public class DocumentProperties
66 {
cleanup()67     @After public void cleanup() {
68                 // nothing to do
69     }
70 
71     // for testing modifications
72     class Listener implements XModifyListener {
73         private boolean m_Called;
74 
Listener()75         Listener() {
76             m_Called = false;
77         }
78 
reset()79         public boolean reset() {
80             boolean oldCalled = m_Called;
81             m_Called = false;
82             return oldCalled;
83         }
84 
modified(EventObject e)85         public void modified(EventObject e) {
86             m_Called = true;
87         }
88 
disposing(EventObject e)89         public void disposing(EventObject e) {
90         }
91     }
92 
check()93     @Test public void check() {
94         try {
95             XMultiServiceFactory xMSF = getMSF();
96             assertNotNull("could not create MultiServiceFactory.", xMSF);
97             XPropertySet xPropertySet = UnoRuntime.queryInterface(XPropertySet.class, xMSF);
98             Object defaultCtx = xPropertySet.getPropertyValue("DefaultContext");
99             XComponentContext xContext = UnoRuntime.queryInterface(XComponentContext.class, defaultCtx);
100             assertNotNull("could not get component context.", xContext);
101 
102             // TODO: Path to temp
103             String temp = util.utils.getOfficeTemp/*Dir*/(xMSF);
104             System.out.println("tempdir: " + temp);
105 
106             PropertyValue[] noArgs = { };
107             PropertyValue mimetype = new PropertyValue();
108             mimetype.Name = "MediaType";
109             mimetype.Value = "application/vnd.oasis.opendocument.text";
110             PropertyValue[] mimeArgs = { mimetype };
111 //                new Any("application/vnd.oasis.opendocument.text")) };
112             PropertyValue cfile = new PropertyValue();
113             cfile.Name = "URL";
114             cfile.Value = temp + "EMPTY.odt";
115             PropertyValue[] mimeEmptyArgs = { mimetype, cfile };
116 
117             System.out.println("Creating service DocumentProperties...");
118 
119             Object oDP =
120 //                xMSF.createInstanceWithContext(
121 //                    "com.sun.star.document.DocumentProperties", xContext);
122                 xMSF.createInstance("com.sun.star.document.DocumentProperties");
123             XDocumentProperties xDP = UnoRuntime.queryInterface(XDocumentProperties.class, oDP);
124 
125             System.out.println("...done");
126 
127 
128             System.out.println("Checking initialize ...");
129 
130             XDocumentProperties xDP2 = UnoRuntime.queryInterface(XDocumentProperties.class, xMSF.createInstance("com.sun.star.document.DocumentProperties"));
131             XInitialization xInit = UnoRuntime.queryInterface(XInitialization.class, xDP2);
132             xInit.initialize(new Object[] { });
133 
134             System.out.println("...done");
135 
136             System.out.println("Checking storing default-initialized meta data ...");
137 
138 //            xDP2.storeToMedium(temp + "EMPTY.odt", mimeArgs);
139             xDP2.storeToMedium("", mimeEmptyArgs);
140 
141             System.out.println("...done");
142 
143             System.out.println("Checking loading default-initialized meta data ...");
144 
145 //            xDP2.loadFromMedium(temp + "EMPTY.odt", noArgs);
146             xDP2.loadFromMedium("", mimeEmptyArgs);
147             assertTrue ("Author", "".equals(xDP2.getAuthor()));
148 
149             System.out.println("...done");
150 
151             System.out.println("(Not) Checking preservation of custom meta data ...");
152 
153             xDP2.loadFromMedium(TestDocument.getUrl("CUSTOM.odt"),
154                 noArgs);
155             assertTrue ("Author", "".equals(xDP2.getAuthor()));
156             xDP2.storeToMedium(temp + "CUSTOM.odt", mimeArgs);
157 
158             //FIXME: now what? comparing for binary equality seems useless
159             // we could unzip the written file and grep for the custom stuff
160             // but would that work on windows...
161 
162             System.out.println("...done");
163 
164             System.out.println("Checking loading from test document...");
165 
166             String file = TestDocument.getUrl("TEST.odt");
167             xDP.loadFromMedium(file, noArgs);
168 /*            XInputStream xStream =
169                 new StreamSimulator("./testdocuments/TEST.odt", true, param);
170             Object oSF =
171                 xMSF.createInstance("com.sun.star.embed.StorageFactory");
172             XSingleServiceFactory xSF = (XSingleServiceFactory)
173                 UnoRuntime.queryInterface(XSingleServiceFactory.class, oSF);
174             Object oStor = xSF.createInstanceWithArguments(
175                 new Object[] { xStream });
176             XStorage xStor = (XStorage) UnoRuntime.queryInterface(
177                 XStorage.class, oStor);
178             xDP.loadFromStorage(xStor);*/
179 
180             System.out.println("...done");
181 
182             System.out.println("Checking meta-data import...");
183 
184             assertTrue("Author", "Karl-Heinz Mustermann".equals(xDP.getAuthor()));
185             assertTrue("Generator",
186             "StarOffice/8$Solaris_x86 OpenOffice.org_project/680m232$Build-9227"
187                 .equals(xDP.getGenerator()));
188             assertTrue("CreationDate", 2007 == xDP.getCreationDate().Year);
189             assertTrue("Title", "Urgent Memo".equals(xDP.getTitle()));
190             assertTrue("Subject", "Wichtige Mitteilung".equals(xDP.getSubject()));
191             assertTrue("Description",
192                 "Modern internal company memorandum in full-blocked style"
193                 .equals(xDP.getDescription()));
194 //            assertTrue("Language", "".equals(xDP.getLanguage()));
195             assertTrue("ModifiedBy",
196                 "Karl-Heinz Mustermann".equals(xDP.getModifiedBy()));
197             assertTrue("ModificationDate", 10 == xDP.getModificationDate().Month);
198             assertTrue("PrintedBy",
199                 "Karl-Heinz Mustermann".equals(xDP.getPrintedBy()));
200             assertTrue("PrintDate", 29 == xDP.getPrintDate().Day);
201             assertTrue("TemplateName",
202                 "Modern Memo".equals(xDP.getTemplateName()));
203             assertTrue("TemplateURL",
204                 xDP.getTemplateURL().endsWith("memmodern.ott"));
205             assertTrue("TemplateDate", 17 == xDP.getTemplateDate().Hours);
206             assertTrue("AutoloadURL", "../TEST.odt".equals(xDP.getAutoloadURL()));
207             assertTrue("AutoloadSecs", 0 == xDP.getAutoloadSecs());
208             assertTrue("DefaultTarget", "_blank".equals(xDP.getDefaultTarget()));
209             assertTrue("EditingCycles", 3 == xDP.getEditingCycles());
210             assertTrue("EditingDuration", 320 == xDP.getEditingDuration());
211 
212             String[] kws = xDP.getKeywords();
213             assertTrue("Keywords", fromArray(kws).containsAll(
214                     fromArray(new Object[] { "Asien", "Memo", "Reis" })));
215 
216             NamedValue[] ds = xDP.getDocumentStatistics();
217 /*            for (int i = 0; i < ds.length; ++i) {
218                 System.out.println("nv: " + ds[i].Name + " " + ds[i].Value);
219             }
220             NamedValue nv1 = new NamedValue("WordCount", new Integer(23));
221             NamedValue nv2 = new NamedValue("WordCount", new Integer(23));
222             System.out.println("eq: " + nv1.equals(nv2)); // grrr, this is false...
223 */
224             assertTrue("DocumentStatistics:WordCount", containsNV(ds,
225                         new NamedValue("WordCount", new Integer(23))));
226             assertTrue("DocumentStatistics:PageCount", containsNV(ds,
227                         new NamedValue("PageCount", new Integer(1))));
228 
229             XPropertyContainer udpc = xDP.getUserDefinedProperties();
230             XPropertySet udps = UnoRuntime.queryInterface( XPropertySet.class, udpc );
231             assertTrue("UserDefined 1", "Dies ist ein wichtiger Hinweis"
232                     .equals(udps.getPropertyValue("Hinweis")));
233             assertTrue("UserDefined 2", ("Kann Spuren von N"
234                 + new String(new byte[] { (byte) 0xc3, (byte) 0xbc }, "UTF-8")
235                 + "ssen enthalten")
236                     .equals(udps.getPropertyValue("Warnung")));
237 
238             System.out.println("...done");
239 
240             System.out.println("Checking meta-data updates...");
241 
242             String str;
243             DateTime dt = new DateTime();
244             Locale l = new Locale();
245             int i;
246 
247             str = "me";
248             xDP.setAuthor(str);
249             assertTrue("setAuthor", str.equals(xDP.getAuthor()));
250             str = "the computa";
251             xDP.setGenerator(str);
252             assertTrue("setGenerator", str.equals(xDP.getGenerator()));
253             dt.Year = 2038;
254             dt.Month = 1;
255             dt.Day = 1;
256             xDP.setCreationDate(dt);
257             assertTrue("setCreationDate", dt.Year == xDP.getCreationDate().Year);
258             str = "El t'itulo";
259             xDP.setTitle(str);
260             assertTrue("setTitle", str.equals(xDP.getTitle()));
261             str = "Ein verkommenes Subjekt";
262             xDP.setSubject(str);
263             assertTrue("setSubject", str.equals(xDP.getSubject()));
264             str = "Este descripci'on no es importante";
265             xDP.setDescription(str);
266             assertTrue("setDescription", str.equals(xDP.getDescription()));
267             l.Language = "en";
268             l.Country = "GB";
269             xDP.setLanguage(l);
270             Locale l2 = xDP.getLanguage();
271             assertTrue("setLanguage Lang", l.Language.equals(l2.Language));
272             assertTrue("setLanguage Cty", l.Country.equals(l2.Country));
273             str = "myself";
274             xDP.setModifiedBy(str);
275             assertTrue("setModifiedBy", str.equals(xDP.getModifiedBy()));
276             dt.Year = 2042;
277             xDP.setModificationDate(dt);
278             assertTrue("setModificationDate",
279                 dt.Year == xDP.getModificationDate().Year);
280             str = "i didnt do it";
281             xDP.setPrintedBy(str);
282             assertTrue("setPrintedBy", str.equals(xDP.getPrintedBy()));
283             dt.Year = 2024;
284             xDP.setPrintDate(dt);
285             assertTrue("setPrintDate", dt.Year == xDP.getPrintDate().Year);
286             str = "blah";
287             xDP.setTemplateName(str);
288             assertTrue("setTemplateName", str.equals(xDP.getTemplateName()));
289             str = "gopher://some-hole-in-the-ground/";
290             xDP.setTemplateURL(str);
291             assertTrue("setTemplateURL", str.equals(xDP.getTemplateURL()));
292             dt.Year = 2043;
293             xDP.setTemplateDate(dt);
294             assertTrue("setTemplateDate", dt.Year == xDP.getTemplateDate().Year);
295             str = "http://nowhere/";
296             xDP.setAutoloadURL(str);
297             assertTrue("setAutoloadURL", str.equals(xDP.getAutoloadURL()));
298             i = 3661; // this might not work (due to conversion via double...)
299             xDP.setAutoloadSecs(i);
300 //            System.out.println("set: " + i + " get: " + xDP.getAutoloadSecs());
301             assertTrue("setAutoloadSecs", i == xDP.getAutoloadSecs());
302             str = "_blank";
303             xDP.setDefaultTarget(str);
304             assertTrue("setDefaultTarget", str.equals(xDP.getDefaultTarget()));
305             i = 42;
306             xDP.setEditingCycles((short) i);
307             assertTrue("setEditingCycles", i == xDP.getEditingCycles());
308             i = 84;
309             xDP.setEditingDuration(i);
310             assertTrue("setEditingDuration", i == xDP.getEditingDuration());
311             str = "";
312 
313             String[] kws2 = new String[] {
314                 "keywordly", "keywordlike", "keywordalicious" };
315             xDP.setKeywords(kws2);
316             kws = xDP.getKeywords();
317             assertTrue("setKeywords", fromArray(kws).containsAll(fromArray(kws2)));
318 
319             NamedValue[] ds2 = new NamedValue[] {
320                     new NamedValue("SyllableCount", new Integer(9)),
321                     new NamedValue("FrameCount", new Integer(2)),
322                     new NamedValue("SentenceCount", new Integer(7)) };
323             xDP.setDocumentStatistics(ds2);
324             ds = xDP.getDocumentStatistics();
325             assertTrue("setDocumentStatistics:SyllableCount", containsNV(ds,
326                         new NamedValue("SyllableCount", new Integer(9))));
327             assertTrue("setDocumentStatistics:FrameCount", containsNV(ds,
328                         new NamedValue("FrameCount", new Integer(2))));
329             assertTrue("setDocumentStatistics:SentenceCount", containsNV(ds,
330                         new NamedValue("SentenceCount", new Integer(7))));
331 
332             System.out.println("...done");
333 
334             System.out.println("Checking user-defined meta-data updates...");
335 
336             // actually, this tests the PropertyBag service
337             // but maybe the DocumentProperties service will be implemented
338             // differently some day...
339             boolean b = true;
340             double d = 3.1415;
341             // note that Time is only supported for backward compatibilty!
342             Time t = new Time();
343             t.Hours = 1;
344             t.Minutes = 16;
345             Date date = new Date();
346             date.Year = 2071;
347             date.Month = 2;
348             date.Day = 3;
349             dt.Year = 2065;
350             Duration dur = new Duration();
351             dur.Negative = true;
352             dur.Years = 1001;
353             dur.Months = 999;
354             dur.Days = 888;
355             dur.Hours = 777;
356             dur.Minutes = 666;
357             dur.Seconds = 555;
358             dur.MilliSeconds = 444;
359 
360             udpc.addProperty("Frobnicate", PropertyAttribute.REMOVEABLE, b);
361             udpc.addProperty("FrobDuration", PropertyAttribute.REMOVEABLE, dur);
362             udpc.addProperty("FrobDuration2", PropertyAttribute.REMOVEABLE, t);
363             udpc.addProperty("FrobEndDate", PropertyAttribute.REMOVEABLE, date);
364             udpc.addProperty("FrobStartTime", PropertyAttribute.REMOVEABLE, dt);
365             udpc.addProperty("Pi", PropertyAttribute.REMOVEABLE, new Double(d));
366             udpc.addProperty("Foo", PropertyAttribute.REMOVEABLE, "bar");
367             udpc.addProperty("Removed", PropertyAttribute.REMOVEABLE, "bar");
368             // #i94175#: empty property name is valid ODF 1.1
369             udpc.addProperty("", PropertyAttribute.REMOVEABLE, "eeeeek");
370             try {
371                 udpc.removeProperty("Info 1");
372                 udpc.removeProperty("Removed");
373             } catch (UnknownPropertyException e) {
374                 fail("removeProperty failed");
375             }
376 
377             try {
378                 udpc.addProperty("Forbidden", PropertyAttribute.REMOVEABLE,
379                     new String[] { "foo", "bar" });
380                 fail("inserting value of non-supported type did not fail");
381             } catch (IllegalTypeException e) {
382                 // ignore
383             }
384 
385             assertTrue("UserDefined bool", new Boolean(b).equals(
386                     udps.getPropertyValue("Frobnicate")));
387             assertTrue("UserDefined duration", eqDuration(dur, (Duration)
388                     udps.getPropertyValue("FrobDuration")));
389             assertTrue("UserDefined time", eqTime(t, (Time)
390                     udps.getPropertyValue("FrobDuration2")));
391             assertTrue("UserDefined date", eqDate(date, (Date)
392                     udps.getPropertyValue("FrobEndDate")));
393             assertTrue("UserDefined datetime", eqDateTime(dt, (DateTime)
394                     udps.getPropertyValue("FrobStartTime")));
395             assertTrue("UserDefined float", new Double(d).equals(
396                     udps.getPropertyValue("Pi")));
397             assertTrue("UserDefined string", "bar".equals(
398                     udps.getPropertyValue("Foo")));
399             assertTrue("UserDefined empty name", "eeeeek".equals(
400                     udps.getPropertyValue("")));
401 
402             try {
403                 udps.getPropertyValue("Removed");
404                 fail("UserDefined remove didn't");
405             } catch (UnknownPropertyException e) {
406                 // ok
407             }
408 
409             System.out.println("...done");
410 
411             System.out.println("Checking storing meta-data to file...");
412 
413             xDP.storeToMedium(temp + "TEST.odt", mimeArgs);
414 
415             System.out.println("...done");
416 
417             System.out.println("Checking loading meta-data from stored file...");
418 
419             xDP.loadFromMedium(temp + "TEST.odt", noArgs);
420 
421             System.out.println("...done");
422 
423             System.out.println("Checking user-defined meta-data from stored file...");
424 
425             udpc = xDP.getUserDefinedProperties();
426             udps = UnoRuntime.queryInterface( XPropertySet.class, udpc );
427 
428             assertTrue("UserDefined bool", new Boolean(b).equals(
429                     udps.getPropertyValue("Frobnicate")));
430             assertTrue("UserDefined duration", eqDuration(dur, (Duration)
431                     udps.getPropertyValue("FrobDuration")));
432             // this is now a Duration!
433             Duration t_dur = new Duration(false, (short)0, (short)0, (short)0,
434                     t.Hours, t.Minutes, t.Seconds,
435                     (short)(10 * t.HundredthSeconds));
436             assertTrue("UserDefined time", eqDuration(t_dur, (Duration)
437                     udps.getPropertyValue("FrobDuration2")));
438             assertTrue("UserDefined date", eqDate(date, (Date)
439                     udps.getPropertyValue("FrobEndDate")));
440             assertTrue("UserDefined datetime", eqDateTime(dt, (DateTime)
441                     udps.getPropertyValue("FrobStartTime")));
442             assertTrue("UserDefined float", new Double(d).equals(
443                     udps.getPropertyValue("Pi")));
444             assertTrue("UserDefined string", "bar".equals(
445                     udps.getPropertyValue("Foo")));
446 
447             try {
448                 udps.getPropertyValue("Removed");
449                 fail("UserDefined remove didn't");
450             } catch (UnknownPropertyException e) {
451                 // ok
452             }
453 
454             System.out.println("...done");
455 
456             System.out.println("Checking notification listener interface...");
457 
458             Listener listener = new Listener();
459             XModifyBroadcaster xMB = UnoRuntime.queryInterface( XModifyBroadcaster.class, xDP );
460             xMB.addModifyListener(listener);
461             xDP.setAuthor("not me");
462             assertTrue("Listener Author", listener.reset());
463             udpc.addProperty("Listener", PropertyAttribute.REMOVEABLE, "foo");
464             assertTrue("Listener UserDefined Add", listener.reset());
465             udps.setPropertyValue("Listener", "bar");
466             assertTrue("Listener UserDefined Set", listener.reset());
467             udpc.removeProperty("Listener");
468             assertTrue("Listener UserDefined Remove", listener.reset());
469             xMB.removeModifyListener(listener);
470             udpc.addProperty("Listener2", PropertyAttribute.REMOVEABLE, "foo");
471             assertTrue("Removed Listener UserDefined Add", !listener.reset());
472 
473             System.out.println("...done");
474 
475         } catch (Exception e) {
476             report(e);
477         }
478     }
479 
480     // grrr...
eqDateTime(DateTime a, DateTime b)481     boolean eqDateTime(DateTime a, DateTime b) {
482         return a.Year == b.Year && a.Month == b.Month && a.Day == b.Day
483             && a.Hours == b.Hours && a.Minutes == b.Minutes
484             && a.Seconds == b.Seconds
485             && a.HundredthSeconds == b.HundredthSeconds;
486     }
487 
eqDate(Date a, Date b)488     boolean eqDate(Date a, Date b) {
489         return a.Year == b.Year && a.Month == b.Month && a.Day == b.Day;
490     }
491 
eqTime(Time a, Time b)492     boolean eqTime(Time a, Time b) {
493         return a.Hours == b.Hours && a.Minutes == b.Minutes
494             && a.Seconds == b.Seconds
495             && a.HundredthSeconds == b.HundredthSeconds;
496     }
497 
eqDuration(Duration a, Duration b)498     boolean eqDuration(Duration a, Duration b) {
499         return a.Years == b.Years && a.Months == b.Months && a.Days == b.Days
500             && a.Hours == b.Hours && a.Minutes == b.Minutes
501             && a.Seconds == b.Seconds
502             && a.MilliSeconds == b.MilliSeconds
503             && a.Negative == b.Negative;
504     }
505 
fromArray(Object[] os)506     java.util.Collection fromArray(Object[] os) {
507         java.util.Collection ret = new java.util.HashSet();
508         for (int i = 0; i < os.length; ++i) {
509             ret.add(os[i]);
510         }
511         return ret;
512     }
513 
514     // bah, structs do not have proper equals(), and uno.Type is not comparable
containsNV(NamedValue[] nvs, NamedValue nv)515     public static boolean containsNV (NamedValue[] nvs, NamedValue nv) {
516         for (int i = 0; i < nvs.length; ++i) {
517             if (nvs[i].Name.equals(nv.Name) && nvs[i].Value.equals(nv.Value)) {
518                 return true;
519             }
520         }
521         return false;
522     }
523 
report(Exception e)524     public void report(Exception e) {
525         System.out.println("Exception occurred:");
526         e.printStackTrace();
527         fail();
528     }
529 
530 
getMSF()531         private XMultiServiceFactory getMSF()
532     {
533         final XMultiServiceFactory xMSF1 = UnoRuntime.queryInterface( XMultiServiceFactory.class, connection.getComponentContext().getServiceManager() );
534         return xMSF1;
535     }
536 
537     // setup and close connections
setUpConnection()538     @BeforeClass public static void setUpConnection() throws Exception {
539         System.out.println( "------------------------------------------------------------" );
540         System.out.println( "starting class: " + DocumentProperties.class.getName() );
541         System.out.println( "------------------------------------------------------------" );
542         connection.setUp();
543     }
544 
tearDownConnection()545     @AfterClass public static void tearDownConnection()
546         throws InterruptedException, com.sun.star.uno.Exception
547     {
548         System.out.println( "------------------------------------------------------------" );
549         System.out.println( "finishing class: " + DocumentProperties.class.getName() );
550         System.out.println( "------------------------------------------------------------" );
551         connection.tearDown();
552     }
553 
554     private static final OfficeConnection connection = new OfficeConnection();
555 
556 }
557 
558