Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: e47d0b8f25c4835527922c1223901beaf1883444 (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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
/*******************************************************************************
 *  Copyright (c) 2000, 2014 IBM Corporation 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
 *
 * This is an implementation of an early-draft specification developed under the Java
 * Community Process (JCP) and is made available for testing and evaluation purposes
 * only. The code is not compatible with any specification of the JCP.
 * 
 *  Contributors:
 *     IBM Corporation - initial API and implementation
 *     Jesper S. Møller - bug 422029: [1.8] Enable debug evaluation support for default methods
 *******************************************************************************/
package org.eclipse.jdt.debug.testplugin;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipFile;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
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.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.ClasspathEntry;
import org.eclipse.ui.dialogs.IOverwriteQuery;
import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
import org.eclipse.ui.wizards.datatransfer.ImportOperation;
import org.eclipse.ui.wizards.datatransfer.ZipFileStructureProvider;

/**
 * Helper methods to set up a IJavaProject.
 */
public class JavaProjectHelper {
	
	public static final String SRC_DIR = "src";
	public static final String BIN_DIR = "bin";
	public static final String J2SE_1_4_EE_NAME = "J2SE-1.4";
	public static final String J2SE_1_5_EE_NAME = "J2SE-1.5";
	public static final String JAVA_SE_1_6_EE_NAME = "JavaSE-1.6";
	public static final String JAVA_SE_1_7_EE_NAME = "JavaSE-1.7";
	public static final String JAVA_SE_1_8_EE_NAME = "JavaSE-1.8";
	
	/**
	 * path to the test src for 'testprograms'
	 */
	public static final IPath TEST_SRC_DIR= new Path("testprograms");
	
	/**
	 * path to the 1.5 test source
	 */
	public static final IPath TEST_1_5_SRC_DIR= new Path("testsource-j2se-1.5");
	/**
	 * path to the 1.7 test source
	 */
	public static final IPath TEST_1_7_SRC_DIR= new Path("java7");
	/**
	 * path to the 1.8 test source
	 */
	public static final IPath TEST_1_8_SRC_DIR= new Path("java8");
	
	/**
	 * path to the compiler error java file
	 */
	public static final IPath TEST_COMPILE_ERROR = new Path("testresources/CompilationError.java");	
	
	public static final String JRE_CONTAINER_NAME = "org.eclipse.jdt.launching.JRE_CONTAINER";

	/**
	 * Returns if the currently running VM is version compatible with Java 7
	 * 
	 * @return <code>true</code> if a Java 7 (or greater) VM is running <code>false</code> otherwise
	 */
	public static boolean isJava7Compatible() {
		return isCompatible(7);
	}
	
	/**
	 * Returns if the currently running VM is version compatible with Java 6
	 * 
	 * @return <code>true</code> if a Java 6 (or greater) VM is running <code>false</code> otherwise
	 */
	public static boolean isJava6Compatible() {
		return isCompatible(6);
	}
	
	/**
	 * Returns if the currently running VM is version compatible with Java 5
	 * 
	 * @return <code>true</code> if a Java 5 (or greater) VM is running <code>false</code> otherwise
	 */
	public static boolean isJava5Compatible() {
		return isCompatible(5);
	}
	
	/**
	 * Returns if the current running system is compatible with the given Java minor version
	 * 
	 * @param ver the version to test - either 4, 5, 6, 7 or 8
	 * @return <code>true</code> if compatible <code>false</code> otherwise
	 */
	static boolean isCompatible(int ver) {
		String version = System.getProperty("java.specification.version");
		if (version != null) {
			String[] nums = version.split("\\.");
			if (nums.length == 2) {
				try {
					int major = Integer.parseInt(nums[0]);
					int minor = Integer.parseInt(nums[1]);
					if (major >= 1) {
						if (minor >= ver) {
							return true;
						}
					}
				} catch (NumberFormatException e) {
				}
			}
		}
		return false;
	}
	
	/**
	 * Creates a new {@link IProject} with the given name unless the project already exists. If it already exists
	 * the project is refreshed and opened (if closed)
	 * 
	 * @param pname the desired name for the project
	 * @return the new {@link IProject} handle
	 * @throws CoreException
	 */
	public static IProject createProject(String pname) throws CoreException {
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		IProject project = root.getProject(pname);
		if (!project.exists()) {
			project.create(null);
		} else {
			project.refreshLocal(IResource.DEPTH_INFINITE, null);
		}
		if (!project.isOpen()) {
			project.open(null);
		}
		return project;
	}
	
	/**
	 * creates a java project with the specified name and output folder
	 * @param projectName
	 * @param binFolderName
	 * @return a new java project
	 * @throws CoreException
	 */
	public static IJavaProject createJavaProject(String projectName, String binFolderName) throws CoreException {
		IProject project = createProject(projectName);
		IPath outputLocation;
		if (binFolderName != null && binFolderName.length() > 0) {
			IFolder binFolder= project.getFolder(binFolderName);
			if (!binFolder.exists()) {
				binFolder.create(false, true, null);
			}
			outputLocation= binFolder.getFullPath();
		} else {
			outputLocation= project.getFullPath();
		}
		if (!project.hasNature(JavaCore.NATURE_ID)) {
			addNatureToProject(project, JavaCore.NATURE_ID, null);
		}
		IJavaProject jproject= JavaCore.create(project);
		jproject.setOutputLocation(outputLocation, null);
		jproject.setRawClasspath(new IClasspathEntry[0], null);
		return jproject;	
	}
		
	/**
	 * Creates a new Java project with the specified name
	 * @param projectName
	 * @return a new java project with the specified name
	 * @throws CoreException
	 */
	public static IJavaProject createJavaProject(String projectName) throws CoreException {
		IProject project = createProject(projectName);
		if (!project.hasNature(JavaCore.NATURE_ID)) {
			addNatureToProject(project, JavaCore.NATURE_ID, null);
		}
		IJavaProject jproject= JavaCore.create(project);
		jproject.setRawClasspath(new IClasspathEntry[0], null);
		return jproject;	
	}	
			
	/**
	 * deletes a java project
	 * @param jproject
	 * @throws CoreException
	 */
	public static void delete(IJavaProject jproject) throws CoreException {
		jproject.setRawClasspath(new ClasspathEntry[0], jproject.getProject().getFullPath(), null);
		jproject.getProject().delete(true, true, null);
	}
		
	/**
	 * Adds a new source container specified by the container name to the source path of the specified project
	 * @param jproject
	 * @param containerName
	 * @return the package fragment root of the container name
	 * @throws CoreException
	 */
	public static IPackageFragmentRoot addSourceContainer(IJavaProject jproject, String containerName) throws CoreException {
		IProject project= jproject.getProject();
		IContainer container= null;
		if (containerName == null || containerName.length() == 0) {
			container= project;
		} else {
			IFolder folder= project.getFolder(containerName);
			if (!folder.exists()) {
				folder.create(false, true, null);
			}
			container= folder;
		}
		IPackageFragmentRoot root= jproject.getPackageFragmentRoot(container);
		
		IClasspathEntry cpe= JavaCore.newSourceEntry(root.getPath());
		addToClasspath(jproject, cpe);		
		return root;
	}
	
	/**
	 * Adds a source container to a IJavaProject.
	 * @param jproject
	 * @param containerName
	 * @param outputName
	 * @return the package fragment root of the new source container
	 * @throws CoreException
	 */
	public static IPackageFragmentRoot addSourceContainer(IJavaProject jproject, String containerName, String outputName) throws CoreException {
		IProject project= jproject.getProject();
		IContainer container= null;
		if (containerName == null || containerName.length() == 0) {
			container= project;
		} else {
			IFolder folder= project.getFolder(containerName);
			if (!folder.exists()) {
				folder.create(false, true, null);
			}
			container= folder;
		}
		IPackageFragmentRoot root= jproject.getPackageFragmentRoot(container);

		IFolder output = null;
		if (outputName!= null) {
			output = project.getFolder(outputName);
			if (!output.exists()) {
				output.create(false, true, null);
			}
		}
				
		IClasspathEntry cpe= JavaCore.newSourceEntry(root.getPath(), new IPath[0], output.getFullPath());
		
		addToClasspath(jproject, cpe);		
		return root;
	}	

	/**
	 * Adds a source container to a IJavaProject and imports all files contained
	 * in the given Zip file.
	 * @param jproject
	 * @param containerName
	 * @param zipFile
	 * @return the package fragment root of the new source container
	 * @throws InvocationTargetException
	 * @throws CoreException
	 */
	public static IPackageFragmentRoot addSourceContainerWithImport(IJavaProject jproject, String containerName, ZipFile zipFile) throws InvocationTargetException, CoreException {
		IPackageFragmentRoot root= addSourceContainer(jproject, containerName);
		importFilesFromZip(zipFile, root.getPath(), null);
		return root;
	}

	/**
	 * Removes a source folder from a IJavaProject.
	 * @param jproject
	 * @param containerName
	 * @throws CoreException
	 */
	public static void removeSourceContainer(IJavaProject jproject, String containerName) throws CoreException {
		IFolder folder= jproject.getProject().getFolder(containerName);
		removeFromClasspath(jproject, folder.getFullPath());
		folder.delete(true, null);
	}

	/**
	 * Adds a library entry to a IJavaProject.
	 * @param jproject
	 * @param path
	 * @return the package fragment root of the new library
	 * @throws JavaModelException
	 */
	public static IPackageFragmentRoot addLibrary(IJavaProject jproject, IPath path) throws JavaModelException {
		return addLibrary(jproject, path, null, null);
	}

	/**
	 * Adds a library entry with source attchment to a IJavaProject.
	 * @param jproject
	 * @param path
	 * @param sourceAttachPath
	 * @param sourceAttachRoot
	 * @return the package fragment root of the new library
	 * @throws JavaModelException
	 */
	public static IPackageFragmentRoot addLibrary(IJavaProject jproject, IPath path, IPath sourceAttachPath, IPath sourceAttachRoot) throws JavaModelException {
		IClasspathEntry cpe= JavaCore.newLibraryEntry(path, sourceAttachPath, sourceAttachRoot);
		addToClasspath(jproject, cpe);
		return jproject.getPackageFragmentRoot(path.toString());
	}

	/**
	 * Copies the library into the project and adds it as library entry.
	 * @param jproject
	 * @param jarPath
	 * @param sourceAttachPath
	 * @param sourceAttachRoot
	 * @return the package fragment root of the new library
	 * @throws IOException
	 * @throws CoreException
	 */
	public static IPackageFragmentRoot addLibraryWithImport(IJavaProject jproject, IPath jarPath, IPath sourceAttachPath, IPath sourceAttachRoot) throws IOException, CoreException {
		IProject project= jproject.getProject();
		IFile newFile= project.getFile(jarPath.lastSegment());
		InputStream inputStream= null;
		try {
			inputStream= new FileInputStream(jarPath.toFile()); 
			newFile.create(inputStream, true, null);
		} finally {
			if (inputStream != null) {
				try { inputStream.close(); } catch (IOException e) { }
			}
		}				
		return addLibrary(jproject, newFile.getFullPath(), sourceAttachPath, sourceAttachRoot);
	}	

		
	/**
	 * Adds a variable entry with source attachment to a IJavaProject.
	 * Can return null if variable can not be resolved.
	 * @param jproject
	 * @param path
	 * @param sourceAttachPath
	 * @param sourceAttachRoot
	 * @return the package fragment root of the new variable entry
	 * @throws JavaModelException
	 */
	public static IPackageFragmentRoot addVariableEntry(IJavaProject jproject, IPath path, IPath sourceAttachPath, IPath sourceAttachRoot) throws JavaModelException {
		IClasspathEntry cpe= JavaCore.newVariableEntry(path, sourceAttachPath, sourceAttachRoot);
		addToClasspath(jproject, cpe);
		IPath resolvedPath= JavaCore.getResolvedVariablePath(path);
		if (resolvedPath != null) {
			return jproject.getPackageFragmentRoot(resolvedPath.toString());
		}
		return null;
	}
	
	/**
	 * Adds a container entry to the specified java project
	 * @param project
	 * @param container
	 * @throws JavaModelException
	 */
	public static void addContainerEntry(IJavaProject project, IPath container) throws JavaModelException {
		IClasspathEntry cpe = JavaCore.newContainerEntry(container, false);
		addToClasspath(project, cpe);
	}
	
	/**
	 * Sets the given compiler compliance on the given {@link IJavaProject}
	 * <br><br>
	 * See {@link JavaCore#VERSION_1_4}, {@link JavaCore#VERSION_1_5}, {@link JavaCore#VERSION_1_6}, 
	 * {@link JavaCore#VERSION_1_7} and {@link JavaCore#VERSION_1_8} for more information on accepted compliances
	 * 
	 * @param project
	 * @param compliance
	 */
	public static void setCompliance(IJavaProject project, String compliance) {
		Map<String, String> map = JavaCore.getOptions();
		map.put(JavaCore.COMPILER_COMPLIANCE, compliance);
		map.put(JavaCore.COMPILER_SOURCE, compliance);
		map.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, compliance);
		project.setOptions(map);
	}
	
	/**
	 * Updates the compiler compliance project setting for the given project to match the given EE. 
	 * I.e. J2SE-1.5 will set a 1.5 compliance for the compiler and the source level.
	 * @param project
	 * @param ee
	 */
	public static void updateCompliance(IJavaProject project, String ee) {
		if(J2SE_1_4_EE_NAME.equals(ee)) {
			setCompliance(project, JavaCore.VERSION_1_4);
		}
		else if(J2SE_1_5_EE_NAME.equals(ee)) {
			setCompliance(project, JavaCore.VERSION_1_5);
		}
		else if(JAVA_SE_1_7_EE_NAME.equals(ee)) {
			setCompliance(project, JavaCore.VERSION_1_7);
		}
		else if(JAVA_SE_1_8_EE_NAME.equals(ee)) {
			setCompliance(project, JavaCore.VERSION_1_8);
		}
	}
	
	/**
	 * Adds a required project entry.
	 * @param jproject
	 * @param required
	 * @throws JavaModelException
	 */
	public static void addRequiredProject(IJavaProject jproject, IJavaProject required) throws JavaModelException {
		IClasspathEntry cpe= JavaCore.newProjectEntry(required.getProject().getFullPath());
		addToClasspath(jproject, cpe);
	}	
	
	/**
	 * Removes a specified path form the specified java project
	 * @param jproject
	 * @param path
	 * @throws JavaModelException
	 */
	public static void removeFromClasspath(IJavaProject jproject, IPath path) throws JavaModelException {
		IClasspathEntry[] oldEntries= jproject.getRawClasspath();
		int nEntries= oldEntries.length;
		ArrayList<IClasspathEntry> list= new ArrayList<IClasspathEntry>(nEntries);
		for (int i= 0 ; i < nEntries ; i++) {
			IClasspathEntry curr= oldEntries[i];
			if (!path.equals(curr.getPath())) {
				list.add(curr);			
			}
		}
		IClasspathEntry[] newEntries= list.toArray(new IClasspathEntry[list.size()]);
		jproject.setRawClasspath(newEntries, null);
	}	

	/**
	 * Adds the specified classpath entry to the specified java project
	 * @param jproject
	 * @param cpe
	 * @throws JavaModelException
	 */
	public static void addToClasspath(IJavaProject jproject, IClasspathEntry cpe) throws JavaModelException {
		IClasspathEntry[] oldEntries= jproject.getRawClasspath();
		ArrayList<IClasspathEntry> entries = new ArrayList<IClasspathEntry>(oldEntries.length);
		for (int i= 0; i < oldEntries.length; i++) {
			if (oldEntries[i].equals(cpe)) {
				return;
			}
			IPath oldpath = oldEntries[i].getPath();
			if(JRE_CONTAINER_NAME.equals(oldpath.segment(0)) && JRE_CONTAINER_NAME.equals(cpe.getPath().segment(0))) {
				continue;
			}
			entries.add(oldEntries[i]);
		}
		entries.add(cpe);
		jproject.setRawClasspath(entries.toArray(new IClasspathEntry[entries.size()]), null);
	}
	
			
	/**
	 * Adds the specified nature to the specified project
	 * @param proj
	 * @param natureId
	 * @param monitor
	 * @throws CoreException
	 */
	private static void addNatureToProject(IProject proj, String natureId, IProgressMonitor monitor) throws CoreException {
		IProjectDescription description = proj.getDescription();
		String[] prevNatures= description.getNatureIds();
		String[] newNatures= new String[prevNatures.length + 1];
		System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);
		newNatures[prevNatures.length]= natureId;
		description.setNatureIds(newNatures);
		proj.setDescription(description, monitor);
	}
	
	/**
	 * Imports files from the specified zip to the specified destination
	 * @param srcZipFile
	 * @param destPath
	 * @param monitor
	 * @throws InvocationTargetException
	 */
	private static void importFilesFromZip(ZipFile srcZipFile, IPath destPath, IProgressMonitor monitor) throws InvocationTargetException {		
		ZipFileStructureProvider structureProvider=	new ZipFileStructureProvider(srcZipFile);
		try {
			ImportOperation op= new ImportOperation(destPath, structureProvider.getRoot(), structureProvider, new ImportOverwriteQuery());
			op.run(monitor);
		} catch (InterruptedException e) {
			// should not happen
		}
	}
	
	/**
	 * Imports files from the specified root dir into the specified path
	 * @param rootDir
	 * @param destPath
	 * @param monitor
	 * @throws InvocationTargetException
	 * @throws IOException
	 */
	public static void importFilesFromDirectory(File rootDir, IPath destPath, IProgressMonitor monitor) throws InvocationTargetException, IOException {		
		IImportStructureProvider structureProvider = FileSystemStructureProvider.INSTANCE;
		List<File> files = new ArrayList<File>(100);
		addJavaFiles(rootDir, files);
		try {
			ImportOperation op= new ImportOperation(destPath, rootDir, structureProvider, new ImportOverwriteQuery(), files);
			op.setCreateContainerStructure(false);
			op.run(monitor);
		} catch (InterruptedException e) {
			// should not happen
		}
	}	
	
	/**
	 * Imports the specified file into the specified path
	 * @param file
	 * @param destPath
	 * @param monitor
	 * @throws InvocationTargetException
	 */
	public static void importFile(File file, IPath destPath, IProgressMonitor monitor) throws InvocationTargetException {		
		IImportStructureProvider structureProvider = FileSystemStructureProvider.INSTANCE;
		List<File> files = new ArrayList<File>(1);
		files.add(file);
		try {
			ImportOperation op= new ImportOperation(destPath, file.getParentFile(), structureProvider, new ImportOverwriteQuery(), files);
			op.setCreateContainerStructure(false);
			op.run(monitor);
		} catch (InterruptedException e) {
			// should not happen
		}
	}
	
	/**
	 * Recursively adds files from the specified dir to the provided list
	 * @param dir
	 * @param collection
	 * @throws IOException
	 */
	private static void addJavaFiles(File dir, List<File> collection) throws IOException {
		File[] files = dir.listFiles();
		if(files != null) {
			List<File> subDirs = new ArrayList<File>(2);
			for (int i = 0; i < files.length; i++) {
				if (files[i].isFile()) {
					collection.add(files[i]);
				} else if (files[i].isDirectory() && files[i].getName().indexOf("CVS") < 0) {
					subDirs.add(files[i]);
				}
			}
			Iterator<File> iter = subDirs.iterator();
			while (iter.hasNext()) {
				File subDir = iter.next();
				addJavaFiles(subDir, collection);
			}
		}
	}
	
	/**
	 * Static class for an <code>IOverwriteQuery</code> implementation
	 */
	private static class ImportOverwriteQuery implements IOverwriteQuery {
		/**
		 * @see org.eclipse.ui.dialogs.IOverwriteQuery#queryOverwrite(java.lang.String)
		 */
		public String queryOverwrite(String file) {
			return ALL;
		}	
	}	
}

Back to the top