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