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.

ClasspathHelper.java 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package com.vaadin.tests.server;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.lang.reflect.Modifier;
  5. import java.net.URI;
  6. import java.nio.file.FileSystem;
  7. import java.nio.file.FileSystemNotFoundException;
  8. import java.nio.file.FileSystems;
  9. import java.nio.file.Files;
  10. import java.nio.file.Path;
  11. import java.util.ArrayList;
  12. import java.util.Collections;
  13. import java.util.List;
  14. import java.util.Locale;
  15. import java.util.Objects;
  16. import java.util.function.Predicate;
  17. import java.util.stream.Collectors;
  18. import java.util.stream.Stream;
  19. /**
  20. * Allows to get classes from the current classpath using classes FQN filter.
  21. * <p>
  22. * The methods in the class return all real (not anonymous and not private)
  23. * classes from the filtered classpath.
  24. *
  25. * @author Vaadin Ltd
  26. *
  27. */
  28. public class ClasspathHelper {
  29. public static final String COM_VAADIN_FILE_PREFIX = "com"
  30. + File.separatorChar + "vaadin" + File.separatorChar;
  31. private final Predicate<String> skipClassesFilter;
  32. public ClasspathHelper(Predicate<String> skipClassesFilter) {
  33. this.skipClassesFilter = skipClassesFilter;
  34. }
  35. public ClasspathHelper() {
  36. this(fqn -> false);
  37. }
  38. public Stream<Class<?>> getVaadinClassesFromClasspath(
  39. Predicate<String> classpathFilter,
  40. Predicate<Class<?>> classFilter) {
  41. return getRawClasspathEntries().stream().filter(classpathFilter)
  42. .map(File::new).map(file -> getVaadinClassesFromFile(file))
  43. .flatMap(List::stream).filter(classFilter)
  44. .filter(cls -> !cls.isSynthetic() && !cls.isAnonymousClass()
  45. && !Modifier.isPrivate(cls.getModifiers()));
  46. }
  47. public Stream<Class<?>> getVaadinClassesFromClasspath(
  48. Predicate<String> classpathFilter) {
  49. return getVaadinClassesFromClasspath(classpathFilter, cls -> true);
  50. }
  51. private List<Class<?>> getVaadinClassesFromFile(File classesRoot) {
  52. try {
  53. if (classesRoot.isDirectory()) {
  54. return Files.walk(classesRoot.toPath())
  55. .filter(Files::isRegularFile)
  56. .filter(path -> path.toFile().getName()
  57. .endsWith(".class"))
  58. .filter(path -> classesRoot.toPath().relativize(path)
  59. .toString().contains(COM_VAADIN_FILE_PREFIX))
  60. .map(path -> getClassFromFile(path,
  61. classesRoot.toPath()))
  62. .filter(Objects::nonNull).collect(Collectors.toList());
  63. } else if (classesRoot.getName().toLowerCase(Locale.ENGLISH)
  64. .endsWith(".jar")) {
  65. URI uri = URI.create("jar:" + classesRoot.toURI());
  66. FileSystem fileSystem;
  67. try {
  68. fileSystem = FileSystems.getFileSystem(uri);
  69. } catch (FileSystemNotFoundException e) {
  70. fileSystem = null;
  71. }
  72. if (fileSystem == null) {
  73. fileSystem = FileSystems.newFileSystem(uri,
  74. Collections.emptyMap());
  75. }
  76. Path root = fileSystem.getPath(File.separator);
  77. return Files.walk(root).filter(Files::isRegularFile)
  78. .filter(path -> path.toUri().getSchemeSpecificPart()
  79. .endsWith(".class"))
  80. .filter(path -> root.relativize(path).toString()
  81. .contains(COM_VAADIN_FILE_PREFIX))
  82. .map(path -> getClassFromFile(path, root))
  83. .filter(Objects::nonNull).collect(Collectors.toList());
  84. }
  85. return null;
  86. } catch (IOException e) {
  87. throw new RuntimeException(e);
  88. }
  89. }
  90. private Class<?> getClassFromFile(Path path, Path root) {
  91. Path relative = root.relativize(path);
  92. String name = relative.toString();
  93. name = name.substring(0, name.length() - ".class".length());
  94. name = name.replace(File.separatorChar, '.');
  95. if (skipClassesFilter.test(name)) {
  96. return null;
  97. }
  98. try {
  99. return Class.forName(name, false, getClass().getClassLoader());
  100. } catch (ClassNotFoundException e) {
  101. throw new RuntimeException(e);
  102. }
  103. }
  104. private static final List<String> getRawClasspathEntries() {
  105. List<String> locations = new ArrayList<>();
  106. String pathSep = System.getProperty("path.separator");
  107. String classpath = System.getProperty("java.class.path");
  108. if (classpath.startsWith("\"")) {
  109. classpath = classpath.substring(1);
  110. }
  111. if (classpath.endsWith("\"")) {
  112. classpath = classpath.substring(0, classpath.length() - 1);
  113. }
  114. String[] split = classpath.split(pathSep);
  115. for (int i = 0; i < split.length; i++) {
  116. String classpathEntry = split[i];
  117. locations.add(classpathEntry);
  118. }
  119. return locations;
  120. }
  121. }