2 * This file is part of the LibreOffice project.
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/.
8 * This file incorporates work covered by the following license notice:
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 .
20 import java
.io
.BufferedReader
;
22 import java
.io
.FileReader
;
23 import java
.io
.InputStream
;
24 import java
.io
.InputStreamReader
;
25 import java
.util
.ArrayList
;
26 import java
.util
.Collections
;
27 import java
.util
.StringTokenizer
;
28 import java
.util
.jar
.JarEntry
;
30 import share
.DescEntry
;
31 import share
.DescGetter
;
34 * This is the Office-API specific DescGetter<br>
37 * -o sw.SwXBodyText<br>
38 * runs the module test of <B>Sw.SwXBodyText</B><br>
40 * -o sw.SwXBodyText::com::sun::star::text::Text<br>
41 * runs only the interface test <B>com.sun.star.textText</B> of the module <B>Sw.SwXBodyText</B><br>
43 * -o sw.SwXBodyText::com::sun::star::text::Text,com::sun::star::text::XSimpleText<br>
44 * runs only the interfaces test <B>com.sun.star.textText</B> and <B>com.sun.star.text.XSimpleText</B> of the module <B>Sw.SwXBodyText</B><br>
47 * runs all modules of the project <B>sw</B><br>
50 * lists all known module tests<br>
52 * -sce SCENARIO_FILE<br>
53 * A scenario file is a property file which could cotain <B>-o</B> and <B>-p</B> properties<br>
55 * -sce sw.SwXBodyText,sw.SwXBookmark<br>
56 * runs the module test of <B>Sw.SwXBodyText</B> and <B>sw.SwXBookmark</B><br>
58 public class APIDescGetter
extends DescGetter
61 private static String fullJob
= null;
64 * gets the needed information about a StarOffice component
65 * @param descPath Path to the ComponentDescription
66 * @param entry contains the entry name, e.g. sw.SwXBodyText
67 * @param debug if true some debug information is displayed on standard out
70 public DescEntry
[] getDescriptionFor(String job
, String descPath
,
74 if (job
.startsWith("-o"))
76 job
= job
.substring(3, job
.length()).trim();
78 if (job
.indexOf('.') < 0)
83 // special in case several Interfaces are given comma separated
84 if (job
.indexOf(',') < 0)
86 DescEntry entry
= getDescriptionForSingleJob(job
, descPath
,
91 return new DescEntry
[]
103 ArrayList
<String
> subs
= getSubInterfaces(job
);
104 String partjob
= job
.substring(0, job
.indexOf(',')).trim();
105 DescEntry entry
= getDescriptionForSingleJob(partjob
, descPath
,
110 for (int i
= 0; i
< entry
.SubEntryCount
; i
++)
112 String subEntry
= entry
.SubEntries
[i
].longName
;
113 int cpLength
= entry
.longName
.length();
114 subEntry
= subEntry
.substring(cpLength
+ 2,
117 if (subs
.contains(subEntry
))
119 entry
.SubEntries
[i
].isToTest
= true;
123 return new DescEntry
[]
135 if (job
.startsWith("-p"))
137 job
= job
.substring(3, job
.length()).trim();
139 String
[] scenario
= createScenario(descPath
, job
, debug
);
140 if (scenario
== null)
144 DescEntry
[] entries
= new DescEntry
[scenario
.length
];
145 for (int i
= 0; i
< scenario
.length
; i
++)
147 entries
[i
] = getDescriptionForSingleJob(
148 scenario
[i
].substring(3).trim(), descPath
, debug
);
150 if (job
.equals("listall"))
152 util
.dbg
.printArray(scenario
);
158 if (job
.startsWith("-sce"))
160 job
= job
.substring(5, job
.length()).trim();
162 File sceFile
= new File(job
);
163 if (sceFile
.exists())
165 return getScenario(job
, descPath
, debug
);
169 //look the scenarion like this? :
170 // sw.SwXBodyText,sw.SwXTextCursor
171 ArrayList
<String
> subs
= getSubObjects(job
);
172 DescEntry
[] entries
= new DescEntry
[subs
.size()];
174 for (int i
= 0; i
< subs
.size(); i
++)
176 entries
[i
] = getDescriptionForSingleJob(
177 subs
.get(i
), descPath
, debug
);
189 protected DescEntry
getDescriptionForSingleJob(String job
, String descPath
,
192 boolean isSingleInterface
= job
.indexOf("::") > 0;
195 if (isSingleInterface
)
197 job
= job
.substring(0, job
.indexOf("::"));
200 if (job
.startsWith("bugs"))
202 DescEntry Entry
= new DescEntry();
203 Entry
.entryName
= job
;
204 Entry
.longName
= job
;
205 Entry
.EntryType
= "bugdoc";
206 Entry
.isOptional
= false;
207 Entry
.isToTest
= true;
208 Entry
.SubEntryCount
= 0;
209 Entry
.hasErrorMsg
= false;
210 Entry
.State
= "non possible";
215 DescEntry entry
= null;
217 if (descPath
!= null)
221 System
.out
.println("## reading from File " + descPath
);
224 entry
= getFromDirectory(descPath
, job
, debug
);
230 System
.out
.println("## reading from jar");
233 entry
= getFromClassPath(job
);
236 boolean foundInterface
= false;
238 if (isSingleInterface
&& (entry
!= null))
240 for (int i
= 0; i
< entry
.SubEntryCount
; i
++)
242 if (!(entry
.SubEntries
[i
].longName
).equals(fullJob
))
244 entry
.SubEntries
[i
].isToTest
= false;
248 foundInterface
= true;
249 entry
.SubEntries
[i
].isToTest
= true;
254 if (isSingleInterface
&& !foundInterface
|| entry
== null)
256 return setErrorDescription(entry
,
257 "couldn't find a description for test '" + fullJob
+ "'");
263 private static DescEntry
[] getSubEntries(BufferedReader cvsFile
,
267 String old_ifc_name
= "";
268 ArrayList
<DescEntry
> ifc_names
= new ArrayList
<DescEntry
>();
269 ArrayList
<DescEntry
> meth_names
= new ArrayList
<DescEntry
>();
270 DescEntry ifcDesc
= null;
276 line
= cvsFile
.readLine();
281 if (line
.startsWith("#"))
285 if (line
.length() <= 0)
289 // TODO Probleme here
291 String ifc_name
= ""; // = line.substring(line.indexOf(";") + 2, line.lastIndexOf(";") - 1);
292 String meth_name
= ""; // = line.substring(line.lastIndexOf(";") + 2, line.length() - 1);
293 StringTokenizer aToken
= new StringTokenizer(line
, ";");
294 if (aToken
.countTokens() < 3)
296 System
.out
.println("Wrong format: Line '" + line
+ "' is not supported.");
299 if (aToken
.hasMoreTokens())
301 StringHelper
.removeQuoteIfExists(aToken
.nextToken());
303 if (aToken
.hasMoreTokens())
305 ifc_name
= StringHelper
.removeQuoteIfExists(aToken
.nextToken());
307 if (aToken
.hasMoreTokens())
309 meth_name
= StringHelper
.removeQuoteIfExists(aToken
.nextToken());
312 DescEntry methDesc
= createDescEntry(meth_name
, ifc_name
, parent
);
314 if (!ifc_name
.equals(old_ifc_name
))
318 ifcDesc
.SubEntries
= getDescArray(meth_names
.toArray());
319 ifcDesc
.SubEntryCount
= meth_names
.size();
321 //mark service/interface as optional if all methods/properties are optional
322 boolean allOptional
= true;
324 for (int k
= 0; k
< ifcDesc
.SubEntryCount
; k
++)
326 if (!ifcDesc
.SubEntries
[k
].isOptional
)
332 if (!ifcDesc
.isOptional
&& allOptional
)
334 ifcDesc
.isOptional
= allOptional
;
338 ifc_names
.add(ifcDesc
);
341 ifcDesc
= new DescEntry();
342 ifcDesc
.isToTest
= true;
343 old_ifc_name
= ifc_name
;
345 if (ifc_name
.indexOf("#optional") > 0)
347 ifcDesc
.isOptional
= true;
348 ifc_name
= ifc_name
.substring(0, ifc_name
.indexOf('#'));
351 String className
= createClassName(ifc_name
);
353 ifcDesc
.EntryType
= entryType
;
354 ifcDesc
.entryName
= "ifc" + className
;
355 ifcDesc
.longName
= parent
.entryName
+ "::" + ifc_name
;
357 meth_names
.add(methDesc
);
360 catch (java
.io
.IOException ioe
)
362 parent
.hasErrorMsg
= true;
363 parent
.ErrorMsg
= "IOException while reading the description";
369 ifcDesc
.SubEntries
= getDescArray(meth_names
.toArray());
370 ifcDesc
.SubEntryCount
= meth_names
.size();
372 //mark service/interface as optional if all methods/properties are optional
373 boolean allOptional
= true;
375 for (int k
= 0; k
< ifcDesc
.SubEntryCount
; k
++)
377 if (!ifcDesc
.SubEntries
[k
].isOptional
)
383 if (!ifcDesc
.isOptional
&& allOptional
)
385 ifcDesc
.isOptional
= allOptional
;
388 ifc_names
.add(ifcDesc
);
390 return getDescArray(makeArray(ifc_names
));
392 private static String
createClassName(String _ifc_name
)
394 StringTokenizer st
= new StringTokenizer(_ifc_name
, ":");
395 String className
= "";
399 if (_ifc_name
.startsWith("drafts"))
404 for (int i
= 0; st
.hasMoreTokens(); i
++)
406 String token
= st
.nextToken();
408 // skipping (drafts.)com.sun.star
411 if (!st
.hasMoreTokens())
413 // inserting '_' before the last token
417 className
+= ("." + token
);
423 private static String entryType
;
425 private static DescEntry
createDescEntry(String meth_name
, String ifc_name
, DescEntry parent
)
427 entryType
= "service";
428 DescEntry methDesc
= new DescEntry();
430 if (meth_name
.indexOf("#optional") > 0)
432 methDesc
.isOptional
= true;
433 meth_name
= meth_name
.substring(0, meth_name
.indexOf('#'));
436 if (meth_name
.endsWith("()"))
438 methDesc
.EntryType
= "method";
439 entryType
= "interface";
443 methDesc
.EntryType
= "property";
444 entryType
= "service";
447 methDesc
.entryName
= meth_name
;
448 methDesc
.isToTest
= true;
451 String withoutHash
= ifc_name
;
453 if (ifc_name
.indexOf("#optional") > 0)
455 withoutHash
= ifc_name
.substring(0, ifc_name
.indexOf('#'));
458 methDesc
.longName
= parent
.entryName
+ "::" + withoutHash
+ "::" + meth_name
;
464 * This method ensures that XComponent will be the last in the list of interfaces
466 private static Object
[] makeArray(ArrayList
<DescEntry
> entries
)
468 Object
[] entriesArray
= entries
.toArray();
469 ArrayList
<Object
> returnArray
= new ArrayList
<Object
>();
470 Object addAtEnd
= null;
472 for (int k
= 0; k
< entriesArray
.length
; k
++)
474 DescEntry entry
= (DescEntry
) entriesArray
[k
];
476 if (entry
.entryName
.equals("ifc.lang._XComponent"))
482 returnArray
.add(entry
);
486 if (addAtEnd
!= null)
488 returnArray
.add(addAtEnd
);
491 return returnArray
.toArray();
494 private static DescEntry
setErrorDescription(DescEntry entry
,
499 entry
= new DescEntry();
501 entry
.hasErrorMsg
= true;
502 entry
.ErrorMsg
= "Error while getting description for test '" +
503 fullJob
+ "' as an API test: " + ErrorMsg
;
508 private static DescEntry
[] getDescArray(Object
[] list
)
510 DescEntry
[] entries
= new DescEntry
[list
.length
];
512 for (int i
= 0; i
< list
.length
; i
++)
514 entries
[i
] = (DescEntry
) list
[i
];
520 private DescEntry
getFromClassPath(String aEntry
)
522 int dotindex
= aEntry
.indexOf('.');
529 String module
= null;
530 String shortName
= null;
532 if (aEntry
.indexOf(".uno") == -1)
534 module
= aEntry
.substring(0, aEntry
.indexOf('.'));
535 shortName
= aEntry
.substring(aEntry
.indexOf('.') + 1);
539 module
= aEntry
.substring(0, aEntry
.lastIndexOf('.'));
540 shortName
= aEntry
.substring(aEntry
.lastIndexOf('.') + 1);
543 DescEntry theEntry
= new DescEntry();
544 theEntry
.entryName
= aEntry
;
545 theEntry
.longName
= aEntry
;
546 theEntry
.isOptional
= false;
547 theEntry
.EntryType
= "component";
548 theEntry
.isToTest
= true;
550 BufferedReader csvFile
= null;
552 java
.net
.URL url
= this.getClass().getResource("/objdsc/" + module
);
556 return setErrorDescription(theEntry
,
557 "couldn't find module '" + module
+ "'");
562 java
.net
.URLConnection con
= url
.openConnection();
564 String sEndsWithCSVName
= "." + shortName
.trim() + ".csv";
565 if (con
instanceof java
.net
.JarURLConnection
)
567 // get Jar file from connection
568 java
.util
.jar
.JarFile f
= ((java
.net
.JarURLConnection
) con
).getJarFile();
570 // Enumerate over all entries
571 java
.util
.Enumeration
<JarEntry
> e
= f
.entries();
573 String sStartModule
= "/" + module
+ "/";
574 while (e
.hasMoreElements())
577 String entry
= e
.nextElement().toString();
579 if ((entry
.lastIndexOf(sStartModule
) != -1) &&
580 entry
.endsWith(sEndsWithCSVName
))
582 InputStream input
= this.getClass().getResourceAsStream("/" + entry
);
583 csvFile
= new BufferedReader(new InputStreamReader(input
));
590 InputStream in
= con
.getInputStream();
591 java
.io
.BufferedReader buf
= new java
.io
.BufferedReader(new InputStreamReader(in
));
594 String entry
= buf
.readLine();
597 if (entry
.endsWith(sEndsWithCSVName
))
599 System
.out
.println("FOUND ####");
601 this.getClass().getResourceAsStream("/objdsc/" +
605 csvFile
= new BufferedReader(new InputStreamReader(input
));
613 catch (java
.io
.IOException e
)
620 return setErrorDescription(theEntry
,
621 "couldn't find component '" +
622 theEntry
.entryName
+ "'");
625 DescEntry
[] subEntries
= getSubEntries(csvFile
, theEntry
);
627 theEntry
.SubEntryCount
= subEntries
.length
;
628 theEntry
.SubEntries
= subEntries
;
633 private static DescEntry
getFromDirectory(String descPath
, String entry
,
636 int dotindex
= entry
.indexOf('.');
643 String fs
= System
.getProperty("file.separator");
644 String module
= null;
645 String shortName
= null;
647 if (entry
.indexOf(".uno") == -1)
649 module
= entry
.substring(0, entry
.indexOf('.'));
650 shortName
= entry
.substring(entry
.indexOf('.') + 1);
654 module
= entry
.substring(0, entry
.lastIndexOf('.'));
655 shortName
= entry
.substring(entry
.lastIndexOf('.') + 1);
658 DescEntry aEntry
= new DescEntry();
659 aEntry
.entryName
= entry
;
660 aEntry
.longName
= entry
;
661 aEntry
.isOptional
= false;
662 aEntry
.EntryType
= "component";
663 aEntry
.isToTest
= true;
667 System
.out
.println("Parsing Description Path: " + descPath
);
668 System
.out
.println("Searching module: " + module
);
669 System
.out
.println("For the Component " + shortName
);
672 File modPath
= new File(descPath
+ fs
+ module
);
674 if (!modPath
.exists())
676 return setErrorDescription(aEntry
,
677 "couldn't find module '" + module
+ "'");
680 String
[] files
= modPath
.list();
681 String found
= "none";
683 for (int i
= 0; i
< files
.length
; i
++)
685 if (files
[i
].endsWith("." + shortName
+ ".csv"))
688 System
.out
.println("found " + found
);
693 if (found
.equals("none"))
695 return setErrorDescription(aEntry
,
696 "couldn't find component '" + entry
+ "'");
699 String aUrl
= descPath
+ fs
+ module
+ fs
+ found
;
701 BufferedReader csvFile
= null;
705 csvFile
= new BufferedReader(new FileReader(aUrl
));
707 catch (java
.io
.FileNotFoundException fnfe
)
709 return setErrorDescription(aEntry
, "couldn't find file '" + aUrl
+ "'");
712 DescEntry
[] subEntries
= getSubEntries(csvFile
, aEntry
);
714 aEntry
.SubEntryCount
= subEntries
.length
;
715 aEntry
.SubEntries
= subEntries
;
721 protected ArrayList
<String
> getSubInterfaces(String job
)
723 ArrayList
<String
> namesList
= new ArrayList
<String
>();
724 StringTokenizer st
= new StringTokenizer(job
, ",");
726 while (st
.hasMoreTokens())
728 String token
= st
.nextToken();
730 if (token
.indexOf('.') < 0)
732 namesList
.add(token
);
739 private ArrayList
<String
> getSubObjects(String job
)
741 ArrayList
<String
> namesList
= new ArrayList
<String
>();
742 StringTokenizer st
= new StringTokenizer(job
, ",");
744 while (st
.hasMoreTokens())
746 namesList
.add(st
.nextToken());
753 protected String
[] createScenario(String descPath
, String job
,
756 String
[] scenario
= null;
758 if (descPath
!= null)
762 System
.out
.println("## reading from File " + descPath
);
765 scenario
= getScenarioFromDirectory(descPath
, job
);
771 System
.out
.println("## reading from jar");
774 scenario
= getScenarioFromClassPath(job
);
780 private String
[] getScenarioFromDirectory(String descPath
, String job
)
782 String
[] modules
= null;
783 ArrayList
<String
> componentList
= new ArrayList
<String
>();
785 if (!job
.equals("unknown") && !job
.equals("listall"))
787 modules
= new String
[]
794 File dirs
= new File(descPath
);
797 modules
= dirs
.list();
801 for (int i
= 0; i
< modules
.length
; i
++)
803 if (!isUnusedModule(modules
[i
]))
805 File moduleDir
= new File(descPath
+ System
.getProperty("file.separator") + modules
[i
]);
806 if (moduleDir
.exists())
808 String
[] components
= moduleDir
.list();
809 for (int j
= 0; j
< components
.length
; j
++)
811 if (components
[j
].endsWith(".csv"))
813 String toAdd
= getComponentForString(components
[j
], modules
[i
]);
814 toAdd
= "-o " + modules
[i
] + "." + toAdd
;
815 componentList
.add(toAdd
);
822 Collections
.sort(componentList
);
823 String
[] scenario
= componentList
.toArray(new String
[componentList
.size()]);
827 private String
[] getScenarioFromClassPath(String job
)
831 if (!job
.equals("unknown") && !job
.equals("listall"))
836 java
.net
.URL url
= this.getClass().getResource("/objdsc" + subdir
);
843 ArrayList
<String
> scenarioList
= new ArrayList
<String
>();
847 java
.net
.URLConnection con
= url
.openConnection();
849 if (con
instanceof java
.net
.JarURLConnection
)
851 // get Jar file from connection
852 java
.util
.jar
.JarFile f
= ((java
.net
.JarURLConnection
) con
).getJarFile();
854 // Enumerate over all entries
855 java
.util
.Enumeration
<JarEntry
> e
= f
.entries();
857 while (e
.hasMoreElements())
859 String entry
= e
.nextElement().toString();
861 if (entry
.startsWith("objdsc" + subdir
) &&
862 (entry
.indexOf("CVS") < 0) &&
863 !entry
.endsWith("/"))
865 int startMod
= entry
.indexOf('/');
866 int endMod
= entry
.lastIndexOf('/');
867 String module
= entry
.substring(startMod
+ 1, endMod
);
868 String component
= getComponentForString(
869 entry
.substring(endMod
+ 1,
873 if (!isUnusedModule(module
))
875 scenarioList
.add("-o " + module
+ "." +
882 catch (java
.io
.IOException e
)
887 Collections
.sort(scenarioList
);
888 String
[] scenario
= scenarioList
.toArray(new String
[scenarioList
.size()]);
892 private String
getComponentForString(String full
, String module
)
894 String component
= "";
898 full
= full
.substring(0, full
.length() - 4);
901 int lastdot
= full
.lastIndexOf('.');
902 component
= full
.substring(lastdot
+ 1, full
.length());
904 if (module
.equals("file") || module
.equals("xmloff"))
906 String withoutComponent
= full
.substring(0, lastdot
);
907 int preLastDot
= withoutComponent
.lastIndexOf('.');
908 component
= withoutComponent
.substring(preLastDot
+ 1,
909 withoutComponent
.length()) +
916 private boolean isUnusedModule(String moduleName
)
918 ArrayList
<String
> removed
= new ArrayList
<String
>();
919 removed
.add("acceptor");
920 removed
.add("brdgfctr");
921 removed
.add("connectr");
922 removed
.add("corefl");
924 removed
.add("defreg");
925 removed
.add("dynamicloader");
926 removed
.add("impreg");
929 removed
.add("invadp");
930 removed
.add("javaloader");
932 removed
.add("namingservice");
933 removed
.add("proxyfac");
934 removed
.add("rdbtdp");
935 removed
.add("remotebridge");
936 removed
.add("simreg");
940 removed
.add("tdmgr");
941 removed
.add("ucprmt");
942 removed
.add("uuresolver");
944 return removed
.contains(moduleName
);