| /******************************************************************************* |
| * Copyright (c) 2006, 2018 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.compiler.tool; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.net.MalformedURLException; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.net.URLClassLoader; |
| import java.nio.charset.Charset; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.text.MessageFormat; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.MissingResourceException; |
| import java.util.Objects; |
| import java.util.ResourceBundle; |
| import java.util.ServiceLoader; |
| import java.util.Set; |
| import java.util.StringTokenizer; |
| import java.util.zip.ZipException; |
| |
| import javax.lang.model.SourceVersion; |
| import javax.tools.FileObject; |
| import javax.tools.JavaFileObject; |
| import javax.tools.JavaFileObject.Kind; |
| import javax.tools.StandardJavaFileManager; |
| import javax.tools.StandardLocation; |
| |
| import org.eclipse.jdt.core.compiler.IProblem; |
| import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; |
| import org.eclipse.jdt.internal.compiler.batch.FileSystem; |
| import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath; |
| import org.eclipse.jdt.internal.compiler.batch.Main; |
| import org.eclipse.jdt.internal.compiler.batch.Main.ResourceBundleFactory; |
| import org.eclipse.jdt.internal.compiler.batch.ModuleFinder; |
| import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; |
| import org.eclipse.jdt.internal.compiler.env.AccessRestriction; |
| import org.eclipse.jdt.internal.compiler.env.AccessRule; |
| import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; |
| import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; |
| import org.eclipse.jdt.internal.compiler.parser.Parser; |
| import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; |
| import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; |
| import org.eclipse.jdt.internal.compiler.tool.JrtFileSystem.JrtFileObject; |
| import org.eclipse.jdt.internal.compiler.tool.ModuleLocationHandler.LocationContainer; |
| import org.eclipse.jdt.internal.compiler.tool.ModuleLocationHandler.LocationWrapper; |
| import org.eclipse.jdt.internal.compiler.tool.ModuleLocationHandler.ModuleLocationWrapper; |
| import org.eclipse.jdt.internal.compiler.util.Util; |
| |
| /** |
| * Implementation of the Standard Java File Manager |
| */ |
| public class EclipseFileManager implements StandardJavaFileManager { |
| private static final String NO_EXTENSION = "";//$NON-NLS-1$ |
| static final int HAS_EXT_DIRS = 1; |
| static final int HAS_BOOTCLASSPATH = 2; |
| static final int HAS_ENDORSED_DIRS = 4; |
| static final int HAS_PROCESSORPATH = 8; |
| static final int HAS_PROC_MODULEPATH = 16; |
| |
| Map<File, Archive> archivesCache; |
| Charset charset; |
| Locale locale; |
| ModuleLocationHandler locationHandler; |
| final Map<Location, URLClassLoader> classloaders; |
| int flags; |
| boolean isOnJvm9; |
| File jrtHome; |
| JrtFileSystem jrtSystem; |
| public ResourceBundle bundle; |
| private String releaseVersion; |
| |
| public EclipseFileManager(Locale locale, Charset charset) { |
| this.locale = locale == null ? Locale.getDefault() : locale; |
| this.charset = charset == null ? Charset.defaultCharset() : charset; |
| this.locationHandler = new ModuleLocationHandler(); |
| this.classloaders = new HashMap<>(); |
| this.archivesCache = new HashMap<>(); |
| this.isOnJvm9 = isRunningJvm9(); |
| try { |
| initialize(Util.getJavaHome()); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| // ignore |
| } |
| try { |
| this.bundle = ResourceBundleFactory.getBundle(this.locale); |
| } catch(MissingResourceException e) { |
| System.out.println("Missing resource : " + Main.bundleName.replace('.', '/') + ".properties for locale " + locale); //$NON-NLS-1$//$NON-NLS-2$ |
| } |
| } |
| protected void initialize(File javahome) throws IOException { |
| if (this.isOnJvm9) { |
| this.jrtSystem = new JrtFileSystem(javahome); |
| this.archivesCache.put(javahome, this.jrtSystem); |
| this.jrtHome = javahome; |
| this.locationHandler.newSystemLocation(StandardLocation.SYSTEM_MODULES, this.jrtSystem); |
| } else { |
| this.setLocation(StandardLocation.PLATFORM_CLASS_PATH, getDefaultBootclasspath()); |
| } |
| Iterable<? extends File> defaultClasspath = getDefaultClasspath(); |
| this.setLocation(StandardLocation.CLASS_PATH, defaultClasspath); |
| // No annotation module path by default |
| this.setLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH, defaultClasspath); |
| } |
| /* (non-Javadoc) |
| * @see javax.tools.JavaFileManager#close() |
| */ |
| @Override |
| public void close() throws IOException { |
| this.locationHandler.close(); |
| for (Archive archive : this.archivesCache.values()) { |
| archive.close(); |
| } |
| this.archivesCache.clear(); |
| for (URLClassLoader cl : this.classloaders.values()) { |
| cl.close(); |
| } |
| this.classloaders.clear(); |
| } |
| |
| private void collectAllMatchingFiles(Location location, File file, String normalizedPackageName, Set<Kind> kinds, boolean recurse, ArrayList<JavaFileObject> collector) { |
| if (file.equals(this.jrtHome)) { |
| if (location instanceof ModuleLocationWrapper) { |
| List<JrtFileObject> list = this.jrtSystem.list((ModuleLocationWrapper) location, normalizedPackageName, kinds, recurse, this.charset); |
| for (JrtFileObject fo : list) { |
| Kind kind = getKind(getExtension(fo.entryName)); |
| if (kinds.contains(kind)) { |
| collector.add(fo); |
| } |
| } |
| } |
| } else if (isArchive(file)) { |
| Archive archive = this.getArchive(file); |
| if (archive == Archive.UNKNOWN_ARCHIVE) return; |
| String key = normalizedPackageName; |
| if (!normalizedPackageName.endsWith("/")) {//$NON-NLS-1$ |
| key += '/'; |
| } |
| // we have an archive file |
| if (recurse) { |
| for (String packageName : archive.allPackages()) { |
| if (packageName.startsWith(key)) { |
| List<String[]> types = archive.getTypes(packageName); |
| if (types != null) { |
| for (String[] entry : types) { |
| final Kind kind = getKind(getExtension(entry[0])); |
| if (kinds.contains(kind)) { |
| collector.add(archive.getArchiveFileObject(packageName + entry[0], entry[1], this.charset)); |
| } |
| } |
| } |
| } |
| } |
| } else { |
| List<String[]> types = archive.getTypes(key); |
| if (types != null) { |
| for (String[] entry : types) { |
| final Kind kind = getKind(getExtension(entry[0])); |
| if (kinds.contains(kind)) { |
| collector.add(archive.getArchiveFileObject(key + entry[0], entry[1], this.charset)); |
| } |
| } |
| } |
| } |
| } else { |
| // we must have a directory |
| File currentFile = new File(file, normalizedPackageName); |
| if (!currentFile.exists()) return; |
| String path; |
| try { |
| path = currentFile.getCanonicalPath(); |
| } catch (IOException e) { |
| return; |
| } |
| if (File.separatorChar == '/') { |
| if (!path.endsWith(normalizedPackageName)) return; |
| } else if (!path.endsWith(normalizedPackageName.replace('/', File.separatorChar))) return; |
| File[] files = currentFile.listFiles(); |
| if (files != null) { |
| // this was a directory |
| for (File f : files) { |
| if (f.isDirectory() && recurse) { |
| collectAllMatchingFiles(location, file, normalizedPackageName + '/' + f.getName(), kinds, recurse, collector); |
| } else { |
| final Kind kind = getKind(f); |
| if (kinds.contains(kind)) { |
| collector.add(new EclipseFileObject(normalizedPackageName + f.getName(), f.toURI(), kind, this.charset)); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| private Iterable<? extends File> concatFiles(Iterable<? extends File> iterable, Iterable<? extends File> iterable2) { |
| ArrayList<File> list = new ArrayList<>(); |
| if (iterable2 == null) return iterable; |
| for (Iterator<? extends File> iterator = iterable.iterator(); iterator.hasNext(); ) { |
| list.add(iterator.next()); |
| } |
| for (Iterator<? extends File> iterator = iterable2.iterator(); iterator.hasNext(); ) { |
| list.add(iterator.next()); |
| } |
| return list; |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.JavaFileManager#flush() |
| */ |
| @Override |
| public void flush() throws IOException { |
| for (Archive archive : this.archivesCache.values()) { |
| archive.flush(); |
| } |
| } |
| |
| private Archive getArchive(File f) { |
| // check the archive (jar/zip) cache |
| Archive archive = this.archivesCache.get(f); |
| if (archive == null) { |
| archive = Archive.UNKNOWN_ARCHIVE; |
| // create a new archive |
| if (f.exists()) { |
| try { |
| if (isJrt(f)) { |
| archive = new JrtFileSystem(f); |
| } else { |
| archive = new Archive(f); |
| } |
| } catch (ZipException e) { |
| // ignore |
| } catch (IOException e) { |
| // ignore |
| } |
| if (archive != null) { |
| this.archivesCache.put(f, archive); |
| } |
| } |
| this.archivesCache.put(f, archive); |
| } |
| return archive; |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.JavaFileManager#getClassLoader(javax.tools.JavaFileManager.Location) |
| */ |
| @Override |
| public ClassLoader getClassLoader(Location location) { |
| validateNonModuleLocation(location); |
| Iterable<? extends File> files = getLocation(location); |
| if (files == null) { |
| // location is unknown |
| return null; |
| } |
| URLClassLoader cl = this.classloaders.get(location); |
| if (cl == null) { |
| ArrayList<URL> allURLs = new ArrayList<>(); |
| for (File f : files) { |
| try { |
| allURLs.add(f.toURI().toURL()); |
| } catch (MalformedURLException e) { |
| // the url is malformed - this should not happen |
| throw new RuntimeException(e); |
| } |
| } |
| URL[] result = new URL[allURLs.size()]; |
| cl = new URLClassLoader(allURLs.toArray(result), getClass().getClassLoader()); |
| this.classloaders.put(location, cl); |
| } |
| return cl; |
| } |
| |
| private Iterable<? extends File> getPathsFrom(String path) { |
| ArrayList<FileSystem.Classpath> paths = new ArrayList<>(); |
| ArrayList<File> files = new ArrayList<>(); |
| try { |
| this.processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, path, this.charset.name(), false, false); |
| } catch (IllegalArgumentException e) { |
| return null; |
| } |
| for (FileSystem.Classpath classpath : paths) { |
| files.add(new File(classpath.getPath())); |
| } |
| return files; |
| } |
| |
| Iterable<? extends File> getDefaultBootclasspath() { |
| List<File> files = new ArrayList<>(); |
| String javaversion = System.getProperty("java.version");//$NON-NLS-1$ |
| if(javaversion.length() > 3) |
| javaversion = javaversion.substring(0, 3); |
| long jdkLevel = CompilerOptions.versionToJdkLevel(javaversion); |
| if (jdkLevel < ClassFileConstants.JDK1_6) { |
| // wrong jdk - 1.6 or above is required |
| return null; |
| } |
| |
| for (FileSystem.Classpath classpath : org.eclipse.jdt.internal.compiler.util.Util.collectFilesNames()) { |
| files.add(new File(classpath.getPath())); |
| } |
| return files; |
| } |
| |
| Iterable<? extends File> getDefaultClasspath() { |
| // default classpath |
| ArrayList<File> files = new ArrayList<>(); |
| String classProp = System.getProperty("java.class.path"); //$NON-NLS-1$ |
| if ((classProp == null) || (classProp.length() == 0)) { |
| return null; |
| } else { |
| StringTokenizer tokenizer = new StringTokenizer(classProp, File.pathSeparator); |
| String token; |
| while (tokenizer.hasMoreTokens()) { |
| token = tokenizer.nextToken(); |
| File file = new File(token); |
| if (file.exists()) { |
| files.add(file); |
| } |
| } |
| } |
| return files; |
| } |
| |
| private Iterable<? extends File> getEndorsedDirsFrom(String path) { |
| ArrayList<FileSystem.Classpath> paths = new ArrayList<>(); |
| ArrayList<File> files = new ArrayList<>(); |
| try { |
| this.processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, path, this.charset.name(), false, false); |
| } catch (IllegalArgumentException e) { |
| return null; |
| } |
| for (FileSystem.Classpath classpath : paths) { |
| files.add(new File(classpath.getPath())); |
| } |
| return files; |
| } |
| |
| private Iterable<? extends File> getExtdirsFrom(String path) { |
| ArrayList<FileSystem.Classpath> paths = new ArrayList<>(); |
| ArrayList<File> files = new ArrayList<>(); |
| try { |
| this.processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, path, this.charset.name(), false, false); |
| } catch (IllegalArgumentException e) { |
| return null; |
| } |
| for (FileSystem.Classpath classpath : paths) { |
| files.add(new File(classpath.getPath())); |
| } |
| return files; |
| } |
| |
| private String getExtension(File file) { |
| String name = file.getName(); |
| return getExtension(name); |
| } |
| private String getExtension(String name) { |
| int index = name.lastIndexOf('.'); |
| if (index == -1) { |
| return EclipseFileManager.NO_EXTENSION; |
| } |
| return name.substring(index); |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.JavaFileManager#getFileForInput(javax.tools.JavaFileManager.Location, java.lang.String, java.lang.String) |
| */ |
| @Override |
| public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException { |
| validateNonModuleLocation(location); |
| Iterable<? extends File> files = getLocation(location); |
| if (files == null) { |
| throw new IllegalArgumentException("Unknown location : " + location);//$NON-NLS-1$ |
| } |
| String normalizedFileName = normalized(packageName) + '/' + relativeName.replace('\\', '/'); |
| for (File file : files) { |
| if (file.isDirectory()) { |
| // handle directory |
| File f = new File(file, normalizedFileName); |
| if (f.exists()) { |
| return new EclipseFileObject(packageName + File.separator + relativeName, f.toURI(), getKind(f), this.charset); |
| } else { |
| continue; // go to next entry in the location |
| } |
| } else if (isArchive(file)) { |
| // handle archive file |
| Archive archive = getArchive(file); |
| if (archive != Archive.UNKNOWN_ARCHIVE) { |
| if (archive.contains(normalizedFileName)) { |
| return archive.getArchiveFileObject(normalizedFileName, null, this.charset); |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.JavaFileManager#getFileForOutput(javax.tools.JavaFileManager.Location, java.lang.String, java.lang.String, javax.tools.FileObject) |
| */ |
| @Override |
| public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) |
| throws IOException { |
| validateOutputLocation(location); |
| Iterable<? extends File> files = getLocation(location); |
| if (files == null) { |
| throw new IllegalArgumentException("Unknown location : " + location);//$NON-NLS-1$ |
| } |
| final Iterator<? extends File> iterator = files.iterator(); |
| if (iterator.hasNext()) { |
| File file = iterator.next(); |
| String normalizedFileName = normalized(packageName) + '/' + relativeName.replace('\\', '/'); |
| File f = new File(file, normalizedFileName); |
| return new EclipseFileObject(packageName + File.separator + relativeName, f.toURI(), getKind(f), this.charset); |
| } else { |
| throw new IllegalArgumentException("location is empty : " + location);//$NON-NLS-1$ |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.JavaFileManager#getJavaFileForInput(javax.tools.JavaFileManager.Location, java.lang.String, javax.tools.JavaFileObject.Kind) |
| */ |
| @Override |
| public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException { |
| validateNonModuleLocation(location); |
| if (kind != Kind.CLASS && kind != Kind.SOURCE) { |
| throw new IllegalArgumentException("Invalid kind : " + kind);//$NON-NLS-1$ |
| } |
| Iterable<? extends File> files = getLocation(location); |
| if (files == null) { |
| throw new IllegalArgumentException("Unknown location : " + location);//$NON-NLS-1$ |
| } |
| String normalizedFileName = normalized(className); |
| normalizedFileName += kind.extension; |
| for (File file : files) { |
| if (file.equals(this.jrtHome)) { |
| String modName; |
| if (location instanceof ModuleLocationWrapper) { |
| modName = ((ModuleLocationWrapper) location).modName; |
| } else { |
| modName = ""; //$NON-NLS-1$ |
| } |
| return this.jrtSystem.getArchiveFileObject(normalizedFileName, modName, this.charset); |
| } else if (file.isDirectory()) { |
| // handle directory |
| File f = new File(file, normalizedFileName); |
| if (f.exists()) { |
| return new EclipseFileObject(className, f.toURI(), kind, this.charset); |
| } else { |
| continue; // go to next entry in the location |
| } |
| } else if (isArchive(file)) { |
| // handle archive file |
| Archive archive = getArchive(file); |
| if (archive != Archive.UNKNOWN_ARCHIVE) { |
| if (archive.contains(normalizedFileName)) { |
| return archive.getArchiveFileObject(normalizedFileName, null, this.charset); |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.JavaFileManager#getJavaFileForOutput(javax.tools.JavaFileManager.Location, java.lang.String, javax.tools.JavaFileObject.Kind, javax.tools.FileObject) |
| */ |
| @Override |
| public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) |
| throws IOException { |
| validateOutputLocation(location); |
| if (kind != Kind.CLASS && kind != Kind.SOURCE) { |
| throw new IllegalArgumentException("Invalid kind : " + kind);//$NON-NLS-1$ |
| } |
| Iterable<? extends File> files = getLocation(location); |
| if (files == null) { |
| if (!location.equals(StandardLocation.CLASS_OUTPUT) |
| && !location.equals(StandardLocation.SOURCE_OUTPUT)) |
| throw new IllegalArgumentException("Unknown location : " + location);//$NON-NLS-1$ |
| // we will use either the sibling or user.dir |
| if (sibling != null) { |
| String normalizedFileName = normalized(className); |
| int index = normalizedFileName.lastIndexOf('/'); |
| if (index != -1) { |
| normalizedFileName = normalizedFileName.substring(index + 1); |
| } |
| normalizedFileName += kind.extension; |
| URI uri = sibling.toUri(); |
| URI uri2 = null; |
| try { |
| String path = uri.getPath(); |
| index = path.lastIndexOf('/'); |
| if (index != -1) { |
| path = path.substring(0, index + 1); |
| path += normalizedFileName; |
| } |
| uri2 = new URI(uri.getScheme(), uri.getHost(), path, uri.getFragment()); |
| } catch (URISyntaxException e) { |
| throw new IllegalArgumentException("invalid sibling", e);//$NON-NLS-1$ |
| } |
| return new EclipseFileObject(className, uri2, kind, this.charset); |
| } else { |
| String normalizedFileName = normalized(className); |
| normalizedFileName += kind.extension; |
| File f = new File(System.getProperty("user.dir"), normalizedFileName);//$NON-NLS-1$ |
| return new EclipseFileObject(className, f.toURI(), kind, this.charset); |
| } |
| } |
| final Iterator<? extends File> iterator = files.iterator(); |
| if (iterator.hasNext()) { |
| File file = iterator.next(); |
| String normalizedFileName = normalized(className); |
| normalizedFileName += kind.extension; |
| File f = new File(file, normalizedFileName); |
| return new EclipseFileObject(className, f.toURI(), kind, this.charset); |
| } else { |
| throw new IllegalArgumentException("location is empty : " + location);//$NON-NLS-1$ |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.StandardJavaFileManager#getJavaFileObjects(java.io.File[]) |
| */ |
| @Override |
| public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) { |
| return getJavaFileObjectsFromFiles(Arrays.asList(files)); |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.StandardJavaFileManager#getJavaFileObjects(java.lang.String[]) |
| */ |
| @Override |
| public Iterable<? extends JavaFileObject> getJavaFileObjects(String... names) { |
| return getJavaFileObjectsFromStrings(Arrays.asList(names)); |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.StandardJavaFileManager#getJavaFileObjectsFromFiles(java.lang.Iterable) |
| */ |
| @Override |
| public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(Iterable<? extends File> files) { |
| ArrayList<JavaFileObject> javaFileArrayList = new ArrayList<>(); |
| for (File f : files) { |
| if (f.isDirectory()) { |
| throw new IllegalArgumentException("file : " + f.getAbsolutePath() + " is a directory"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| javaFileArrayList.add(new EclipseFileObject(f.getAbsolutePath(), f.toURI(), getKind(f), this.charset)); |
| } |
| return javaFileArrayList; |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.StandardJavaFileManager#getJavaFileObjectsFromStrings(java.lang.Iterable) |
| */ |
| @Override |
| public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) { |
| ArrayList<File> files = new ArrayList<>(); |
| for (String name : names) { |
| files.add(new File(name)); |
| } |
| return getJavaFileObjectsFromFiles(files); |
| } |
| |
| public Kind getKind(File f) { |
| return getKind(getExtension(f)); |
| } |
| |
| private Kind getKind(String extension) { |
| if (Kind.CLASS.extension.equals(extension)) { |
| return Kind.CLASS; |
| } else if (Kind.SOURCE.extension.equals(extension)) { |
| return Kind.SOURCE; |
| } else if (Kind.HTML.extension.equals(extension)) { |
| return Kind.HTML; |
| } |
| return Kind.OTHER; |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.StandardJavaFileManager#getLocation(javax.tools.JavaFileManager.Location) |
| */ |
| @Override |
| public Iterable<? extends File> getLocation(Location location) { |
| if (location instanceof LocationWrapper) { |
| return getFiles(((LocationWrapper) location).paths); |
| } |
| LocationWrapper loc = this.locationHandler.getLocation(location); |
| if (loc == null) { |
| return null; |
| } |
| return getFiles(loc.getPaths()); |
| } |
| |
| private Iterable<? extends File> getOutputDir(String string) { |
| if ("none".equals(string)) {//$NON-NLS-1$ |
| return null; |
| } |
| File file = new File(string); |
| if (file.exists() && !file.isDirectory()) { |
| throw new IllegalArgumentException("file : " + file.getAbsolutePath() + " is not a directory");//$NON-NLS-1$//$NON-NLS-2$ |
| } |
| ArrayList<File> list = new ArrayList<>(1); |
| list.add(file); |
| return list; |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.JavaFileManager#handleOption(java.lang.String, java.util.Iterator) |
| */ |
| @Override |
| public boolean handleOption(String current, Iterator<String> remaining) { |
| try { |
| switch(current) { |
| case "-bootclasspath": //$NON-NLS-1$ |
| if (remaining.hasNext()) { |
| final Iterable<? extends File> bootclasspaths = getPathsFrom(remaining.next()); |
| if (bootclasspaths != null) { |
| Iterable<? extends File> iterable = getLocation(StandardLocation.PLATFORM_CLASS_PATH); |
| if ((this.flags & EclipseFileManager.HAS_ENDORSED_DIRS) == 0 |
| && (this.flags & EclipseFileManager.HAS_EXT_DIRS) == 0) { |
| // override default bootclasspath |
| setLocation(StandardLocation.PLATFORM_CLASS_PATH, bootclasspaths); |
| } else if ((this.flags & EclipseFileManager.HAS_ENDORSED_DIRS) != 0) { |
| // endorseddirs have been processed first |
| setLocation(StandardLocation.PLATFORM_CLASS_PATH, |
| concatFiles(iterable, bootclasspaths)); |
| } else { |
| // extdirs have been processed first |
| setLocation(StandardLocation.PLATFORM_CLASS_PATH, |
| prependFiles(iterable, bootclasspaths)); |
| } |
| } |
| this.flags |= EclipseFileManager.HAS_BOOTCLASSPATH; |
| return true; |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| case "--system": //$NON-NLS-1$ |
| if (remaining.hasNext()) { |
| final Iterable<? extends File> classpaths = getPathsFrom(remaining.next()); |
| if (classpaths != null) { |
| Iterable<? extends File> iterable = getLocation(StandardLocation.SYSTEM_MODULES); |
| if (iterable != null) { |
| setLocation(StandardLocation.SYSTEM_MODULES, concatFiles(iterable, classpaths)); |
| } else { |
| setLocation(StandardLocation.SYSTEM_MODULES, classpaths); |
| } |
| } |
| return true; |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| case "--upgrade-module-path": //$NON-NLS-1$ |
| if (remaining.hasNext()) { |
| final Iterable<? extends File> classpaths = getPathsFrom(remaining.next()); |
| if (classpaths != null) { |
| Iterable<? extends File> iterable = getLocation(StandardLocation.UPGRADE_MODULE_PATH); |
| if (iterable != null) { |
| setLocation(StandardLocation.UPGRADE_MODULE_PATH, |
| concatFiles(iterable, classpaths)); |
| } else { |
| setLocation(StandardLocation.UPGRADE_MODULE_PATH, classpaths); |
| } |
| } |
| return true; |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| case "-classpath": //$NON-NLS-1$ |
| case "-cp": //$NON-NLS-1$ |
| if (remaining.hasNext()) { |
| final Iterable<? extends File> classpaths = getPathsFrom(remaining.next()); |
| if (classpaths != null) { |
| Iterable<? extends File> iterable = getLocation(StandardLocation.CLASS_PATH); |
| if (iterable != null) { |
| setLocation(StandardLocation.CLASS_PATH, |
| concatFiles(iterable, classpaths)); |
| } else { |
| setLocation(StandardLocation.CLASS_PATH, classpaths); |
| } |
| if ((this.flags & EclipseFileManager.HAS_PROCESSORPATH) == 0) { |
| setLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH, classpaths); |
| } else if ((this.flags & EclipseFileManager.HAS_PROC_MODULEPATH) == 0) { |
| if (this.isOnJvm9) |
| setLocation(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH, classpaths); |
| } |
| } |
| return true; |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| case "--module-path": //$NON-NLS-1$ |
| case "-p": //$NON-NLS-1$ |
| final Iterable<? extends File> classpaths = getPathsFrom(remaining.next()); |
| if (classpaths != null) { |
| Iterable<? extends File> iterable = getLocation(StandardLocation.MODULE_PATH); |
| if (iterable != null) { |
| setLocation(StandardLocation.MODULE_PATH, concatFiles(iterable, classpaths)); |
| } else { |
| setLocation(StandardLocation.MODULE_PATH, classpaths); |
| } |
| if ((this.flags & EclipseFileManager.HAS_PROCESSORPATH) == 0) { |
| setLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH, classpaths); |
| } else if ((this.flags & EclipseFileManager.HAS_PROC_MODULEPATH) == 0) { |
| if (this.isOnJvm9) |
| setLocation(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH, classpaths); |
| } |
| } |
| return true; |
| case "-encoding": //$NON-NLS-1$ |
| if (remaining.hasNext()) { |
| this.charset = Charset.forName(remaining.next()); |
| return true; |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| case "-sourcepath": //$NON-NLS-1$ |
| if (remaining.hasNext()) { |
| final Iterable<? extends File> sourcepaths = getPathsFrom(remaining.next()); |
| if (sourcepaths != null) setLocation(StandardLocation.SOURCE_PATH, sourcepaths); |
| return true; |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| case "--module-source-path": //$NON-NLS-1$ |
| if (remaining.hasNext()) { |
| final Iterable<? extends File> sourcepaths = getPathsFrom(remaining.next()); |
| if (sourcepaths != null && this.isOnJvm9) |
| setLocation(StandardLocation.MODULE_SOURCE_PATH, sourcepaths); |
| return true; |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| case "-extdirs": //$NON-NLS-1$ |
| if (this.isOnJvm9) { |
| throw new IllegalArgumentException(); |
| } |
| if (remaining.hasNext()) { |
| Iterable<? extends File> iterable = getLocation(StandardLocation.PLATFORM_CLASS_PATH); |
| setLocation(StandardLocation.PLATFORM_CLASS_PATH, |
| concatFiles(iterable, getExtdirsFrom(remaining.next()))); |
| this.flags |= EclipseFileManager.HAS_EXT_DIRS; |
| return true; |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| case "-endorseddirs": //$NON-NLS-1$ |
| if (remaining.hasNext()) { |
| Iterable<? extends File> iterable = getLocation(StandardLocation.PLATFORM_CLASS_PATH); |
| setLocation(StandardLocation.PLATFORM_CLASS_PATH, |
| prependFiles(iterable, getEndorsedDirsFrom(remaining.next()))); |
| this.flags |= EclipseFileManager.HAS_ENDORSED_DIRS; |
| return true; |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| case "-d": //$NON-NLS-1$ |
| if (remaining.hasNext()) { |
| final Iterable<? extends File> outputDir = getOutputDir(remaining.next()); |
| if (outputDir != null) { |
| setLocation(StandardLocation.CLASS_OUTPUT, outputDir); |
| } |
| return true; |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| case "-s": //$NON-NLS-1$ |
| if (remaining.hasNext()) { |
| final Iterable<? extends File> outputDir = getOutputDir(remaining.next()); |
| if (outputDir != null) { |
| setLocation(StandardLocation.SOURCE_OUTPUT, outputDir); |
| } |
| return true; |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| case "-processorpath": //$NON-NLS-1$ |
| if (remaining.hasNext()) { |
| final Iterable<? extends File> processorpaths = getPathsFrom(remaining.next()); |
| if (processorpaths != null) { |
| setLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH, processorpaths); |
| } |
| this.flags |= EclipseFileManager.HAS_PROCESSORPATH; |
| return true; |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| case "--processor-module-path": //$NON-NLS-1$ |
| if (remaining.hasNext()) { |
| final Iterable<? extends File> processorpaths = getPathsFrom(remaining.next()); |
| if (processorpaths != null && this.isOnJvm9) { |
| setLocation(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH, processorpaths); |
| this.flags |= EclipseFileManager.HAS_PROC_MODULEPATH; |
| } |
| return true; |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| case "--release": //$NON-NLS-1$ |
| if (remaining.hasNext()) { |
| this.releaseVersion = remaining.next(); |
| return true; |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| } |
| } catch (IOException e) { |
| // ignore |
| } |
| return false; |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.JavaFileManager#hasLocation(javax.tools.JavaFileManager.Location) |
| */ |
| @Override |
| public boolean hasLocation(Location location) { |
| String mod = null; |
| if (location instanceof ModuleLocationWrapper) { |
| mod = ((ModuleLocationWrapper) location).modName; |
| } |
| LocationWrapper impl = null; |
| if (mod == null) { |
| impl = this.locationHandler.getLocation(location); |
| } else { |
| impl = this.locationHandler.getLocation(location, mod); |
| } |
| return (impl != null); |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.JavaFileManager#inferBinaryName(javax.tools.JavaFileManager.Location, javax.tools.JavaFileObject) |
| */ |
| @Override |
| public String inferBinaryName(Location location, JavaFileObject file) { |
| validateNonModuleLocation(location); |
| Iterable<? extends Path> paths = getLocationAsPaths(location); |
| if (paths == null) { |
| return null; |
| } |
| if (file instanceof JrtFileObject) { |
| Path filePath = ((JrtFileObject) file).path; |
| filePath = filePath.subpath(2, filePath.getNameCount()); |
| String name = filePath.toString(); |
| int index = name.lastIndexOf('.'); |
| if (index != -1) { |
| name = name.substring(0, index); |
| } |
| return name.replace('/', '.'); |
| } |
| String name = file.getName(); |
| JavaFileObject javaFileObject = null; |
| int index = name.lastIndexOf('.'); |
| if (index != -1) { |
| name = name.substring(0, index); |
| } |
| try { |
| javaFileObject = getJavaFileForInput(location, name, file.getKind()); |
| } catch (IOException e) { |
| // ignore |
| } catch (IllegalArgumentException iae) { |
| return null; // Either unknown kind or location not present |
| } |
| if (javaFileObject == null) { |
| return null; |
| } |
| return name.replace('/', '.'); |
| } |
| |
| private boolean isArchive(File f) { |
| if (isJrt(f)) |
| return false; |
| String extension = getExtension(f); |
| return extension.equalsIgnoreCase(".jar") || extension.equalsIgnoreCase(".zip"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| private boolean isJrt(File f) { |
| return f.getName().toLowerCase().equals(JrtFileSystem.BOOT_MODULE); |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.StandardJavaFileManager#isSameFile(javax.tools.FileObject, javax.tools.FileObject) |
| */ |
| @Override |
| public boolean isSameFile(FileObject fileObject1, FileObject fileObject2) { |
| // EclipseFileManager creates only EcliseFileObject |
| if (!(fileObject1 instanceof EclipseFileObject)) throw new IllegalArgumentException("Unsupported file object class : " + fileObject1.getClass());//$NON-NLS-1$ |
| if (!(fileObject2 instanceof EclipseFileObject)) throw new IllegalArgumentException("Unsupported file object class : " + fileObject2.getClass());//$NON-NLS-1$ |
| return fileObject1.equals(fileObject2); |
| } |
| /* (non-Javadoc) |
| * @see javax.tools.OptionChecker#isSupportedOption(java.lang.String) |
| */ |
| @Override |
| public int isSupportedOption(String option) { |
| return Options.processOptionsFileManager(option); |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.tools.JavaFileManager#list(javax.tools.JavaFileManager.Location, java.lang.String, java.util.Set, boolean) |
| */ |
| @Override |
| public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse) |
| throws IOException { |
| validateNonModuleLocation(location); |
| Iterable<? extends Path> allPaths = getLocationAsPaths(location); |
| if (allPaths == null) { |
| throw new IllegalArgumentException("Unknown location : " + location);//$NON-NLS-1$ |
| } |
| |
| ArrayList<JavaFileObject> collector = new ArrayList<>(); |
| String normalizedPackageName = normalized(packageName); |
| for (Path file : allPaths) { |
| collectAllMatchingFiles(location, file.toFile(), normalizedPackageName, kinds, recurse, collector); |
| } |
| return collector; |
| } |
| |
| private String normalized(String className) { |
| char[] classNameChars = className.toCharArray(); |
| for (int i = 0, max = classNameChars.length; i < max; i++) { |
| switch(classNameChars[i]) { |
| case '\\' : |
| classNameChars[i] = '/'; |
| break; |
| case '.' : |
| classNameChars[i] = '/'; |
| } |
| } |
| return new String(classNameChars); |
| } |
| |
| private Iterable<? extends File> prependFiles(Iterable<? extends File> iterable, |
| Iterable<? extends File> iterable2) { |
| if (iterable2 == null) return iterable; |
| ArrayList<File> list = new ArrayList<>(); |
| for (Iterator<? extends File> iterator = iterable2.iterator(); iterator.hasNext(); ) { |
| list.add(iterator.next()); |
| } |
| for (Iterator<? extends File> iterator = iterable.iterator(); iterator.hasNext(); ) { |
| list.add(iterator.next()); |
| } |
| return list; |
| } |
| private boolean isRunningJvm9() { |
| return (SourceVersion.latest().compareTo(SourceVersion.RELEASE_8) > 0); |
| } |
| /* (non-Javadoc) |
| * @see javax.tools.StandardJavaFileManager#setLocation(javax.tools.JavaFileManager.Location, java.lang.Iterable) |
| */ |
| @Override |
| public void setLocation(Location location, Iterable<? extends File> files) throws IOException { |
| if (location.isOutputLocation() && files != null) { |
| // output location |
| int count = 0; |
| for (Iterator<? extends File> iterator = files.iterator(); iterator.hasNext(); ) { |
| iterator.next(); |
| count++; |
| } |
| if (count != 1) { |
| throw new IllegalArgumentException("output location can only have one path");//$NON-NLS-1$ |
| } |
| } |
| this.locationHandler.setLocation(location, getPaths(files)); |
| } |
| |
| public void setLocale(Locale locale) { |
| this.locale = locale == null ? Locale.getDefault() : locale; |
| try { |
| this.bundle = ResourceBundleFactory.getBundle(this.locale); |
| } catch(MissingResourceException e) { |
| System.out.println("Missing resource : " + Main.bundleName.replace('.', '/') + ".properties for locale " + locale); //$NON-NLS-1$//$NON-NLS-2$ |
| throw e; |
| } |
| } |
| |
| @SuppressWarnings({"unchecked", "rawtypes"}) |
| public void processPathEntries(final int defaultSize, final ArrayList paths, |
| final String currentPath, String customEncoding, boolean isSourceOnly, |
| boolean rejectDestinationPathOnJars) { |
| |
| String currentClasspathName = null; |
| String currentDestinationPath = null; |
| ArrayList currentRuleSpecs = new ArrayList(defaultSize); |
| StringTokenizer tokenizer = new StringTokenizer(currentPath, |
| File.pathSeparator + "[]", true); //$NON-NLS-1$ |
| ArrayList tokens = new ArrayList(); |
| while (tokenizer.hasMoreTokens()) { |
| tokens.add(tokenizer.nextToken()); |
| } |
| // state machine |
| final int start = 0; |
| final int readyToClose = 1; |
| // 'path' 'path1[rule];path2' |
| final int readyToCloseEndingWithRules = 2; |
| // 'path[rule]' 'path1;path2[rule]' |
| final int readyToCloseOrOtherEntry = 3; |
| // 'path[rule];' 'path;' 'path1;path2;' |
| final int rulesNeedAnotherRule = 4; |
| // 'path[rule1;' |
| final int rulesStart = 5; |
| // 'path[' 'path1;path2[' |
| final int rulesReadyToClose = 6; |
| // 'path[rule' 'path[rule1;rule2' |
| final int destinationPathReadyToClose = 7; |
| // 'path[-d bin' |
| final int readyToCloseEndingWithDestinationPath = 8; |
| // 'path[-d bin]' 'path[rule][-d bin]' |
| final int destinationPathStart = 9; |
| // 'path[rule][' |
| final int bracketOpened = 10; |
| // '.*[.*' |
| final int bracketClosed = 11; |
| // '.*([.*])+' |
| |
| final int error = 99; |
| int state = start; |
| String token = null; |
| int cursor = 0, tokensNb = tokens.size(), bracket = -1; |
| while (cursor < tokensNb && state != error) { |
| token = (String) tokens.get(cursor++); |
| if (token.equals(File.pathSeparator)) { |
| switch (state) { |
| case start: |
| case readyToCloseOrOtherEntry: |
| case bracketOpened: |
| break; |
| case readyToClose: |
| case readyToCloseEndingWithRules: |
| case readyToCloseEndingWithDestinationPath: |
| state = readyToCloseOrOtherEntry; |
| addNewEntry(paths, currentClasspathName, currentRuleSpecs, |
| customEncoding, currentDestinationPath, isSourceOnly, |
| rejectDestinationPathOnJars); |
| currentRuleSpecs.clear(); |
| break; |
| case rulesReadyToClose: |
| state = rulesNeedAnotherRule; |
| break; |
| case destinationPathReadyToClose: |
| throw new IllegalArgumentException( |
| this.bind("configure.incorrectDestinationPathEntry", //$NON-NLS-1$ |
| currentPath)); |
| case bracketClosed: |
| cursor = bracket + 1; |
| state = rulesStart; |
| break; |
| default: |
| state = error; |
| } |
| } else if (token.equals("[")) { //$NON-NLS-1$ |
| switch (state) { |
| case start: |
| currentClasspathName = ""; //$NON-NLS-1$ |
| //$FALL-THROUGH$ |
| case readyToClose: |
| bracket = cursor - 1; |
| //$FALL-THROUGH$ |
| case bracketClosed: |
| state = bracketOpened; |
| break; |
| case readyToCloseEndingWithRules: |
| state = destinationPathStart; |
| break; |
| case readyToCloseEndingWithDestinationPath: |
| state = rulesStart; |
| break; |
| case bracketOpened: |
| default: |
| state = error; |
| } |
| } else if (token.equals("]")) { //$NON-NLS-1$ |
| switch (state) { |
| case rulesReadyToClose: |
| state = readyToCloseEndingWithRules; |
| break; |
| case destinationPathReadyToClose: |
| state = readyToCloseEndingWithDestinationPath; |
| break; |
| case bracketOpened: |
| state = bracketClosed; |
| break; |
| case bracketClosed: |
| default: |
| state = error; |
| } |
| } else { |
| // regular word |
| switch (state) { |
| case start: |
| case readyToCloseOrOtherEntry: |
| state = readyToClose; |
| currentClasspathName = token; |
| break; |
| case rulesStart: |
| if (token.startsWith("-d ")) { //$NON-NLS-1$ |
| if (currentDestinationPath != null) { |
| throw new IllegalArgumentException( |
| this.bind("configure.duplicateDestinationPathEntry", //$NON-NLS-1$ |
| currentPath)); |
| } |
| currentDestinationPath = token.substring(3).trim(); |
| state = destinationPathReadyToClose; |
| break; |
| } // else we proceed with a rule |
| //$FALL-THROUGH$ |
| case rulesNeedAnotherRule: |
| if (currentDestinationPath != null) { |
| throw new IllegalArgumentException( |
| this.bind("configure.accessRuleAfterDestinationPath", //$NON-NLS-1$ |
| currentPath)); |
| } |
| state = rulesReadyToClose; |
| currentRuleSpecs.add(token); |
| break; |
| case destinationPathStart: |
| if (!token.startsWith("-d ")) { //$NON-NLS-1$ |
| state = error; |
| } else { |
| currentDestinationPath = token.substring(3).trim(); |
| state = destinationPathReadyToClose; |
| } |
| break; |
| case bracketClosed: |
| for (int i = bracket; i < cursor ; i++) { |
| currentClasspathName += (String) tokens.get(i); |
| } |
| state = readyToClose; |
| break; |
| case bracketOpened: |
| break; |
| default: |
| state = error; |
| } |
| } |
| if (state == bracketClosed && cursor == tokensNb) { |
| cursor = bracket + 1; |
| state = rulesStart; |
| } |
| } |
| switch(state) { |
| case readyToCloseOrOtherEntry: |
| break; |
| case readyToClose: |
| case readyToCloseEndingWithRules: |
| case readyToCloseEndingWithDestinationPath: |
| addNewEntry(paths, currentClasspathName, currentRuleSpecs, |
| customEncoding, currentDestinationPath, isSourceOnly, |
| rejectDestinationPathOnJars); |
| break; |
| case bracketOpened: |
| case bracketClosed: |
| default : |
| // we go on anyway |
| } |
| } |
| @SuppressWarnings({"rawtypes", "unchecked"}) |
| protected void addNewEntry(ArrayList paths, String currentClasspathName, |
| ArrayList currentRuleSpecs, String customEncoding, |
| String destPath, boolean isSourceOnly, |
| boolean rejectDestinationPathOnJars) { |
| |
| int rulesSpecsSize = currentRuleSpecs.size(); |
| AccessRuleSet accessRuleSet = null; |
| if (rulesSpecsSize != 0) { |
| AccessRule[] accessRules = new AccessRule[currentRuleSpecs.size()]; |
| boolean rulesOK = true; |
| Iterator i = currentRuleSpecs.iterator(); |
| int j = 0; |
| while (i.hasNext()) { |
| String ruleSpec = (String) i.next(); |
| char key = ruleSpec.charAt(0); |
| String pattern = ruleSpec.substring(1); |
| if (pattern.length() > 0) { |
| switch (key) { |
| case '+': |
| accessRules[j++] = new AccessRule(pattern |
| .toCharArray(), 0); |
| break; |
| case '~': |
| accessRules[j++] = new AccessRule(pattern |
| .toCharArray(), |
| IProblem.DiscouragedReference); |
| break; |
| case '-': |
| accessRules[j++] = new AccessRule(pattern |
| .toCharArray(), |
| IProblem.ForbiddenReference); |
| break; |
| case '?': |
| accessRules[j++] = new AccessRule(pattern |
| .toCharArray(), |
| IProblem.ForbiddenReference, true/*keep looking for accessible type*/); |
| break; |
| default: |
| rulesOK = false; |
| } |
| } else { |
| rulesOK = false; |
| } |
| } |
| if (rulesOK) { |
| accessRuleSet = new AccessRuleSet(accessRules, AccessRestriction.COMMAND_LINE, currentClasspathName); |
| } else { |
| return; |
| } |
| } |
| if (Main.NONE.equals(destPath)) { |
| destPath = Main.NONE; // keep == comparison valid |
| } |
| if (rejectDestinationPathOnJars && destPath != null && |
| (currentClasspathName.endsWith(".jar") || //$NON-NLS-1$ |
| currentClasspathName.endsWith(".zip"))) { //$NON-NLS-1$ |
| throw new IllegalArgumentException( |
| this.bind("configure.unexpectedDestinationPathEntryFile", //$NON-NLS-1$ |
| currentClasspathName)); |
| } |
| FileSystem.Classpath currentClasspath = FileSystem.getClasspath( |
| currentClasspathName, |
| customEncoding, |
| isSourceOnly, |
| accessRuleSet, |
| destPath, |
| null, |
| this.releaseVersion); |
| if (currentClasspath != null) { |
| paths.add(currentClasspath); |
| } |
| } |
| /* |
| * Lookup the message with the given ID in this catalog and bind its |
| * substitution locations with the given string. |
| */ |
| private String bind(String id, String binding) { |
| return bind(id, new String[] { binding }); |
| } |
| |
| /* |
| * Lookup the message with the given ID in this catalog and bind its |
| * substitution locations with the given string values. |
| */ |
| private String bind(String id, String[] arguments) { |
| if (id == null) |
| return "No message available"; //$NON-NLS-1$ |
| String message = null; |
| try { |
| message = this.bundle.getString(id); |
| } catch (MissingResourceException e) { |
| // If we got an exception looking for the message, fail gracefully by just returning |
| // the id we were looking for. In most cases this is semi-informative so is not too bad. |
| return "Missing message: " + id + " in: " + Main.bundleName; //$NON-NLS-2$ //$NON-NLS-1$ |
| } |
| return MessageFormat.format(message, (Object[]) arguments); |
| } |
| |
| private Iterable<? extends File> getFiles(final Iterable<? extends Path> paths) { |
| if (paths == null) |
| return null; |
| return () -> new Iterator<File>() { |
| Iterator<? extends Path> original = paths.iterator(); |
| @Override |
| public boolean hasNext() { |
| return this.original.hasNext(); |
| } |
| @Override |
| public File next() { |
| return this.original.next().toFile(); |
| } |
| }; |
| } |
| private Iterable<? extends Path> getPaths(final Iterable<? extends File> files) { |
| if (files == null) |
| return null; |
| return () -> new Iterator<Path>() { |
| Iterator<? extends File> original = files.iterator(); |
| @Override |
| public boolean hasNext() { |
| return this.original.hasNext(); |
| } |
| @Override |
| public Path next() { |
| return this.original.next().toPath(); |
| } |
| }; |
| } |
| |
| private void validateFileObject(FileObject file) { |
| // FIXME: fill-up |
| } |
| private void validateModuleLocation(Location location, String modName) { |
| Objects.requireNonNull(location); |
| if (modName == null) { |
| throw new IllegalArgumentException("module must not be null"); //$NON-NLS-1$ |
| } |
| if (this.isOnJvm9) { |
| if (!location.isModuleOrientedLocation() && !location.isOutputLocation()) { |
| throw new IllegalArgumentException("location is module related :" + location.getName()); //$NON-NLS-1$ |
| } |
| } |
| } |
| private void validateNonModuleLocation(Location location) { |
| Objects.requireNonNull(location); |
| if (this.isOnJvm9) { |
| if (location.isModuleOrientedLocation() && location.isOutputLocation()) { |
| throw new IllegalArgumentException("location is module related :" + location.getName()); //$NON-NLS-1$ |
| } |
| } |
| } |
| private void validateOutputLocation(Location location) { |
| Objects.requireNonNull(location); |
| if (!location.isOutputLocation()) { |
| throw new IllegalArgumentException("location is not output location :" + location.getName()); //$NON-NLS-1$ |
| } |
| } |
| @Override |
| public Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths) { |
| return getJavaFileObjectsFromPaths(Arrays.asList(paths)); |
| } |
| |
| @Override |
| public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(Iterable<? extends Path> paths) { |
| return getJavaFileObjectsFromFiles(getFiles(paths)); |
| } |
| |
| @Override |
| public Iterable<? extends Path> getLocationAsPaths(Location location) { |
| if (location instanceof LocationWrapper) { |
| return ((LocationWrapper) location).paths; |
| } |
| LocationWrapper loc = this.locationHandler.getLocation(location); |
| if (loc == null) { |
| return null; |
| } |
| return loc.getPaths(); |
| } |
| |
| @Override |
| public void setLocationFromPaths(Location location, Collection<? extends Path> paths) throws IOException { |
| setLocation(location, getFiles(paths)); |
| if (location == StandardLocation.MODULE_PATH || location == StandardLocation.MODULE_SOURCE_PATH) { |
| // FIXME: same for module source path? |
| Map<String, String> options = new HashMap<>(); |
| // FIXME: Find a way to get the options from the EclipseCompiler and pass it to the parser. |
| // FIXME: need to be the latest and not hardcoded value |
| options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_12); |
| options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_12); |
| options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_12); |
| CompilerOptions compilerOptions = new CompilerOptions(options); |
| ProblemReporter problemReporter = |
| new ProblemReporter( |
| DefaultErrorHandlingPolicies.proceedWithAllProblems(), |
| compilerOptions, |
| new DefaultProblemFactory()); |
| for (Path path : paths) { |
| List<Classpath> mp = ModuleFinder.findModules(path.toFile(), null, |
| new Parser(problemReporter, true), null, true, this.releaseVersion); |
| for (Classpath cp : mp) { |
| Collection<String> moduleNames = cp.getModuleNames(null); |
| for (String string : moduleNames) { |
| Path p = Paths.get(cp.getPath()); |
| setLocationForModule(location, string, Collections.singletonList(p)); |
| } |
| } |
| } |
| } |
| } |
| |
| @Override |
| public boolean contains(Location location, FileObject fo) throws IOException { |
| validateFileObject(fo); |
| Iterable<? extends File> files = getLocation(location); |
| if (files == null) { |
| throw new IllegalArgumentException("Unknown location : " + location);//$NON-NLS-1$ |
| } |
| for (File file : files) { |
| if (file.isDirectory()) { |
| if (fo instanceof EclipseFileObject) { |
| Path filepath = ((EclipseFileObject) fo).f.toPath(); |
| if (filepath.startsWith(Paths.get(file.toURI()).toAbsolutePath())) { |
| return true; |
| } |
| } |
| } else if (isArchive(file)) { |
| if (fo instanceof ArchiveFileObject) { |
| Archive archive = getArchive(file); |
| if (archive != Archive.UNKNOWN_ARCHIVE) { |
| if (archive.contains(((ArchiveFileObject) fo ).entryName)) { |
| return true; |
| } |
| } |
| } |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public Location getLocationForModule(Location location, String moduleName) throws IOException { |
| validateModuleLocation(location, moduleName); |
| Location result = this.locationHandler.getLocation(location, moduleName); |
| if (result == null && location == StandardLocation.CLASS_OUTPUT) { |
| LocationWrapper wrapper = this.locationHandler.getLocation(StandardLocation.MODULE_SOURCE_PATH, moduleName); |
| deriveOutputLocationForModules(moduleName, wrapper.paths); |
| result = getLocationForModule(location, moduleName); |
| } else if (result == null && location == StandardLocation.SOURCE_OUTPUT) { |
| LocationWrapper wrapper = this.locationHandler.getLocation(StandardLocation.MODULE_SOURCE_PATH, moduleName); |
| deriveSourceOutputLocationForModules(moduleName, wrapper.paths); |
| result = getLocationForModule(location, moduleName); |
| } |
| return result; |
| } |
| |
| @Override |
| public Location getLocationForModule(Location location, JavaFileObject fo) { |
| validateModuleLocation(location, ""); //$NON-NLS-1$ |
| Path path = null; |
| if (fo instanceof ArchiveFileObject) { |
| path = ((ArchiveFileObject) fo).file.toPath(); |
| return this.locationHandler.getLocation(location, path); |
| } else if (fo instanceof EclipseFileObject) { |
| path = ((EclipseFileObject) fo).f.toPath(); |
| try { |
| path = path.toRealPath(); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| LocationContainer container = this.locationHandler.getLocation(location); |
| while (path != null) { |
| Location loc = container.get(path); |
| if (loc != null) |
| return loc; |
| path = path.getParent(); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public <S> ServiceLoader<S> getServiceLoader(Location location, Class<S> service) throws IOException { |
| // FIXME: Need special handling in case of module class loaders. |
| return ServiceLoader.load(service, getClassLoader(location)); |
| } |
| |
| @Override |
| public String inferModuleName(Location location) throws IOException { |
| if (location instanceof ModuleLocationWrapper) { |
| ModuleLocationWrapper wrapper = (ModuleLocationWrapper) location; |
| return wrapper.modName; |
| } |
| return null; |
| } |
| |
| @Override |
| public Iterable<Set<Location>> listLocationsForModules(Location location) { |
| validateModuleLocation(location, ""); //$NON-NLS-1$ |
| return this.locationHandler.listLocationsForModules(location); |
| } |
| |
| @Override |
| public Path asPath(FileObject file) { |
| validateFileObject(file); |
| EclipseFileObject eclFile = (EclipseFileObject) file; |
| if (eclFile.f != null) { |
| return eclFile.f.toPath(); |
| } |
| return null; |
| } |
| private void deriveOutputLocationForModules(String moduleName, Collection<? extends Path> paths) { |
| LocationWrapper wrapper = this.locationHandler.getLocation(StandardLocation.CLASS_OUTPUT, moduleName); |
| if (wrapper == null) { |
| // First get from our internally known location for legacy/unnamed location |
| wrapper = this.locationHandler.getLocation(StandardLocation.CLASS_OUTPUT, ""); //$NON-NLS-1$ |
| if (wrapper == null) { |
| wrapper = this.locationHandler.getLocation(StandardLocation.CLASS_OUTPUT); |
| } |
| if (wrapper != null) { |
| Iterator<? extends Path> iterator = wrapper.paths.iterator(); |
| if (iterator.hasNext()) { |
| try { |
| // Per module output location is always a singleton list |
| Path path = iterator.next().resolve(moduleName); |
| this.locationHandler.setLocation(StandardLocation.CLASS_OUTPUT, moduleName, Collections.singletonList(path)); |
| } catch(Exception e) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| } |
| } |
| private void deriveSourceOutputLocationForModules(String moduleName, Collection<? extends Path> paths) { |
| LocationWrapper wrapper = this.locationHandler.getLocation(StandardLocation.SOURCE_OUTPUT, moduleName); |
| if (wrapper == null) { |
| // First get from our internally known location for legacy/unnamed location |
| wrapper = this.locationHandler.getLocation(StandardLocation.SOURCE_OUTPUT, ""); //$NON-NLS-1$ |
| if (wrapper == null) { |
| wrapper = this.locationHandler.getLocation(StandardLocation.SOURCE_OUTPUT); |
| } |
| if (wrapper != null) { |
| Iterator<? extends Path> iterator = wrapper.paths.iterator(); |
| if (iterator.hasNext()) { |
| try { |
| // Per module output location is always a singleton list |
| Path path = iterator.next().resolve(moduleName); |
| this.locationHandler.setLocation(StandardLocation.SOURCE_OUTPUT, moduleName, Collections.singletonList(path)); |
| } catch(Exception e) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| } |
| } |
| @Override |
| public void setLocationForModule(Location location, String moduleName, Collection<? extends Path> paths) throws IOException { |
| validateModuleLocation(location, moduleName); |
| this.locationHandler.setLocation(location, moduleName, paths); |
| if (location == StandardLocation.MODULE_SOURCE_PATH) { |
| deriveOutputLocationForModules(moduleName, paths); |
| } |
| } |
| } |