Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 2cfca8762fa03370566691b9ed6390568c1300e7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/*******************************************************************************
 * Copyright (c) 2007 - 2009 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.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.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);
		
		//TODO: check whether file has already been generated in this run
		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");
		}
		//TODO: check whether file has already been generated in this run
		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();
    	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$
    			IOException ioe = new IOException();
    			ioe.initCause(e);
    			throw ioe;
    		}
    	}
    	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);
        	IOException ioe = new IOException("Invalid path: " + file.toString()); //$NON-NLS-1$
        	ioe.initCause(ce);
        	throw ioe;
        }
	}

}

Back to the top