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 contain <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 scenario 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)
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())
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";
368 if (ifcDesc
== null) {
372 ifcDesc
.SubEntries
= getDescArray(meth_names
.toArray());
373 ifcDesc
.SubEntryCount
= meth_names
.size();
375 //mark service/interface as optional if all methods/properties are optional
376 boolean allOptional
= true;
378 for (int k
= 0; k
< ifcDesc
.SubEntryCount
; k
++)
380 if (!ifcDesc
.SubEntries
[k
].isOptional
)
386 if (!ifcDesc
.isOptional
&& allOptional
)
388 ifcDesc
.isOptional
= allOptional
;
391 ifc_names
.add(ifcDesc
);
393 return getDescArray(makeArray(ifc_names
));
395 private static String
createClassName(String _ifc_name
)
397 StringTokenizer st
= new StringTokenizer(_ifc_name
, ":");
401 if (_ifc_name
.startsWith("drafts"))
406 StringBuilder className
= new StringBuilder();
408 for (int i
= 0; st
.hasMoreTokens(); i
++)
410 String token
= st
.nextToken();
412 // skipping (drafts.)com.sun.star
415 if (!st
.hasMoreTokens())
417 // inserting '_' before the last token
421 className
.append(".").append(token
);
424 return className
.toString();
427 private static String entryType
;
429 private static DescEntry
createDescEntry(String meth_name
, String ifc_name
, DescEntry parent
)
431 entryType
= "service";
432 DescEntry methDesc
= new DescEntry();
434 if (meth_name
.indexOf("#optional") > 0)
436 methDesc
.isOptional
= true;
437 meth_name
= meth_name
.substring(0, meth_name
.indexOf('#'));
440 if (meth_name
.endsWith("()"))
442 methDesc
.EntryType
= "method";
443 entryType
= "interface";
447 methDesc
.EntryType
= "property";
448 entryType
= "service";
451 methDesc
.entryName
= meth_name
;
452 methDesc
.isToTest
= true;
455 String withoutHash
= ifc_name
;
457 if (ifc_name
.indexOf("#optional") > 0)
459 withoutHash
= ifc_name
.substring(0, ifc_name
.indexOf('#'));
462 methDesc
.longName
= parent
.entryName
+ "::" + withoutHash
+ "::" + meth_name
;
468 * This method ensures that XComponent will be the last in the list of interfaces
470 private static Object
[] makeArray(ArrayList
<DescEntry
> entries
)
472 Object
[] entriesArray
= entries
.toArray();
473 ArrayList
<Object
> returnArray
= new ArrayList
<Object
>();
474 Object addAtEnd
= null;
476 for (int k
= 0; k
< entriesArray
.length
; k
++)
478 DescEntry entry
= (DescEntry
) entriesArray
[k
];
480 if (entry
.entryName
.equals("ifc.lang._XComponent"))
486 returnArray
.add(entry
);
490 if (addAtEnd
!= null)
492 returnArray
.add(addAtEnd
);
495 return returnArray
.toArray();
498 private static DescEntry
setErrorDescription(DescEntry entry
,
503 entry
= new DescEntry();
505 entry
.hasErrorMsg
= true;
506 entry
.ErrorMsg
= "Error while getting description for test '" +
507 fullJob
+ "' as an API test: " + ErrorMsg
;
512 private static DescEntry
[] getDescArray(Object
[] list
)
514 DescEntry
[] entries
= new DescEntry
[list
.length
];
516 for (int i
= 0; i
< list
.length
; i
++)
518 entries
[i
] = (DescEntry
) list
[i
];
524 private DescEntry
getFromClassPath(String aEntry
)
526 int dotindex
= aEntry
.indexOf('.');
533 String module
= null;
534 String shortName
= null;
536 if (aEntry
.indexOf(".uno") == -1)
538 module
= aEntry
.substring(0, aEntry
.indexOf('.'));
539 shortName
= aEntry
.substring(aEntry
.indexOf('.') + 1);
543 module
= aEntry
.substring(0, aEntry
.lastIndexOf('.'));
544 shortName
= aEntry
.substring(aEntry
.lastIndexOf('.') + 1);
547 DescEntry theEntry
= new DescEntry();
548 theEntry
.entryName
= aEntry
;
549 theEntry
.longName
= aEntry
;
550 theEntry
.isOptional
= false;
551 theEntry
.EntryType
= "component";
552 theEntry
.isToTest
= true;
554 BufferedReader csvFile
= null;
556 java
.net
.URL url
= this.getClass().getResource("/objdsc/" + module
);
560 return setErrorDescription(theEntry
,
561 "couldn't find module '" + module
+ "'");
566 java
.net
.URLConnection con
= url
.openConnection();
568 String sEndsWithCSVName
= "." + shortName
.trim() + ".csv";
569 if (con
instanceof java
.net
.JarURLConnection
)
571 // get Jar file from connection
572 java
.util
.jar
.JarFile f
= ((java
.net
.JarURLConnection
) con
).getJarFile();
574 // Enumerate over all entries
575 java
.util
.Enumeration
<JarEntry
> e
= f
.entries();
577 String sStartModule
= "/" + module
+ "/";
578 while (e
.hasMoreElements())
581 String entry
= e
.nextElement().toString();
583 if ((entry
.lastIndexOf(sStartModule
) != -1) &&
584 entry
.endsWith(sEndsWithCSVName
))
586 InputStream input
= this.getClass().getResourceAsStream("/" + entry
);
587 csvFile
= new BufferedReader(new InputStreamReader(input
, "UTF-8"));
594 InputStream in
= con
.getInputStream();
595 java
.io
.BufferedReader buf
= new java
.io
.BufferedReader(new InputStreamReader(in
, "UTF-8"));
598 String entry
= buf
.readLine();
601 if (entry
.endsWith(sEndsWithCSVName
))
603 System
.out
.println("FOUND ####");
605 this.getClass().getResourceAsStream("/objdsc/" +
609 csvFile
= new BufferedReader(new InputStreamReader(input
, "UTF-8"));
617 catch (java
.io
.IOException e
)
624 return setErrorDescription(theEntry
,
625 "couldn't find component '" +
626 theEntry
.entryName
+ "'");
629 DescEntry
[] subEntries
= getSubEntries(csvFile
, theEntry
);
631 theEntry
.SubEntryCount
= subEntries
!= null ? subEntries
.length
: 0;
632 theEntry
.SubEntries
= subEntries
;
638 catch (java
.io
.IOException ioe
)
640 System
.out
.println("Exception while closing csvFile");
646 private static DescEntry
getFromDirectory(String descPath
, String entry
,
649 int dotindex
= entry
.indexOf('.');
656 String fs
= System
.getProperty("file.separator");
657 String module
= null;
658 String shortName
= null;
660 if (entry
.indexOf(".uno") == -1)
662 module
= entry
.substring(0, entry
.indexOf('.'));
663 shortName
= entry
.substring(entry
.indexOf('.') + 1);
667 module
= entry
.substring(0, entry
.lastIndexOf('.'));
668 shortName
= entry
.substring(entry
.lastIndexOf('.') + 1);
671 DescEntry aEntry
= new DescEntry();
672 aEntry
.entryName
= entry
;
673 aEntry
.longName
= entry
;
674 aEntry
.isOptional
= false;
675 aEntry
.EntryType
= "component";
676 aEntry
.isToTest
= true;
680 System
.out
.println("Parsing Description Path: " + descPath
);
681 System
.out
.println("Searching module: " + module
);
682 System
.out
.println("For the Component " + shortName
);
685 File modPath
= new File(descPath
+ fs
+ module
);
687 if (!modPath
.exists())
689 return setErrorDescription(aEntry
,
690 "couldn't find module '" + module
+ "'");
693 String
[] files
= modPath
.list();
694 String found
= "none";
696 for (int i
= 0; i
< files
.length
; i
++)
698 if (files
[i
].endsWith("." + shortName
+ ".csv"))
701 System
.out
.println("found " + found
);
706 if (found
.equals("none"))
708 return setErrorDescription(aEntry
,
709 "couldn't find component '" + entry
+ "'");
712 String aUrl
= descPath
+ fs
+ module
+ fs
+ found
;
714 BufferedReader csvFile
= null;
718 csvFile
= new BufferedReader(new FileReader(aUrl
));
720 catch (java
.io
.FileNotFoundException fnfe
)
722 return setErrorDescription(aEntry
, "couldn't find file '" + aUrl
+ "'");
725 DescEntry
[] subEntries
= getSubEntries(csvFile
, aEntry
);
731 catch (java
.io
.IOException ioe
)
733 System
.out
.println("Exception while closing csvFile");
736 aEntry
.SubEntryCount
= subEntries
!= null ? subEntries
.length
: 0;
737 aEntry
.SubEntries
= subEntries
;
743 protected ArrayList
<String
> getSubInterfaces(String job
)
745 ArrayList
<String
> namesList
= new ArrayList
<String
>();
746 StringTokenizer st
= new StringTokenizer(job
, ",");
748 while (st
.hasMoreTokens())
750 String token
= st
.nextToken();
752 if (token
.indexOf('.') < 0)
754 namesList
.add(token
);
761 private ArrayList
<String
> getSubObjects(String job
)
763 ArrayList
<String
> namesList
= new ArrayList
<String
>();
764 StringTokenizer st
= new StringTokenizer(job
, ",");
766 while (st
.hasMoreTokens())
768 namesList
.add(st
.nextToken());
775 protected String
[] createScenario(String descPath
, String job
,
778 String
[] scenario
= null;
780 if (descPath
!= null)
784 System
.out
.println("## reading from File " + descPath
);
787 scenario
= getScenarioFromDirectory(descPath
, job
);
793 System
.out
.println("## reading from jar");
796 scenario
= getScenarioFromClassPath(job
);
802 private String
[] getScenarioFromDirectory(String descPath
, String job
)
804 String
[] modules
= null;
805 ArrayList
<String
> componentList
= new ArrayList
<String
>();
807 if (!job
.equals("unknown") && !job
.equals("listall"))
809 modules
= new String
[]
816 File dirs
= new File(descPath
);
819 modules
= dirs
.list();
823 int moduleLength
= modules
!= null ? modules
.length
: 0;
825 for (int i
= 0; i
< moduleLength
; ++i
)
827 if (!isUnusedModule(modules
[i
]))
829 File moduleDir
= new File(descPath
+ System
.getProperty("file.separator") + modules
[i
]);
830 if (moduleDir
.exists())
832 String
[] components
= moduleDir
.list();
833 for (int j
= 0; j
< components
.length
; j
++)
835 if (components
[j
].endsWith(".csv"))
837 String toAdd
= getComponentForString(components
[j
], modules
[i
]);
838 toAdd
= "-o " + modules
[i
] + "." + toAdd
;
839 componentList
.add(toAdd
);
846 Collections
.sort(componentList
);
847 String
[] scenario
= componentList
.toArray(new String
[componentList
.size()]);
851 private String
[] getScenarioFromClassPath(String job
)
855 if (!job
.equals("unknown") && !job
.equals("listall"))
860 java
.net
.URL url
= this.getClass().getResource("/objdsc" + subdir
);
867 ArrayList
<String
> scenarioList
= new ArrayList
<String
>();
871 java
.net
.URLConnection con
= url
.openConnection();
873 if (con
instanceof java
.net
.JarURLConnection
)
875 // get Jar file from connection
876 java
.util
.jar
.JarFile f
= ((java
.net
.JarURLConnection
) con
).getJarFile();
878 // Enumerate over all entries
879 java
.util
.Enumeration
<JarEntry
> e
= f
.entries();
881 while (e
.hasMoreElements())
883 String entry
= e
.nextElement().toString();
885 if (entry
.startsWith("objdsc" + subdir
) &&
886 (entry
.indexOf("CVS") < 0) &&
887 !entry
.endsWith("/"))
889 int startMod
= entry
.indexOf('/');
890 int endMod
= entry
.lastIndexOf('/');
891 String module
= entry
.substring(startMod
+ 1, endMod
);
892 String component
= getComponentForString(
893 entry
.substring(endMod
+ 1,
897 if (!isUnusedModule(module
))
899 scenarioList
.add("-o " + module
+ "." +
906 catch (java
.io
.IOException e
)
911 Collections
.sort(scenarioList
);
912 String
[] scenario
= scenarioList
.toArray(new String
[scenarioList
.size()]);
916 private String
getComponentForString(String full
, String module
)
918 String component
= "";
922 full
= full
.substring(0, full
.length() - 4);
925 int lastdot
= full
.lastIndexOf('.');
926 component
= full
.substring(lastdot
+ 1, full
.length());
928 if (module
.equals("file") || module
.equals("xmloff"))
930 String withoutComponent
= full
.substring(0, lastdot
);
931 int preLastDot
= withoutComponent
.lastIndexOf('.');
932 component
= withoutComponent
.substring(preLastDot
+ 1,
933 withoutComponent
.length()) +
940 private boolean isUnusedModule(String moduleName
)
942 ArrayList
<String
> removed
= new ArrayList
<String
>();
943 removed
.add("acceptor");
944 removed
.add("brdgfctr");
945 removed
.add("connector");
946 removed
.add("corefl");
948 removed
.add("defreg");
949 removed
.add("dynamicloader");
950 removed
.add("impreg");
953 removed
.add("invadp");
954 removed
.add("javaloader");
956 removed
.add("namingservice");
957 removed
.add("proxyfac");
958 removed
.add("rdbtdp");
959 removed
.add("remotebridge");
960 removed
.add("simreg");
964 removed
.add("tdmgr");
965 removed
.add("ucprmt");
966 removed
.add("uuresolver");
968 return removed
.contains(moduleName
);