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
69 public DescEntry
[] getDescriptionFor(String job
, String descPath
,
73 if (job
.startsWith("-o"))
75 job
= job
.substring(3, job
.length()).trim();
77 if (job
.indexOf(".") < 0)
82 // special in case several Interfaces are given comma separated
83 if (job
.indexOf(",") < 0)
85 DescEntry entry
= getDescriptionForSingleJob(job
, descPath
,
90 return new DescEntry
[]
102 ArrayList
<String
> subs
= getSubInterfaces(job
);
103 String partjob
= job
.substring(0, job
.indexOf(",")).trim();
104 DescEntry entry
= getDescriptionForSingleJob(partjob
, descPath
,
109 for (int i
= 0; i
< entry
.SubEntryCount
; i
++)
111 String subEntry
= entry
.SubEntries
[i
].longName
;
112 int cpLength
= entry
.longName
.length();
113 subEntry
= subEntry
.substring(cpLength
+ 2,
116 if (subs
.contains(subEntry
))
118 entry
.SubEntries
[i
].isToTest
= true;
122 return new DescEntry
[]
134 if (job
.startsWith("-p"))
136 job
= job
.substring(3, job
.length()).trim();
138 String
[] scenario
= createScenario(descPath
, job
, debug
);
139 if (scenario
== null)
143 DescEntry
[] entries
= new DescEntry
[scenario
.length
];
144 for (int i
= 0; i
< scenario
.length
; i
++)
146 entries
[i
] = getDescriptionForSingleJob(
147 scenario
[i
].substring(3).trim(), descPath
, debug
);
149 if (job
.equals("listall"))
151 util
.dbg
.printArray(scenario
);
157 if (job
.startsWith("-sce"))
159 job
= job
.substring(5, job
.length()).trim();
161 File sceFile
= new File(job
);
162 if (sceFile
.exists())
164 return getScenario(job
, descPath
, debug
);
168 //look the scenarion like this? :
169 // sw.SwXBodyText,sw.SwXTextCursor
170 ArrayList
<String
> subs
= getSubObjects(job
);
171 DescEntry
[] entries
= new DescEntry
[subs
.size()];
173 for (int i
= 0; i
< subs
.size(); i
++)
175 entries
[i
] = getDescriptionForSingleJob(
176 subs
.get(i
), descPath
, debug
);
187 protected DescEntry
getDescriptionForSingleJob(String job
, String descPath
,
190 boolean isSingleInterface
= job
.indexOf("::") > 0;
193 if (isSingleInterface
)
195 job
= job
.substring(0, job
.indexOf("::"));
198 if (job
.startsWith("bugs"))
200 DescEntry Entry
= new DescEntry();
201 Entry
.entryName
= job
;
202 Entry
.longName
= job
;
203 Entry
.EntryType
= "bugdoc";
204 Entry
.isOptional
= false;
205 Entry
.isToTest
= true;
206 Entry
.SubEntryCount
= 0;
207 Entry
.hasErrorMsg
= false;
208 Entry
.State
= "non possible";
213 DescEntry entry
= null;
215 if (descPath
!= null)
219 System
.out
.println("## reading from File " + descPath
);
222 entry
= getFromDirectory(descPath
, job
, debug
);
228 System
.out
.println("## reading from jar");
231 entry
= getFromClassPath(job
, debug
);
234 boolean foundInterface
= false;
236 if (isSingleInterface
&& (entry
!= null))
238 for (int i
= 0; i
< entry
.SubEntryCount
; i
++)
240 if (!(entry
.SubEntries
[i
].longName
).equals(fullJob
))
242 entry
.SubEntries
[i
].isToTest
= false;
246 foundInterface
= true;
247 entry
.SubEntries
[i
].isToTest
= true;
252 if (isSingleInterface
&& !foundInterface
|| entry
== null)
254 return setErrorDescription(entry
,
255 "couldn't find a description for test '" + fullJob
+ "'");
261 protected static DescEntry
[] getSubEntries(BufferedReader cvsFile
,
262 DescEntry parent
, boolean debug
)
265 String old_ifc_name
= "";
266 ArrayList
<DescEntry
> ifc_names
= new ArrayList
<DescEntry
>();
267 ArrayList
<DescEntry
> meth_names
= new ArrayList
<DescEntry
>();
268 DescEntry ifcDesc
= null;
274 line
= cvsFile
.readLine();
279 if (line
.startsWith("#"))
283 if (line
.length() <= 0)
287 // TODO Probleme here
288 // int nFirstSemicolon = line.indexOf(";");
289 // int nLastSemicolon = line.lastIndexOf(";");
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 // String ifc_name = line.substring(line.indexOf(";") + 2, line.lastIndexOf(";") - 1);
313 // String meth_name = line.substring(line.lastIndexOf(";") + 2, line.length() - 1);
315 DescEntry methDesc
= createDescEntry(meth_name
, ifc_name
, parent
);
317 if (!ifc_name
.equals(old_ifc_name
))
321 ifcDesc
.SubEntries
= getDescArray(meth_names
.toArray());
322 ifcDesc
.SubEntryCount
= meth_names
.size();
324 //mark service/interface as optional if all methods/properties are optional
325 boolean allOptional
= true;
327 for (int k
= 0; k
< ifcDesc
.SubEntryCount
; k
++)
329 if (!ifcDesc
.SubEntries
[k
].isOptional
)
335 if (!ifcDesc
.isOptional
&& allOptional
)
337 ifcDesc
.isOptional
= allOptional
;
341 ifc_names
.add(ifcDesc
);
344 ifcDesc
= new DescEntry();
345 ifcDesc
.isToTest
= true;
346 old_ifc_name
= ifc_name
;
348 if (ifc_name
.indexOf("#optional") > 0)
350 ifcDesc
.isOptional
= true;
351 ifc_name
= ifc_name
.substring(0, ifc_name
.indexOf("#"));
354 String className
= createClassName(ifc_name
);
356 ifcDesc
.EntryType
= entryType
;
357 ifcDesc
.entryName
= "ifc" + className
;
358 ifcDesc
.longName
= parent
.entryName
+ "::" + ifc_name
;
360 meth_names
.add(methDesc
);
363 catch (java
.io
.IOException ioe
)
365 parent
.hasErrorMsg
= true;
366 parent
.ErrorMsg
= "IOException while reading the description";
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
, ":");
398 String className
= "";
402 if (_ifc_name
.startsWith("drafts"))
407 for (int i
= 0; st
.hasMoreTokens(); i
++)
409 String token
= st
.nextToken();
411 // skipping (drafts.)com.sun.star
414 if (!st
.hasMoreTokens())
416 // inserting '_' before the last token
420 className
+= ("." + token
);
426 private static String entryType
;
428 private static DescEntry
createDescEntry(String meth_name
, String ifc_name
, DescEntry parent
)
430 entryType
= "service";
431 DescEntry methDesc
= new DescEntry();
433 if (meth_name
.indexOf("#optional") > 0)
435 methDesc
.isOptional
= true;
436 meth_name
= meth_name
.substring(0, meth_name
.indexOf("#"));
439 if (meth_name
.endsWith("()"))
441 methDesc
.EntryType
= "method";
442 entryType
= "interface";
446 methDesc
.EntryType
= "property";
447 entryType
= "service";
450 methDesc
.entryName
= meth_name
;
451 methDesc
.isToTest
= true;
454 String withoutHash
= ifc_name
;
456 if (ifc_name
.indexOf("#optional") > 0)
458 withoutHash
= ifc_name
.substring(0, ifc_name
.indexOf("#"));
461 methDesc
.longName
= parent
.entryName
+ "::" + withoutHash
+ "::" + meth_name
;
467 * This method ensures that XComponent will be the last in the list of interfaces
469 protected static Object
[] makeArray(ArrayList
<DescEntry
> entries
)
471 Object
[] entriesArray
= entries
.toArray();
472 ArrayList
<Object
> returnArray
= new ArrayList
<Object
>();
473 Object addAtEnd
= null;
475 for (int k
= 0; k
< entriesArray
.length
; k
++)
477 DescEntry entry
= (DescEntry
) entriesArray
[k
];
479 if (entry
.entryName
.equals("ifc.lang._XComponent"))
485 returnArray
.add(entry
);
489 if (addAtEnd
!= null)
491 returnArray
.add(addAtEnd
);
494 return returnArray
.toArray();
497 protected static DescEntry
setErrorDescription(DescEntry entry
,
502 entry
= new DescEntry();
504 entry
.hasErrorMsg
= true;
505 entry
.ErrorMsg
= "Error while getting description for test '" +
506 fullJob
+ "' as an API test: " + ErrorMsg
;
511 protected static DescEntry
[] getDescArray(Object
[] list
)
513 DescEntry
[] entries
= new DescEntry
[list
.length
];
515 for (int i
= 0; i
< list
.length
; i
++)
517 entries
[i
] = (DescEntry
) list
[i
];
523 protected DescEntry
getFromClassPath(String aEntry
, boolean debug
)
525 int dotindex
= aEntry
.indexOf('.');
532 String module
= null;
533 String shortName
= null;
535 if (aEntry
.indexOf(".uno") == -1)
537 module
= aEntry
.substring(0, aEntry
.indexOf('.'));
538 shortName
= aEntry
.substring(aEntry
.indexOf('.') + 1);
542 module
= aEntry
.substring(0, aEntry
.lastIndexOf('.'));
543 shortName
= aEntry
.substring(aEntry
.lastIndexOf('.') + 1);
546 DescEntry theEntry
= new DescEntry();
547 theEntry
.entryName
= aEntry
;
548 theEntry
.longName
= aEntry
;
549 theEntry
.isOptional
= false;
550 theEntry
.EntryType
= "component";
551 theEntry
.isToTest
= true;
553 BufferedReader csvFile
= null;
555 java
.net
.URL url
= this.getClass().getResource("/objdsc/" + module
);
559 return setErrorDescription(theEntry
,
560 "couldn't find module '" + module
+ "'");
565 java
.net
.URLConnection con
= url
.openConnection();
567 String sEndsWithCSVName
= "." + shortName
.trim() + ".csv";
568 if (con
instanceof java
.net
.JarURLConnection
)
570 // get Jar file from connection
571 java
.util
.jar
.JarFile f
= ((java
.net
.JarURLConnection
) con
).getJarFile();
573 // Enumerate over all entries
574 java
.util
.Enumeration
<JarEntry
> e
= f
.entries();
576 String sStartModule
= "/" + module
+ "/";
577 while (e
.hasMoreElements())
580 String entry
= e
.nextElement().toString();
583 // System.out.println("### Read from connetion: " + entry);
586 if ((entry
.lastIndexOf(sStartModule
) != -1) &&
587 entry
.endsWith(sEndsWithCSVName
))
589 InputStream input
= this.getClass().getResourceAsStream("/" + entry
);
590 csvFile
= new BufferedReader(new InputStreamReader(input
));
597 InputStream in
= con
.getInputStream();
598 java
.io
.BufferedReader buf
= new java
.io
.BufferedReader(new InputStreamReader(in
));
599 boolean found
= false;
601 while (buf
.ready() && !found
)
603 String entry
= buf
.readLine();
605 if (entry
.endsWith(sEndsWithCSVName
))
607 System
.out
.println("FOUND ####");
608 InputStream input
= this.getClass().getResourceAsStream("/objdsc/" +
612 csvFile
= new BufferedReader(
613 new InputStreamReader(input
));
621 catch (java
.io
.IOException e
)
628 return setErrorDescription(theEntry
,
629 "couldn't find component '" +
630 theEntry
.entryName
+ "'");
633 DescEntry
[] subEntries
= getSubEntries(csvFile
, theEntry
, debug
);
635 theEntry
.SubEntryCount
= subEntries
.length
;
636 theEntry
.SubEntries
= subEntries
;
641 protected static DescEntry
getFromDirectory(String descPath
, String entry
,
644 int dotindex
= entry
.indexOf('.');
651 String fs
= System
.getProperty("file.separator");
652 String module
= null;
653 String shortName
= null;
655 if (entry
.indexOf(".uno") == -1)
657 module
= entry
.substring(0, entry
.indexOf('.'));
658 shortName
= entry
.substring(entry
.indexOf('.') + 1);
662 module
= entry
.substring(0, entry
.lastIndexOf('.'));
663 shortName
= entry
.substring(entry
.lastIndexOf('.') + 1);
666 DescEntry aEntry
= new DescEntry();
667 aEntry
.entryName
= entry
;
668 aEntry
.longName
= entry
;
669 aEntry
.isOptional
= false;
670 aEntry
.EntryType
= "component";
671 aEntry
.isToTest
= true;
675 System
.out
.println("Parsing Description Path: " + descPath
);
676 System
.out
.println("Searching module: " + module
);
677 System
.out
.println("For the Component " + shortName
);
680 File modPath
= new File(descPath
+ fs
+ module
);
682 if (!modPath
.exists())
684 return setErrorDescription(aEntry
,
685 "couldn't find module '" + module
+ "'");
688 String
[] files
= modPath
.list();
689 String found
= "none";
691 for (int i
= 0; i
< files
.length
; i
++)
693 if (files
[i
].endsWith("." + shortName
+ ".csv"))
696 System
.out
.println("found " + found
);
701 if (found
.equals("none"))
703 return setErrorDescription(aEntry
,
704 "couldn't find component '" + entry
+ "'");
707 String aUrl
= descPath
+ fs
+ module
+ fs
+ found
;
709 BufferedReader csvFile
= null;
713 csvFile
= new BufferedReader(new FileReader(aUrl
));
715 catch (java
.io
.FileNotFoundException fnfe
)
717 return setErrorDescription(aEntry
, "couldn't find file '" + aUrl
+ "'");
720 DescEntry
[] subEntries
= getSubEntries(csvFile
, aEntry
, debug
);
722 aEntry
.SubEntryCount
= subEntries
.length
;
723 aEntry
.SubEntries
= subEntries
;
728 protected ArrayList
<String
> getSubInterfaces(String job
)
730 ArrayList
<String
> namesList
= new ArrayList
<String
>();
731 StringTokenizer st
= new StringTokenizer(job
, ",");
733 for (; st
.hasMoreTokens();)
735 String token
= st
.nextToken();
737 if (token
.indexOf(".") < 0)
739 namesList
.add(token
);
746 protected ArrayList
<String
> getSubObjects(String job
)
748 ArrayList
<String
> namesList
= new ArrayList
<String
>();
749 StringTokenizer st
= new StringTokenizer(job
, ",");
751 for (; st
.hasMoreTokens();)
753 namesList
.add(st
.nextToken());
759 protected String
[] createScenario(String descPath
, String job
,
762 String
[] scenario
= null;
764 if (descPath
!= null)
768 System
.out
.println("## reading from File " + descPath
);
771 scenario
= getScenarioFromDirectory(descPath
, job
, debug
);
777 System
.out
.println("## reading from jar");
780 scenario
= getScenarioFromClassPath(job
, debug
);
786 protected String
[] getScenarioFromDirectory(String descPath
, String job
,
789 String
[] modules
= null;
790 ArrayList
<String
> componentList
= new ArrayList
<String
>();
792 if (!job
.equals("unknown") && !job
.equals("listall"))
794 modules
= new String
[]
801 File dirs
= new File(descPath
);
809 modules
= dirs
.list();
813 for (int i
= 0; i
< modules
.length
; i
++)
815 if (!isUnusedModule(modules
[i
]))
817 File moduleDir
= new File(descPath
+ System
.getProperty("file.separator") + modules
[i
]);
818 if (moduleDir
.exists())
820 String
[] components
= moduleDir
.list();
821 for (int j
= 0; j
< components
.length
; j
++)
823 if (components
[j
].endsWith(".csv"))
825 String toAdd
= getComponentForString(components
[j
], modules
[i
]);
826 toAdd
= "-o " + modules
[i
] + "." + toAdd
;
827 componentList
.add(toAdd
);
834 String
[] scenario
= new String
[componentList
.size()];
835 Collections
.sort(componentList
);
837 for (int i
= 0; i
< componentList
.size(); i
++)
839 scenario
[i
] = componentList
.get(i
);
846 protected String
[] getScenarioFromClassPath(String job
, boolean debug
)
850 if (!job
.equals("unknown") && !job
.equals("listall"))
855 java
.net
.URL url
= this.getClass().getResource("/objdsc" + subdir
);
862 ArrayList
<String
> scenarioList
= new ArrayList
<String
>();
866 java
.net
.URLConnection con
= url
.openConnection();
868 if (con
instanceof java
.net
.JarURLConnection
)
870 // get Jar file from connection
871 java
.util
.jar
.JarFile f
= ((java
.net
.JarURLConnection
) con
).getJarFile();
873 // Enumerate over all entries
874 java
.util
.Enumeration
<JarEntry
> e
= f
.entries();
876 while (e
.hasMoreElements())
878 String entry
= e
.nextElement().toString();
880 if (entry
.startsWith("objdsc" + subdir
) &&
881 (entry
.indexOf("CVS") < 0) &&
882 !entry
.endsWith("/"))
884 int startMod
= entry
.indexOf("/");
885 int endMod
= entry
.lastIndexOf("/");
886 String module
= entry
.substring(startMod
+ 1, endMod
);
887 String component
= getComponentForString(
888 entry
.substring(endMod
+ 1,
892 if (!isUnusedModule(module
))
894 scenarioList
.add("-o " + module
+ "." +
901 catch (java
.io
.IOException e
)
906 String
[] scenario
= new String
[scenarioList
.size()];
907 Collections
.sort(scenarioList
);
909 for (int i
= 0; i
< scenarioList
.size(); i
++)
911 scenario
[i
] = scenarioList
.get(i
);
917 protected String
getComponentForString(String full
, String module
)
919 String component
= "";
923 full
= full
.substring(0, full
.length() - 4);
926 int lastdot
= full
.lastIndexOf(".");
927 component
= full
.substring(lastdot
+ 1, full
.length());
929 if (module
.equals("file") || module
.equals("xmloff"))
931 String withoutComponent
= full
.substring(0, lastdot
);
932 int preLastDot
= withoutComponent
.lastIndexOf(".");
933 component
= withoutComponent
.substring(preLastDot
+ 1,
934 withoutComponent
.length()) +
941 protected boolean isUnusedModule(String moduleName
)
943 ArrayList
<String
> removed
= new ArrayList
<String
>();
944 removed
.add("acceptor");
945 removed
.add("brdgfctr");
946 removed
.add("connectr");
947 removed
.add("corefl");
949 removed
.add("defreg");
950 removed
.add("dynamicloader");
951 removed
.add("impreg");
954 removed
.add("invadp");
955 removed
.add("javaloader");
957 removed
.add("namingservice");
958 removed
.add("proxyfac");
959 removed
.add("rdbtdp");
960 removed
.add("remotebridge");
961 removed
.add("simreg");
965 removed
.add("tdmgr");
966 removed
.add("ucprmt");
967 removed
.add("uuresolver");
969 return removed
.contains(moduleName
);