protected Set<Class> processFileUrl(URL url, String basepath, Class clazz) throws IOException { Set<Class> set = new HashSet<Class>(); String urlBase = url.getFile(); // We can't URLDecoder.decode(path) since some encoded chars are allowed on file uris urlBase = urlBase.replaceAll("%20", " "); File dir = new File(urlBase); if (!dir.isDirectory()) { logger.warn("Cannot process File URL: " + url + ". Path is not a directory"); return set; } Collection<File> files = FileUtils.listFiles(new File(urlBase), new String[] {"class"}, true); for (File file : files) { try { InputStream classStream = new FileInputStream(file); ClassReader reader = new ClosableClassReader(classStream); ClassScanner visitor = getScanner(clazz); reader.accept(visitor, 0); if (visitor.isMatch()) { Class c = loadClass(visitor.getClassName()); if (c != null) { set.add(c); } } } catch (IOException e) { if (logger.isDebugEnabled()) { Throwable t = ExceptionHelper.getRootException(e); logger.debug(String.format("%s: caused by: %s", e.toString(), t.toString())); } } } return set; }
protected Set<Class> processFileUrl(URL url, String basepath, Class clazz) throws IOException { Set<Class> set = new HashSet<Class>(); String urlBase = url.getFile(); urlBase = URLDecoder.decode(urlBase); Collection<File> files = FileUtils.listFiles(new File(urlBase), new String[] {"class"}, true); for (File file : files) { try { ClassReader reader = new ClassReader(new FileInputStream(file)); ClassScanner visitor = getScanner(clazz); reader.accept(visitor, 0); if (visitor.isMatch()) { Class c = loadClass(visitor.getClassName()); if (c != null) { set.add(c); } } } catch (IOException e) { if (logger.isDebugEnabled()) { Throwable t = ExceptionHelper.getRootException(e); logger.debug(String.format("%s: caused by: %s", e.toString(), t.toString())); } } } return set; }
protected Set<Class> processJarUrl(URL url, String basepath, Class clazz) throws IOException { Set<Class> set = new HashSet<Class>(); String path = url.getFile().substring(5, url.getFile().indexOf("!")); JarFile jar = new JarFile(path); for (Enumeration entries = jar.entries(); entries.hasMoreElements(); ) { JarEntry entry = (JarEntry) entries.nextElement(); if (entry.getName().startsWith(basepath) && entry.getName().endsWith(".class")) { try { String name = entry.getName(); // Ignore anonymous // TODO RM what about the other anonymous classes like $2, $3 ? if (name.contains("$1")) { continue; } URL classURL = classLoader.getResource(name); ClassReader reader = new ClassReader(classURL.openStream()); ClassScanner visitor = getScanner(clazz); reader.accept(visitor, 0); if (visitor.isMatch()) { Class c = loadClass(visitor.getClassName()); if (c != null) { set.add(c); } } } catch (Exception e) { if (logger.isDebugEnabled()) { Throwable t = ExceptionHelper.getRootException(e); logger.debug(String.format("%s: caused by: %s", e.toString(), t.toString())); } } } } return set; }
private void generateMetadata(Archiver archiver) throws ArchiverException, MojoExecutionException { Log log = getLog(); File tmpServicesDir = new File(new File(tmpDirectory, "META-INF"), "services"); File buildServicesDir = new File(new File(buildOutputDirectory, "META-INF"), "services"); if (!tmpServicesDir.mkdirs()) { throw new MojoExecutionException( "Error while creating the directory: " + tmpServicesDir.getPath()); } log.debug("Initializing class scanner ..."); ClassScanner scanner = new ClassScanner(buildOutputDirectory); for (Artifact artifact : filterArtifacts( (Set<Artifact>) project.getArtifacts(), new ScopeArtifactFilter(Artifact.SCOPE_COMPILE))) { scanner.addToClasspath(artifact.getFile()); } List<ServiceLocator> serviceLocators = new ArrayList<ServiceLocator>(serviceClassNames.length); for (String serviceClassName : serviceClassNames) { // If the user provided its own service file, skip generation File file = new File(buildServicesDir, serviceClassName); if (file.exists()) { log.debug(file + " exists; don't scan for " + serviceClassName + " implementation"); } else { ServiceLocator sl = new ServiceLocator(serviceClassName); serviceLocators.add(sl); scanner.addVisitor(sl); } } try { scanner.scan(); } catch (ClassScannerException e) { throw new MojoExecutionException("Failed to scan classes for services", e); } for (ServiceLocator sl : serviceLocators) { File file = new File(tmpServicesDir, sl.getServiceClassName()); if (!sl.getImplementations().isEmpty()) { String destFileName = "META-INF/services/" + sl.getServiceClassName(); log.info("Generating " + destFileName); try { Writer out = new OutputStreamWriter(new FileOutputStream(file)); try { for (String impl : sl.getImplementations()) { log.debug(" " + impl); out.write(impl); out.write("\n"); } } finally { out.close(); } } catch (IOException e) { throw new MojoExecutionException("Unable to create temporary file " + file, e); } archiver.addFile(file, destFileName); } } }
/** * Requests the {@link #classScanner} to add a class or all classes from a package. A {@code null} * argument indicates the unnamed package. */ public Builder classesOrPackages(String... classesOrPackages) throws IOException { if (classesOrPackages == null) { classScanner.addPackage(null, true); } else for (String s : classesOrPackages) { classScanner.addClassOrPackage(s); } return this; }
@Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testGetActionsByClassIfHasValidSize() { Class clazz = UserController.class; List<ControllerMapping> mappings = classScanner.getActionsByClass(clazz, "user"); assertEquals(7, mappings.size()); }
@Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testGetActionsByClassIfIsNotNull() { Class clazz = UserController.class; List<ControllerMapping> mappings = classScanner.getActionsByClass(clazz, "user"); assertNotNull(mappings); }
@Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testObtainControllerAnnotationByClassWithoutValidClass() { Class clazz = User.class; Controller controller = classScanner.obtainControllerAnnotationByClass(clazz); assertNull(controller); }
@Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testIsControllerWithoutValidClass() { Class clazz = User.class; boolean annotated = classScanner.isAnnotatedWithController(clazz); assertFalse(annotated); }
@Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testObtainControllerAnnotationByClassWithValidClass() { Class clazz = UserController.class; Controller controller = classScanner.obtainControllerAnnotationByClass(clazz); assertNotNull(controller); assertEquals("user", controller.mappedBy()); }
@Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testGetActionsByClassIfHasValidMethodForRunBeforeAllActions() { Class clazz = UserController.class; List<ControllerMapping> mappings = classScanner.getActionsByClass(clazz, "user"); for (ControllerMapping mapping : mappings) { assertNotNull(mapping.getRunBeforeActions()); } }
protected Set<Class> processJarUrl(URL url, String basepath, Class clazz) throws IOException { Set<Class> set = new HashSet<Class>(); String path = url.getFile().substring(5, url.getFile().indexOf("!")); // We can't URLDecoder.decode(path) since some encoded chars are allowed on file uris path = path.replaceAll("%20", " "); JarFile jar = new JarFile(path); for (Enumeration entries = jar.entries(); entries.hasMoreElements(); ) { JarEntry entry = (JarEntry) entries.nextElement(); if (entry.getName().startsWith(basepath) && entry.getName().endsWith(".class")) { try { String name = entry.getName(); // Ignore anonymous if (name.matches("\\$[1-9]")) { continue; } URL classURL = classLoader.getResource(name); InputStream classStream = classURL.openStream(); ClassReader reader = new ClosableClassReader(classStream); ClassScanner visitor = getScanner(clazz); reader.accept(visitor, 0); if (visitor.isMatch()) { Class c = loadClass(visitor.getClassName()); if (c != null) { set.add(c); } } } catch (Exception e) { if (logger.isDebugEnabled()) { Throwable t = ExceptionHelper.getRootException(e); logger.debug(String.format("%s: caused by: %s", e.toString(), t.toString())); } } } } jar.close(); return set; }
@Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testGetActionsByClassIfHasValidMethodForRunBeforeSomeActions() { Class clazz = PersonController.class; List<ControllerMapping> mappings = classScanner.getActionsByClass(clazz, "user"); for (ControllerMapping mapping : mappings) { String action = mapping.getActionName(); if ("save".equals(action) || "update".equals(action) || "delete".equals(action)) { assertNotNull(mapping.getRunBeforeActions()); } else { assertNull(mapping.getRunBeforeActions()); } } }
@Test public void testCreateInstanceWithDefaultDirectoryClasses() { ClassScanner instance = ClassScanner.createInstance().withDefaultDirectoryClasses(); assertNotNull(instance); }
/** * Starts the build process and returns an array of {@link File} produced. * * @return the array of File produced * @throws IOException * @throws InterruptedException * @throws ParserException */ public File[] build() throws IOException, InterruptedException, ParserException { if (classScanner.getClasses().isEmpty()) { return null; } List<File> outputFiles = new ArrayList<File>(); Map<String, List<Class>> map = new LinkedHashMap<String, List<Class>>(); for (Class c : classScanner.getClasses()) { if (Loader.getEnclosingClass(c) != c) { continue; } ClassProperties p = Loader.loadProperties(c, properties, false); String target = p.getProperty("target"); if (target != null && !c.getName().equals(target)) { File f = parse(classScanner.getClassLoader().getPaths(), c); if (f != null) { outputFiles.add(f); } continue; } String libraryName = outputName != null ? outputName : p.getProperty("platform.library", ""); if (libraryName.length() == 0) { continue; } List<Class> classList = map.get(libraryName); if (classList == null) { map.put(libraryName, classList = new ArrayList<Class>()); } classList.addAll(p.getEffectiveClasses()); } for (String libraryName : map.keySet()) { List<Class> classList = map.get(libraryName); Class[] classArray = classList.toArray(new Class[classList.size()]); File f = generateAndCompile(classArray, libraryName); if (f != null) { outputFiles.add(f); if (copyLibs) { // Do not copy library files from inherit properties ... ClassProperties p = Loader.loadProperties(classArray, properties, false); List<String> preloads = new ArrayList<String>(); preloads.addAll(p.get("platform.preload")); preloads.addAll(p.get("platform.link")); // ... but we should use all the inherited paths! p = Loader.loadProperties(classArray, properties, true); File directory = f.getParentFile(); for (String s : preloads) { URL[] urls = Loader.findLibrary(null, p, s); File fi; try { fi = new File(urls[0].toURI()); } catch (Exception e) { continue; } File fo = new File(directory, fi.getName()); if (fi.exists() && !outputFiles.contains(fo)) { logger.info("Copying " + fi); FileInputStream fis = new FileInputStream(fi); FileOutputStream fos = new FileOutputStream(fo); byte[] buffer = new byte[1024]; int length; while ((length = fis.read(buffer)) != -1) { fos.write(buffer, 0, length); } fos.close(); fis.close(); outputFiles.add(fo); } } } } } File[] files = outputFiles.toArray(new File[outputFiles.size()]); if (jarPrefix != null && files.length > 0) { File jarFile = new File(jarPrefix + "-" + properties.get("platform") + ".jar"); File d = jarFile.getParentFile(); if (d != null && !d.exists()) { d.mkdir(); } createJar( jarFile, outputDirectory == null ? classScanner.getClassLoader().getPaths() : null, files); } return files; }
public static void main(String[] args) throws ParseException, IOException { Options options = createOptions(); CommandLineParser parser = new GnuParser(); CommandLine cmd = parser.parse(options, args); if (cmd.hasOption("?")) { new HelpFormatter().printHelp("java " + ShowMoves.class.getName(), options); System.exit(1); } File rootFile = new File(cmd.getOptionValue("root")); File movesFile = new File(cmd.getOptionValue("moves")); Predicate<ClassName> packageFilter = new PackagePredicate(cmd.getOptionValue("package", "")); String groupPrefix = cmd.getOptionValue("group", ""); File refsFile = cmd.hasOption("refs") ? new File(cmd.getOptionValue("refs")) : null; // scan all the pom.xml files Modules modules = new Modules(); modules.scan(rootFile, groupPrefix); // load the moves and refs files ClassLocations moves = ClassLocations.parseFile(movesFile, groupPrefix); ClassLocations refs = (refsFile != null) ? ClassLocations.parseFile(refsFile, groupPrefix) : null; // scan the compiled classes of all the maven targets ClassScanner classScanner = new ClassScanner(packageFilter); classScanner.scan(modules.getAllModules()); ClassLocations locations = classScanner.getLocations(); ClassDependencies dependencies = classScanner.getDependencies(); // apply the moves file locations.moveAll(moves); // apply the refs file, if one was specified if (refs != null) { for (ModuleName moduleName : refs.getAllModules()) { ClassName refsName = new ClassName(moduleName + ":" + refsFile); locations.add(refsName, moduleName); dependencies.add(refsName, refs.getClasses(moduleName)); } } // find modules that reference classes they don't have access to Map<ModuleName, ListMultimap<ClassName, ClassName>> brokenMap = Maps.newHashMap(); for (Map.Entry<ClassName, ModuleName> entry : locations.getLocations()) { ClassName className = entry.getKey(); ModuleName moduleName = entry.getValue(); Set<ClassName> referencedClasses = dependencies.getReferencedClasses(className); ListMultimap<ClassName, ClassName> moduleBrokenMap = null; for (ClassName referencedClass : referencedClasses) { ModuleName referencedModule = locations.getModule(referencedClass); if (referencedModule != null && !modules.isDependentOf(moduleName, referencedModule)) { if (moduleBrokenMap == null) { moduleBrokenMap = brokenMap.get(moduleName); if (moduleBrokenMap == null) { brokenMap.put(moduleName, moduleBrokenMap = ArrayListMultimap.create()); } } moduleBrokenMap.put(className, referencedClass); } } } // report broken dependencies System.out.println(); for (ModuleName moduleName : Utils.sorted(brokenMap.keySet())) { ListMultimap<ClassName, ClassName> missingMap = brokenMap.get(moduleName); System.out.println(); System.out.println(moduleName.toString(groupPrefix)); for (ClassName className : Utils.sorted(missingMap.keySet())) { System.out.println(" " + className); for (ClassName referencedClass : Utils.sorted(missingMap.get(className))) { ModuleName referencedModule = locations.getModule(referencedClass); System.out.println( " " + referencedClass + " (" + referencedModule.toString(groupPrefix) + ")"); } } } }
@Test public void testGetDirectoryClassesByDefault() { String directory = classScanner.getDirectoryClasses(); String defaultDirectory = Constants.DEFAULT_DIRECTORY_CLASSES; assertEquals(defaultDirectory, directory); }
/** Appends argument to the paths of the {@link #classScanner}. */ public Builder classPaths(String... classPaths) { classScanner.getClassLoader().addPaths(classPaths); return this; }
public class ClassScannerTest { private ClassScanner classScanner = ClassScanner.createInstance().withDefaultDirectoryClasses(); @Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testIsControllerWithValidClass() { Class clazz = UserController.class; boolean annotated = classScanner.isAnnotatedWithController(clazz); assertTrue(annotated); } @Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testIsControllerWithoutValidClass() { Class clazz = User.class; boolean annotated = classScanner.isAnnotatedWithController(clazz); assertFalse(annotated); } @Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testObtainControllerAnnotationByClassWithValidClass() { Class clazz = UserController.class; Controller controller = classScanner.obtainControllerAnnotationByClass(clazz); assertNotNull(controller); assertEquals("user", controller.mappedBy()); } @Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testObtainControllerAnnotationByClassWithoutValidClass() { Class clazz = User.class; Controller controller = classScanner.obtainControllerAnnotationByClass(clazz); assertNull(controller); } @Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testGetActionsByClassIfIsNotNull() { Class clazz = UserController.class; List<ControllerMapping> mappings = classScanner.getActionsByClass(clazz, "user"); assertNotNull(mappings); } @Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testGetActionsByClassIfHasValidSize() { Class clazz = UserController.class; List<ControllerMapping> mappings = classScanner.getActionsByClass(clazz, "user"); assertEquals(7, mappings.size()); } @Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testGetActionsByClassIfHasValidMethodForRunBeforeAllActions() { Class clazz = UserController.class; List<ControllerMapping> mappings = classScanner.getActionsByClass(clazz, "user"); for (ControllerMapping mapping : mappings) { assertNotNull(mapping.getRunBeforeActions()); } } @Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testGetActionsByClassIfHasValidMethodForRunBeforeSomeActions() { Class clazz = PersonController.class; List<ControllerMapping> mappings = classScanner.getActionsByClass(clazz, "user"); for (ControllerMapping mapping : mappings) { String action = mapping.getActionName(); if ("save".equals(action) || "update".equals(action) || "delete".equals(action)) { assertNotNull(mapping.getRunBeforeActions()); } else { assertNull(mapping.getRunBeforeActions()); } } } @Test public void testCreateInstance() { Builder builder = ClassScanner.createInstance(); assertNotNull(builder); } @Test public void testCreateInstanceWithDefaultDirectoryClasses() { ClassScanner instance = ClassScanner.createInstance().withDefaultDirectoryClasses(); assertNotNull(instance); } @Test public void testCreateInstanceWithCustomDirectoryClasses() { ClassScanner instance = ClassScanner.createInstance().withCustomDirectoryClasses("xpto"); assertNotNull(instance); } @Test public void testGetDirectoryClassesByDefault() { String directory = classScanner.getDirectoryClasses(); String defaultDirectory = Constants.DEFAULT_DIRECTORY_CLASSES; assertEquals(defaultDirectory, directory); } }
@Test public void testCreateInstanceWithCustomDirectoryClasses() { ClassScanner instance = ClassScanner.createInstance().withCustomDirectoryClasses("xpto"); assertNotNull(instance); }
@Test public void testCreateInstance() { Builder builder = ClassScanner.createInstance(); assertNotNull(builder); }