Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: e9d501eab753aabf469ee62e326cb5add22318f0 (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
/*******************************************************************************
 * Copyright (c) 2006, 2015 BEA Systems, Inc. 
 *
 * 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:
 *    wharley@bea.com - initial API and implementation
 *    philippe.marschall@netcetera.ch - Fix for 338370
 *    IBM Corporation - Fix for validating relative name
 *******************************************************************************/

package org.eclipse.jdt.internal.compiler.apt.dispatch;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.util.HashSet;

import javax.annotation.processing.Filer;
import javax.annotation.processing.FilerException;
import javax.lang.model.element.Element;
import javax.tools.FileObject;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.StandardLocation;
import javax.tools.JavaFileManager.Location;

import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;

/**
 * Implementation of Filer used when compilation is driven by command line
 * or by Tool interface.  This version does not need to keep track of
 * dependencies.
 */
public class BatchFilerImpl implements Filer {
	
	protected final BaseAnnotationProcessorManager _dispatchManager;
	protected final BaseProcessingEnvImpl _env;
	protected final JavaFileManager _fileManager;
	protected final HashSet<URI> _createdFiles;

	public BatchFilerImpl(BaseAnnotationProcessorManager dispatchManager, BatchProcessingEnvImpl env) 
	{
		_dispatchManager = dispatchManager;
		_fileManager = env._fileManager;
		_env = env;
		_createdFiles = new HashSet<>();
	}

	public void addNewUnit(ICompilationUnit unit) {
		_env.addNewUnit(unit);
	}
	
	public void addNewClassFile(ReferenceBinding binding) {
		_env.addNewClassFile(binding);
	}

	/* (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 {
		JavaFileObject jfo = _fileManager.getJavaFileForOutput(
				StandardLocation.CLASS_OUTPUT, name.toString(), JavaFileObject.Kind.CLASS, null);
		URI uri = jfo.toUri();
		if (_createdFiles.contains(uri)) {
			throw new FilerException("Class file already created : " + name); //$NON-NLS-1$
		}

		_createdFiles.add(uri);
		return new HookedJavaFileObject(jfo, jfo.getName(), name.toString(), this);
	}

	/* (non-Javadoc)
	 * @see javax.annotation.processing.Filer#createResource(javax.tools.JavaFileManager.Location, java.lang.CharSequence, java.lang.CharSequence, javax.lang.model.element.Element[])
	 */
	@Override
	public FileObject createResource(Location location, CharSequence pkg,
			CharSequence relativeName, Element... originatingElements)
			throws IOException {
		validateName(relativeName);
		FileObject fo = _fileManager.getFileForOutput(
				location, pkg.toString(), relativeName.toString(), null);
		URI uri = fo.toUri();
		if (_createdFiles.contains(uri)) {
			throw new FilerException("Resource already created : " + location + '/' + pkg + '/' + relativeName); //$NON-NLS-1$
		}

		_createdFiles.add(uri);
		return fo;
	}

	private static void validateName(CharSequence relativeName) {
		int length = relativeName.length();
		if (length == 0) {
			throw new IllegalArgumentException("relative path cannot be empty"); //$NON-NLS-1$
		}
		String path = relativeName.toString();
		if (path.indexOf('\\') != -1) {
			// normalize the path with '/'
			path = path.replace('\\', '/');
		}
		if (path.charAt(0) == '/') {
			throw new IllegalArgumentException("relative path is absolute"); //$NON-NLS-1$
		}
		boolean hasDot = false;
		for (int i = 0; i < length; i++) {
			switch(path.charAt(i)) {
				case '/' :
					if (hasDot) {
						throw new IllegalArgumentException("relative name " + relativeName + " is not relative"); //$NON-NLS-1$ //$NON-NLS-2$
					}
					break;
				case '.' :
					hasDot = true;
					break;
				default:
					hasDot = false;
			}
		}
		if (hasDot) {
			throw new IllegalArgumentException("relative name " + relativeName + " is not relative"); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	/* (non-Javadoc)
	 * @see javax.annotation.processing.Filer#createSourceFile(java.lang.CharSequence, javax.lang.model.element.Element[])
	 */
	@Override
	public JavaFileObject createSourceFile(CharSequence name,
			Element... originatingElements) throws IOException {
		JavaFileObject jfo = _fileManager.getJavaFileForOutput(
				StandardLocation.SOURCE_OUTPUT, name.toString(), JavaFileObject.Kind.SOURCE, null);
		URI uri = jfo.toUri();
		if (_createdFiles.contains(uri)) {
			throw new FilerException("Source file already created : " + name); //$NON-NLS-1$
		}

		_createdFiles.add(uri);
		// hook the file object's writers to create compilation unit and add to addedUnits()
		return new HookedJavaFileObject(jfo, jfo.getName(), name.toString(), this);
	}
	
	/* (non-Javadoc)
	 * @see javax.annotation.processing.Filer#getResource(javax.tools.JavaFileManager.Location, java.lang.CharSequence, java.lang.CharSequence)
	 */
	@Override
	public FileObject getResource(Location location, CharSequence pkg,
			CharSequence relativeName) throws IOException {
		validateName(relativeName);
		FileObject fo = _fileManager.getFileForInput(
				location, pkg.toString(), relativeName.toString());
		if (fo == null) {
			throw new FileNotFoundException("Resource does not exist : " + location + '/' + pkg + '/' + relativeName); //$NON-NLS-1$
		}
		URI uri = fo.toUri();
		if (_createdFiles.contains(uri)) {
			throw new FilerException("Resource already created : " + location + '/' + pkg + '/' + relativeName); //$NON-NLS-1$
		}
		return fo;
	}

}

Back to the top