| /******************************************************************************* |
| * Copyright (c) 2007, 2021 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 |
| * IBM Corporation - fix for 342936 |
| * Kenneth Olson - Contribution for bug 188796 - [jsr199] Using JSR199 to extend ECJ |
| * Dennis Hendriks - Contribution for bug 188796 - [jsr199] Using JSR199 to extend ECJ |
| * Frits Jalvingh - fix for bug 533830. |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.compiler.tool; |
| |
| import java.io.BufferedOutputStream; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.io.PrintWriter; |
| import java.nio.charset.Charset; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.util.ArrayList; |
| 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.Optional; |
| import java.util.stream.Stream; |
| |
| import javax.annotation.processing.Processor; |
| import javax.lang.model.SourceVersion; |
| import javax.tools.Diagnostic; |
| import javax.tools.DiagnosticListener; |
| import javax.tools.JavaFileManager; |
| import javax.tools.JavaFileManager.Location; |
| import javax.tools.JavaFileObject; |
| import javax.tools.StandardJavaFileManager; |
| import javax.tools.StandardLocation; |
| |
| import org.eclipse.jdt.core.compiler.CategorizedProblem; |
| import org.eclipse.jdt.core.compiler.CharOperation; |
| import org.eclipse.jdt.core.compiler.CompilationProgress; |
| import org.eclipse.jdt.internal.compiler.ClassFile; |
| import org.eclipse.jdt.internal.compiler.CompilationResult; |
| import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy; |
| import org.eclipse.jdt.internal.compiler.IProblemFactory; |
| import org.eclipse.jdt.internal.compiler.batch.ClasspathJrt; |
| import org.eclipse.jdt.internal.compiler.batch.ClasspathJsr199; |
| import org.eclipse.jdt.internal.compiler.batch.CompilationUnit; |
| 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.classfmt.ClassFileConstants; |
| import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; |
| import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; |
| import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit; |
| import org.eclipse.jdt.internal.compiler.problem.DefaultProblem; |
| import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; |
| import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; |
| import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; |
| import org.eclipse.jdt.internal.compiler.util.Messages; |
| import org.eclipse.jdt.internal.compiler.util.SuffixConstants; |
| import org.eclipse.jdt.internal.compiler.util.Util; |
| |
| public class EclipseCompilerImpl extends Main { |
| private static final CompilationUnit[] NO_UNITS = new CompilationUnit[0]; |
| private static final String RELEASE_FILE = "release"; //$NON-NLS-1$ |
| private static final String JAVA_VERSION = "JAVA_VERSION"; //$NON-NLS-1$ |
| private HashMap<CompilationUnit, JavaFileObject> javaFileObjectMap; |
| Iterable<? extends JavaFileObject> compilationUnits; |
| public JavaFileManager fileManager; |
| protected Processor[] processors; |
| public DiagnosticListener<? super JavaFileObject> diagnosticListener; |
| |
| public EclipseCompilerImpl(PrintWriter out, PrintWriter err, boolean systemExitWhenFinished) { |
| super(out, err, systemExitWhenFinished, null/*options*/, null/*progress*/); |
| } |
| |
| public boolean call() { |
| try { |
| handleLocations(); |
| if (this.proceed) { |
| this.globalProblemsCount = 0; |
| this.globalErrorsCount = 0; |
| this.globalWarningsCount = 0; |
| this.globalTasksCount = 0; |
| this.exportedClassFilesCounter = 0; |
| // request compilation |
| performCompilation(); |
| } |
| } catch(IllegalArgumentException e) { |
| this.diagnosticListener.report(new ExceptionDiagnostic(e)); |
| this.logger.logException(e); |
| if (this.systemExitWhenFinished) { |
| cleanup(); |
| System.exit(-1); |
| } |
| return false; |
| } catch (RuntimeException e) { // internal compiler failure |
| this.diagnosticListener.report(new ExceptionDiagnostic(e)); |
| this.logger.logException(e); |
| return false; |
| } finally { |
| cleanup(); |
| } |
| if (this.failOnWarning && this.globalWarningsCount > 0) { |
| return false; |
| } |
| return this.globalErrorsCount == 0; |
| } |
| |
| private void cleanup() { |
| this.logger.flush(); |
| this.logger.close(); |
| this.processors = null; |
| try { |
| if (this.fileManager != null) { |
| this.fileManager.flush(); |
| } |
| } catch (IOException e) { |
| // ignore |
| } |
| } |
| |
| @Override |
| public CompilationUnit[] getCompilationUnits() { |
| // This method is largely a copy of Main#getCompilationUnits() |
| if (this.compilationUnits == null) return EclipseCompilerImpl.NO_UNITS; |
| HashtableOfObject knownFileNames = new HashtableOfObject(); |
| ArrayList<CompilationUnit> units = new ArrayList<>(); |
| for (int round = 0; round < 2; round++) { |
| int i = 0; |
| for (final JavaFileObject javaFileObject : this.compilationUnits) { |
| String name = javaFileObject.getName(); |
| char[] charName = name.toCharArray(); |
| boolean isModuleInfo = CharOperation.endsWith(charName, TypeConstants.MODULE_INFO_FILE_NAME); |
| if (isModuleInfo == (round==0)) { // 1st round: modules, 2nd round others (to ensure populating pathToModCU well in time) |
| if (knownFileNames.get(charName) != null) |
| throw new IllegalArgumentException(this.bind("unit.more", name)); //$NON-NLS-1$ |
| knownFileNames.put(charName, charName); |
| |
| boolean found = false; |
| try { |
| if (this.fileManager.hasLocation(StandardLocation.SOURCE_PATH)) { |
| found = this.fileManager.contains(StandardLocation.SOURCE_PATH, javaFileObject); |
| } |
| if (!found) { |
| if (this.fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH)) { |
| found = this.fileManager.contains(StandardLocation.MODULE_SOURCE_PATH, javaFileObject); |
| } |
| } |
| } catch (IOException e) { |
| // Not found. |
| } |
| if (!found) { |
| File file = new File(name); |
| if (!file.exists()) |
| throw new IllegalArgumentException(this.bind("unit.missing", name)); //$NON-NLS-1$ |
| } |
| |
| CompilationUnit cu = new CompilationUnit(null, |
| name, |
| null, |
| this.destinationPaths[i], |
| shouldIgnoreOptionalProblems(this.ignoreOptionalProblemsFromFolders, name.toCharArray()), this.modNames[i]) { |
| |
| @Override |
| public char[] getContents() { |
| try { |
| return javaFileObject.getCharContent(true).toString().toCharArray(); |
| } catch(IOException e) { |
| e.printStackTrace(); |
| throw new AbortCompilationUnit(null, e, null); |
| } |
| } |
| }; |
| units.add(cu); |
| this.javaFileObjectMap.put(cu, javaFileObject); |
| } |
| i++; |
| } |
| } |
| CompilationUnit[] result = new CompilationUnit[units.size()]; |
| units.toArray(result); |
| return result; |
| } |
| /* |
| * Low-level API performing the actual compilation |
| */ |
| @Override |
| public IErrorHandlingPolicy getHandlingPolicy() { |
| // passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match) |
| return new IErrorHandlingPolicy() { |
| @Override |
| public boolean proceedOnErrors() { |
| return false; // stop if there are some errors |
| } |
| @Override |
| public boolean stopOnFirstError() { |
| return false; |
| } |
| @Override |
| public boolean ignoreAllErrors() { |
| return false; |
| } |
| }; |
| } |
| |
| @Override |
| public IProblemFactory getProblemFactory() { |
| return new DefaultProblemFactory() { |
| @Override |
| public CategorizedProblem createProblem( |
| final char[] originatingFileName, |
| final int problemId, |
| final String[] problemArguments, |
| final String[] messageArguments, |
| final int severity, |
| final int startPosition, |
| final int endPosition, |
| final int lineNumber, |
| final int columnNumber) { |
| |
| DiagnosticListener<? super JavaFileObject> diagListener = EclipseCompilerImpl.this.diagnosticListener; |
| Diagnostic<JavaFileObject> diagnostic = null; |
| if (diagListener != null) { |
| diagnostic = new Diagnostic<>() { |
| @Override |
| public String getCode() { |
| return Integer.toString(problemId); |
| } |
| @Override |
| public long getColumnNumber() { |
| return columnNumber; |
| } |
| @Override |
| public long getEndPosition() { |
| return endPosition; |
| } |
| @Override |
| public Kind getKind() { |
| if ((severity & ProblemSeverities.Error) != 0) { |
| return Diagnostic.Kind.ERROR; |
| } |
| if ((severity & ProblemSeverities.Optional) != 0) { |
| return Diagnostic.Kind.WARNING; |
| } |
| if ((severity & ProblemSeverities.Warning) != 0) { |
| return Diagnostic.Kind.MANDATORY_WARNING; |
| } |
| return Diagnostic.Kind.OTHER; |
| } |
| @Override |
| public long getLineNumber() { |
| return lineNumber; |
| } |
| @Override |
| public String getMessage(Locale locale) { |
| if (locale != null) { |
| setLocale(locale); |
| } |
| return getLocalizedMessage(problemId, problemArguments); |
| } |
| @Override |
| public long getPosition() { |
| return startPosition; |
| } |
| @Override |
| public JavaFileObject getSource() { |
| File f = new File(new String(originatingFileName)); |
| if (f.exists()) { |
| return new EclipseFileObject(null, f.toURI(), JavaFileObject.Kind.SOURCE, null); |
| } |
| return null; |
| } |
| @Override |
| public long getStartPosition() { |
| return startPosition; |
| } |
| }; |
| } |
| CategorizedProblem problem = super.createProblem(originatingFileName, problemId, problemArguments, messageArguments, severity, startPosition, endPosition, lineNumber, columnNumber); |
| if (problem instanceof DefaultProblem && diagnostic != null) { |
| return new Jsr199ProblemWrapper((DefaultProblem) problem, diagnostic, diagListener); |
| } |
| return problem; |
| } |
| @Override |
| public CategorizedProblem createProblem( |
| final char[] originatingFileName, |
| final int problemId, |
| final String[] problemArguments, |
| final int elaborationID, |
| final String[] messageArguments, |
| final int severity, |
| final int startPosition, |
| final int endPosition, |
| final int lineNumber, |
| final int columnNumber) { |
| |
| DiagnosticListener<? super JavaFileObject> diagListener = EclipseCompilerImpl.this.diagnosticListener; |
| Diagnostic<JavaFileObject> diagnostic = null; |
| if (diagListener != null) { |
| diagnostic = new Diagnostic<>() { |
| @Override |
| public String getCode() { |
| return Integer.toString(problemId); |
| } |
| @Override |
| public long getColumnNumber() { |
| return columnNumber; |
| } |
| @Override |
| public long getEndPosition() { |
| return endPosition; |
| } |
| @Override |
| public Kind getKind() { |
| if ((severity & ProblemSeverities.Error) != 0) { |
| return Diagnostic.Kind.ERROR; |
| } |
| if ((severity & ProblemSeverities.Info) != 0) { |
| return Diagnostic.Kind.NOTE; |
| } |
| if ((severity & ProblemSeverities.Optional) != 0) { |
| return Diagnostic.Kind.WARNING; |
| } |
| if ((severity & ProblemSeverities.Warning) != 0) { |
| return Diagnostic.Kind.MANDATORY_WARNING; |
| } |
| return Diagnostic.Kind.OTHER; |
| } |
| @Override |
| public long getLineNumber() { |
| return lineNumber; |
| } |
| @Override |
| public String getMessage(Locale locale) { |
| if (locale != null) { |
| setLocale(locale); |
| } |
| return getLocalizedMessage(problemId, problemArguments); |
| } |
| @Override |
| public long getPosition() { |
| return startPosition; |
| } |
| @Override |
| public JavaFileObject getSource() { |
| File f = new File(new String(originatingFileName)); |
| if (f.exists()) { |
| return new EclipseFileObject(null, f.toURI(), JavaFileObject.Kind.SOURCE, null); |
| } |
| return null; |
| } |
| @Override |
| public long getStartPosition() { |
| return startPosition; |
| } |
| }; |
| } |
| CategorizedProblem problem = super.createProblem(originatingFileName, problemId, problemArguments, elaborationID, messageArguments, severity, startPosition, endPosition, lineNumber, columnNumber); |
| if (problem instanceof DefaultProblem && diagnostic != null) { |
| return new Jsr199ProblemWrapper((DefaultProblem) problem, diagnostic, diagListener); |
| } |
| return problem; |
| } |
| }; |
| } |
| |
| @Override |
| protected void initialize(PrintWriter outWriter, PrintWriter errWriter, boolean systemExit, Map<String, String> customDefaultOptions, CompilationProgress compilationProgress) { |
| super.initialize(outWriter, errWriter, systemExit, customDefaultOptions, compilationProgress); |
| this.javaFileObjectMap = new HashMap<>(); |
| } |
| |
| @Override |
| protected void initializeAnnotationProcessorManager() { |
| super.initializeAnnotationProcessorManager(); |
| if (this.batchCompiler.annotationProcessorManager != null && this.processors != null) { |
| this.batchCompiler.annotationProcessorManager.setProcessors(this.processors); |
| } else if (this.processors != null) { |
| throw new UnsupportedOperationException("Cannot handle annotation processing"); //$NON-NLS-1$ |
| } |
| } |
| |
| // Dump classfiles onto disk for all compilation units that where successful |
| // and do not carry a -d none spec, either directly or inherited from Main. |
| @Override |
| public void outputClassFiles(CompilationResult unitResult) { |
| if (!((unitResult == null) || (unitResult.hasErrors() && !this.proceedOnError))) { |
| ClassFile[] classFiles = unitResult.getClassFiles(); |
| boolean generateClasspathStructure = this.fileManager.hasLocation(StandardLocation.CLASS_OUTPUT); |
| File outputLocation = null; |
| String currentDestinationPath = unitResult.getCompilationUnit().getDestinationPath(); |
| if (currentDestinationPath == null) |
| currentDestinationPath = this.destinationPath; |
| if (currentDestinationPath != null) { |
| outputLocation = new File(currentDestinationPath); |
| outputLocation.mkdirs(); |
| } |
| for (int i = 0, fileCount = classFiles.length; i < fileCount; i++) { |
| // retrieve the key and the corresponding classfile |
| ClassFile classFile = classFiles[i]; |
| char[] filename = classFile.fileName(); |
| int length = filename.length; |
| char[] relativeName = new char[length + 6]; |
| System.arraycopy(filename, 0, relativeName, 0, length); |
| System.arraycopy(SuffixConstants.SUFFIX_class, 0, relativeName, length, 6); |
| CharOperation.replace(relativeName, '/', File.separatorChar); |
| String relativeStringName = new String(relativeName); |
| if (this.compilerOptions.verbose) { |
| EclipseCompilerImpl.this.out.println( |
| Messages.bind( |
| Messages.compilation_write, |
| new String[] { |
| String.valueOf(this.exportedClassFilesCounter+1), |
| relativeStringName |
| })); |
| } |
| try { |
| char[] modName = unitResult.compilationUnit.getModuleName(); |
| Location location = null; |
| if (modName == null) { |
| location = StandardLocation.CLASS_OUTPUT; |
| } else { |
| // TODO: Still possible to end up with a non-null module name without JDK 9 in build path |
| location = this.fileManager.getLocationForModule(StandardLocation.CLASS_OUTPUT, new String(modName)); |
| } |
| JavaFileObject javaFileForOutput = |
| this.fileManager.getJavaFileForOutput( |
| location, |
| new String(filename), |
| JavaFileObject.Kind.CLASS, |
| this.javaFileObjectMap.get(unitResult.compilationUnit)); |
| |
| if (generateClasspathStructure) { |
| if (currentDestinationPath != null) { |
| int index = CharOperation.lastIndexOf(File.separatorChar, relativeName); |
| if (index != -1) { |
| File currentFolder = new File(currentDestinationPath, relativeStringName.substring(0, index)); |
| currentFolder.mkdirs(); |
| } |
| } else { |
| // create the subfolfers is necessary |
| // need a way to retrieve the folders to create |
| String path = javaFileForOutput.toUri().getPath(); |
| int index = path.lastIndexOf('/'); |
| if (index != -1) { |
| File file = new File(path.substring(0, index)); |
| file.mkdirs(); |
| } |
| } |
| } |
| |
| try (OutputStream openOutputStream = javaFileForOutput.openOutputStream(); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(openOutputStream)) { |
| bufferedOutputStream.write(classFile.header, 0, classFile.headerOffset); |
| bufferedOutputStream.write(classFile.contents, 0, classFile.contentsOffset); |
| bufferedOutputStream.flush(); |
| } |
| } catch (IOException e) { |
| this.logger.logNoClassFileCreated(currentDestinationPath, relativeStringName, e); |
| } |
| this.logger.logClassFile( |
| generateClasspathStructure, |
| currentDestinationPath, |
| relativeStringName); |
| this.exportedClassFilesCounter++; |
| } |
| this.batchCompiler.lookupEnvironment.releaseClassFiles(classFiles); |
| } |
| } |
| |
| @Override |
| protected void setPaths(ArrayList<String> bootclasspaths, |
| String sourcepathClasspathArg, |
| ArrayList<String> sourcepathClasspaths, |
| ArrayList<String> classpaths, |
| String modulePath, |
| String moduleSourcepath, |
| ArrayList<String> extdirsClasspaths, |
| ArrayList<String> endorsedDirClasspaths, |
| String customEncoding) { |
| // Sometimes this gets called too early there by losing locations set after that point. |
| // The code is now moved to handleLocations() which is invoked just before compilation |
| validateClasspathOptions(bootclasspaths, endorsedDirClasspaths, extdirsClasspaths); |
| } |
| |
| protected void handleLocations() { |
| ArrayList<FileSystem.Classpath> fileSystemClasspaths = new ArrayList<>(); |
| EclipseFileManager eclipseJavaFileManager = null; |
| StandardJavaFileManager standardJavaFileManager = null; |
| JavaFileManager javaFileManager = null; |
| boolean havePlatformPaths = false; |
| boolean haveClassPaths = false; |
| if (this.fileManager instanceof EclipseFileManager) { |
| eclipseJavaFileManager = (EclipseFileManager) this.fileManager; |
| } |
| if (this.fileManager instanceof StandardJavaFileManager) { |
| standardJavaFileManager = (StandardJavaFileManager) this.fileManager; |
| } |
| javaFileManager = this.fileManager; |
| |
| if (eclipseJavaFileManager != null) { |
| if ((eclipseJavaFileManager.flags & EclipseFileManager.HAS_ENDORSED_DIRS) == 0 |
| && (eclipseJavaFileManager.flags & EclipseFileManager.HAS_BOOTCLASSPATH) != 0) { |
| fileSystemClasspaths.addAll(this.handleEndorseddirs(null)); |
| } |
| } |
| Iterable<? extends File> locationFiles = null; |
| if (standardJavaFileManager != null) { |
| locationFiles = standardJavaFileManager.getLocation(StandardLocation.PLATFORM_CLASS_PATH); |
| if (locationFiles != null) { |
| for (File file : locationFiles) { |
| if (file.isDirectory()) { |
| List<Classpath> platformLocations = getPlatformLocations(file); |
| if (standardJavaFileManager instanceof EclipseFileManager) { |
| if (platformLocations.size() == 1) { |
| Classpath jrt = platformLocations.get(0); |
| if (jrt instanceof ClasspathJrt) { |
| ClasspathJrt classpathJrt = (ClasspathJrt) jrt; |
| // TODO: double check, should it be platform or system module? |
| try { |
| EclipseFileManager efm = (EclipseFileManager) standardJavaFileManager; |
| @SuppressWarnings("resource") // XXX EclipseFileManager should close jrtfs but it looks like standardJavaFileManager is never closed |
| // Was leaking new JrtFileSystem(classpathJrt.file): |
| JrtFileSystem jrtfs = efm.getJrtFileSystem(classpathJrt.file); |
| efm.locationHandler.newSystemLocation(StandardLocation.SYSTEM_MODULES, jrtfs); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| } |
| fileSystemClasspaths.addAll(platformLocations); |
| break; // Only possible scenario is, we have one and only entry representing the Java home. |
| } else { |
| Classpath classpath = FileSystem.getClasspath( |
| file.getAbsolutePath(), |
| null, |
| null, |
| this.options, |
| this.releaseVersion); |
| if (classpath != null) { |
| fileSystemClasspaths.add(classpath); |
| havePlatformPaths = true; |
| } |
| } |
| } |
| } |
| } else if (javaFileManager != null) { |
| File javaHome = Util.getJavaHome(); |
| long jdkLevel = Util.getJDKLevel(javaHome); |
| if (jdkLevel >= ClassFileConstants.JDK9) { |
| Classpath systemClasspath = getSystemClasspath(javaHome, jdkLevel); |
| Classpath classpath = new ClasspathJsr199(systemClasspath, this.fileManager, StandardLocation.SYSTEM_MODULES); |
| fileSystemClasspaths.add(classpath); |
| classpath = new ClasspathJsr199(systemClasspath, this.fileManager, StandardLocation.PLATFORM_CLASS_PATH); |
| fileSystemClasspaths.add(classpath); |
| } else { |
| Classpath classpath = new ClasspathJsr199(this.fileManager, StandardLocation.PLATFORM_CLASS_PATH); |
| fileSystemClasspaths.add(classpath); |
| } |
| havePlatformPaths = true; |
| } |
| if (eclipseJavaFileManager != null) { |
| if ((eclipseJavaFileManager.flags & EclipseFileManager.HAS_EXT_DIRS) == 0 |
| && (eclipseJavaFileManager.flags & EclipseFileManager.HAS_BOOTCLASSPATH) != 0) { |
| fileSystemClasspaths.addAll(this.handleExtdirs(null)); |
| } |
| } |
| if (standardJavaFileManager != null) { |
| locationFiles = standardJavaFileManager.getLocation(StandardLocation.SOURCE_PATH); |
| if (locationFiles != null) { |
| for (File file : locationFiles) { |
| Classpath classpath = FileSystem.getClasspath( |
| file.getAbsolutePath(), |
| null, |
| null, |
| this.options, |
| this.releaseVersion); |
| if (classpath != null) { |
| fileSystemClasspaths.add(classpath); |
| } |
| } |
| } |
| locationFiles = standardJavaFileManager.getLocation(StandardLocation.CLASS_PATH); |
| if (locationFiles != null) { |
| for (File file : locationFiles) { |
| Classpath classpath = FileSystem.getClasspath( |
| file.getAbsolutePath(), |
| null, |
| null, |
| this.options, |
| this.releaseVersion); |
| if (classpath != null) { |
| fileSystemClasspaths.add(classpath); |
| haveClassPaths = true; |
| } |
| } |
| } |
| locationFiles = standardJavaFileManager.getLocation(StandardLocation.PLATFORM_CLASS_PATH); |
| if (locationFiles != null) { |
| for (File file : locationFiles) { |
| if (file.isDirectory()) { |
| String javaVersion = getJavaVersion(file); |
| long jdkLevel = javaVersion.equals("") ? this.complianceLevel : CompilerOptions.versionToJdkLevel(javaVersion); //$NON-NLS-1$ |
| Classpath systemClasspath = getSystemClasspath(file, jdkLevel); |
| Classpath classpath = new ClasspathJsr199(systemClasspath, this.fileManager, StandardLocation.PLATFORM_CLASS_PATH); |
| fileSystemClasspaths.add(classpath); |
| // Copy over to modules location as well |
| if (standardJavaFileManager.getLocation(StandardLocation.SYSTEM_MODULES) == null) { |
| classpath = new ClasspathJsr199(systemClasspath, this.fileManager, StandardLocation.SYSTEM_MODULES); |
| fileSystemClasspaths.add(classpath); |
| } |
| haveClassPaths = true; |
| break; //unlikely to have more than one path |
| } |
| } |
| } |
| locationFiles = standardJavaFileManager.getLocation(StandardLocation.SYSTEM_MODULES); |
| if (locationFiles != null) { |
| for (File file : locationFiles) { |
| if (file.isDirectory()) { |
| String javaVersion = getJavaVersion(file); |
| long jdkLevel = javaVersion.equals("") ? this.complianceLevel : CompilerOptions.versionToJdkLevel(javaVersion); //$NON-NLS-1$ |
| Classpath systemClasspath = getSystemClasspath(file, jdkLevel); |
| Classpath classpath = new ClasspathJsr199(systemClasspath, this.fileManager, StandardLocation.SYSTEM_MODULES); |
| fileSystemClasspaths.add(classpath); |
| // Copy over to platform location as well |
| if (standardJavaFileManager.getLocation(StandardLocation.PLATFORM_CLASS_PATH) == null) { |
| classpath = new ClasspathJsr199(systemClasspath, this.fileManager, StandardLocation.PLATFORM_CLASS_PATH); |
| fileSystemClasspaths.add(classpath); |
| } |
| haveClassPaths = true; |
| break; //unlikely to have more than one path |
| } |
| } |
| } |
| try { |
| Iterable<? extends Path> locationAsPaths = standardJavaFileManager.getLocationAsPaths(StandardLocation.MODULE_SOURCE_PATH); |
| if (locationAsPaths != null) { |
| StringBuilder builder = new StringBuilder(); |
| for (Path path : locationAsPaths) { |
| // Append all of them |
| builder.append(path.toFile().getCanonicalPath()); |
| builder.append(File.pathSeparator); |
| } |
| ArrayList<Classpath> modulepaths = handleModuleSourcepath(builder.toString()); |
| for (Classpath classpath : modulepaths) { |
| Collection<String> moduleNames = classpath.getModuleNames(null); |
| for (String modName : moduleNames) { |
| Path p = Paths.get(classpath.getPath()); |
| standardJavaFileManager.setLocationForModule(StandardLocation.MODULE_SOURCE_PATH, modName, |
| Collections.singletonList(p)); |
| p = Paths.get(classpath.getDestinationPath()); |
| } |
| } |
| fileSystemClasspaths.addAll(modulepaths); |
| } |
| } catch (IllegalStateException e) { |
| // Ignore this as JRE 9 throws IllegalStateException for getLocation returning null |
| } catch (IllegalArgumentException e) { |
| throw e; |
| } catch (Exception e) { |
| this.logger.logException(e); |
| } |
| try { |
| locationFiles = standardJavaFileManager.getLocation(StandardLocation.MODULE_PATH); |
| if (locationFiles != null) { |
| for (File file : locationFiles) { |
| try { |
| ArrayList<Classpath> modulepaths = handleModulepath(file.getCanonicalPath()); |
| for (Classpath classpath : modulepaths) { |
| Collection<String> moduleNames = classpath.getModuleNames(null); |
| for (String string : moduleNames) { |
| Path path = Paths.get(classpath.getPath()); |
| standardJavaFileManager.setLocationForModule(StandardLocation.MODULE_PATH, string, |
| Collections.singletonList(path)); |
| } |
| } |
| fileSystemClasspaths.addAll(modulepaths); |
| } catch (IOException e) { |
| throw new AbortCompilationUnit(null, e, null); |
| } |
| } |
| } |
| } catch (IllegalStateException e) { |
| // Ignore this as JRE 9 throws IllegalStateException for getLocation returning null |
| } catch (IllegalArgumentException e) { |
| throw e; |
| } catch (Exception e) { |
| this.logger.logException(e); |
| } |
| } else if (javaFileManager != null) { |
| Classpath classpath = null; |
| if (this.fileManager.hasLocation(StandardLocation.SOURCE_PATH)) { |
| classpath = new ClasspathJsr199(this.fileManager, StandardLocation.SOURCE_PATH); |
| fileSystemClasspaths.add(classpath); |
| } |
| // Add the locations to search for in specific order |
| if (this.fileManager.hasLocation(StandardLocation.UPGRADE_MODULE_PATH)) { |
| classpath = new ClasspathJsr199(this.fileManager, StandardLocation.UPGRADE_MODULE_PATH); |
| } |
| if (this.fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH)) { |
| classpath = new ClasspathJsr199(this.fileManager, StandardLocation.PATCH_MODULE_PATH); |
| fileSystemClasspaths.add(classpath); |
| } |
| if (this.fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH)) { |
| classpath = new ClasspathJsr199(this.fileManager, StandardLocation.MODULE_SOURCE_PATH); |
| fileSystemClasspaths.add(classpath); |
| } |
| if (this.fileManager.hasLocation(StandardLocation.MODULE_PATH)) { |
| classpath = new ClasspathJsr199(this.fileManager, StandardLocation.MODULE_PATH); |
| fileSystemClasspaths.add(classpath); |
| } |
| classpath = new ClasspathJsr199(this.fileManager, StandardLocation.CLASS_PATH); |
| fileSystemClasspaths.add(classpath); |
| haveClassPaths = true; |
| } |
| if (this.checkedClasspaths == null) { |
| // It appears to be necessary to handleBootclasspath() for IBM JVMs |
| // in order to have visibility to java.lang.String (not present in rt.jar). |
| // The jars returned by StandardFileManager.getLocation(PLATFORM_CLASS_PATH) are |
| // not sufficient to resolve all standard classes. |
| if (!havePlatformPaths) fileSystemClasspaths.addAll(this.handleBootclasspath(null, null)); |
| if (!haveClassPaths) fileSystemClasspaths.addAll(this.handleClasspath(null, null)); |
| } |
| fileSystemClasspaths = FileSystem.ClasspathNormalizer.normalize(fileSystemClasspaths); |
| final int size = fileSystemClasspaths.size(); |
| if (size != 0) { |
| this.checkedClasspaths = new FileSystem.Classpath[size]; |
| int i = 0; |
| for (FileSystem.Classpath classpath : fileSystemClasspaths) { |
| this.checkedClasspaths[i++] = classpath; |
| } |
| } |
| } |
| private String getJavaVersion(File javaHome) { |
| String version = ""; //$NON-NLS-1$ |
| if (Files.notExists(Paths.get(javaHome.getAbsolutePath(), RELEASE_FILE))) { |
| return version; |
| } |
| try (Stream<String> lines = Files.lines(Paths.get(javaHome.getAbsolutePath(), RELEASE_FILE), Charset.defaultCharset()).filter(s -> s.contains(JAVA_VERSION))) { |
| Optional<String> hasVersion = lines.findFirst(); |
| if (hasVersion.isPresent()) { |
| String line = hasVersion.get(); |
| version = line.substring(14, line.length() - 1); // length of JAVA_VERSION + 2 in JAVA_VERSION="9" |
| } |
| } |
| catch (Exception e) { |
| // return default |
| } |
| return version; |
| } |
| private Classpath getSystemClasspath(File jdkHome, long jdkLevel) { |
| Classpath system; |
| if (this.releaseVersion != null && this.complianceLevel < jdkLevel) { |
| String versionFromJdkLevel = CompilerOptions.versionFromJdkLevel(this.complianceLevel); |
| if (versionFromJdkLevel.length() >= 3) { |
| versionFromJdkLevel = versionFromJdkLevel.substring(2); |
| } |
| // TODO: Revisit for access rules |
| system = FileSystem.getOlderSystemRelease(jdkHome.getAbsolutePath(), versionFromJdkLevel, null); |
| } else { |
| system = FileSystem.getJrtClasspath(jdkHome.toString(), null, null, null); |
| } |
| return system; |
| } |
| |
| protected List<Classpath> getPlatformLocations(File file) { |
| List<Classpath> platformLibraries = Util.collectPlatformLibraries(file); |
| return platformLibraries; |
| } |
| @Override |
| protected void loggingExtraProblems() { |
| super.loggingExtraProblems(); |
| for (@SuppressWarnings("rawtypes") |
| Iterator iterator = this.extraProblems.iterator(); iterator.hasNext(); ) { |
| final CategorizedProblem problem = (CategorizedProblem) iterator.next(); |
| if (this.diagnosticListener != null && !isIgnored(problem)) { |
| Diagnostic<JavaFileObject> diagnostic = new Diagnostic<>() { |
| @Override |
| public String getCode() { |
| return null; |
| } |
| @Override |
| public long getColumnNumber() { |
| if (problem instanceof DefaultProblem) { |
| return ((DefaultProblem) problem).column; |
| } |
| return Diagnostic.NOPOS; |
| } |
| @Override |
| public long getEndPosition() { |
| if (problem instanceof DefaultProblem) { |
| return ((DefaultProblem) problem).getSourceEnd(); |
| } |
| return Diagnostic.NOPOS; |
| } |
| @Override |
| public Kind getKind() { |
| if (problem.isError()) { |
| return Diagnostic.Kind.ERROR; |
| } |
| if (problem.isWarning()) { |
| return Diagnostic.Kind.WARNING; |
| } else if (problem instanceof DefaultProblem && ((DefaultProblem) problem).isInfo()) { |
| return Diagnostic.Kind.NOTE; |
| } |
| return Diagnostic.Kind.OTHER; |
| } |
| @Override |
| public long getLineNumber() { |
| if (problem instanceof DefaultProblem) { |
| return ((DefaultProblem) problem).getSourceLineNumber(); |
| } |
| return Diagnostic.NOPOS; |
| } |
| @Override |
| public String getMessage(Locale locale) { |
| return problem.getMessage(); |
| } |
| @Override |
| public long getPosition() { |
| if (problem instanceof DefaultProblem) { |
| return ((DefaultProblem) problem).getSourceStart(); |
| } |
| return Diagnostic.NOPOS; |
| } |
| @Override |
| public JavaFileObject getSource() { |
| if (problem instanceof DefaultProblem) { |
| char[] originatingName = ((DefaultProblem) problem).getOriginatingFileName(); |
| if (originatingName == null) { |
| return null; |
| } |
| File f = new File(new String(originatingName)); |
| if (f.exists()) { |
| Charset charset = (EclipseCompilerImpl.this.fileManager instanceof EclipseFileManager) ? |
| ((EclipseFileManager) EclipseCompilerImpl.this.fileManager).charset : Charset.defaultCharset(); |
| return new EclipseFileObject(null, f.toURI(), JavaFileObject.Kind.SOURCE, charset); |
| } |
| return null; |
| } |
| return null; |
| } |
| @Override |
| public long getStartPosition() { |
| return getPosition(); |
| } |
| }; |
| this.diagnosticListener.report(diagnostic); |
| } |
| } |
| } |
| class Jsr199ProblemWrapper extends DefaultProblem { |
| |
| DefaultProblem original; |
| DiagnosticListener<? super JavaFileObject> listener; |
| Diagnostic<JavaFileObject> diagnostic; |
| |
| public Jsr199ProblemWrapper(DefaultProblem original, Diagnostic<JavaFileObject> diagnostic, DiagnosticListener<? super JavaFileObject> listener) { |
| super(original.getOriginatingFileName(), |
| original.getMessage(), |
| original.getID(), |
| original.getArguments(), |
| original.severity, |
| original.getSourceStart(), |
| original.getSourceEnd(), |
| original.getSourceLineNumber(), |
| original.column); |
| this.original = original; |
| this.listener = listener; |
| this.diagnostic = diagnostic; |
| } |
| @Override |
| public void reportError() { |
| this.listener.report(this.diagnostic); |
| } |
| |
| @Override |
| public String[] getArguments() { |
| return this.original.getArguments(); |
| } |
| |
| @Override |
| public int getID() { |
| return this.original.getID(); |
| } |
| |
| @Override |
| public String getMessage() { |
| return this.original.getMessage(); |
| } |
| |
| @Override |
| public char[] getOriginatingFileName() { |
| return this.original.getOriginatingFileName(); |
| } |
| |
| @Override |
| public int getSourceEnd() { |
| return this.original.getSourceEnd(); |
| } |
| |
| @Override |
| public int getSourceLineNumber() { |
| return this.original.getSourceLineNumber(); |
| } |
| |
| @Override |
| public int getSourceStart() { |
| return this.original.getSourceStart(); |
| } |
| |
| @Override |
| public boolean isError() { |
| return this.original.isError(); |
| } |
| |
| @Override |
| public boolean isWarning() { |
| return this.original.isWarning(); |
| } |
| |
| @Override |
| public boolean isInfo() { |
| return this.original.isInfo(); |
| } |
| |
| @Override |
| public void setSourceEnd(int sourceEnd) { |
| this.original.setSourceEnd(sourceEnd); |
| } |
| |
| @Override |
| public void setSourceLineNumber(int lineNumber) { |
| this.original.setSourceLineNumber(lineNumber); |
| } |
| |
| @Override |
| public void setSourceStart(int sourceStart) { |
| this.original.setSourceStart(sourceStart); |
| } |
| |
| @Override |
| public int getCategoryID() { |
| return this.original.getCategoryID(); |
| } |
| |
| @Override |
| public String getMarkerType() { |
| return this.original.getMarkerType(); |
| } |
| |
| } |
| } |