/* * Copyright 2005-2010 Ignis Software Tools Ltd. All rights reserved. */ package jsystem.treeui.tree; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Collections; import java.util.Enumeration; import java.util.Vector; import java.util.jar.JarEntry; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.tree.DefaultMutableTreeNode; import jsystem.framework.FrameworkOptions; import jsystem.framework.JSystemProperties; import jsystem.framework.fixture.Fixture; import jsystem.framework.scenario.RunnerScript; import jsystem.framework.scenario.Scenario; import jsystem.framework.scenario.ScenarioHelpers; import jsystem.framework.scripts.ScriptEngine; import jsystem.framework.scripts.ScriptExecutor; import jsystem.framework.scripts.ScriptsEngineManager; import jsystem.framework.system.DefaultSystemObjectAdaptor; import jsystem.framework.system.SystemObjectAdaptor; import jsystem.runner.loader.LoadersManager; import jsystem.treeui.TestFilterManager; import jsystem.treeui.suteditor.planner.SutTreeNode; import jsystem.treeui.suteditor.planner.SutTreeNode.NodeType; import jsystem.utils.StringUtils; import jsystem.utils.XmlUtils; import jsystem.utils.beans.AsmUtils; import jsystem.utils.beans.MethodElement; import junit.framework.SystemTestCase; import junit.framework.TestCase; import org.apache.xpath.XPathAPI; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Representing Node at the Tests tree. * * * @author guy.arieli * */ public abstract class AssetNode extends DefaultMutableTreeNode implements Comparable<Object>{ /** * */ private static final long serialVersionUID = -7663450817941582253L; protected static Logger log = Logger.getLogger(AssetNode.class.getName()); protected boolean isSelected; private boolean isClassPath; private static Vector<String[]> loadErrors = new Vector<String[]>(); public static void initFailLoadClassVector() { loadErrors = null; } public static boolean isErrorsFound() { return (loadErrors != null); } public static Vector<String[]> getLoadsErrors() { return loadErrors; } public AssetNode(AssetNode parent, Object userObject) { super(userObject); setParent(parent); isSelected = false; } public AssetNode(){ isSelected = false; if (children == null) { children = new Vector<AssetNode>(); } } @SuppressWarnings("unchecked") protected void initChildren(Object[] child) throws Exception { if (children == null) { children = new Vector(); } for (int i = 0; i < child.length; i++) { if (child[i] instanceof File) { File f = (File) child[i]; ScriptEngine se =ScriptsEngineManager.getInstance().findExecutor(f); if(se != null){ ScriptExecutor[] executors = se.getExecutor(f); for(ScriptExecutor executor: executors){ //executor.configEngine(se); executor.configFilePath(f.getAbsolutePath().substring(JSystemProperties.getCurrentTestsPath().length() + 1).replace('\\', '/')); RunnerScript rs = new RunnerScript(executor); children.addElement(new ScriptNode(this, rs)); } } String fileNameToLower = f.getName().toLowerCase(); if (f.isDirectory()) { children.add(new DirectoryNode(this, f)); } else if (f.isFile()) { if (isJar(f)) { if (exludedJar(f)) { continue; } children.add(new JarNode(this, f)); } else if (fileNameToLower.endsWith(".xml")) { File root = (File) this.getRootUserObject(); String resource = f.getAbsolutePath().substring( root.getAbsolutePath().length()); if (!resource.matches(".sut.*") && Scenario.isScenario(resource)) { /** * init scenario */ String scenarioName = f .getAbsolutePath() .substring( root.getAbsolutePath().length() + 1, f.getAbsolutePath().length() - 4); if (TestFilterManager.getInstance().filter( scenarioName)) { continue; } if (ScenarioHelpers.isPackedScenario(resource.replace(".xml",""))){ children.add(new ScenarioAsATestNode(this, scenarioName, Scenario.getMeaningfulNameFromScenarioFile(f))); }else{ children.add(new ScenarioNode(this, scenarioName, Scenario.getMeaningfulNameFromScenarioFile(f))); } } } else if(fileNameToLower.endsWith(".class") && ! fileNameToLower.endsWith("$py.class")){ // class File root = (File) this.getRootUserObject(); String className; try { className = StringUtils.getClassName(f.getPath(), root.getPath()); } catch (Throwable e) { log.log(Level.FINE, "Unable to extract class name", e); continue; } Class testClass; try { testClass = LoadersManager.getInstance() .getLoader().loadClass(className); /* * Check the class is a non abstract test */ boolean isAbstract = Modifier.isAbstract(testClass.getModifiers()); if (!isAbstract) { // JUnit3 style test case or fixture if (TestCase.class.isAssignableFrom(testClass)) { try { /** * if the class don't have empty * constractor it will not show * in the tree */ testClass.getConstructor(new Class[0]); } catch (Throwable t) { continue; } /** * check if class is a Fixture and the Option to * show i ton tests tree is avilable */ boolean fixturesOnTestTree = "false".equals( JSystemProperties.getInstance().getPreference( FrameworkOptions.FIXTURES_ON_TEST_TREE)); if (Fixture.class.isAssignableFrom(testClass) && !fixturesOnTestTree) { if (TestFilterManager.getInstance().filter(testClass.getName())) { continue; } children.add(new FixtureNode(this, testClass.getName())); } else { children.add(new TestCaseNode(this, testClass)); } // JUnit 4 style test case } else { children.add(new TestCaseNode(this, testClass)); } } } catch (Throwable ex) { if (loadErrors == null) { loadErrors = new Vector(); loadErrors.addElement(new String[] { "Class name", "Method name", "Error cause" }); } loadErrors.addElement(new String[] { className, " ", ex.getClass().getName() + ": " + ex.getMessage() }); continue; } } } } else if (child[i] instanceof JarEntry) { JarEntry entry = (JarEntry) child[i]; if (entry.isDirectory()) { children.add(new JarEntryNode(this, entry)); } else { String className; try { className = StringUtils.getClassName(entry.getName(), ""); } catch (Exception e) { log.log(Level.FINE, "Unable to extract class name", e); continue; } try { Class testClass = LoadersManager.getInstance() .getLoader().loadClass(className); if (SystemTestCase.class.isAssignableFrom(testClass)) { children.add(new TestCaseNode(this, testClass)); } } catch (Throwable ignore) { log.log(Level.FINE, "Fail to add class", ignore); } } } } if("true".equals(JSystemProperties.getInstance().getPreferenceOrDefault(FrameworkOptions.SORT_ASSETS_TREE))){ Collections.sort(children); } } protected Object getRootUserObject() { if (parent instanceof RootNode) { return getUserObject(); } else { return ((AssetNode) parent).getRootUserObject(); } } protected int getTestsCount() { if(children == null){ return 0; } int size = children.size(); int count = 0; for (int i = 0; i < size; i++) { count += ((AssetNode) children.elementAt(i)).getTestsCount(); } return count; } @SuppressWarnings("unchecked") public void cleanLeafsWithoutTests() { if (isLeaf()) { return; } Vector<AssetNode> c = (Vector<AssetNode>) children.clone(); for (int i = 0; i < c.size(); i++) { AssetNode n = (AssetNode) c.elementAt(i); if (n.getTestsCount() == 0) { children.removeElement(n); } } for (int i = 0; i < children.size(); i++) { AssetNode n = (AssetNode) children.elementAt(i); n.cleanLeafsWithoutTests(); } } private boolean isJar(File file) { String filePath = file.getPath().toLowerCase(); return filePath.endsWith(".jar"); } private boolean exludedJar(File f) { return true; } public Enumeration<Object> getAllChildren() { Vector<Object> tmp = new Vector<Object>(); get(this, tmp); return tmp.elements(); } public int getSelectedChildrenCount() { Vector<Object> tmp = new Vector<Object>(); get(this, tmp); return tmp.size(); } // Get all the children @SuppressWarnings("unchecked") private void get(AssetNode node, Vector v) { if (node.children() == null) { return; } // copy the vector for (Enumeration e = node.children(); e.hasMoreElements();) { v.addElement(e.nextElement()); } for (Enumeration e = node.children(); e.hasMoreElements();) { AssetNode child = (AssetNode) e.nextElement(); get(child, v); } } public boolean isSelected() { return isSelected; } public void setSelected(boolean status) { boolean statusChanged = status != isSelected; isSelected = status; if (statusChanged){ if (isSelected) { TestTreePanel.currentSelectedTests++; } else { TestTreePanel.currentSelectedTests--; } } selectChildren(status); } public void toggleSelection() { setSelected(!isSelected); } private void selectChildren(boolean isSelected) { if (children == null) { return; } for (int i = 0; i < children.size(); i++) { ((AssetNode) children.get(i)).setSelected(isSelected); } } protected void loadDefaultSelection(Scenario selector) { if (children == null) { return; } for (int i = 0; i < children.size(); i++) { ((AssetNode) children.get(i)).loadDefaultSelection(selector); } } /** * @return Returns the isClassPath. */ public boolean isClassPath() { return isClassPath; } /** * @param isClassPath * The isClassPath to set. */ public void setClassPath(boolean isClassPath) { this.isClassPath = isClassPath; } /** * Utility function to build the real tree table model. This is done by going * recursively all over the XML document. * The idea is: * 1. Find all sub system objects * 2. Find all fields that are not in the sut * @param root * @param doc * @param nonModelDoc * @return new SutTreeNode * @throws Exception */ public static SutTreeNode createModel(SutTreeNode root, Document doc) throws Exception { // If the parent is the root node search for all the system object // found under the sut tag. if (root.getType() == NodeType.ROOT) { NodeList list = XPathAPI.selectNodeList(doc, "/sut/*[class]"); for (int i = 0; i < list.getLength(); i++) { Node n = list.item(i); if (n instanceof Element) { SutTreeNode node = new SutTreeNode(NodeType.MAIN_SO, n.getNodeName()); if (XmlUtils.isSubTagExist(n, "class")) { node.setClassName(XmlUtils.getSubTagValue(n, "class")); } node.setElement((Element) n); root.add(createModel(node, doc)); } } } else { Element element = root.getElement(); if (!XmlUtils.isSubTagExist(element, "class")) { // not a system object // continue return null; } String className = XmlUtils.getSubTagValue(element, "class"); Class<?> systemObjectClass = LoadersManager.getInstance().getLoader() .loadClass(className); // Go over all the existing nodes they can be sub // system objects or properties NodeList nodeList = element.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node n = nodeList.item(i); if (!(n instanceof Element)) { continue; } // Look for tags if (XmlUtils.isSubTagExist(n, "class")) { // if it as a class tag it's system object SutTreeNode sub_so; String atrib = ((Element) n).getAttribute("index"); String nodeName = ((Element)n).getNodeName(); if (atrib == null || atrib.equals("")) { sub_so = new SutTreeNode(NodeType.SUB_SO, nodeName); } else { sub_so = new SutTreeNode(NodeType.ARRAY_SO, nodeName); sub_so.setIndex(Integer.parseInt(atrib)); Field field = systemObjectClass.getField(nodeName); if(field != null && field.getType().isArray()){ sub_so.setArraySuperClassName(field.getType().getComponentType().getName()); } } sub_so.setElement((Element) n); // Set the name of the class sub_so.setClassName(XmlUtils.getSubTagValue(n, "class")); // See if there is underlying objects root.add(createModel(sub_so, doc)); } } if(root.getType().equals(NodeType.SUB_SO) || root.getType().equals(NodeType.MAIN_SO) || root.getType().equals(NodeType.ARRAY_SO)){ String cName = root.getClassName(); try { // Find all the methods that are supported Class<?> soClass = LoadersManager.getInstance().getLoader().loadClass(cName); SystemObjectAdaptor adaptor = new DefaultSystemObjectAdaptor(); Method[] methods = soClass.getMethods(); for(Method method: methods){ if(!adaptor.isMethodSupported(method)){ continue; } SystemObjectMethod tn = new SystemObjectMethod(method.getName(), AsmUtils.getParameterNames(method),method.getParameterTypes(),MethodElement.getMethodDescriptor(method)); root.add(tn); } } catch (Exception e){ e.printStackTrace(); } } } return root; } @Override public int compareTo(Object o) { return this.getUserObject().toString().compareTo(((AssetNode)o).getUserObject().toString()); } }