All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.groovy.vmplugin.v9.ClassFinder Maven / Gradle / Ivy

There is a newer version: 3.0.8-01
Show newest version
/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */
package org.codehaus.groovy.vmplugin.v9;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystemAlreadyExistsException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * Find classes under the specified package via some classpath entry
 *
 * Usage:
 * 

 *   // find classes under `me.sunlan` package via classpath entry(directory) `D:/_APPS/git_apps/java8-labs/out/production/classes/`
 *   ClassFinder.find(URI.create("file:/D:/_APPS/git_apps/java8-labs/out/production/classes/"), "me/sunlan")
 *
 *   // find classes under `groovy.lang` package via classpath entry(jar file) `D:/_DEV/Groovy/groovy-3.0.1/lib/groovy-3.0.1.jar`
 *   ClassFinder.find(URI.create("file:/D:/_DEV/Groovy/groovy-3.0.1/lib/groovy-3.0.1.jar"), "groovy/lang")
 *
 *   // find classes under `java.lang` package via classpath entry(jrt)
 *   ClassFinder.find(URI.create("jrt:/modules/java.base/"), "java/lang")
 *
 *   // find classes under the sub-packages too, e.g. we can get {@link groovy.lang.groovydoc.GroovydocHolder} via the following code
 *   ClassFinder.find(URI.create("file:/D:/_DEV/Groovy/groovy-3.0.1/lib/groovy-3.0.1.jar"), "groovy/lang", true)
 * 
* * @since 3.0.2 */ public class ClassFinder { /** * Returns the found classes * * @param classpathEntryURI the classpath entry * @param packageName the package under which we find classes * @return the found classes * @since 3.0.2 */ public static Map> find(URI classpathEntryURI, String packageName) { return find(classpathEntryURI, packageName, false); } /** * Returns the found classes * * @param classpathEntryURI the classpath entry * @param packageName the package under which we find classes * @param recursive whether to find sub-packages * @return the found classes * @since 3.0.2 */ public static Map> find(URI classpathEntryURI, String packageName, boolean recursive) { URI uri; String prefix; String scheme = classpathEntryURI.getScheme(); if ("jrt".equals(scheme)) { uri = URI.create("jrt:/"); prefix = classpathEntryURI.getPath().substring(1) + "/"; } else if ("file".equals(scheme)) { Path path = Paths.get(classpathEntryURI); if (!Files.exists(path)) { throw new IllegalArgumentException(path + " does not exist"); } if (Files.isDirectory(path)) { uri = URI.create("file:/"); prefix = path.toString(); } else { uri = URI.create("jar:" + classpathEntryURI.toString()); prefix = ""; } } else { throw new UnsupportedOperationException(classpathEntryURI + " is not supported"); } return find(uri, prefix, packageName, recursive); } private static Map> find(URI uri, String prefix, String packageName, boolean recursive) { boolean wfs = "file".equals(uri.getScheme()); if (wfs) prefix = prefix.replace("/", File.separator); final String sepPatten = Pattern.quote(wfs ? File.separator : "/"); final int prefixElemCnt = prefix.trim().isEmpty() ? 0 : prefix.split(sepPatten).length; Map> result = new LinkedHashMap<>(); try (FileSystem fs = newFileSystem(uri)) { Files.walkFileTree(fs.getPath(prefix + "/" + packageName), new SimpleFileVisitor() { @Override public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes attrs) { return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) { String[] pathElems = path.toString().split(sepPatten); int nameCount = pathElems.length; if (nameCount <= prefixElemCnt) { return FileVisitResult.CONTINUE; } String filename = pathElems[nameCount - 1]; if (!filename.endsWith(".class") || "module-info.class".equals(filename) || "package-info.class".equals(filename)) { return FileVisitResult.CONTINUE; } String packagePathStr = String.join("/", Arrays.copyOfRange(pathElems, prefixElemCnt + (!wfs && pathElems[0].isEmpty() ? 1 : 0), nameCount - 1)); if (recursive || packageName.equals(packagePathStr)) { Set packageNameSet = result.computeIfAbsent(filename.substring(0, filename.lastIndexOf('.')), f -> new HashSet<>(2)); packageNameSet.add(packagePathStr); } return FileVisitResult.CONTINUE; } }); } catch (UnsupportedOperationException ignored) { } catch (Exception e) { throw new ClassFindFailedException( String.format("Failed to find classes via uri: %s, prefix: %s, packageName: %s, recursive: %s", uri, prefix, packageName, recursive ), e); } return result; } private static FileSystem newFileSystem(URI uri) throws IOException { try { return FileSystems.newFileSystem(uri, Collections.emptyMap()); } catch (FileSystemAlreadyExistsException e) { return FileSystems.getFileSystem(uri); } } private ClassFinder() {} }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy