| /******************************************************************************* |
| * Copyright (c) 2007 - 2018 BEA Systems, Inc. and others |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * wharley@bea.com - initial API and implementation |
| * |
| *******************************************************************************/ |
| |
| package org.eclipse.jdt.internal.apt.pluggable.core.filer; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| import javax.annotation.processing.Filer; |
| import javax.annotation.processing.FilerException; |
| import javax.lang.model.element.Element; |
| import javax.tools.FileObject; |
| import javax.tools.JavaFileObject; |
| import javax.tools.StandardLocation; |
| import javax.tools.JavaFileManager.Location; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspace; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.jdt.apt.core.internal.AptCompilationParticipant; |
| import org.eclipse.jdt.apt.core.internal.generatedfile.GeneratedSourceFolderManager; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.internal.apt.pluggable.core.Apt6Plugin; |
| import org.eclipse.jdt.internal.apt.pluggable.core.dispatch.IdeAnnotationProcessorManager; |
| import org.eclipse.jdt.internal.apt.pluggable.core.dispatch.IdeProcessingEnvImpl; |
| |
| /** |
| * Implementation of the Filer interface that is used in IDE mode. |
| * @see org.eclipse.jdt.internal.compiler.apt.dispatch.BatchFilerImpl |
| * @since 3.3 |
| */ |
| public class IdeFilerImpl implements Filer { |
| |
| //private final IdeAnnotationProcessorManager _dispatchManager; |
| private final IdeProcessingEnvImpl _env; |
| |
| public IdeFilerImpl(IdeAnnotationProcessorManager dispatchManager, |
| IdeProcessingEnvImpl env) { |
| //_dispatchManager = dispatchManager; |
| _env = env; |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.annotation.processing.Filer#createClassFile(java.lang.CharSequence, javax.lang.model.element.Element[]) |
| */ |
| @Override |
| public JavaFileObject createClassFile(CharSequence name, Element... originatingElements) |
| throws IOException { |
| //TODO |
| throw new UnsupportedOperationException("Creating class files is not yet implemented"); //$NON-NLS-1$ |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.annotation.processing.Filer#createResource(javax.tools.JavaFileManager.Location, java.lang.CharSequence, java.lang.CharSequence, javax.lang.model.element.Element[]) |
| * In the IDE implementation, we support only two Locations: SOURCE_OUTPUT, which means the APT generated source folder, |
| * and CLASS_OUTPUT, which means the binary output folder associated with the APT generated source folder. |
| */ |
| @Override |
| public FileObject createResource(Location location, CharSequence pkg, |
| CharSequence relativeName, Element... originatingElements) throws IOException |
| { |
| // Pre-emptively check parameters here, rather than later on when the resource is written and closed. |
| if (null == location) { |
| throw new IllegalArgumentException("Location is null"); |
| } |
| if (!location.isOutputLocation()) { |
| throw new IllegalArgumentException("Location " + location.getName() + " is not an output location"); |
| } |
| |
| if (null == pkg) { |
| throw new IllegalArgumentException("Package is null"); |
| } |
| if (null == relativeName) { |
| throw new IllegalArgumentException("Relative name is null"); |
| } |
| if ( relativeName.length() == 0) { |
| throw new IllegalArgumentException("Relative name is zero length"); |
| } |
| IFile file = getFileFromOutputLocation(location, pkg, relativeName); |
| if (AptCompilationParticipant.getInstance().getJava6GeneratedFiles().contains(file)) { |
| throw new FilerException("Source file already created: " + file.getFullPath()); //$NON-NLS-1$ |
| } |
| |
| Set<IFile> parentFiles; |
| if (originatingElements != null && originatingElements.length > 0) { |
| parentFiles = new HashSet<IFile>(originatingElements.length); |
| for (Element elem : originatingElements) { |
| IFile enclosing = _env.getEnclosingIFile(elem); |
| if (null != enclosing) { |
| parentFiles.add(enclosing); |
| } |
| } |
| } else { |
| parentFiles = Collections.emptySet(); |
| } |
| return new IdeOutputNonSourceFileObject(_env, file, parentFiles); |
| } |
| |
| /** |
| * @param originatingElements should all be source types; binary types (ie elements in jar files) |
| * will be ignored. |
| * @see javax.annotation.processing.Filer#createSourceFile(java.lang.CharSequence, javax.lang.model.element.Element[]) |
| */ |
| @Override |
| public JavaFileObject createSourceFile(CharSequence name, Element... originatingElements) |
| throws IOException |
| { |
| // Pre-emptively check parameters here, rather than later on when the resource is written and closed. |
| if (null == name) { |
| throw new IllegalArgumentException("Name is null"); |
| } |
| IFile file = _env.getAptProject().getGeneratedFileManager(_env.isTestCode()).getIFileForTypeName(name.toString()); |
| if (AptCompilationParticipant.getInstance().getJava6GeneratedFiles().contains(file)) { |
| throw new FilerException("Source file already created: " + file.getFullPath()); //$NON-NLS-1$ |
| } |
| |
| Set<IFile> parentFiles = Collections.emptySet(); |
| if (originatingElements != null && originatingElements.length > 0) { |
| parentFiles = new HashSet<IFile>(originatingElements.length); |
| for (Element elem : originatingElements) { |
| IFile enclosing = _env.getEnclosingIFile(elem); |
| if (null != enclosing) { |
| parentFiles.add(enclosing); |
| } |
| } |
| } |
| return new IdeOutputJavaFileObject(_env, name, parentFiles); |
| } |
| |
| /* (non-Javadoc) |
| * @see javax.annotation.processing.Filer#getResource(javax.tools.JavaFileManager.Location, java.lang.CharSequence, java.lang.CharSequence) |
| * Returns a FileObject representing the specified resource. The only supported locations |
| * are CLASS_OUTPUT and SOURCE_OUTPUT. |
| */ |
| @Override |
| public FileObject getResource(Location location, CharSequence pkg, CharSequence relativeName) |
| throws IOException |
| { |
| IFile file = getFileFromOutputLocation(location, pkg, relativeName); |
| return new IdeInputFileObject(file); |
| } |
| |
| /** |
| * Return a project-relative path. This does not create the file nor its parent directories, |
| * but it does validate the path. |
| * @param pkg must be non-null but can be empty. |
| * @param relPath must be non-null and non-empty. |
| * @throws IOException if the path is not valid. |
| */ |
| protected IFile getFileFromOutputLocation( Location loc, CharSequence pkg, CharSequence relPath ) |
| throws IOException |
| { |
| GeneratedSourceFolderManager gsfm = _env.getAptProject().getGeneratedSourceFolderManager(_env.isTestCode()); |
| IPath path = null; |
| if ( loc == StandardLocation.CLASS_OUTPUT ) |
| { |
| try |
| { |
| path = gsfm.getBinaryOutputLocation(); |
| } |
| catch ( JavaModelException e ) |
| { |
| Apt6Plugin.log(e, "Failure getting the binary output location"); //$NON-NLS-1$ |
| throw new IOException(e); |
| } |
| } |
| else if ( loc == StandardLocation.SOURCE_OUTPUT ) { |
| path = gsfm.getFolder().getProjectRelativePath(); |
| } |
| else { |
| throw new IllegalArgumentException("Unsupported location: " + loc); |
| } |
| |
| if( pkg.length() > 0 ) |
| path = path.append(pkg.toString().replace('.', File.separatorChar) ); |
| |
| path = path.append(relPath.toString()); |
| |
| IFile file = _env.getProject().getFile(path); |
| |
| validatePath(file); |
| |
| return file; |
| } |
| |
| /** |
| * Validate that a path fits the rules for being created. |
| * @see IWorkspace#validatePath() |
| * @throws IOException |
| */ |
| private void validatePath(IFile file) throws IOException |
| { |
| IStatus status = _env.getProject().getWorkspace().validatePath(file.getFullPath().toOSString(), IResource.FILE); |
| if (!status.isOK()) { |
| CoreException ce = new CoreException(status); |
| throw new IOException("Invalid path: " + file.toString(), ce); //$NON-NLS-1$ |
| } |
| } |
| |
| } |