Bump version to 24.04.3.4
[LibreOffice.git] / qadevOOo / runner / helper / APIDescGetter.java
blob65f8da05c99d5f6ae64757b7893db3eb0bef0086
1 /*
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 .
18 package helper;
20 import java.io.BufferedReader;
21 import java.io.File;
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;
33 /**
34 * This is the Office-API specific DescGetter<br>
35 * <br>
36 * Examples:<br><br>
37 * -o sw.SwXBodyText<br>
38 * runs the module test of <B>Sw.SwXBodyText</B><br>
39 * <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>
42 * <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>
45 * <br>
46 * -p sw<br>
47 * runs all modules of the project <B>sw</B><br>
48 * <br>
49 * -p listall<br>
50 * lists all known module tests<br>
51 * <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>
54 * <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 @Override
70 public DescEntry[] getDescriptionFor(String job, String descPath,
71 boolean debug)
74 if (job.startsWith("-o"))
76 job = job.substring(3, job.length()).trim();
78 if (job.indexOf('.') < 0)
80 return null;
83 // special in case several Interfaces are given comma separated
84 if (job.indexOf(',') < 0)
86 DescEntry entry = getDescriptionForSingleJob(job, descPath,
87 debug);
89 if (entry != null)
91 return new DescEntry[]
93 entry
96 else
98 return null;
101 else
103 ArrayList<String> subs = getSubInterfaces(job);
104 String partjob = job.substring(0, job.indexOf(',')).trim();
105 DescEntry entry = getDescriptionForSingleJob(partjob, descPath,
106 debug);
108 if (entry != null)
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,
115 subEntry.length());
117 if (subs.contains(subEntry))
119 entry.SubEntries[i].isToTest = true;
123 return new DescEntry[]
125 entry
128 else
130 return null;
135 if (job.startsWith("-p"))
137 job = job.substring(3, job.length()).trim();
139 String[] scenario = createScenario(descPath, job, debug);
140 if (scenario == null)
142 return 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);
153 System.exit(0);
155 return entries;
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);
167 else
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);
179 return entries;
182 else
184 return null;
188 @Override
189 protected DescEntry getDescriptionForSingleJob(String job, String descPath,
190 boolean debug)
192 boolean isSingleInterface = job.indexOf("::") > 0;
193 fullJob = job;
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";
212 return Entry;
215 DescEntry entry = null;
217 if (descPath != null)
219 if (debug)
221 System.out.println("## reading from File " + descPath);
224 entry = getFromDirectory(descPath, job, debug);
226 else
228 if (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;
246 else
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 + "'");
260 return entry;
263 private static DescEntry[] getSubEntries(BufferedReader cvsFile,
264 DescEntry parent)
266 String line = "";
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;
272 while (line != null)
276 line = cvsFile.readLine();
277 if (line == null)
279 continue;
281 if (line.startsWith("#"))
283 continue;
285 if (line.length() <= 0)
287 continue;
289 // TODO Problem 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.");
297 continue;
299 if (aToken.hasMoreTokens())
301 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))
316 if (ifcDesc != null)
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)
328 allOptional = false;
332 if (!ifcDesc.isOptional && allOptional)
334 ifcDesc.isOptional = allOptional;
337 meth_names.clear();
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";
364 break;
368 if (ifcDesc == null) {
369 return 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)
382 allOptional = false;
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, ":");
399 int count = 3;
401 if (_ifc_name.startsWith("drafts"))
403 count = 4;
406 StringBuilder className = new StringBuilder();
408 for (int i = 0; st.hasMoreTokens(); i++)
410 String token = st.nextToken();
412 // skipping (drafts.)com.sun.star
413 if (i >= count)
415 if (!st.hasMoreTokens())
417 // inserting '_' before the last token
418 token = "_" + 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";
445 else
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;
464 return methDesc;
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"))
482 addAtEnd = entry;
484 else
486 returnArray.add(entry);
490 if (addAtEnd != null)
492 returnArray.add(addAtEnd);
495 return returnArray.toArray();
498 private static DescEntry setErrorDescription(DescEntry entry,
499 String ErrorMsg)
501 if (entry == null)
503 entry = new DescEntry();
505 entry.hasErrorMsg = true;
506 entry.ErrorMsg = "Error while getting description for test '" +
507 fullJob + "' as an API test: " + ErrorMsg;
509 return entry;
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];
521 return entries;
524 private DescEntry getFromClassPath(String aEntry)
526 int dotindex = aEntry.indexOf('.');
528 if (dotindex == -1)
530 return null;
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);
541 else
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);
558 if (url == null)
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"));
588 break;
592 else
594 InputStream in = con.getInputStream();
595 java.io.BufferedReader buf = new java.io.BufferedReader(new InputStreamReader(in, "UTF-8"));
596 while (true)
598 String entry = buf.readLine();
599 if (entry == null)
600 break;
601 if (entry.endsWith(sEndsWithCSVName))
603 System.out.println("FOUND ####");
604 InputStream input =
605 this.getClass().getResourceAsStream("/objdsc/" +
606 module +
607 "/" +
608 entry);
609 csvFile = new BufferedReader(new InputStreamReader(input, "UTF-8"));
610 break;
614 buf.close();
617 catch (java.io.IOException e)
619 e.printStackTrace();
622 if (csvFile == null)
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;
636 csvFile.close();
638 catch (java.io.IOException ioe)
640 System.out.println("Exception while closing csvFile");
643 return theEntry;
646 private static DescEntry getFromDirectory(String descPath, String entry,
647 boolean debug)
649 int dotindex = entry.indexOf('.');
651 if (dotindex == -1)
653 return null;
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);
665 else
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;
678 if (debug)
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"))
700 found = files[i];
701 System.out.println("found " + found);
702 break;
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);
729 csvFile.close();
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;
739 return aEntry;
742 @Override
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);
758 return namesList;
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());
771 return namesList;
774 @Override
775 protected String[] createScenario(String descPath, String job,
776 boolean debug)
778 String[] scenario = null;
780 if (descPath != null)
782 if (debug)
784 System.out.println("## reading from File " + descPath);
787 scenario = getScenarioFromDirectory(descPath, job);
789 else
791 if (debug)
793 System.out.println("## reading from jar");
796 scenario = getScenarioFromClassPath(job);
799 return scenario;
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[]
814 else
816 File dirs = new File(descPath);
818 if (dirs.exists()) {
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()]);
848 return scenario;
851 private String[] getScenarioFromClassPath(String job)
853 String subdir = "/";
855 if (!job.equals("unknown") && !job.equals("listall"))
857 subdir += job;
860 java.net.URL url = this.getClass().getResource("/objdsc" + subdir);
862 if (url == null)
864 return null;
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,
894 entry.length()),
895 module);
897 if (!isUnusedModule(module))
899 scenarioList.add("-o " + module + "." +
900 component);
906 catch (java.io.IOException e)
908 e.printStackTrace();
911 Collections.sort(scenarioList);
912 String[] scenario = scenarioList.toArray(new String[scenarioList.size()]);
913 return scenario;
916 private String getComponentForString(String full, String module)
918 String component = "";
921 //cutting .csv
922 full = full.substring(0, full.length() - 4);
924 //cutting component
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()) +
934 "." + component;
937 return component;
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");
947 removed.add("cpld");
948 removed.add("defreg");
949 removed.add("dynamicloader");
950 removed.add("impreg");
951 removed.add("insp");
952 removed.add("inv");
953 removed.add("invadp");
954 removed.add("javaloader");
955 removed.add("jen");
956 removed.add("namingservice");
957 removed.add("proxyfac");
958 removed.add("rdbtdp");
959 removed.add("remotebridge");
960 removed.add("simreg");
961 removed.add("smgr");
962 removed.add("stm");
963 removed.add("tcv");
964 removed.add("tdmgr");
965 removed.add("ucprmt");
966 removed.add("uuresolver");
968 return removed.contains(moduleName);