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.

DeclarativeTestUI.java 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package com.vaadin.tests.components;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.lang.annotation.ElementType;
  5. import java.lang.annotation.Retention;
  6. import java.lang.annotation.RetentionPolicy;
  7. import java.lang.annotation.Target;
  8. import java.lang.reflect.InvocationTargetException;
  9. import java.lang.reflect.Method;
  10. import java.util.logging.Level;
  11. import java.util.logging.Logger;
  12. import com.vaadin.server.VaadinRequest;
  13. import com.vaadin.ui.Component;
  14. import com.vaadin.ui.declarative.Design;
  15. /**
  16. * Declarative test UI. Provides simple instantiation of HTML designs located
  17. * under {@code uitest/src}. Also provides {@link OnLoad} annotation that lets
  18. * you easily hook up methods to run after the UI has been created. Note: you
  19. * <i>must</i> add the {@link DeclarativeUI} annotation to your subclass; not
  20. * doing this will result in program failure.
  21. */
  22. @SuppressWarnings("serial")
  23. public class DeclarativeTestUI extends AbstractTestUI {
  24. private Logger logger;
  25. private Component component;
  26. /**
  27. * Class marker indicating the design .html file to load
  28. */
  29. @Retention(RetentionPolicy.RUNTIME)
  30. @Target(ElementType.TYPE)
  31. public static @interface DeclarativeUI {
  32. String value();
  33. /**
  34. * Set this property to true if you provide an absolute path to your
  35. * design; otherwise, the DeclarativeTestUI logic will look for the HTML
  36. * design file under {@code vaadin_project/uitest/src/<package path>/}.
  37. */
  38. boolean absolutePath() default false;
  39. }
  40. /**
  41. * Method marker interface indicating that a method should be run after the
  42. * declarative UI has been created
  43. */
  44. @Retention(RetentionPolicy.RUNTIME)
  45. @Target(ElementType.METHOD)
  46. public static @interface OnLoad {
  47. }
  48. /**
  49. * Figure out the proper path for the HTML design file
  50. */
  51. private String getDesignPath() {
  52. Class<?> clazz = getClass();
  53. String designFilePath = null;
  54. if (clazz.getAnnotation(DeclarativeUI.class).absolutePath()) {
  55. designFilePath = "";
  56. } else {
  57. // This is rather nasty.. but it works well enough for now.
  58. String userDir = System.getProperty("user.dir");
  59. designFilePath = userDir + "/uitest/src/"
  60. + clazz.getPackage().getName().replace('.', '/') + "/";
  61. }
  62. String designFileName = clazz.getAnnotation(DeclarativeUI.class)
  63. .value();
  64. return designFilePath + designFileName;
  65. }
  66. private Component readDesign() throws Exception {
  67. String path = getDesignPath();
  68. getLogger().log(Level.INFO, "Reading design from " + path);
  69. File file = new File(path);
  70. return Design.read(new FileInputStream(file));
  71. }
  72. @Override
  73. protected void setup(VaadinRequest request) {
  74. Class<?> clazz = getClass();
  75. if (clazz.isAnnotationPresent(DeclarativeUI.class)) {
  76. // Create component
  77. try {
  78. component = readDesign();
  79. } catch (Exception e1) {
  80. getLogger().log(Level.SEVERE, "Error reading design", e1);
  81. return;
  82. }
  83. addComponent(component);
  84. // Call on-load methods (if applicable)
  85. Method[] methods = clazz.getMethods();
  86. for (Method m : methods) {
  87. if (m.isAnnotationPresent(OnLoad.class)) {
  88. try {
  89. m.invoke(this, (Object[]) null);
  90. } catch (IllegalAccessException e) {
  91. getLogger().log(Level.SEVERE,
  92. "Error invoking @OnLoad method", e);
  93. return;
  94. } catch (IllegalArgumentException e) {
  95. getLogger().log(Level.SEVERE,
  96. "Error invoking @OnLoad method", e);
  97. return;
  98. } catch (InvocationTargetException e) {
  99. getLogger().log(Level.SEVERE,
  100. "Error invoking @OnLoad method", e);
  101. return;
  102. }
  103. }
  104. }
  105. } else {
  106. throw new IllegalStateException(
  107. "Cannot find declarative UI annotation");
  108. }
  109. }
  110. /**
  111. * Get access to the declaratively created component. This method typecasts
  112. * the component to the receiving type; if there's a mismatch between what
  113. * you expect and what's written in the design, this will fail with a
  114. * ClassCastException.
  115. *
  116. * @return a Vaadin component
  117. */
  118. @SuppressWarnings("unchecked")
  119. public <T extends Component> T getComponent() {
  120. try {
  121. return (T) component;
  122. } catch (ClassCastException ex) {
  123. getLogger().log(Level.SEVERE, "Component code/design type mismatch",
  124. ex);
  125. }
  126. return null;
  127. }
  128. /**
  129. * Get access to the logger of this class
  130. *
  131. * @return a Logger instance
  132. */
  133. protected Logger getLogger() {
  134. if (logger == null) {
  135. logger = Logger.getLogger(getClass().getName());
  136. }
  137. return logger;
  138. }
  139. }