1 /*******************************************************************************
2  * Copyright (c) 2000, 2017 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jdt.core.tests.model;
15 
16 import java.io.*;
17 import java.util.StringTokenizer;
18 
19 import org.eclipse.core.resources.*;
20 import org.eclipse.core.runtime.*;
21 import org.eclipse.jdt.core.*;
22 import org.eclipse.jdt.core.compiler.batch.BatchCompiler;
23 import org.eclipse.jdt.core.tests.util.Util;
24 import org.eclipse.jdt.internal.core.JavaElement;
25 import org.eclipse.jdt.internal.core.nd.indexer.Indexer;
26 
27 public class ModifyingResourceTests extends AbstractJavaModelTests {
28 
ModifyingResourceTests(String name)29 public ModifyingResourceTests(String name) {
30 	super(name);
31 }
ModifyingResourceTests(String name, int tabs)32 public ModifyingResourceTests(String name, int tabs) {
33 	super(name, tabs);
34 }
assertElementDescendants(String message, String expected, IJavaElement element)35 protected void assertElementDescendants(String message,  String expected, IJavaElement element) throws CoreException {
36 	String actual = expandAll(element);
37 	if (!expected.equals(actual)){
38 	 	System.out.print(displayString(actual, 3));
39 	 	System.out.println(",");
40 	}
41 	assertEquals(
42 		message,
43 		expected,
44 		actual);
45 }
assertStatus(String expected, IStatus status)46 protected void assertStatus(String expected, IStatus status) {
47 	String actual = status.getMessage();
48 	if (!expected.equals(actual)) {
49 	 	System.out.print(Util.displayString(actual, 2));
50 	 	System.out.println(",");
51 	}
52 	assertEquals(expected, actual);
53 }
assertStatus(String message, String expected, IStatus status)54 protected void assertStatus(String message, String expected, IStatus status) {
55 	String actual = status.getMessage();
56 	if (!expected.equals(actual)) {
57 	 	System.out.print(Util.displayString(actual, 2));
58 	 	System.out.println(",");
59 	}
60 	assertEquals(message, expected, actual);
61 }
62 /**
63  * E.g. <code>
64  * org.eclipse.jdt.tests.core.ModifyingResourceTests.generateClassFile(
65  *   "A",
66  *   "public class A {\n" +
67  *   "}")
68  */
generateClassFile(String className, String javaSource)69 public static void generateClassFile(String className, String javaSource) throws IOException {
70 	String cu = "d:/temp/" + className + ".java";
71 	Util.createFile(cu, javaSource);
72 	BatchCompiler.compile(cu + " -d d:/temp -classpath " + System.getProperty("java.home") + "/lib/rt.jar", new PrintWriter(System.out), new PrintWriter(System.err), null/*progress*/);
73 	FileInputStream input = new FileInputStream("d:/temp/" + className + ".class");
74 	try {
75 		System.out.println("{");
76 		byte[] buffer = new byte[80];
77 		int read = 0;
78 		while (read != -1) {
79 			read = input.read(buffer);
80 			if (read != -1) System.out.print("\t");
81 			for (int i = 0; i < read; i++) {
82 				System.out.print(buffer[i]);
83 				System.out.print(", ");
84 			}
85 			if (read != -1) System.out.println();
86 		}
87 		System.out.print("}");
88 	} finally {
89 		input.close();
90 	}
91 }
92 
createExternalFolder(String relativePath)93 protected boolean createExternalFolder(String relativePath) {
94 	return new File(getExternalPath(), relativePath).mkdirs();
95 }
96 
createExternalFile(String relativePath, String contents)97 protected void createExternalFile(String relativePath, String contents) {
98 	Util.writeToFile(contents, getExternalPath() + relativePath);
99 }
100 
101 @Override
createFile(String path, InputStream content)102 protected IFile createFile(String path, InputStream content) throws CoreException {
103 	IFile file = getFile(path);
104 	file.create(content, true, null);
105 	try {
106 		content.close();
107 	} catch (IOException e) {
108 		e.printStackTrace();
109 	}
110 	Indexer.getInstance().waitForIndex(null);
111 	return file;
112 }
113 
114 @Override
createFile(String path, byte[] content)115 protected IFile createFile(String path, byte[] content) throws CoreException {
116 	return createFile(path, new ByteArrayInputStream(content));
117 }
118 
119 @Override
createFile(String path, String content)120 protected IFile createFile(String path, String content) throws CoreException {
121 	return createFile(path, content.getBytes());
122 }
createFile(String path, String content, String charsetName)123 protected IFile createFile(String path, String content, String charsetName) throws CoreException, UnsupportedEncodingException {
124 	return createFile(path, content.getBytes(charsetName));
125 }
createFolder(File parent, String name)126 protected File createFolder(File parent, String name) {
127 	File file = new File(parent, name);
128 	file.mkdirs();
129 	return file;
130 }
131 @Override
createFolder(String path)132 protected IFolder createFolder(String path) throws CoreException {
133 	return createFolder(new Path(path));
134 }
deleteExternalResource(String relativePath)135 protected void deleteExternalResource(String relativePath) {
136 	deleteResource(new File(getExternalPath() + relativePath));
137 }
deleteFile(String filePath)138 protected void deleteFile(String filePath) throws CoreException {
139 	deleteResource(getFile(filePath));
140 }
deleteFolder(String folderPath)141 protected void deleteFolder(String folderPath) throws CoreException {
142 	deleteFolder(new Path(folderPath));
143 }
editFile(String path, String content)144 protected IFile editFile(String path, String content) throws CoreException {
145 	IFile file = getFile(path);
146 	InputStream input = new ByteArrayInputStream(content.getBytes());
147 	file.setContents(input, IResource.FORCE, null);
148 	return file;
149 }
150 /*
151  * Expands (i.e. open) the given element and returns a toString() representation
152  * of the tree.
153  */
expandAll(IJavaElement element)154 protected String expandAll(IJavaElement element) throws CoreException {
155 	StringBuffer buffer = new StringBuffer();
156 	this.expandAll(element, 0, buffer);
157 	return buffer.toString();
158 }
expandAll(IJavaElement element, int tab, StringBuffer buffer)159 private void expandAll(IJavaElement element, int tab, StringBuffer buffer) throws CoreException {
160 	IJavaElement[] children = null;
161 	// force opening of element by getting its children
162 	if (element instanceof IParent) {
163 		IParent parent = (IParent)element;
164 		children = parent.getChildren();
165 	}
166 	((JavaElement)element).toStringInfo(tab, buffer);
167 	if (children != null) {
168 		for (int i = 0, length = children.length; i < length; i++) {
169 			buffer.append("\n");
170 			this.expandAll(children[i], tab+1, buffer);
171 		}
172 	}
173 }
renameProject(String project, String newName)174 protected void renameProject(String project, String newName) throws CoreException {
175 	getProject(project).move(new Path(newName), true, null);
176 }
getClassFile(String path)177 protected IOrdinaryClassFile getClassFile(String path) {
178 	return (IOrdinaryClassFile)JavaCore.create(getFile(path));
179 }
getFolder(String path)180 protected IFolder getFolder(String path) {
181 	return getFolder(new Path(path));
182 }
getPackage(String path)183 protected IPackageFragment getPackage(String path) {
184 	if (path.indexOf('/', 1) != -1) { // if path as more than one segment
185 		IJavaElement element = JavaCore.create(this.getFolder(path));
186 		if (element instanceof IPackageFragmentRoot) {
187 			return ((IPackageFragmentRoot)element).getPackageFragment("");
188 		}
189 		return (IPackageFragment)element;
190 	}
191 	IProject project = getProject(path);
192 	return JavaCore.create(project).getPackageFragmentRoot(project).getPackageFragment("");
193 }
getPackageFragmentRoot(String path)194 protected IPackageFragmentRoot getPackageFragmentRoot(String path) {
195 	if (path.indexOf('/', 1) != -1) { // if path as more than one segment
196 		if (path.endsWith(".jar")) {
197 			return  (IPackageFragmentRoot)JavaCore.create(getFile(path));
198 		}
199 		return (IPackageFragmentRoot)JavaCore.create(this.getFolder(path));
200 	}
201 	IProject project = getProject(path);
202 	return JavaCore.create(project).getPackageFragmentRoot(project);
203 }
moveFile(String sourcePath, String destPath)204 protected void moveFile(String sourcePath, String destPath) throws CoreException {
205 	getFile(sourcePath).move(getFile(destPath).getFullPath(), false, null);
206 }
moveFolder(String sourcePath, String destPath)207 protected void moveFolder(String sourcePath, String destPath) throws CoreException {
208 	this.getFolder(sourcePath).move(this.getFolder(destPath).getFullPath(), false, null);
209 }
swapFiles(String firstPath, String secondPath)210 protected void swapFiles(String firstPath, String secondPath) throws CoreException {
211 	final IFile first = getFile(firstPath);
212 	final IFile second = getFile(secondPath);
213 	IWorkspaceRunnable runnable = new IWorkspaceRunnable(	) {
214 		public void run(IProgressMonitor monitor) throws CoreException {
215 			IPath tempPath = first.getParent().getFullPath().append("swappingFile.temp");
216 			first.move(tempPath, false, monitor);
217 			second.move(first.getFullPath(), false, monitor);
218 			getWorkspaceRoot().getFile(tempPath).move(second.getFullPath(), false, monitor);
219 		}
220 	};
221 	getWorkspace().run(runnable, null);
222 }
createClassFile(String libPath, String classFileRelativePath, String contents)223 protected IClassFile createClassFile(String libPath, String classFileRelativePath, String contents) throws CoreException {
224 	IOrdinaryClassFile classFile = getClassFile(libPath + "/" + classFileRelativePath);
225 //	classFile.getResource().delete(false, null);
226 	Util.delete(classFile.getResource());
227 	IJavaProject javaProject = classFile.getJavaProject();
228 	IProject project = javaProject.getProject();
229 	String sourcePath = project.getLocation().toOSString() + File.separatorChar + classFile.getType().getElementName() + ".java";
230 	String libOSPath = new Path(libPath).segmentCount() > 1 ? getFolder(libPath).getLocation().toOSString() : getProject(libPath).getLocation().toOSString();
231 	Util.compile(new String[] {sourcePath, contents}, javaProject.getOptions(true), libOSPath);
232 	project.refreshLocal(IResource.DEPTH_INFINITE, null);
233 	return classFile;
234 }
235 /*
236  * Returns a new classpath from the given source folders and their respective exclusion/inclusion patterns.
237  * The folder path is an absolute workspace-relative path.
238  * The given array as the following form:
239  * [<folder>, "<pattern>[|<pattern]*"]*
240  * E.g. new String[] {
241  *   "/P/src1", "p/A.java",
242  *   "/P", "*.txt|com.tests/**"
243  * }
244  */
createClasspath(String[] foldersAndPatterns, boolean hasInclusionPatterns, boolean hasExclusionPatterns)245 protected IClasspathEntry[] createClasspath(String[] foldersAndPatterns, boolean hasInclusionPatterns, boolean hasExclusionPatterns) {
246 	int length = foldersAndPatterns.length;
247 	int increment = 1;
248 	if (hasInclusionPatterns) increment++;
249 	if (hasExclusionPatterns) increment++;
250 	IClasspathEntry[] classpath = new IClasspathEntry[length/increment];
251 	for (int i = 0; i < length; i+=increment) {
252 		String src = foldersAndPatterns[i];
253 		IPath[] accessibleFiles = new IPath[0];
254 		if (hasInclusionPatterns) {
255 			String patterns = foldersAndPatterns[i+1];
256 			StringTokenizer tokenizer = new StringTokenizer(patterns, "|");
257 			int patternsCount =  tokenizer.countTokens();
258 			accessibleFiles = new IPath[patternsCount];
259 			for (int j = 0; j < patternsCount; j++) {
260 				accessibleFiles[j] = new Path(tokenizer.nextToken());
261 			}
262 		}
263 		IPath[] nonAccessibleFiles = new IPath[0];
264 		if (hasExclusionPatterns) {
265 			String patterns = foldersAndPatterns[i+increment-1];
266 			StringTokenizer tokenizer = new StringTokenizer(patterns, "|");
267 			int patternsCount =  tokenizer.countTokens();
268 			nonAccessibleFiles = new IPath[patternsCount];
269 			for (int j = 0; j < patternsCount; j++) {
270 				nonAccessibleFiles[j] = new Path(tokenizer.nextToken());
271 			}
272 		}
273 		IPath folderPath = new Path(src);
274 		classpath[i/increment] = JavaCore.newSourceEntry(folderPath, accessibleFiles, nonAccessibleFiles, null);
275 	}
276 	return classpath;
277 }
278 /*
279  * Returns a new classpath from the given folders and their respective accessible/non accessible files patterns.
280  * The folder path is an absolute workspace-relative path. If the given project name is non-null,
281  * the folder path is considered a project path if it has 1 segment that is different from the project name.
282  * The given array as the following form:
283  * [<folder>, "<+|-><pattern>[|<+|-><pattern]*"]*
284  * E.g. new String[] {
285  *   "/P/src1", "+p/A.java",
286  *   "/P", "-*.txt|+com.tests/**"
287  * }
288  */
createClasspath(String projectName, String[] foldersAndPatterns)289 protected IClasspathEntry[] createClasspath(String projectName, String[] foldersAndPatterns) {
290 	int length = foldersAndPatterns.length;
291 	IClasspathEntry[] classpath = new IClasspathEntry[length/2];
292 	for (int i = 0; i < length; i+=2) {
293 		String src = foldersAndPatterns[i];
294 		String patterns = foldersAndPatterns[i+1];
295 		classpath[i/2] = createSourceEntry(projectName, src, patterns);
296 	}
297 	return classpath;
298 }
createSourceEntry(String referingProjectName, String src, String patterns)299 public IClasspathEntry createSourceEntry(String referingProjectName, String src, String patterns) {
300 	StringTokenizer tokenizer = new StringTokenizer(patterns, "|");
301 	int ruleCount =  tokenizer.countTokens();
302 	IAccessRule[] accessRules = new IAccessRule[ruleCount];
303 	int nonAccessibleRules = 0;
304 	for (int j = 0; j < ruleCount; j++) {
305 		String rule = tokenizer.nextToken();
306 		int kind;
307 		boolean ignoreIfBetter = false;
308 		switch (rule.charAt(0)) {
309 			case '+':
310 				kind = IAccessRule.K_ACCESSIBLE;
311 				break;
312 			case '~':
313 				kind = IAccessRule.K_DISCOURAGED;
314 				break;
315 			case '?':
316 				kind = IAccessRule.K_NON_ACCESSIBLE;
317 				ignoreIfBetter = true;
318 				break;
319 			case '-':
320 			default:		// TODO (maxime) consider forbidding unspecified rule start; this one tolerates
321 							// 		shortcuts that only specify a path matching pattern
322 				kind = IAccessRule.K_NON_ACCESSIBLE;
323 				break;
324 		}
325 		nonAccessibleRules++;
326 		accessRules[j] = JavaCore.newAccessRule(new Path(rule.substring(1)), ignoreIfBetter ? kind | IAccessRule.IGNORE_IF_BETTER : kind);
327 	}
328 
329 	IPath folderPath = new Path(src);
330 	if (referingProjectName != null && folderPath.segmentCount() == 1 && !referingProjectName.equals(folderPath.lastSegment())) {
331 		return JavaCore.newProjectEntry(folderPath, accessRules, true/*combine access restrictions*/, new IClasspathAttribute[0], false);
332 	} else {
333 		IPath[] accessibleFiles = new IPath[ruleCount-nonAccessibleRules];
334 		int accessibleIndex = 0;
335 		IPath[] nonAccessibleFiles = new IPath[nonAccessibleRules];
336 		int nonAccessibleIndex = 0;
337 		for (int j = 0; j < ruleCount; j++) {
338 			IAccessRule accessRule = accessRules[j];
339 			if (accessRule.getKind() == IAccessRule.K_ACCESSIBLE)
340 				accessibleFiles[accessibleIndex++] = accessRule.getPattern();
341 			else
342 				nonAccessibleFiles[nonAccessibleIndex++] = accessRule.getPattern();
343 		}
344 		return JavaCore.newSourceEntry(folderPath, accessibleFiles, nonAccessibleFiles, null);
345 	}
346 }
deleteExternalFile(String filePath)347 protected void deleteExternalFile(String filePath) throws CoreException {
348 	deleteResource(new File(filePath));
349 }
350 }
351