| /******************************************************************************* |
| * Copyright (c) 2017 GK Software AG, 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: |
| * Stephan Herrmann - initial API and implementation |
| *******************************************************************************/ |
| package org.aspectj.org.eclipse.jdt.internal.core.nd.java.model; |
| |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.zip.ZipEntry; |
| import java.util.zip.ZipFile; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IResourceStatus; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.aspectj.org.eclipse.jdt.core.IJavaModelStatusConstants; |
| import org.aspectj.org.eclipse.jdt.core.JavaModelException; |
| import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader; |
| import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException; |
| import org.aspectj.org.eclipse.jdt.internal.compiler.env.IBinaryModule; |
| import org.aspectj.org.eclipse.jdt.internal.compiler.env.IDependent; |
| import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeConstants; |
| import org.aspectj.org.eclipse.jdt.internal.core.JarPackageFragmentRoot; |
| import org.aspectj.org.eclipse.jdt.internal.core.JavaModelManager; |
| import org.aspectj.org.eclipse.jdt.internal.core.JrtPackageFragmentRoot; |
| import org.aspectj.org.eclipse.jdt.internal.core.ModularClassFile; |
| import org.aspectj.org.eclipse.jdt.internal.core.PackageFragmentRoot; |
| import org.aspectj.org.eclipse.jdt.internal.core.nd.java.JavaIndex; |
| |
| /** |
| * <strong>FIXME:</strong> this class is a stub as of now, it does not support modules in the new index. |
| */ |
| public class BinaryModuleFactory { |
| |
| public static BinaryModuleDescriptor createDescriptor(ModularClassFile modularClassFile) { |
| return createDescriptor(modularClassFile.getPackageFragmentRoot(), modularClassFile); |
| } |
| |
| /** |
| * Returns a descriptor for the given class within the given package fragment, or null if the fragment doesn't have |
| * a location on the filesystem. |
| */ |
| private static BinaryModuleDescriptor createDescriptor(PackageFragmentRoot root, ModularClassFile classFile) { |
| IPath location = JavaIndex.getLocationForElement(root); |
| if (location == null) { |
| return null; |
| } |
| String entryName = TypeConstants.MODULE_INFO_CLASS_NAME_STRING; |
| IPath workspacePath = root.getPath(); |
| String indexPath; |
| char[] moduleName = null; |
| |
| if (root instanceof JarPackageFragmentRoot) { |
| entryName = ((JarPackageFragmentRoot) root).getClassFilePath(entryName); |
| indexPath = root.getHandleIdentifier() + IDependent.JAR_FILE_ENTRY_SEPARATOR + entryName; |
| // see additional comments in BinaryTypeFactor.createDescriptor() |
| if (root instanceof JrtPackageFragmentRoot) { |
| moduleName = root.getElementName().toCharArray(); |
| } |
| } else { |
| location = location.append(entryName); |
| indexPath = workspacePath.append(entryName).toString(); |
| workspacePath = classFile.resource().getFullPath(); |
| } |
| |
| return new BinaryModuleDescriptor(location.toString().toCharArray(), moduleName, // TODO: module name only known for JRT |
| workspacePath.toString().toCharArray(), indexPath.toCharArray()); |
| } |
| |
| /** |
| * Reads the given binary module. If the module can be found in the index with a fingerprint that exactly matches |
| * the file on disk, the type is read from the index. Otherwise the type is read from disk. Returns null if |
| * no such type exists. |
| * <strong>caveat</strong> modules are not yet supported in the index. |
| * |
| * @throws ClassFormatException |
| */ |
| public static IBinaryModule readModule(BinaryModuleDescriptor descriptor, IProgressMonitor monitor) throws JavaModelException, ClassFormatException { |
| // FIXME: support module in the new index |
| // if (JavaIndex.isEnabled()) { |
| // try { |
| // return readFromIndex(JavaIndex.getIndex(), descriptor, monitor); |
| // } catch (NotInIndexException e) { |
| // // fall back to reading the zip file, below |
| // } |
| // } |
| return rawReadModule(descriptor, true); |
| } |
| |
| public static IBinaryModule rawReadModule(BinaryModuleDescriptor descriptor, boolean fullyInitialize) throws JavaModelException, ClassFormatException { |
| try { |
| return rawReadModuleTestForExists(descriptor, fullyInitialize, true); |
| } catch (FileNotFoundException e) { |
| throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); |
| } |
| } |
| |
| /** |
| * Read the class file from disk, circumventing the index's cache. This should only be used by callers |
| * that need to read information from the class file which aren't present in the index (such as method bodies). |
| * |
| * @return the newly-created IBinaryModule or null if the given class file does not exist. |
| * @throws ClassFormatException if the class file existed but was corrupt |
| * @throws JavaModelException if unable to read the class file due to a transient failure |
| * @throws FileNotFoundException if the file does not exist |
| */ |
| public static IBinaryModule rawReadModuleTestForExists(BinaryModuleDescriptor descriptor, boolean fullyInitialize, |
| boolean useInvalidArchiveCache) throws JavaModelException, ClassFormatException, FileNotFoundException { |
| if (descriptor == null) { |
| return null; |
| } |
| if (descriptor.isInJarFile()) { |
| ZipFile zip = null; |
| try { |
| zip = JavaModelManager.getJavaModelManager().getZipFile(new Path(new String(descriptor.workspacePath)), |
| useInvalidArchiveCache); |
| String entryName = TypeConstants.MODULE_INFO_CLASS_NAME_STRING; |
| ZipEntry ze = zip.getEntry(entryName); |
| if (ze != null) { |
| byte contents[]; |
| try { |
| contents = org.aspectj.org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip); |
| } catch (IOException ioe) { |
| throw new JavaModelException(ioe, IJavaModelStatusConstants.IO_EXCEPTION); |
| } |
| ClassFileReader classFileReader = new ClassFileReader(contents, descriptor.indexPath, fullyInitialize); |
| return classFileReader.getModuleDeclaration(); |
| } |
| } catch (CoreException e) { |
| throw new JavaModelException(e); |
| } finally { |
| JavaModelManager.getJavaModelManager().closeZipFile(zip); |
| } |
| } else { |
| IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(new String(descriptor.workspacePath))); |
| byte[] contents; |
| try (InputStream stream = file.getContents(true)) { |
| contents = org.aspectj.org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, -1); |
| } catch (CoreException e) { |
| IStatus status = e.getStatus(); |
| if (status.getCode() == IResourceStatus.RESOURCE_NOT_FOUND) { |
| throw new FileNotFoundException(); |
| } |
| throw new JavaModelException(e); |
| } catch (IOException e) { |
| throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); |
| } |
| ClassFileReader classFileReader = new ClassFileReader(contents, file.getFullPath().toString().toCharArray(), fullyInitialize); |
| return classFileReader.getModuleDeclaration(); |
| } |
| return null; |
| } |
| } |