diff options
author | Aleksi Hietanen <aleksi@vaadin.com> | 2016-10-14 11:41:06 +0300 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2016-10-24 07:55:31 +0000 |
commit | 2cdb3b39329232dcefee2ae61ded92f2c3fe54b0 (patch) | |
tree | e1bcdcab7065ae5b5723e8400580d50055aae77f /compatibility-server | |
parent | 02ed73dc9ea247b13fbef63007af6c3c53ad9423 (diff) | |
download | vaadin-framework-2cdb3b39329232dcefee2ae61ded92f2c3fe54b0.tar.gz vaadin-framework-2cdb3b39329232dcefee2ae61ded92f2c3fe54b0.zip |
Add utility for outputting the full declarative syntax of components
Change-Id: I4bc740154ffb5a30892b1859a7550a7aeff94fb3
Diffstat (limited to 'compatibility-server')
4 files changed, 353 insertions, 91 deletions
diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/ClasspathHelper.java b/compatibility-server/src/test/java/com/vaadin/tests/server/ClasspathHelper.java new file mode 100644 index 0000000000..d32718196b --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/ClasspathHelper.java @@ -0,0 +1,121 @@ +package com.vaadin.tests.server; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Modifier; +import java.net.URI; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Allows to get classes from the current classpath using classes FQN filter. + * <p> + * The methods in the class return all real (not anonymous and not private) + * classes from the filtered classpath. + * + * @author Vaadin Ltd + * + */ +class ClasspathHelper { + + private final Predicate<String> skipClassesFilter; + + ClasspathHelper(Predicate<String> skipClassesFilter) { + this.skipClassesFilter = skipClassesFilter; + } + + Stream<Class<?>> getVaadinClassesFromClasspath( + Predicate<String> classpathFilter, + Predicate<Class<?>> classFilter) { + return getRawClasspathEntries().stream().filter(classpathFilter) + .map(File::new).map(file -> getVaadinClassesFromFile(file)) + .flatMap(List::stream).filter(classFilter) + .filter(cls -> !cls.isSynthetic() && !cls.isAnonymousClass() + && !Modifier.isPrivate(cls.getModifiers())); + + } + + Stream<Class<?>> getVaadinClassesFromClasspath( + Predicate<String> classpathFilter) { + return getVaadinClassesFromClasspath(classpathFilter, cls -> true); + } + + private List<Class<?>> getVaadinClassesFromFile(File classesRoot) { + try { + if (classesRoot.isDirectory()) { + return Files.walk(classesRoot.toPath()) + .filter(Files::isRegularFile) + .filter(path -> path.toFile().getName() + .endsWith(".class")) + .filter(path -> classesRoot.toPath().relativize(path) + .toString().contains("com/vaadin/")) + .map(path -> getClassFromFile(path, + classesRoot.toPath())) + .filter(Objects::nonNull).collect(Collectors.toList()); + } else if (classesRoot.getName().toLowerCase(Locale.ENGLISH) + .endsWith(".jar")) { + URI uri = URI.create("jar:file:" + classesRoot.getPath()); + Path root = FileSystems + .newFileSystem(uri, Collections.emptyMap()) + .getPath("/"); + return Files.walk(root).filter(Files::isRegularFile) + .filter(path -> path.toUri().getSchemeSpecificPart() + .endsWith(".class")) + .filter(path -> root.relativize(path).toString() + .contains("com/vaadin/")) + .map(path -> getClassFromFile(path, root)) + .filter(Objects::nonNull).collect(Collectors.toList()); + } + return null; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private Class<?> getClassFromFile(Path path, Path root) { + Path relative = root.relativize(path); + String name = relative.toString(); + name = name.substring(0, name.length() - ".class".length()); + name = name.replace('/', '.'); + if (skipClassesFilter.test(name)) { + return null; + } + try { + return Class.forName(name, false, getClass().getClassLoader()); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + private final static List<String> getRawClasspathEntries() { + List<String> locations = new ArrayList<>(); + + String pathSep = System.getProperty("path.separator"); + String classpath = System.getProperty("java.class.path"); + + if (classpath.startsWith("\"")) { + classpath = classpath.substring(1); + } + if (classpath.endsWith("\"")) { + classpath = classpath.substring(0, classpath.length() - 1); + } + + String[] split = classpath.split(pathSep); + for (int i = 0; i < split.length; i++) { + String classpathEntry = split[i]; + locations.add(classpathEntry); + } + + return locations; + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/ComponentDesignWriterUtility.java b/compatibility-server/src/test/java/com/vaadin/tests/server/ComponentDesignWriterUtility.java new file mode 100644 index 0000000000..15ae1c9cf4 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/ComponentDesignWriterUtility.java @@ -0,0 +1,204 @@ +package com.vaadin.tests.server; + +import java.io.File; +import java.lang.reflect.Modifier; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.navigator.Navigator; +import com.vaadin.ui.Component; +import com.vaadin.ui.DragAndDropWrapper; +import com.vaadin.ui.components.colorpicker.ColorPickerGradient; +import com.vaadin.ui.components.colorpicker.ColorPickerGrid; +import com.vaadin.ui.components.colorpicker.ColorPickerHistory; +import com.vaadin.ui.components.colorpicker.ColorPickerPopup; +import com.vaadin.ui.components.colorpicker.ColorPickerPreview; +import com.vaadin.ui.components.colorpicker.ColorPickerSelect; +import com.vaadin.ui.declarative.Design; +import com.vaadin.ui.declarative.DesignAttributeHandler; +import com.vaadin.ui.declarative.DesignContext; + +/** + * Utility class for outputting the declarative syntax of Vaadin components. + */ +public class ComponentDesignWriterUtility { + + private static final Set<String> WHITE_LIST_FQNS = new HashSet<>(); + static { + WHITE_LIST_FQNS.add(DragAndDropWrapper.class.getName()); + WHITE_LIST_FQNS.add(Navigator.EmptyView.class.getName()); + + WHITE_LIST_FQNS.add(ColorPickerGradient.class.getName()); + WHITE_LIST_FQNS.add(ColorPickerPopup.class.getName()); + WHITE_LIST_FQNS.add(ColorPickerPreview.class.getName()); + WHITE_LIST_FQNS.add(ColorPickerGrid.class.getName()); + WHITE_LIST_FQNS.add(ColorPickerSelect.class.getName()); + WHITE_LIST_FQNS.add(ColorPickerHistory.class.getName()); + + WHITE_LIST_FQNS + .add(com.vaadin.v7.ui.components.colorpicker.ColorPickerGradient.class + .getName()); + WHITE_LIST_FQNS + .add(com.vaadin.v7.ui.components.colorpicker.ColorPickerPopup.class + .getName()); + WHITE_LIST_FQNS + .add(com.vaadin.v7.ui.components.colorpicker.ColorPickerPreview.class + .getName()); + WHITE_LIST_FQNS + .add(com.vaadin.v7.ui.components.colorpicker.ColorPickerGrid.class + .getName()); + WHITE_LIST_FQNS + .add(com.vaadin.v7.ui.components.colorpicker.ColorPickerSelect.class + .getName()); + WHITE_LIST_FQNS + .add(com.vaadin.v7.ui.components.colorpicker.ColorPickerHistory.class + .getName()); + + // ================================================================== + // Classes that cannot be loaded + // ================================================================== + WHITE_LIST_FQNS.add( + "com.vaadin.server.communication.PushAtmosphereHandler$AtmosphereResourceListener"); + WHITE_LIST_FQNS + .add("com.vaadin.server.communication.PushAtmosphereHandler"); + WHITE_LIST_FQNS + .add("com.vaadin.server.communication.PushRequestHandler$2"); + WHITE_LIST_FQNS.add("com.vaadin.server.LegacyVaadinPortlet"); + WHITE_LIST_FQNS.add("com.vaadin.server.RestrictedRenderResponse"); + WHITE_LIST_FQNS + .add("com.vaadin.server.VaadinPortlet$VaadinGateInRequest"); + WHITE_LIST_FQNS.add( + "com.vaadin.server.VaadinPortlet$VaadinHttpAndPortletRequest"); + WHITE_LIST_FQNS + .add("com.vaadin.server.VaadinPortlet$VaadinLiferayRequest"); + WHITE_LIST_FQNS.add( + "com.vaadin.server.VaadinPortlet$VaadinWebLogicPortalRequest"); + WHITE_LIST_FQNS.add( + "com.vaadin.server.VaadinPortlet$VaadinWebSpherePortalRequest"); + WHITE_LIST_FQNS.add("com.vaadin.server.VaadinPortlet"); + WHITE_LIST_FQNS.add("com.vaadin.server.VaadinPortletRequest"); + } + + private static final Document document = new Document(""); + private static final DesignContext designContext = new DesignContext( + document); + + @SafeVarargs + public static List<String> getDeclarativeSyntax( + Class<? extends Component>... components) { + return getDeclarativeSyntax(Arrays.asList(components)); + } + + public static List<String> getDeclarativeSyntax( + List<Class<? extends Component>> components) { + DesignAttributeHandler.setWriteDefaultValues(true); + + List<String> declarativeStrings = components.stream() + .map(ComponentDesignWriterUtility::getDeclarativeSyntax) + .collect(Collectors.toList()); + + DesignAttributeHandler.setWriteDefaultValues(false); + return declarativeStrings; + } + + @Test + public void vaadin8ComponentsElementStartsWithVaadinPrefix() + throws URISyntaxException { + Assert.assertTrue(getVaadin8Components().stream() + .map(ComponentDesignWriterUtility::getDeclarativeSyntax) + .allMatch(element -> element.startsWith("<vaadin-"))); + } + + @Test + public void vaadin7ComponentsElementStartsWithVaadinPrefix() + throws URISyntaxException { + Assert.assertTrue(getVaadin7Components().stream() + .map(ComponentDesignWriterUtility::getDeclarativeSyntax) + .allMatch(element -> element.startsWith("<vaadin7-"))); + } + + private static String getDeclarativeSyntax( + Class<? extends Component> componentClass) { + try { + Component component = componentClass.newInstance(); + Element element = document.createElement(Design.getComponentMapper() + .componentToTag(component, designContext)); + component.writeDesign(element, designContext); + return element.toString(); + } catch (Exception e) { + throw new RuntimeException( + "Could not write the declarative syntax for component " + + componentClass.getName(), + e); + } + } + + public static void main(String[] args) throws URISyntaxException { + System.out.println("Vaadin 8 components:"); + printFullDeclarativeSyntax(getVaadin8Components()); + + System.out.println("Vaadin 7 components:"); + printFullDeclarativeSyntax(getVaadin7Components()); + + System.out.println("\nClases that are explicitely excluded from " + + "the design support introspection:"); + WHITE_LIST_FQNS.forEach(System.out::println); + } + + private static void printFullDeclarativeSyntax( + List<Class<? extends Component>> components) { + DesignAttributeHandler.setWriteDefaultValues(true); + components.stream().forEach(component -> System.out + .println(getDeclarativeSyntax(component))); + DesignAttributeHandler.setWriteDefaultValues(false); + } + + private static List<Class<? extends Component>> getVaadin8Components() + throws URISyntaxException { + List<Class<? extends Component>> vaadin8Components = getVaadinComponentsFromClasspath( + "/server/target/classes"); + if (vaadin8Components.isEmpty()) { + throw new RuntimeException( + "No vaadin 8 components found on your classpath."); + } + return vaadin8Components; + } + + private static List<Class<? extends Component>> getVaadin7Components() + throws URISyntaxException { + List<Class<? extends Component>> vaadin7Components = getVaadinComponentsFromClasspath( + "compatibility-server"); + if (vaadin7Components.isEmpty()) { + throw new RuntimeException( + "No vaadin 7 components found on your classpath."); + } + return vaadin7Components; + } + + @SuppressWarnings("unchecked") + private static List<Class<? extends Component>> getVaadinComponentsFromClasspath( + String classpathFilter) throws URISyntaxException { + File testRoot = new File( + ComponentDesignWriterUtility.class.getResource("/").toURI()); + List<Class<? extends Component>> classes = new ClasspathHelper( + WHITE_LIST_FQNS::contains).getVaadinClassesFromClasspath( + entry -> entry.contains(classpathFilter) + && !testRoot.equals(new File(entry)), + cls -> Component.class.isAssignableFrom(cls) + && !cls.isInterface() + && !Modifier.isAbstract(cls.getModifiers())) + .map(cls -> (Class<? extends Component>) cls) + .collect(Collectors.toList()); + return classes; + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/DeprecatedTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/DeprecatedTest.java index e8475b6750..671fc65080 100644 --- a/compatibility-server/src/test/java/com/vaadin/tests/server/DeprecatedTest.java +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/DeprecatedTest.java @@ -16,19 +16,8 @@ package com.vaadin.tests.server; import java.io.File; -import java.io.IOException; -import java.lang.reflect.Modifier; -import java.net.URI; import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.stream.Collectors; +import java.util.concurrent.atomic.AtomicInteger; import org.junit.Assert; import org.junit.Test; @@ -39,86 +28,24 @@ import org.junit.Test; */ public class DeprecatedTest { - private static String CLASS_SUFFIX = ".class"; - @Test public void allTypesAreDeprecated() throws URISyntaxException { - URL url = DeprecatedTest.class.getResource("/"); - File file = new File(url.toURI()); - List<File> classpath = getRawClasspathEntries().stream() - .filter(entry -> entry.contains("compatibility-server")) - .map(File::new).filter(fileEntry -> !fileEntry.equals(file)) - .collect(Collectors.toList()); - Assert.assertFalse(classpath.isEmpty()); - classpath.forEach(this::checkDeprecatedClasses); - } - - private void checkDeprecatedClasses(File classesRoot) { - try { - if (classesRoot.isDirectory()) { - Files.walk(classesRoot.toPath()).filter(Files::isRegularFile) - .filter(path -> path.toFile().getName() - .endsWith(CLASS_SUFFIX)) - .forEach(path -> checkDeprecatedClass(path, - classesRoot.toPath())); - } else if (classesRoot.getName().toLowerCase(Locale.ENGLISH) - .endsWith(".jar")) { - URI uri = URI.create("jar:file:" + classesRoot.getPath()); - Path root = FileSystems - .newFileSystem(uri, Collections.emptyMap()) - .getPath("/"); - Files.walk(root).filter(Files::isRegularFile) - .filter(path -> path.toUri().getSchemeSpecificPart() - .endsWith(CLASS_SUFFIX)) - .forEach(path -> checkDeprecatedClass(path, root)); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private void checkDeprecatedClass(Path path, Path root) { - Path relative = root.relativize(path); - String name = relative.toString(); - name = name.substring(0, name.length() - CLASS_SUFFIX.length()); - name = name.replace('/', '.'); - try { - Class<?> clazz = Class.forName(name); - if (clazz.isSynthetic() || clazz.isAnonymousClass()) { - return; - } - if (Modifier.isPrivate(clazz.getModifiers())) { - return; - } - Assert.assertNotNull( - "Class " + clazz - + " is in compatability package and it's not deprecated", - clazz.getAnnotation(Deprecated.class)); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } + AtomicInteger count = new AtomicInteger(0); + + File testRoot = new File(DeprecatedTest.class.getResource("/").toURI()); + + new ClasspathHelper(fqn -> false) + .getVaadinClassesFromClasspath( + entry -> entry.contains("compatibility-server") + && !testRoot.equals(new File(entry))) + .forEach(cls -> { + count.incrementAndGet(); + Assert.assertNotNull( + "Class " + cls + + " is in compatability package and it's not deprecated", + cls.getAnnotation(Deprecated.class)); + }); + Assert.assertTrue(count.get() > 0); } - private final static List<String> getRawClasspathEntries() { - // try to keep the order of the classpath - List<String> locations = new ArrayList<>(); - - String pathSep = System.getProperty("path.separator"); - String classpath = System.getProperty("java.class.path"); - - if (classpath.startsWith("\"")) { - classpath = classpath.substring(1); - } - if (classpath.endsWith("\"")) { - classpath = classpath.substring(0, classpath.length() - 1); - } - - String[] split = classpath.split(pathSep); - for (int i = 0; i < split.length; i++) { - String classpathEntry = split[i]; - locations.add(classpathEntry); - } - - return locations; - } } diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/VaadinClasses.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/VaadinClasses.java index b37f1bbe86..251f8b0223 100644 --- a/compatibility-server/src/test/java/com/vaadin/v7/tests/VaadinClasses.java +++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/VaadinClasses.java @@ -3,6 +3,7 @@ package com.vaadin.v7.tests; import java.io.IOException; import java.util.List; +import com.vaadin.ui.Component; import com.vaadin.v7.ui.Field; @SuppressWarnings("deprecation") @@ -11,11 +12,20 @@ public class VaadinClasses { public static List<Class<? extends Field>> getFields() { try { return com.vaadin.tests.VaadinClasses.findClasses(Field.class, - "com.vaadin.ui"); + "com.vaadin.v7.ui"); } catch (IOException e) { e.printStackTrace(); return null; } } + public static List<Class<? extends Component>> getComponents() { + try { + return com.vaadin.tests.VaadinClasses.findClasses(Component.class, + "com.vaadin.v7.ui"); + } catch (IOException e) { + throw new RuntimeException( + "Could not find all Vaadin component classes", e); + } + } } |