package com.itmill.toolkit.tests.testbench; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.List; import com.itmill.toolkit.Application; import com.itmill.toolkit.data.Property; import com.itmill.toolkit.data.util.HierarchicalContainer; import com.itmill.toolkit.terminal.Sizeable; import com.itmill.toolkit.ui.Component; import com.itmill.toolkit.ui.CustomComponent; import com.itmill.toolkit.ui.ExpandLayout; import com.itmill.toolkit.ui.Label; import com.itmill.toolkit.ui.Panel; import com.itmill.toolkit.ui.SplitPanel; import com.itmill.toolkit.ui.Tree; import com.itmill.toolkit.ui.Window; /** * TestBench finds out testable classes within given java packages and adds them * to menu from where they can be executed. Class is considered testable if it * is of class CustomComponent. * * Note: edit TestBench.testablePackages array * * @author IT Mill Ltd. * */ public class TestBench extends com.itmill.toolkit.Application implements Property.ValueChangeListener { // Add here packages which are used for finding testable classes String[] testablePackages = { "com.itmill.toolkit.demo.testbench" }; HierarchicalContainer testables = new HierarchicalContainer(); Window mainWindow = new Window("TestBench window"); // Main layout consists of tree menu and body layout SplitPanel mainLayout = new SplitPanel(SplitPanel.ORIENTATION_HORIZONTAL); Tree menu; Panel bodyLayout = new Panel(); HashMap itemCaptions = new HashMap(); public void init() { // Add testable classes to hierarchical container for (int p = 0; p < testablePackages.length; p++) { testables.addItem(testablePackages[p]); try { List testableClasses = getTestableClassesForPackage(testablePackages[p]); for (Iterator it = testableClasses.iterator(); it.hasNext();) { Class t = (Class) it.next(); // ignore TestBench itself if (t.equals(TestBench.class)) { continue; } try { testables.addItem(t); itemCaptions.put(t, t.getName()); testables.setParent(t, testablePackages[p]); continue; } catch (Exception e) { try { testables.addItem(t); itemCaptions.put(t, t.getName()); testables.setParent(t, testablePackages[p]); continue; } catch (Exception e1) { e1.printStackTrace(); } } } } catch (Exception e) { e.printStackTrace(); } } menu = new Tree("Testables", testables); for (Iterator i = itemCaptions.keySet().iterator(); i.hasNext();) { Class testable = (Class) i.next(); // simplify captions String name = testable.getName().substring( testable.getName().lastIndexOf('.') + 1); menu.setItemCaption(testable, name); } // expand all root items for (Iterator i = menu.rootItemIds().iterator(); i.hasNext();) { menu.expandItemsRecursively(i.next()); } menu.addListener(this); menu.setImmediate(true); mainLayout.addComponent(menu); bodyLayout.addStyleName("light"); bodyLayout.setHeight(100); bodyLayout.setHeightUnits(Sizeable.UNITS_PERCENTAGE); bodyLayout.setLayout(new ExpandLayout()); mainLayout.addComponent(bodyLayout); mainLayout.setSplitPosition(30); mainWindow.setLayout(mainLayout); setMainWindow(mainWindow); } private Component createTestable(Class c) { try { Application app = (Application) c.newInstance(); app.init(); return app.getMainWindow().getLayout(); } catch (Exception e) { try { CustomComponent cc = (CustomComponent) c.newInstance(); return cc; } catch (Exception e1) { e1.printStackTrace(); return new Label("Cannot create custom component: " + e1.toString()); } } } // Handle menu selection and update body public void valueChange(Property.ValueChangeEvent event) { bodyLayout.removeAllComponents(); bodyLayout.setCaption(null); Object o = menu.getValue(); if (o != null && o instanceof Class) { Class c = (Class) o; String title = c.getName(); bodyLayout.setCaption(title); bodyLayout.addComponent(createTestable(c)); } else { // NOP node selected or deselected tree item } } /** * Return all testable classes within given package. Class is considered * testable if it's superclass is CustomComponent. * * @param packageName * @return * @throws ClassNotFoundException */ public static List getTestableClassesForPackage(String packageName) throws Exception { ArrayList directories = new ArrayList(); try { ClassLoader cld = Thread.currentThread().getContextClassLoader(); if (cld == null) { throw new ClassNotFoundException("Can't get class loader."); } String path = packageName.replace('.', '/'); // Ask for all resources for the path Enumeration resources = cld.getResources(path); while (resources.hasMoreElements()) { URL url = (URL) resources.nextElement(); directories.add(new File(url.getFile())); } } catch (Exception x) { throw new Exception(packageName + " does not appear to be a valid package."); } ArrayList classes = new ArrayList(); // For every directory identified capture all the .class files for (Iterator it = directories.iterator(); it.hasNext();) { File directory = (File) it.next(); if (directory.exists()) { // Get the list of the files contained in the package String[] files = directory.list(); for (int j = 0; j < files.length; j++) { // we are only interested in .class files if (files[j].endsWith(".class")) { // removes the .class extension String p = packageName + '.' + files[j].substring(0, files[j].length() - 6); Class c = Class.forName(p); if (c.getSuperclass() != null) { if ((c.getSuperclass() .equals(com.itmill.toolkit.ui.CustomComponent.class))) { classes.add(c); } } } } } } return classes; } }