001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: /*
043: * MTestConfig.java
044: *
045: * Created on March 25, 2003, 2:36 PM
046: */
047:
048: package org.netbeans.xtest.harness;
049:
050: import java.io.*;
051: import java.util.*;
052:
053: import org.netbeans.xtest.xmlserializer.*;
054: import org.netbeans.xtest.util.SerializeDOM;
055: import org.netbeans.xtest.XTestEntityResolver;
056: import javax.xml.parsers.DocumentBuilder;
057: import org.w3c.dom.Document;
058: import org.xml.sax.SAXException;
059:
060: /**
061: *
062: * @author mb115822
063: */
064: public class MTestConfig implements XMLSerializable {
065:
066: private String name;
067: private Testbag testbags[];
068: private AntExecType executors[];
069: private AntExecType compilers[];
070: private AntExecType resultsprocessors[];
071:
072: private AntExecType defaultExecutor;
073: private AntExecType defaultCompiler;
074: private AntExecType defaultResultsprocessor;
075:
076: private Hashtable executors_table = new Hashtable();
077: private Hashtable compilers_table = new Hashtable();
078: private Hashtable resultsprocessors_table = new Hashtable();
079:
080: private Testbag filtered_testbags[];
081:
082: private String additionalIncludes[];
083: private String additionalExcludes[];
084:
085: private String testtype;
086:
087: static ClassMappingRegistry classMappingRegistry = new ClassMappingRegistry(
088: MTestConfig.class);
089: static {
090: try {
091: // load global registry
092: GlobalMappingRegistry.registerClassForElementName(
093: "mconfig", MTestConfig.class);
094: // register this classMTestConfig
095: classMappingRegistry.registerSimpleField("name",
096: ClassMappingRegistry.ATTRIBUTE, "name");
097: classMappingRegistry.registerContainerField("testbags",
098: "testbag", ClassMappingRegistry.DIRECT);
099: classMappingRegistry.registerContainerField("executors",
100: "executor", ClassMappingRegistry.DIRECT);
101: classMappingRegistry.registerContainerField("compilers",
102: "compiler", ClassMappingRegistry.DIRECT);
103: classMappingRegistry.registerContainerField(
104: "resultsprocessors", "resultsprocessor",
105: ClassMappingRegistry.DIRECT);
106: } catch (MappingException me) {
107: me.printStackTrace();
108: classMappingRegistry = null;
109: }
110: }
111:
112: public ClassMappingRegistry registerXMLMapping() {
113: return classMappingRegistry;
114: }
115:
116: // empty constructor - required by XMLSerializer
117: public MTestConfig() {
118: }
119:
120: public String getName() {
121: return name;
122: }
123:
124: public void setTesttype(String testtype) {
125: this .testtype = testtype;
126: }
127:
128: public String getTesttype() {
129: return testtype;
130: }
131:
132: public void setAdditionalIncludes(String in[]) {
133: additionalIncludes = in;
134: }
135:
136: public void setAdditionalExcludes(String ex[]) {
137: additionalExcludes = ex;
138: }
139:
140: public String[] getAdditionalIncludes() {
141: return additionalIncludes;
142: }
143:
144: public String[] getAdditionalExcludes() {
145: return additionalExcludes;
146: }
147:
148: public void setTestbags(Testbag[] testbags) {
149: this .testbags = testbags;
150: }
151:
152: public Testbag[] getTestbags() {
153: return testbags;
154: }
155:
156: public Testbag[] getFilteredTestbags() {
157: return filtered_testbags;
158: }
159:
160: public Testbag createSingleTestbag(String testset_dir,
161: Vector test_includes) throws XMLSerializeException {
162: System.out
163: .println("Preparing single testbag with default executor/compiler/result processor");
164: if (defaultExecutor == null)
165: throw new XMLSerializeException(
166: "You have to set default executor when executing single test.");
167: if (defaultCompiler == null)
168: throw new XMLSerializeException(
169: "You have to set default compiler when executing single test.");
170: // results processor settings are no longer used - always a corresponding result processor for executor is used
171: /*
172: if (defaultResultsprocessor == null)
173: throw new XMLSerializeException("You have to set default resultsprocessor when executes single test.");
174: */
175: Testbag testbag = new Testbag();
176: testbag.setName("Autogenerated single testbag");
177: testbag.setAntExecutor(defaultExecutor);
178: testbag.setAntCompiler(defaultCompiler);
179: //testbag.setAntResultsprocessor(defaultResultsprocessor);
180:
181: Testbag.Testset testset = new Testbag.Testset();
182: testset.setDir(testset_dir);
183: Testbag.Patternset patternset = new Testbag.Patternset();
184:
185: Testbag.InExclude includes[] = new Testbag.InExclude[test_includes
186: .size()];
187: for (int i = 0; i < test_includes.size(); i++) {
188: includes[i] = new Testbag.InExclude();
189: includes[i].setName((String) test_includes.get(i));
190: }
191: patternset.setIncludes(includes);
192: testset.setPatternsets(new Testbag.Patternset[] { patternset });
193: testset.filterPatternsets(null);
194: testbag.setTestsets(new Testbag.Testset[] { testset });
195: // set parents
196: testset.setParent(testbag);
197: testbag.setParent(this );
198: return testbag;
199: }
200:
201: public static MTestConfig loadConfig(File configFile)
202: throws XMLSerializeException {
203: return loadConfig(configFile, null, null, null, null);
204: }
205:
206: public static MTestConfig loadConfig(File configFile,
207: HashSet passed_patternattribs, HashSet passed_testattribs,
208: HashSet passed_executors, HashSet passed_testbags)
209: throws XMLSerializeException {
210: System.out.println("Loading config...");
211: if (!configFile.isFile()) {
212: throw new XMLSerializeException(
213: "Cannot load config from file "
214: + configFile.getPath()
215: + ", file does not exist");
216: }
217: try {
218: DocumentBuilder db = SerializeDOM.getDocumentBuilder();
219: db.setEntityResolver(new XTestEntityResolver());
220: Document doc = db.parse(configFile);
221:
222: XMLSerializable xmlObject = XMLSerializer
223: .getXMLSerializable(doc);
224: if (xmlObject instanceof MTestConfig) {
225: MTestConfig config = (MTestConfig) xmlObject;
226: config.validateAndSetup(passed_patternattribs);
227: config.sortTestbagsByPriority();
228: if (passed_testattribs != null
229: || passed_executors != null
230: || passed_testbags != null)
231: config.filterTestbag(passed_testattribs,
232: passed_executors, passed_testbags);
233: return config;
234: }
235: } catch (SAXException saxe) {
236: throw new XMLSerializeException(
237: "SAXException thrown when loading config file "
238: + configFile.getPath() + ": "
239: + saxe.getMessage(), saxe);
240: } catch (IOException ioe) {
241: throw new XMLSerializeException(
242: "IOException thrown when loading config file "
243: + configFile.getPath() + ": "
244: + ioe.getMessage(), ioe);
245: }
246: // xmlobject is not of required type
247: throw new XMLSerializeException(
248: "Loaded xml document is not MTestConfig");
249: }
250:
251: private void filterTestbag(HashSet passed_testattribs,
252: HashSet passed_executors, HashSet passed_testbags) {
253: Vector v = new Vector();
254: for (int i = 0; i < testbags.length; i++) {
255: // compare passed attributes with attribs from this testbag,
256: AttribParser ap = new AttribParser(testbags[i]
257: .getTestattribs(), passed_testattribs);
258:
259: // test if tbg_exec is in passed_executors too
260: if ((!passed_testbags.isEmpty() && passed_testbags
261: .contains(testbags[i].getName()))
262: || (passed_testbags.isEmpty() && ap.parse() && (passed_executors
263: .contains(testbags[i].getExecutor()
264: .getName()) || passed_executors
265: .isEmpty()))) {
266: v.add(testbags[i]);
267: }
268: }
269: filtered_testbags = (Testbag[]) v.toArray(new Testbag[0]);
270: }
271:
272: private void sortTestbagsByPriority() {
273: Arrays.sort(testbags, new Comparator() {
274: public int compare(Object o1, Object o2) {
275: if (((Testbag) o1).getPrio() == null
276: && ((Testbag) o2).getPrio() == null)
277: return 0;
278: if (((Testbag) o1).getPrio() == null)
279: return +1;
280: if (((Testbag) o2).getPrio() == null)
281: return -1;
282: if (((Testbag) o1).getPrio().intValue() < ((Testbag) o2)
283: .getPrio().intValue())
284: return -1;
285: if (((Testbag) o1).getPrio().intValue() > ((Testbag) o2)
286: .getPrio().intValue())
287: return +1;
288: return 0;
289: }
290: });
291:
292: }
293:
294: private void validateAndSetup(HashSet passed_patternset)
295: throws XMLSerializeException {
296: if (getName() == null)
297: throw new XMLSerializeException(
298: "Attribute name is required for root element mconfig.");
299:
300: // This is not required when plugin are used !!! -- TBD !!!
301:
302: if (executors == null || executors.length == 0)
303: throw new XMLSerializeException(
304: "At least one element executor is required.");
305: if (compilers == null || compilers.length == 0)
306: throw new XMLSerializeException(
307: "At least one element compiler is required.");
308: // result processos is no longer required
309: if (resultsprocessors != null) {
310: System.out
311: .println("!!! Element resultprocessor is no longer used. Please delete it.");
312: }
313: /*
314: if (resultsprocessors == null || resultsprocessors.length == 0)
315: throw new XMLSerializeException("At least one element resultsprocessor is required.");
316: */
317:
318: if (testbags == null || testbags.length == 0)
319: throw new XMLSerializeException(
320: "At least one element testbag is required.");
321:
322: defaultExecutor = processAntExecTypes(executors,
323: executors_table, "executor");
324: defaultCompiler = processAntExecTypes(compilers,
325: compilers_table, "compiler");
326: //defaultResultsprocessor = processAntExecTypes(resultsprocessors, resultsprocessors_table, "resultsprocessor");
327:
328: for (int i = 0; i < testbags.length; i++) {
329: testbags[i].setParent(this );
330: testbags[i].setAntExecutor(getTestbagAntExecType(
331: testbags[i].getExecutorName(), defaultExecutor,
332: executors_table, "executor", testbags[i]
333: .getPluginName()));
334: testbags[i].setAntCompiler(getTestbagAntExecType(
335: testbags[i].getCompilerName(), defaultCompiler,
336: compilers_table, "compiler", testbags[i]
337: .getPluginName()));
338: //testbags[i].setAntResultsprocessor(getTestbagAntExecType(testbags[i].getResultsprocessorName(), defaultResultsprocessor, resultsprocessors_table, "resultsprocessor",testbags[i].getPluginName()));
339: testbags[i].validate(passed_patternset);
340: }
341:
342: }
343:
344: /** Validate all AntExecTypes, find ones with duplicate names and create hastable where key is name.
345: */
346: private AntExecType processAntExecTypes(AntExecType types[],
347: Hashtable types_table, String name)
348: throws XMLSerializeException {
349: if (types == null)
350: return null;
351: AntExecType defaultType = null;
352: for (int i = 0; i < types.length; i++) {
353: types[i].validate();
354: AntExecType duplicate = (AntExecType) types_table
355: .get(types[i].getName());
356: if (duplicate != null)
357: throw new XMLSerializeException("Name of " + name
358: + " must be unique. Found duplicate name "
359: + types[i].getName() + ".");
360: types_table.put(types[i].getName(), types[i]);
361: if (types[i].isDefault()) {
362: if (defaultType != null)
363: throw new XMLSerializeException("Only one " + name
364: + " can be set as default.");
365: defaultType = types[i];
366: }
367: }
368: return defaultType;
369: }
370:
371: /** Find AntExecType for given type_name or return default i type_name is null.
372: */
373: private AntExecType getTestbagAntExecType(String type_name,
374: AntExecType defaultType, Hashtable types_table,
375: String name, String pluginName)
376: throws XMLSerializeException {
377: if (type_name == null) {
378: if (defaultType == null) {
379: if (name.equals("compiler")) {
380: return null;
381: } else {
382: throw new XMLSerializeException("No default "
383: + name + " was found.");
384: }
385: } else {
386: if (pluginName == null) {
387: // if plugin is not defined - return default
388: return defaultType;
389: } else {
390: // else each plugin have to contain at least one default action
391: return null;
392: }
393: }
394: } else {
395: AntExecType type = (AntExecType) types_table.get(type_name);
396: if (type == null) {
397: throw new XMLSerializeException("No " + name
398: + " with name " + type_name + " was found.");
399: } else {
400: return type;
401: }
402: }
403: }
404:
405: // public inner classes
406:
407: public static class AntExecType implements XMLSerializable {
408: private String name;
409: private String antfile;
410: private String dir;
411: private String target;
412: private String def;
413:
414: static ClassMappingRegistry classMappingRegistry = new ClassMappingRegistry(
415: MTestConfig.AntExecType.class);
416: static {
417: try {
418: // register this class
419: classMappingRegistry.registerSimpleField("name",
420: ClassMappingRegistry.ATTRIBUTE, "name");
421: classMappingRegistry.registerSimpleField("antfile",
422: ClassMappingRegistry.ATTRIBUTE, "antfile");
423: classMappingRegistry.registerSimpleField("dir",
424: ClassMappingRegistry.ATTRIBUTE, "dir");
425: classMappingRegistry.registerSimpleField("target",
426: ClassMappingRegistry.ATTRIBUTE, "target");
427: classMappingRegistry.registerSimpleField("def",
428: ClassMappingRegistry.ATTRIBUTE, "default");
429: } catch (MappingException me) {
430: me.printStackTrace();
431: classMappingRegistry = null;
432: }
433: }
434:
435: public ClassMappingRegistry registerXMLMapping() {
436: return classMappingRegistry;
437: }
438:
439: public String getName() {
440: return name;
441: }
442:
443: public String getAntFile() {
444: return antfile;
445: }
446:
447: public String getTarget() {
448: return target;
449: }
450:
451: public String getDir() {
452: return dir;
453: }
454:
455: protected void validate() throws XMLSerializeException {
456: if (name == null)
457: throw new XMLSerializeException(
458: "Attribute name is required for element executor/compiler.");
459: if (def != null
460: && !(def.equalsIgnoreCase("false")
461: || def.equalsIgnoreCase("no")
462: || def.equalsIgnoreCase("0")
463: || def.equalsIgnoreCase("true")
464: || def.equalsIgnoreCase("yes") || def
465: .equalsIgnoreCase("1")))
466: throw new XMLSerializeException(
467: "Invalid value "
468: + def
469: + " in attribute default in element executor/compiler. Valid values are true, false, yes, no, 0 or 1.");
470: }
471:
472: public boolean isDefault() {
473: if (def != null
474: && (def.equalsIgnoreCase("true")
475: || def.equalsIgnoreCase("yes") || def
476: .equalsIgnoreCase("1")))
477: return true;
478: return false;
479: }
480:
481: }
482:
483: public void dump() {
484: System.out.println("DUMP:");
485: System.out.println("Name=" + getName());
486: Testbag testbags[] = getTestbags();
487: if (testbags != null)
488: for (int i = 0; i < testbags.length; i++) {
489: System.out.println("Testbags[" + i + "].name="
490: + testbags[i].getName());
491: System.out.println("Testbags[" + i + "].prio="
492: + testbags[i].getPrio());
493: Testbag.Testset testsets[] = testbags[i].getTestsets();
494: for (int j = 0; j < testsets.length; j++) {
495: System.out.println(" Testset[" + j + "].dir="
496: + testsets[j].getDir());
497: Testbag.Patternset patternsets[] = testsets[j]
498: .getPatternset();
499: if (patternsets != null)
500: for (int k = 0; k < patternsets.length; k++) {
501: System.out.println(" Patternset[" + k
502: + "]");
503: System.out.println(" Patternset["
504: + k
505: + "].patternattribs="
506: + patternsets[k]
507: .getPatternattribs());
508: }
509: }
510: }
511: if (executors != null)
512: for (int i = 0; i < executors.length; i++)
513: System.out.println("Executors[" + i + "].name="
514: + executors[i].getName());
515: if (compilers != null)
516: for (int i = 0; i < compilers.length; i++)
517: System.out.println("Compilers[" + i + "].name="
518: + compilers[i].getName());
519: /*
520: if (resultsprocessors != null)
521: for (int i=0; i<resultsprocessors.length;i++)
522: System.out.println("Resultsprocessors["+i+"].name="+resultsprocessors[i].getName());
523: */
524:
525: }
526: }
|