You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TestBench.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*
  2. @ITMillApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.tests;
  5. import java.io.File;
  6. import java.net.URL;
  7. import java.util.ArrayList;
  8. import java.util.Enumeration;
  9. import java.util.HashMap;
  10. import java.util.Iterator;
  11. import java.util.List;
  12. import com.vaadin.Application;
  13. import com.vaadin.data.Property;
  14. import com.vaadin.data.util.HierarchicalContainer;
  15. import com.vaadin.terminal.ExternalResource;
  16. import com.vaadin.ui.Component;
  17. import com.vaadin.ui.CustomComponent;
  18. import com.vaadin.ui.ExpandLayout;
  19. import com.vaadin.ui.Label;
  20. import com.vaadin.ui.Layout;
  21. import com.vaadin.ui.Link;
  22. import com.vaadin.ui.Panel;
  23. import com.vaadin.ui.SplitPanel;
  24. import com.vaadin.ui.Tree;
  25. import com.vaadin.ui.UriFragmentUtility;
  26. import com.vaadin.ui.VerticalLayout;
  27. import com.vaadin.ui.Window;
  28. import com.vaadin.ui.UriFragmentUtility.FragmentChangedEvent;
  29. /**
  30. * TestBench finds out testable classes within given java packages and adds them
  31. * to menu from where they can be executed. Class is considered testable if it
  32. * is of class Application or CustomComponent.
  33. *
  34. * Note: edit TestBench.testablePackages array
  35. *
  36. * @author IT Mill Ltd.
  37. *
  38. */
  39. public class TestBench extends com.vaadin.Application implements
  40. Property.ValueChangeListener {
  41. // Add here packages which are used for finding testable classes
  42. String[] testablePackages = { "com.vaadin.tests", "com.vaadin.demo",
  43. "com.vaadin.demo.colorpicker", "com.vaadin.demo.reservation",
  44. "com.vaadin.demo.features", "com.vaadin.tests.tickets",
  45. "com.vaadin.tests.book" };
  46. HierarchicalContainer testables = new HierarchicalContainer();
  47. Window mainWindow = new Window("TestBench window");
  48. // Main layout consists of tree menu and body layout
  49. SplitPanel mainLayout = new SplitPanel(SplitPanel.ORIENTATION_HORIZONTAL);
  50. Tree menu;
  51. Panel bodyLayout = new Panel();
  52. HashMap itemCaptions = new HashMap();
  53. @Override
  54. public void init() {
  55. // Add testable classes to hierarchical container
  56. for (int p = 0; p < testablePackages.length; p++) {
  57. testables.addItem(testablePackages[p]);
  58. try {
  59. final List testableClasses = getTestableClassesForPackage(testablePackages[p]);
  60. for (final Iterator it = testableClasses.iterator(); it
  61. .hasNext();) {
  62. final Class t = (Class) it.next();
  63. // ignore TestBench itself
  64. if (t.equals(TestBench.class)) {
  65. continue;
  66. }
  67. try {
  68. testables.addItem(t);
  69. itemCaptions.put(t, t.getName());
  70. testables.setParent(t, testablePackages[p]);
  71. testables.setChildrenAllowed(t, false);
  72. continue;
  73. } catch (final Exception e) {
  74. try {
  75. testables.addItem(t);
  76. itemCaptions.put(t, t.getName());
  77. testables.setParent(t, testablePackages[p]);
  78. testables.setChildrenAllowed(t, false);
  79. continue;
  80. } catch (final Exception e1) {
  81. e1.printStackTrace();
  82. }
  83. }
  84. }
  85. } catch (final Exception e) {
  86. e.printStackTrace();
  87. }
  88. }
  89. menu = new Tree("Testables", testables);
  90. for (final Iterator i = itemCaptions.keySet().iterator(); i.hasNext();) {
  91. final Class testable = (Class) i.next();
  92. // simplify captions
  93. final String name = testable.getName().substring(
  94. testable.getName().lastIndexOf('.') + 1);
  95. menu.setItemCaption(testable, name);
  96. }
  97. // expand all root items
  98. for (final Iterator i = menu.rootItemIds().iterator(); i.hasNext();) {
  99. menu.expandItemsRecursively(i.next());
  100. }
  101. menu.addListener(this);
  102. menu.setImmediate(true);
  103. menu.setNullSelectionAllowed(false);
  104. VerticalLayout lo = new VerticalLayout();
  105. lo.addComponent(menu);
  106. UriFragmentUtility uri = new UriFragmentUtility();
  107. lo.addComponent(uri);
  108. uri.addListener(new UriFragmentUtility.FragmentChangedListener() {
  109. public void fragmentChanged(FragmentChangedEvent source) {
  110. String fragment = source.getUriFragmentUtility().getFragment();
  111. if (fragment != null && !"".equals(fragment)) {
  112. // try to find a proper test class
  113. // exact match
  114. Iterator iterator = menu.getItemIds().iterator();
  115. while (iterator.hasNext()) {
  116. Object next = iterator.next();
  117. if (next instanceof Class) {
  118. Class c = (Class) next;
  119. String string = c.getName();
  120. if (string.equals(fragment)) {
  121. menu.setValue(c);
  122. mainLayout.setSplitPosition(0);
  123. return;
  124. }
  125. }
  126. }
  127. // simple name match
  128. iterator = menu.getItemIds().iterator();
  129. while (iterator.hasNext()) {
  130. Object next = iterator.next();
  131. if (next instanceof Class) {
  132. Class c = (Class) next;
  133. String string = c.getSimpleName();
  134. if (string.equals(fragment)) {
  135. menu.setValue(c);
  136. mainLayout.setSplitPosition(0);
  137. return;
  138. }
  139. }
  140. }
  141. // ticket match
  142. iterator = menu.getItemIds().iterator();
  143. while (iterator.hasNext()) {
  144. Object next = iterator.next();
  145. if (next instanceof Class) {
  146. Class c = (Class) next;
  147. String string = c.getSimpleName();
  148. if (string.startsWith("Ticket" + fragment)) {
  149. menu.setValue(c);
  150. mainLayout.setSplitPosition(0);
  151. return;
  152. }
  153. }
  154. }
  155. // just partly mach lowercase
  156. iterator = menu.getItemIds().iterator();
  157. while (iterator.hasNext()) {
  158. Object next = iterator.next();
  159. if (next instanceof Class) {
  160. Class c = (Class) next;
  161. String string = c.getSimpleName();
  162. if (string.toLowerCase().contains(
  163. fragment.toLowerCase())) {
  164. menu.setValue(c);
  165. mainLayout.setSplitPosition(0);
  166. return;
  167. }
  168. }
  169. }
  170. getMainWindow().showNotification(
  171. "No potential matc for #" + fragment);
  172. }
  173. }
  174. });
  175. mainLayout.addComponent(lo);
  176. bodyLayout.addStyleName("light");
  177. bodyLayout.setSizeFull();
  178. bodyLayout.setLayout(new ExpandLayout());
  179. mainLayout.addComponent(bodyLayout);
  180. mainLayout.setSplitPosition(30);
  181. mainWindow.setLayout(mainLayout);
  182. setMainWindow(mainWindow);
  183. }
  184. private Component createTestable(Class c) {
  185. try {
  186. final Application app = (Application) c.newInstance();
  187. app.init();
  188. Layout lo = app.getMainWindow().getLayout();
  189. lo.setParent(null);
  190. return lo;
  191. } catch (final Exception e) {
  192. try {
  193. final CustomComponent cc = (CustomComponent) c.newInstance();
  194. cc.setSizeFull();
  195. return cc;
  196. } catch (final Exception e1) {
  197. e1.printStackTrace();
  198. VerticalLayout lo = new VerticalLayout();
  199. lo.addComponent(new Label(
  200. "Cannot create application / custom component: "
  201. + e1.toString()));
  202. Link l = new Link("Try opening via app runner",
  203. new ExternalResource("../run/" + c.getName()));
  204. lo.addComponent(l);
  205. return lo;
  206. }
  207. }
  208. }
  209. // Handle menu selection and update body
  210. public void valueChange(Property.ValueChangeEvent event) {
  211. bodyLayout.removeAllComponents();
  212. bodyLayout.setCaption(null);
  213. final Object o = menu.getValue();
  214. if (o != null && o instanceof Class) {
  215. final Class c = (Class) o;
  216. final String title = c.getName();
  217. bodyLayout.setCaption(title);
  218. bodyLayout.addComponent(createTestable(c));
  219. } else {
  220. // NOP node selected or deselected tree item
  221. }
  222. }
  223. /**
  224. * Return all testable classes within given package. Class is considered
  225. * testable if it's superclass is Application or CustomComponent.
  226. *
  227. * @param packageName
  228. * @return
  229. * @throws ClassNotFoundException
  230. */
  231. public static List getTestableClassesForPackage(String packageName)
  232. throws Exception {
  233. final ArrayList directories = new ArrayList();
  234. try {
  235. final ClassLoader cld = Thread.currentThread()
  236. .getContextClassLoader();
  237. if (cld == null) {
  238. throw new ClassNotFoundException("Can't get class loader.");
  239. }
  240. final String path = packageName.replace('.', '/');
  241. // Ask for all resources for the path
  242. final Enumeration resources = cld.getResources(path);
  243. while (resources.hasMoreElements()) {
  244. final URL url = (URL) resources.nextElement();
  245. directories.add(new File(url.getFile()));
  246. }
  247. } catch (final Exception x) {
  248. throw new Exception(packageName
  249. + " does not appear to be a valid package.");
  250. }
  251. final ArrayList classes = new ArrayList();
  252. // For every directory identified capture all the .class files
  253. for (final Iterator it = directories.iterator(); it.hasNext();) {
  254. final File directory = (File) it.next();
  255. if (directory.exists()) {
  256. // Get the list of the files contained in the package
  257. final String[] files = directory.list();
  258. for (int j = 0; j < files.length; j++) {
  259. // we are only interested in .class files
  260. if (files[j].endsWith(".class")) {
  261. // removes the .class extension
  262. final String p = packageName + '.'
  263. + files[j].substring(0, files[j].length() - 6);
  264. final Class c = Class.forName(p);
  265. if (c.getSuperclass() != null) {
  266. if ((c.getSuperclass()
  267. .equals(com.vaadin.Application.class))) {
  268. classes.add(c);
  269. } else if ((c.getSuperclass()
  270. .equals(com.vaadin.ui.CustomComponent.class))) {
  271. classes.add(c);
  272. }
  273. }
  274. // for (int i = 0; i < c.getInterfaces().length; i++) {
  275. // Class cc = c.getInterfaces()[i];
  276. // if (c.getInterfaces()[i].equals(Testable.class)) {
  277. // // Class is testable
  278. // classes.add(c);
  279. // }
  280. // }
  281. }
  282. }
  283. } else {
  284. throw new ClassNotFoundException(packageName + " ("
  285. + directory.getPath()
  286. + ") does not appear to be a valid package");
  287. }
  288. }
  289. return classes;
  290. }
  291. }