Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: ad5aad0d3bd2cbdf5ea61d2b37d9c386aea9da54 (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
/*******************************************************************************
 * Copyright (c) 2012 Red Hat 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
 *******************************************************************************/
package org.eclipse.cdt.autotools.tests;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.zip.ZipFile;

import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.CommandLauncher;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.internal.autotools.core.configure.AutotoolsConfigurationManager;
import org.eclipse.cdt.internal.autotools.core.configure.IAConfiguration;
import org.eclipse.cdt.internal.autotools.ui.wizards.ConvertToAutotoolsProjectWizard;
import org.eclipse.cdt.internal.autotools.ui.wizards.ConvertToAutotoolsProjectWizardPage;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo;
import org.eclipse.cdt.managedbuilder.core.IProjectType;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.ui.wizards.conversion.ConvertProjectWizardPage;
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.IWorkspace;
import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.dialogs.IOverwriteQuery;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.wizards.datatransfer.ImportOperation;
import org.eclipse.ui.wizards.datatransfer.ZipFileStructureProvider;
import org.osgi.framework.FrameworkUtil;


@SuppressWarnings("restriction")
public class ProjectTools {

	static IWorkspace workspace;
    static IWorkspaceRoot root;
    static NullProgressMonitor monitor;
    static String pluginRoot;
    static ConvertProjectWizardPage page;
    static boolean setupComplete;

    /**
     * Setup routine for tests.
     * @return true if setup successful, false otherwise
     * @throws CoreException 
     */
	public static boolean setup() throws CoreException  {
		if (!setupComplete) {
			IWorkspaceDescription desc;
			workspace = ResourcesPlugin.getWorkspace();
			if (workspace == null) {
				return false;
			}
			root = workspace.getRoot();
			monitor = new NullProgressMonitor();
			if (root == null) {
				return false;
			}
			desc = workspace.getDescription();
			desc.setAutoBuilding(false);
			workspace.setDescription(desc);
		}
		setupComplete = true;
		return true;
	}
	
	/**
	 * Build the project.
	 * @return true if build started successfully or false otherwise
	 */
	public static boolean build() {
		try {
			workspace.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			workspace.getRoot().refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
		} catch (CoreException e) {
		    return false;	
		}
		return true;
	}
	
	/**
	 * Get the default monitor.
	 * @return The current monitor
	 */
	public static IProgressMonitor getMonitor() {
		return monitor;
	}

	/**
	 * Get the workspace.
	 * @return The workspace
	 */
	public static IWorkspaceRoot getWorkspaceRoot() {
		return root;
	}

	/**
	 * Mark a specified file in a project as executable.
	 * @param project The project that the file is found in
	 * @param filePath The relative path to the file
	 * @return true if the change was successful, false otherwise
	 */
	public static boolean markExecutable(IProject project, String filePath) {
		// Get a launcher for the config command
		CommandLauncher launcher = new CommandLauncher();
		OutputStream stdout = new ByteArrayOutputStream();
		OutputStream stderr = new ByteArrayOutputStream();

		launcher.showCommand(true);
		IPath commandPath = new Path("chmod");
		IPath runPath = project.getLocation().append(filePath).removeLastSegments(1);
		// if the path points to an actual object, use its resource to get its run path location
		// which will handle any linked directories
		if (project.findMember(filePath) != null)
		   runPath = project.findMember(filePath).getLocation().removeLastSegments(1);
		String[] args = new String[2];
		args[0] = "+x";
		// if the path points to an actual object, use its resource to get its location
		// which will handle any linked directories
		if (project.findMember(filePath) != null)
			args[1] = project.findMember(filePath).getLocation().toOSString();
		else // otherwise, just append to project location
			args[1] = project.getLocation().append(filePath).toOSString();
		try {
			Process proc = launcher.execute(commandPath, args, new String[0],
					runPath, new NullProgressMonitor());
			if (proc != null) {
				try {
					// Close the input of the process since we will never write to
					// it
					proc.getOutputStream().close();
				} catch (IOException e) {
				}

				if (launcher.waitAndRead(stdout, stderr,
						SubMonitor.convert(monitor, IProgressMonitor.UNKNOWN)) != CommandLauncher.OK) {
					return false;
				}
			} else
				return false;
		} catch (CoreException e) {
			return false;
		}
		return true;
	}
	
	// Inner class to allow us to fake a project wizard without starting up
	// the UI for it.
	protected static class ConvertToAutotoolsProjectWizardTest extends ConvertToAutotoolsProjectWizard {
		ConvertToAutotoolsProjectWizardTest() {
			super();
		}

		// The following is a kludge to allow testing to occur for the
		// wizard code.  The regular applyOptions() method would also attempt
		// to call performApply() for the optionPage.  This doesn't work in
		// the test scenario because the UI display logic is needed to
		// initialize some things.  The performApply() call is only needed
		// to check out referenced projects.  In our test scenario, this is
		// not required.
		@Override
		public void applyOptions(IProject project, IProgressMonitor monitor) {
			setCurrentProject(project);
	    }
		
		@Override
		public IConfiguration[] getSelectedConfigurations() {
			IProjectType projectType = ManagedBuildManager.getExtensionProjectType("org.eclipse.linuxtools.cdt.autotools.core.projectType"); //$NON-NLS-1$
			return projectType.getConfigurations();
		}
	}
	
	/**
	 * Creates an empty Autotools project.
	 * @param name The name of the new project
	 * @return The newly created project or null
	 */		
	public static IProject createProject(String name) {
		IProject testProject = root.getProject(name);
		if (testProject == null) {
			return null;
        }
		IProjectDescription description = workspace.newProjectDescription(name);
		try {
			testProject.create(monitor);
			testProject.open(monitor);
			IProject newProject = CCorePlugin.getDefault().createCDTProject(description, testProject, SubMonitor.convert(monitor,25));
			ConvertToAutotoolsProjectWizardTest wizard = new ConvertToAutotoolsProjectWizardTest();
			wizard.addPages();
			ConvertToAutotoolsProjectWizardPage page = new ConvertToAutotoolsProjectWizardPage("test", wizard);
			page.convertProject(newProject, monitor, wizard.getProjectID());
		} catch (CoreException e) {
			testProject = null;
		}
		return testProject;
	}
	
	/**
	 * Set the configuration source directory for an Autotools project.
	 * @param project The Autotools project to modify
	 * @param dir The relative project directory to use
	 */
	public static void setConfigDir(IProject project, String dir) {
		IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project);
		IConfiguration c = info.getDefaultConfiguration();
		ICConfigurationDescription cfgd = ManagedBuildManager.getDescriptionForConfiguration(c);
		String id = cfgd.getId();
		IAConfiguration cfg = AutotoolsConfigurationManager.getInstance().getConfiguration(project, id, true);
		cfg.setConfigToolDirectory(dir);
	}
	
	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
		}
	}

	private static boolean generateFiles(IPath destPath) {
		// Get a launcher for the config command
		CommandLauncher launcher = new CommandLauncher();
		OutputStream stdout = new ByteArrayOutputStream();
		OutputStream stderr = new ByteArrayOutputStream();
		
		IPath runPath = root.getLocation().append(destPath);

		// Run the genfiles.sh shell script which will simulate
		// running aclocal, autoconf, and automake
		launcher.showCommand(true);
		IPath commandPath = new Path("sh");
		String[] cmdargs = new String[]{"genfiles.sh"};
		try {
			Process proc = launcher.execute(commandPath, cmdargs, new String[0],
					runPath, new NullProgressMonitor());
			if (proc != null) {
				try {
					// Close the input of the process since we will never write to
					// it
					proc.getOutputStream().close();
				} catch (IOException e) {
				}

				if (launcher.waitAndRead(stdout, stderr, SubMonitor.convert(
						monitor, IProgressMonitor.UNKNOWN)) != CommandLauncher.OK) {
					return false;
				}
			} else
				return false;
		} catch (CoreException e) {
			return false;
		}

		return true;
	}

	private static void importFilesFromZipAndGenerate(ZipFile srcZipFile, IPath destPath, IProgressMonitor monitor) throws InvocationTargetException {
		importFilesFromZip(srcZipFile, destPath, monitor);
		if (!generateFiles(destPath))
			throw new InvocationTargetException(new Exception("Unsuccessful test file generation"));
	}
	
	private static class ImportOverwriteQuery implements IOverwriteQuery {
		@Override
		public String queryOverwrite(String file) {
			return ALL;
		}	
	}		
	
	/**
	 * Adds a source container to a IProject.
	 * @param jproject The parent project
	 * @param containerName The name of the new source container
	 * @return The handle to the new source container
	 * @throws CoreException Creation failed
	 */				
	public static IContainer addSourceContainer(IProject 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()) {
				createFolder(folder, false, true, null);
			}
			container= folder;
		}
	
		return container;
	}
	
	/**
	 * Adds a source container to a IProject and imports all files contained
	 * in the given ZIP file.
	 * @param project The parent project
	 * @param containerName Name of the source container
	 * @param zipFile Archive to import
	 * @param generate true if configuration files need to be pre-generated
	 * @param exclusionFilters Exclusion filters to set
	 * @return The handle to the new source container
	 * @throws InvocationTargetException Creation failed
	 * @throws CoreException Creation failed
	 * @throws IOException Creation failed
	 */		
	public static IContainer addSourceContainerWithImport(IProject project, String containerName, File zipFile, boolean generate) throws InvocationTargetException, CoreException, IOException {
		try (ZipFile file= new ZipFile(zipFile)){
			IContainer root= addSourceContainer(project, containerName);
			if (generate)
				importFilesFromZipAndGenerate(file, root.getFullPath(), null);
			else
				importFilesFromZip(file, root.getFullPath(), null);
			return root;
		}
	}

	/**
	 * Adds a source container to a IProject and imports all files contained
	 * in the given ZIP file and generates configuration files if needed.
	 * @param project The parent project
	 * @param containerName Name of the source container
	 * @param path path of zipFile Archive to import
	 * @param generate true if configuration files need to be pre-generated
	 * @return The handle to the new source container
	 * @throws InvocationTargetException Creation failed
	 * @throws CoreException Creation failed
	 * @throws IOException Creation failed
	 */		
	public static IContainer addSourceContainerWithImport(IProject project, String containerName, Path zipFilePath, boolean generate) throws InvocationTargetException, CoreException, IOException {
		File zipFile = new File(FileLocator.toFileURL(FileLocator.find(FrameworkUtil.getBundle(ProjectTools.class), zipFilePath, null)).getFile());
		return addSourceContainerWithImport(project, containerName, zipFile, generate);
	}
	
	/**
	 * Adds a source container to a IProject and imports all files contained
	 * in the given ZIP file.
	 * @param project The parent project
	 * @param containerName Name of the source container
	 * @param path path of zipFile Archive to import
	 * @return The handle to the new source container
	 * @throws InvocationTargetException Creation failed
	 * @throws CoreException Creation failed
	 * @throws IOException Creation failed
	 */		
	public static IContainer addSourceContainerWithImport(IProject project, String containerName, Path zipFilePath) throws InvocationTargetException, CoreException, IOException {
		return addSourceContainerWithImport(project, containerName, zipFilePath, false);
	}

	/**
	 * Create a file for a project and initialize the contents.
	 * @param project The project to create a file for
	 * @param filename Name of the new file
	 * @param contents String containing the initial contents of the file
	 * @return the created file
	 * @throws CoreException
	 */
	public IFile createFile(IProject project, String filename, String contents) throws CoreException {
		IFile file = project.getFile(filename);
		file.create(null, false, null);
		file.setContents(new ByteArrayInputStream(contents.getBytes()), false, false, null);
		return file;
	}
	
	/**
	 * Create a linked folder for a project
	 * @param project The project
	 * @param folderName Name of the linked folder in the project
	 * @param path The URI of the real file/folder
	 * 
	 * @return
	 * @throws CoreException
	 */
	public static IFolder createLinkedFolder(IProject project, String folderName, final URI linkTarget) throws Exception {
		final IFolder folderHandle = root.getFolder(project.getFullPath().append(folderName));

		WorkspaceModifyOperation operation = new WorkspaceModifyOperation() {
			@Override
			public void execute(IProgressMonitor monitor) throws CoreException {
				try {
					monitor.beginTask(IDEWorkbenchMessages.NewFolderDialog_progress, 2000);
					if (monitor.isCanceled()) {
						throw new OperationCanceledException();
					}
					folderHandle.createLink(linkTarget, IResource.ALLOW_MISSING_LOCAL, monitor);
					if (monitor.isCanceled()) {
						throw new OperationCanceledException();
					}
				} finally {
					monitor.done();
				}
			}
		};
		try {
			PlatformUI.getWorkbench().getProgressService().busyCursorWhile(operation);
		} catch (InterruptedException exception) {
			return null;
		}
		return folderHandle;
	}

	/**
	 * Creates a folder and all parent folders if not existing.
	 * Project must exist.
	 * <code> org.eclipse.ui.dialogs.ContainerGenerator</code> is too heavy
	 * (creates a runnable)
	 */
	public static void createFolder(IFolder folder, boolean force, boolean local, IProgressMonitor monitor) throws CoreException {
		if (!folder.exists()) {
			IContainer parent= folder.getParent();
			if (parent instanceof IFolder) {
				createFolder((IFolder)parent, force, local, null);
			}
			folder.create(force, local, monitor);
		}
	}
	
}

Back to the top