1 /*******************************************************************************
2  * Copyright (c) 2000, 2019 IBM Corporation and others.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License 2.0 which accompanies this distribution,
6  * and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors: IBM - Initial API and implementation Prosyst - create proper
12  * OSGi bundles (bug 174157)
13  ******************************************************************************/
14 package org.eclipse.pde.internal.build.builder;
15 
16 import java.io.*;
17 import java.util.*;
18 import java.util.Map.Entry;
19 import java.util.jar.JarFile;
20 import org.eclipse.core.runtime.*;
21 import org.eclipse.equinox.p2.publisher.eclipse.FeatureEntry;
22 import org.eclipse.osgi.service.resolver.*;
23 import org.eclipse.osgi.util.ManifestElement;
24 import org.eclipse.osgi.util.NLS;
25 import org.eclipse.pde.build.Constants;
26 import org.eclipse.pde.internal.build.*;
27 import org.eclipse.pde.internal.build.ant.*;
28 import org.eclipse.pde.internal.build.builder.ClasspathComputer3_0.ClasspathElement;
29 import org.eclipse.pde.internal.build.site.ProfileManager;
30 import org.osgi.framework.BundleException;
31 import org.osgi.framework.Version;
32 
33 /**
34  * Generic class for generating scripts for plug-ins and fragments.
35  */
36 public class ModelBuildScriptGenerator extends AbstractBuildScriptGenerator {
37 	public static final String SRC_ZIP = "src.zip"; //$NON-NLS-1$
38 	public static final String EXPANDED_DOT = "@dot"; //$NON-NLS-1$
39 	public static final String DOT = "."; //$NON-NLS-1$
40 
41 	/**
42 	 * Represents a entry that must be compiled and which is listed in the build.properties file.
43 	 */
44 	static public class CompiledEntry {
45 		static public final byte JAR = 0;
46 		static public final byte FOLDER = 1;
47 		private final String name;
48 		private String resolvedName;
49 		private final String[] source;
50 		private final String[] output;
51 		private final String[] extraClasspath;
52 		private final String excludedFromJar;
53 		byte type;
54 
CompiledEntry(String entryName, String[] entrySource, String[] entryOutput, String[] entryExtraClasspath, String excludedFromJar, byte entryType)55 		protected CompiledEntry(String entryName, String[] entrySource, String[] entryOutput, String[] entryExtraClasspath, String excludedFromJar, byte entryType) {
56 			this.name = entryName;
57 			this.source = entrySource;
58 			this.output = entryOutput;
59 			this.extraClasspath = entryExtraClasspath;
60 			this.type = entryType;
61 			this.excludedFromJar = excludedFromJar;
62 		}
63 
getName(boolean resolved)64 		public String getName(boolean resolved) {
65 			if (!resolved)
66 				return name;
67 
68 			if (resolvedName == null)
69 				resolvedName = replaceVariables(name, true);
70 
71 			return resolvedName;
72 		}
73 
getSource()74 		protected String[] getSource() {
75 			return source;
76 		}
77 
getOutput()78 		public String[] getOutput() {
79 			return output;
80 		}
81 
getExtraClasspath()82 		public String[] getExtraClasspath() {
83 			return extraClasspath;
84 		}
85 
getType()86 		public byte getType() {
87 			return type;
88 		}
89 
getExcludedFromJar()90 		public String getExcludedFromJar() {
91 			return excludedFromJar;
92 		}
93 	}
94 
95 	/**
96 	 * Bundle for which we are generating the script.
97 	 */
98 	protected BundleDescription model;
99 	/**
100 	 * PluginEntry corresponding to the bundle
101 	 */
102 	private FeatureEntry associatedEntry;
103 
104 	protected String fullName;
105 	protected String pluginZipDestination;
106 	protected String pluginUpdateJarDestination;
107 
108 	private BuildDirector featureGenerator;
109 
110 	/** constants */
111 	protected final String PLUGIN_DESTINATION = Utils.getPropertyFormat(PROPERTY_PLUGIN_DESTINATION);
112 
113 	private Properties permissionProperties;
114 
115 	private String propertiesFileName = PROPERTIES_FILE;
116 	private String buildScriptFileName = DEFAULT_BUILD_SCRIPT_FILENAME;
117 	private String customBuildCallbacks = null;
118 	private String customCallbacksBuildpath = null;
119 	private String customCallbacksFailOnError = null;
120 	private String customCallbacksInheritAll = null;
121 	private String warningProperties = null;
122 	// array of extensions of recognized source files (eg- *.java, *.aj, etc)
123 	private String[] sourceFileExtensions;
124 	//This list is initialized by the generateBuildJarsTarget
125 	private ArrayList<CompiledEntry> compiledJarNames;
126 	private boolean dotOnTheClasspath = false;
127 	private boolean binaryPlugin = false;
128 	private boolean signJars = false;
129 	private Map<String, Set<IPath>> workspaceOutputFolders = null;
130 
131 	private boolean generateErrorPropertyAttribute = true;
132 	private boolean sourceReferences = false;
133 
134 	/**
135 	 * @see AbstractScriptGenerator#generate()
136 	 */
137 	@Override
generate()138 	public void generate() throws CoreException {
139 		//If it is a binary plugin, then we don't generate scripts
140 		if (binaryPlugin)
141 			return;
142 
143 		if (model == null) {
144 			throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_ELEMENT_MISSING, Messages.error_missingElement, null));
145 		}
146 
147 		// If the the plugin we want to generate is a source plugin, and the feature that required the generation of this plugin is not being asked to build the source
148 		// we want to leave. This is particularly usefull for the case of the pde.source building (at least for now since the source of pde is not in a feature)
149 		//		if (featureGenerator != null && featureGenerator.getBuildProperties().containsKey(GENERATION_SOURCE_PLUGIN_PREFIX + model.getSymbolicName()))
150 		//			return;
151 
152 		initializeVariables();
153 		if (BundleHelper.getDefault().isDebugging())
154 			System.out.println("Generating plugin " + model.getSymbolicName()); //$NON-NLS-1$
155 
156 		String custom = (String) getBuildProperties().get(PROPERTY_CUSTOM);
157 		if (custom != null && custom.equalsIgnoreCase("true")) { //$NON-NLS-1$
158 			updateExistingScript();
159 			return;
160 		}
161 
162 		openScript(getLocation(model), buildScriptFileName);
163 		try {
164 			generateBuildScript();
165 		} finally {
166 			closeScript();
167 		}
168 	}
169 
getNormalizedName(BundleDescription bundle)170 	public static String getNormalizedName(BundleDescription bundle) {
171 		return bundle.getSymbolicName() + '_' + bundle.getVersion();
172 	}
173 
initializeVariables()174 	private void initializeVariables() throws CoreException {
175 		fullName = getNormalizedName(model);
176 		pluginZipDestination = PLUGIN_DESTINATION + '/' + fullName + ".zip"; //$NON-NLS-1$
177 		pluginUpdateJarDestination = PLUGIN_DESTINATION + '/' + fullName + ".jar"; //$NON-NLS-1$
178 		String[] classpathInfo = getClasspathEntries(model);
179 		dotOnTheClasspath = specialDotProcessing(getBuildProperties(), classpathInfo);
180 		generateErrorPropertyAttribute = shouldGenerateErrorAttribute();
181 
182 		//Persist this information for use in the assemble script generation
183 		Properties bundleProperties = (Properties) model.getUserObject();
184 		bundleProperties.put(WITH_DOT, Boolean.valueOf(dotOnTheClasspath));
185 
186 		Properties properties = getBuildProperties();
187 		customBuildCallbacks = properties.getProperty(PROPERTY_CUSTOM_BUILD_CALLBACKS);
188 		if (TRUE.equalsIgnoreCase(customBuildCallbacks))
189 			customBuildCallbacks = DEFAULT_CUSTOM_BUILD_CALLBACKS_FILE;
190 		else if (FALSE.equalsIgnoreCase(customBuildCallbacks))
191 			customBuildCallbacks = null;
192 
193 		customCallbacksBuildpath = properties.getProperty(PROPERTY_CUSTOM_CALLBACKS_BUILDPATH, "."); //$NON-NLS-1$
194 		customCallbacksFailOnError = properties.getProperty(PROPERTY_CUSTOM_CALLBACKS_FAILONERROR, FALSE);
195 		customCallbacksInheritAll = properties.getProperty(PROPERTY_CUSTOM_CALLBACKS_INHERITALL);
196 
197 		// Bug 303960 determine all source files recognized in this bundle
198 		String sourceFileExtensionsStr = properties.getProperty(PROPERTY_SOURCE_FILE_EXTENSIONS);
199 		if (sourceFileExtensionsStr == null) {
200 			sourceFileExtensions = DEFAULT_SOURCE_FILE_EXTENSIONS;
201 		} else {
202 			String[] sourceFileExtensionsArr = sourceFileExtensionsStr.split(","); //$NON-NLS-1$
203 			sourceFileExtensions = new String[sourceFileExtensionsArr.length];
204 			for (int i = 0; i < sourceFileExtensionsArr.length; i++) {
205 				sourceFileExtensions[i] = sourceFileExtensionsArr[i].trim();
206 			}
207 		}
208 
209 		if (featureGenerator != null && featureGenerator.useWorkspaceBinaries() && havePDEUIState()) {
210 			PDEUIStateWrapper wrapper = getSite(false).getSiteContentProvider().getInitialState();
211 			if (wrapper != null && wrapper.getOutputFolders() != null) {
212 				Map<String, Map<String, Set<IPath>>> folders = wrapper.getOutputFolders();
213 				if (folders.containsKey(model.getSymbolicName())) {
214 					workspaceOutputFolders = folders.get(model.getSymbolicName());
215 				}
216 			}
217 		}
218 
219 		String projectWarningSettings = getBuildProperties().getProperty(PROPERTY_PROJECT_SETTINGS);
220 		if (Boolean.valueOf(projectWarningSettings).booleanValue()) {
221 			//find default prefs file
222 			if (new File(model.getLocation(), JDT_CORE_PREFS).exists())
223 				warningProperties = JDT_CORE_PREFS;
224 		} else if (projectWarningSettings != null && !FALSE.equalsIgnoreCase(projectWarningSettings)) {
225 			if (new File(model.getLocation(), projectWarningSettings).exists())
226 				warningProperties = projectWarningSettings;
227 		}
228 	}
229 
findAndReplaceDot(String[] classpathInfo)230 	protected static boolean findAndReplaceDot(String[] classpathInfo) {
231 		for (int i = 0; i < classpathInfo.length; i++) {
232 			if (DOT.equals(classpathInfo[i])) {
233 				classpathInfo[i] = EXPANDED_DOT;
234 				return true;
235 			}
236 		}
237 		return false;
238 	}
239 
specialDotProcessing(Properties properties, String[] classpathInfo)240 	public static boolean specialDotProcessing(Properties properties, String[] classpathInfo) {
241 		findAndReplaceDot(classpathInfo);
242 
243 		String outputValue = properties.getProperty(PROPERTY_OUTPUT_PREFIX + DOT);
244 		if (outputValue != null) {
245 			properties.setProperty(PROPERTY_OUTPUT_PREFIX + EXPANDED_DOT, outputValue);
246 			properties.remove(PROPERTY_OUTPUT_PREFIX + DOT);
247 		}
248 
249 		String sourceFolder = properties.getProperty(PROPERTY_SOURCE_PREFIX + DOT);
250 		if (sourceFolder != null) {
251 			properties.setProperty(PROPERTY_SOURCE_PREFIX + EXPANDED_DOT, sourceFolder);
252 			properties.remove(PROPERTY_SOURCE_PREFIX + DOT);
253 
254 			String excludedFromJar = properties.getProperty(PROPERTY_EXCLUDE_PREFIX + DOT);
255 			if (excludedFromJar != null) {
256 				properties.setProperty(PROPERTY_EXCLUDE_PREFIX + EXPANDED_DOT, excludedFromJar);
257 				properties.remove(PROPERTY_EXCLUDE_PREFIX + DOT);
258 			}
259 			String buildOrder = properties.getProperty(PROPERTY_JAR_ORDER);
260 			if (buildOrder != null) {
261 				String[] order = Utils.getArrayFromString(buildOrder);
262 				for (int i = 0; i < order.length; i++)
263 					if (order[i].equals(DOT))
264 						order[i] = EXPANDED_DOT;
265 				properties.setProperty(PROPERTY_JAR_ORDER, Utils.getStringFromArray(order, ",")); //$NON-NLS-1$
266 			}
267 
268 			String extraEntries = properties.getProperty(PROPERTY_EXTRAPATH_PREFIX + '.');
269 			if (extraEntries != null) {
270 				properties.setProperty(PROPERTY_EXTRAPATH_PREFIX + EXPANDED_DOT, extraEntries);
271 			}
272 
273 			String includeString = properties.getProperty(PROPERTY_BIN_INCLUDES);
274 			if (includeString != null) {
275 				String[] includes = Utils.getArrayFromString(includeString);
276 				for (int i = 0; i < includes.length; i++)
277 					if (includes[i].equals(DOT))
278 						includes[i] = EXPANDED_DOT + '/';
279 				properties.setProperty(PROPERTY_BIN_INCLUDES, Utils.getStringFromArray(includes, ",")); //$NON-NLS-1$
280 			}
281 			return true;
282 		}
283 		return false;
284 	}
285 
286 	/**
287 	 * Main call for generating the script.
288 	 *
289 	 * @throws CoreException
290 	 */
generateBuildScript()291 	private void generateBuildScript() throws CoreException {
292 		generatePrologue();
293 		generateBuildUpdateJarTarget();
294 
295 		if (getBuildProperties().getProperty(SOURCE_PLUGIN, null) == null) {
296 			generateBuildJarsTarget(model);
297 		} else {
298 			generateBuildJarsTargetForSourceGathering();
299 			generateEmptyBuildSourcesTarget();
300 		}
301 
302 		generatePublishBinPartsTarget();
303 		generateGatherBinPartsTarget();
304 		generateBuildZipsTarget();
305 		generateGatherSourcesTarget();
306 		generateGatherIndividualSourcesTarget();
307 		generateCopySourcesTarget();
308 		generateGatherLogTarget();
309 		generateCleanTarget();
310 		generateRefreshTarget();
311 		generateZipPluginTarget();
312 		generateAPIToolsTarget();
313 		generateEpilogue();
314 	}
315 
316 	/**
317 	 * Method generateEmptyBuildSourceTarget.
318 	 */
generateEmptyBuildSourcesTarget()319 	private void generateEmptyBuildSourcesTarget() {
320 		script.printTargetDeclaration(TARGET_BUILD_SOURCES, null, null, null, null);
321 		script.printTargetEnd();
322 	}
323 
324 	/**
325 	 * Method generateBuildJarsTargetForSourceGathering.
326 	 */
generateBuildJarsTargetForSourceGathering()327 	private void generateBuildJarsTargetForSourceGathering() {
328 		script.printTargetDeclaration(TARGET_BUILD_JARS, null, null, null, null);
329 		compiledJarNames = new ArrayList<>(0);
330 
331 		if (Utils.isSourceBundle(model)) {
332 			//We are an individual source bundle, source gathering is done in gather.bin.parts via gather.individual.sources
333 			script.printTargetEnd();
334 			return;
335 		}
336 
337 		File previousSrcRoot = Utils.getOldSourceLocation(model);
338 		Set<BundleDescription> pluginsToGatherSourceFrom = featureGenerator.sourceToGather.getElementEntries().get(model.getSymbolicName());
339 		if (pluginsToGatherSourceFrom != null) {
340 			for (Iterator<BundleDescription> iter = pluginsToGatherSourceFrom.iterator(); iter.hasNext();) {
341 				BundleDescription plugin = iter.next();
342 				// We are not trying to gather the source from ourself since we are generated and we know we don't have source...
343 				if (plugin.getSymbolicName().equals(model.getSymbolicName()))
344 					continue;
345 
346 				if (Utils.isBinary(plugin)) {
347 					// this plug-in wasn't compiled, take source from the previous source plug-in
348 					if (previousSrcRoot != null) {
349 						File previousSrc = new File(previousSrcRoot, getNormalizedName(plugin));
350 						if (previousSrc.exists()) {
351 							FileSet[] fileSets = new FileSet[1];
352 							fileSets[0] = new FileSet(previousSrc.getAbsolutePath(), null, "**/*", null, null, null, null); //$NON-NLS-1$
353 							script.printCopyTask(null, Utils.getPropertyFormat(PROPERTY_BASEDIR) + "/src/" + previousSrc.getName(), fileSets, true, false); //$NON-NLS-1$
354 						}
355 					}
356 				} else {
357 					// gather up source that was built for this plug-in
358 					// The two steps are required, because some plug-ins (xerces, junit, ...) don't build their source: the source already comes zipped
359 					IPath location = Utils.makeRelative(new Path(getLocation(plugin)), new Path(getLocation(model)));
360 					script.printAntTask(DEFAULT_BUILD_SCRIPT_FILENAME, location.toOSString(), TARGET_BUILD_SOURCES, null, null, null);
361 					Map<String, String> params = new HashMap<>(1);
362 					params.put(PROPERTY_DESTINATION_TEMP_FOLDER, Utils.getPropertyFormat(PROPERTY_BASEDIR) + "/src"); //$NON-NLS-1$
363 					script.printAntTask(DEFAULT_BUILD_SCRIPT_FILENAME, location.toOSString(), TARGET_GATHER_SOURCES, null, null, params);
364 				}
365 			}
366 		}
367 		script.printTargetEnd();
368 	}
369 
370 	/**
371 	 * Add the <code>clean</code> target to the given Ant script.
372 	 *
373 	 * @throws CoreException
374 	 */
generateCleanTarget()375 	private void generateCleanTarget() throws CoreException {
376 		script.println();
377 		Properties properties = getBuildProperties();
378 		CompiledEntry[] availableJars = extractEntriesToCompile(properties);
379 		script.printTargetDeclaration(TARGET_CLEAN, TARGET_INIT, null, null, NLS.bind(Messages.build_plugin_clean, model.getSymbolicName()));
380 
381 		Map<String, String> params = null;
382 		if (customBuildCallbacks != null) {
383 			params = new HashMap<>(3);
384 			params.put(PROPERTY_PLUGIN_DESTINATION, PLUGIN_DESTINATION);
385 			params.put(PROPERTY_TEMP_FOLDER, Utils.getPropertyFormat(PROPERTY_TEMP_FOLDER));
386 			params.put(PROPERTY_BUILD_RESULT_FOLDER, Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER));
387 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_PRE + TARGET_CLEAN, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
388 		}
389 		for (int i = 0; i < availableJars.length; i++) {
390 			String jarName = availableJars[i].getName(true);
391 			String jarLocation = getJARLocation(jarName);
392 			//avoid destructive cleans
393 			if (jarLocation.equals("") || jarLocation.startsWith(DOT + DOT) || jarLocation.equals(Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER))) //$NON-NLS-1$
394 				continue;
395 			if (availableJars[i].type == CompiledEntry.JAR) {
396 				script.printDeleteTask(null, jarLocation, null);
397 			} else {
398 				script.printDeleteTask(jarLocation, null, null);
399 			}
400 			script.printDeleteTask(null, getSRCLocation(jarName), null);
401 		}
402 		script.printDeleteTask(null, pluginUpdateJarDestination, null);
403 		script.printDeleteTask(null, pluginZipDestination, null);
404 		script.printDeleteTask(Utils.getPropertyFormat(IXMLConstants.PROPERTY_TEMP_FOLDER), null, null);
405 		script.printDeleteTask(null, Utils.getPropertyFormat(PROPERTY_COMPILE_PROBLEM_MARKER), TRUE, null);
406 
407 		if (customBuildCallbacks != null) {
408 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_POST + TARGET_CLEAN, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
409 		}
410 		script.printTargetEnd();
411 	}
412 
413 	/**
414 	 * Add the <code>gather.logs</code> target to the given Ant script.
415 	 *
416 	 * @throws CoreException
417 	 */
generateGatherLogTarget()418 	private void generateGatherLogTarget() throws CoreException {
419 		script.println();
420 		script.printTargetDeclaration(TARGET_GATHER_LOGS, TARGET_INIT, PROPERTY_DESTINATION_TEMP_FOLDER, null, null);
421 		IPath baseDestination = new Path(Utils.getPropertyFormat(PROPERTY_DESTINATION_TEMP_FOLDER));
422 		baseDestination = baseDestination.append(fullName);
423 		Map<String, String> params = null;
424 		if (customBuildCallbacks != null) {
425 			params = new HashMap<>(1);
426 			params.put(PROPERTY_DESTINATION_TEMP_FOLDER, baseDestination.toString());
427 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_PRE + TARGET_GATHER_LOGS, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
428 		}
429 		List<IPath> destinations = new ArrayList<>(5);
430 		Properties properties = getBuildProperties();
431 		CompiledEntry[] availableJars = extractEntriesToCompile(properties);
432 		for (int i = 0; i < availableJars.length; i++) {
433 			String name = availableJars[i].getName(true);
434 			IPath destination = baseDestination.append(name).removeLastSegments(1); // remove the jar name
435 			if (!destinations.contains(destination)) {
436 				script.printMkdirTask(destination.toString());
437 				destinations.add(destination);
438 			}
439 			String logFolder = (availableJars[i].getType() == CompiledEntry.FOLDER) ? getJARLocation(name) : getTempJARFolderLocation(name);
440 			Path logPath = new Path(logFolder + Utils.getPropertyFormat(PROPERTY_LOG_EXTENSION));
441 			FileSet logSet = new FileSet(logPath.removeLastSegments(1).toString(), null, logPath.lastSegment(), null, null, null, null);
442 			script.printCopyTask(null, destination.toString(), new FileSet[] {logSet}, false, false);
443 		}
444 
445 		if (customBuildCallbacks != null) {
446 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_POST + TARGET_GATHER_LOGS, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
447 		}
448 		script.printTargetEnd();
449 	}
450 
451 	/**
452 	 *
453 	 * @param zipName
454 	 * @param source
455 	 */
generateZipIndividualTarget(String zipName, String source)456 	private void generateZipIndividualTarget(String zipName, String source) {
457 		script.println();
458 		script.printTargetDeclaration(zipName, TARGET_INIT, null, null, null);
459 		IPath root = new Path(Utils.getPropertyFormat(IXMLConstants.PROPERTY_BASEDIR));
460 		script.printZipTask(root.append(zipName).toString(), root.append(source).toString(), false, false, null);
461 		script.printTargetEnd();
462 	}
463 
464 	/**
465 	 * Add the <code>gather.sources</code> target to the given Ant script.
466 	 *
467 	 * @throws CoreException
468 	 */
generateGatherSourcesTarget()469 	private void generateGatherSourcesTarget() throws CoreException {
470 		script.println();
471 		script.printTargetDeclaration(TARGET_GATHER_SOURCES, TARGET_INIT, PROPERTY_DESTINATION_TEMP_FOLDER, null, null);
472 
473 		IPath baseDestination = new Path(Utils.getPropertyFormat(PROPERTY_DESTINATION_TEMP_FOLDER));
474 		baseDestination = baseDestination.append(fullName);
475 		Map<String, String> params = null;
476 		if (customBuildCallbacks != null) {
477 			params = new HashMap<>(1);
478 			params.put(PROPERTY_TARGET_FOLDER, baseDestination.toString());
479 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_PRE + TARGET_GATHER_SOURCES, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
480 		}
481 		List<IPath> destinations = new ArrayList<>(5);
482 		Properties properties = getBuildProperties();
483 		CompiledEntry[] availableJars = extractEntriesToCompile(properties);
484 		for (int i = 0; i < availableJars.length; i++) {
485 			String jar = availableJars[i].getName(true);
486 			IPath destination = baseDestination.append(jar).removeLastSegments(1); // remove the jar name
487 			if (!destinations.contains(destination)) {
488 				script.printMkdirTask(destination.toString());
489 				destinations.add(destination);
490 			}
491 			script.printCopyTask(getSRCLocation(jar), destination.toString(), null, false, false);
492 		}
493 
494 		Map<String, String> copyParams = new HashMap<>();
495 		copyParams.put(PROPERTY_SOURCE_DESTINATION_FOLDER, baseDestination.toString());
496 		script.printAntCallTask(TARGET_COPY_SRC_INCLUDES, true, copyParams);
497 
498 		if (customBuildCallbacks != null) {
499 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_POST + TARGET_GATHER_SOURCES, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
500 		}
501 		script.printTargetEnd();
502 	}
503 
generateGatherIndividualSourcesTarget()504 	private void generateGatherIndividualSourcesTarget() throws CoreException {
505 		script.println();
506 		script.printTargetDeclaration(TARGET_GATHER_INDIVIDUAL_SOURCES, TARGET_INIT, null, null, null);
507 
508 		IPath baseDestination = new Path(Utils.getPropertyFormat(PROPERTY_DESTINATION_TEMP_FOLDER));
509 
510 		Map<String, String> params = null;
511 		if (customBuildCallbacks != null) {
512 			params = new HashMap<>(1);
513 			params.put(PROPERTY_TARGET_FOLDER, baseDestination.toString());
514 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_PRE + TARGET_GATHER_SOURCES, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
515 		}
516 
517 		Map<String, String> copyParams = new HashMap<>();
518 		copyParams.put(PROPERTY_SOURCE_DESTINATION_FOLDER, baseDestination.toString());
519 
520 		Properties properties = getBuildProperties();
521 		CompiledEntry[] availableJars = extractEntriesToCompile(properties);
522 		for (int i = 0; i < availableJars.length; i++) {
523 			String jar = availableJars[i].getName(true);
524 			String srcName = getSRCName(jar);
525 
526 			script.printAntCallTask("copy." + srcName, true, copyParams); //$NON-NLS-1$
527 		}
528 
529 		script.printAntCallTask(TARGET_COPY_SRC_INCLUDES, true, copyParams);
530 
531 		if (customBuildCallbacks != null) {
532 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_POST + TARGET_GATHER_SOURCES, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
533 		}
534 		script.printTargetEnd();
535 	}
536 
generateCopySourcesTarget()537 	private void generateCopySourcesTarget() throws CoreException {
538 		script.println();
539 		script.printTargetDeclaration(TARGET_COPY_SRC_INCLUDES, TARGET_INIT, null, null, null);
540 
541 		IPath baseDestination = new Path(Utils.getPropertyFormat(PROPERTY_SOURCE_DESTINATION_FOLDER));
542 		String include = (String) getBuildProperties().get(PROPERTY_SRC_INCLUDES);
543 		String exclude = (String) getBuildProperties().get(PROPERTY_SRC_EXCLUDES);
544 		if (include != null || exclude != null) {
545 			FileSet fileSet = new FileSet(Utils.getPropertyFormat(PROPERTY_BASEDIR), null, include, null, exclude, null, null);
546 			script.printCopyTask(null, baseDestination.toString(), new FileSet[] {fileSet}, false, false);
547 		}
548 		script.printTargetEnd();
549 	}
550 
generateAPIToolsTarget()551 	private void generateAPIToolsTarget() {
552 		script.println();
553 		script.printTargetDeclaration(TARGET_API_GENERATION, null, PROPERTY_GENERATE_API_DESCRIPTION, null, null);
554 		script.printTab();
555 		script.print("<apitooling.apigeneration "); //$NON-NLS-1$
556 		script.printAttribute("projectName", Utils.getPropertyFormat(PROPERTY_PROJECT_NAME), true); //$NON-NLS-1$
557 		script.printAttribute("project", Utils.getPropertyFormat(PROPERTY_PROJECT_LOCATION), true); //$NON-NLS-1$
558 		script.printAttribute("binary", Utils.getPropertyFormat(PROPERTY_BINARY_FOLDERS), true); //$NON-NLS-1$
559 		script.printAttribute("target", Utils.getPropertyFormat(PROPERTY_TARGET_FOLDER), true); //$NON-NLS-1$
560 		script.printAttribute("extramanifests", Utils.getPropertyFormat(PROPERTY_EXTRA_MANIFESTS), true); //$NON-NLS-1$
561 		script.printAttribute("allownonapiproject", Utils.getPropertyFormat(PROPERTY_ALLOW_NON_API_PROJECT), false); //$NON-NLS-1$
562 		script.println("/>"); //$NON-NLS-1$
563 		script.printTargetEnd();
564 	}
565 
generateAPIToolsCall(String[] binaries, boolean dotIncluded, String target)566 	private void generateAPIToolsCall(String[] binaries, boolean dotIncluded, String target) throws CoreException {
567 		Set<String> classpathEntries = new HashSet<>(Arrays.asList(getClasspathEntries(model)));
568 		StringBuffer binaryFolders = new StringBuffer();
569 		if (workspaceOutputFolders != null && workspaceOutputFolders.size() > 0) {
570 			for (Iterator<String> iterator = workspaceOutputFolders.keySet().iterator(); iterator.hasNext();) {
571 				String key = iterator.next();
572 				Set<IPath> paths = workspaceOutputFolders.get(key);
573 				for (Iterator<IPath> iterator2 = paths.iterator(); iterator2.hasNext();) {
574 					IPath path = iterator2.next();
575 					if (binaryFolders.length() > 0)
576 						binaryFolders.append(File.pathSeparator);
577 					binaryFolders.append(Utils.getPropertyFormat(PROPERTY_BASEDIR) + '/' + path.toString());
578 				}
579 				if (key.equals(DOT))
580 					classpathEntries.remove(EXPANDED_DOT);
581 				else
582 					classpathEntries.remove(key);
583 			}
584 		} else {
585 			for (int i = 0; i < binaries.length; i++) {
586 				if (binaries[i] != null) {
587 					if (i > 0)
588 						binaryFolders.append(File.pathSeparator);
589 					binaryFolders.append(target + '/' + binaries[i]);
590 					classpathEntries.remove(binaries[i]);
591 				}
592 			}
593 			if (dotIncluded) {
594 				if (binaryFolders.length() > 0)
595 					binaryFolders.append(File.pathSeparator);
596 				binaryFolders.append(Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER) + '/' + EXPANDED_DOT);
597 				classpathEntries.remove(EXPANDED_DOT);
598 			}
599 		}
600 		for (Iterator<String> iterator = classpathEntries.iterator(); iterator.hasNext();) {
601 			String entry = iterator.next();
602 			if (entry.equals(EXPANDED_DOT) || new File(model.getLocation(), entry).exists()) {
603 				if (binaryFolders.length() > 0)
604 					binaryFolders.append(File.pathSeparator);
605 				if (entry.equals(EXPANDED_DOT))
606 					binaryFolders.append(model.getLocation());
607 				else {
608 					binaryFolders.append(model.getLocation() + '/' + entry);
609 				}
610 			}
611 		}
612 
613 		Map<String, String> params = new HashMap<>();
614 		params.put(PROPERTY_PROJECT_NAME, Utils.getPropertyFormat(PROPERTY_BUNDLE_ID) + "_" + Utils.getPropertyFormat(PROPERTY_BUNDLE_VERSION)); //$NON-NLS-1$
615 		params.put(PROPERTY_PROJECT_LOCATION, Utils.getPropertyFormat(PROPERTY_BASEDIR));
616 		params.put(PROPERTY_BINARY_FOLDERS, binaryFolders.toString());
617 		params.put(PROPERTY_TARGET_FOLDER, target);
618 
619 		HostSpecification host = model.getHost();
620 		if (host != null && host.getSupplier() != null) {
621 			BundleDescription hostBundle = host.getSupplier().getSupplier();
622 			String hostLocation = hostBundle.getLocation();
623 			String modelLocation = model.getLocation();
624 			if (hostLocation != null && modelLocation != null) {
625 				IPath location = null;
626 				if (new File(hostLocation).isFile()) {
627 					location = Utils.makeRelative(new Path(hostLocation), new Path(modelLocation));
628 				} else {
629 					IPath hostPath = new Path(hostLocation);
630 					location = Utils.makeRelative(hostPath.append(JarFile.MANIFEST_NAME), new Path(modelLocation));
631 				}
632 				if (location.isAbsolute())
633 					params.put(PROPERTY_EXTRA_MANIFESTS, location.toString());
634 				else
635 					params.put(PROPERTY_EXTRA_MANIFESTS, Utils.getPropertyFormat(PROPERTY_BASEDIR) + '/' + location.toString());
636 			}
637 		}
638 		script.printAntCallTask(TARGET_API_GENERATION, true, params);
639 	}
640 
generatePublishBinPartsTarget()641 	private void generatePublishBinPartsTarget() throws CoreException {
642 		script.println();
643 		script.printTargetDeclaration(TARGET_PUBLISH_BIN_PARTS, TARGET_INIT, PROPERTY_P2_PUBLISH_PARTS, PROPERTY_COMPILE_PROBLEM_MARKER_EXISTS, null);
644 		IPath destination = new Path(Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER));
645 		destination = destination.append(fullName);
646 		String root = destination.toString();
647 		script.printMkdirTask(root);
648 
649 		Map<String, String> params = null;
650 		if (customBuildCallbacks != null) {
651 			params = new HashMap<>(3);
652 			params.put(PROPERTY_TARGET_FOLDER, root);
653 			params.put(PROPERTY_BUILD_RESULT_FOLDER, Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER));
654 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_PRE + TARGET_GATHER_BIN_PARTS, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
655 
656 			generateGatherBinParts(destination);
657 
658 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_POST + TARGET_GATHER_BIN_PARTS, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
659 		} else {
660 			String include = (String) getBuildProperties().get(PROPERTY_BIN_INCLUDES);
661 			String exclude = (String) getBuildProperties().get(PROPERTY_BIN_EXCLUDES);
662 
663 			String files = JarFile.MANIFEST_NAME + "," + Constants.PLUGIN_FILENAME_DESCRIPTOR + "," + Constants.FRAGMENT_FILENAME_DESCRIPTOR; //$NON-NLS-1$ //$NON-NLS-2$
664 			FileSet metadata = new FileSet(Utils.getPropertyFormat(PROPERTY_BASEDIR), null, files, null, exclude, null, null);
665 			script.printCopyTask(null, Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER), new FileSet[] {metadata}, true, true);
666 
667 			if (Utils.isSourceBundle(model)) {
668 				Set<BundleDescription> pluginsToGatherSourceFrom = getPluginSourceProviders();
669 				if (pluginsToGatherSourceFrom != null) {
670 					for (Iterator<BundleDescription> iter = pluginsToGatherSourceFrom.iterator(); iter.hasNext();) {
671 						BundleDescription plugin = iter.next();
672 						IPath location = Utils.makeRelative(new Path(getLocation(plugin)), new Path(getLocation(model)));
673 						Map<String, String> taskParams = new HashMap<>(1);
674 						taskParams.put(PROPERTY_DESTINATION_TEMP_FOLDER, Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER) + "/sources"); //$NON-NLS-1$
675 						script.printAntTask(DEFAULT_BUILD_SCRIPT_FILENAME, location.toOSString(), TARGET_GATHER_INDIVIDUAL_SOURCES, null, null, taskParams);
676 					}
677 				}
678 			}
679 
680 			String[] splitIncludes = Utils.getArrayFromString(include);
681 			genarateIdReplacementCall(Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER));
682 			generateAPIToolsCall(getCompiledLocations(), Utils.isStringIn(splitIncludes, EXPANDED_DOT + '/') != -1, Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER));
683 		}
684 
685 		script.println("<eclipse.gatherBundle "); //$NON-NLS-1$
686 		script.println("   metadataRepository=\"" + Utils.getPropertyFormat(PROPERTY_P2_BUILD_REPO) + "\""); //$NON-NLS-1$ //$NON-NLS-2$
687 		script.println("   artifactRepository=\"" + Utils.getPropertyFormat(PROPERTY_P2_BUILD_REPO) + "\""); //$NON-NLS-1$ //$NON-NLS-2$
688 		script.println("   buildResultFolder=\"" + Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER) + "\""); //$NON-NLS-1$ //$NON-NLS-2$
689 
690 		//if the feature specifies the bundle shape, or the bundle itself doesn't have a preferred shape, then use the feature shape value (true by default)
691 		if (associatedEntry != null && (associatedEntry.unpackSet() || !Utils.hasBundleShapeHeader(model)))
692 			script.println("   unpack=\"" + String.valueOf(associatedEntry.isUnpack()) + "\""); //$NON-NLS-1$ //$NON-NLS-2$
693 
694 		if (customBuildCallbacks != null) {
695 			script.println("   targetFolder=\"" + root + "\""); //$NON-NLS-1$ //$NON-NLS-2$
696 			script.println("/>"); //$NON-NLS-1$
697 		} else {
698 			script.println("   baseDirectory=\"${basedir}\""); //$NON-NLS-1$
699 			if (Utils.isSourceBundle(model))
700 				script.println("   gatheredSource=\"" + Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER) + "/sources\""); //$NON-NLS-1$//$NON-NLS-2$
701 
702 			if (workspaceOutputFolders == null || workspaceOutputFolders.size() == 0 || customBuildCallbacks != null) {
703 				script.println("/>"); //$NON-NLS-1$
704 			} else {
705 				//reuse workspace compiled classes
706 				script.println(">"); //$NON-NLS-1$
707 
708 				for (Iterator<String> iterator = workspaceOutputFolders.keySet().iterator(); iterator.hasNext();) {
709 					String key = iterator.next();
710 					Set<IPath> paths = workspaceOutputFolders.get(key);
711 
712 					for (Iterator<IPath> pathIterator = paths.iterator(); pathIterator.hasNext();) {
713 						IPath path = pathIterator.next();
714 						script.printTabs();
715 						script.print("   <outputFolder "); //$NON-NLS-1$
716 						script.printAttribute("library", key, true); //$NON-NLS-1$
717 						script.printAttribute("dir", Utils.getPropertyFormat(PROPERTY_BASEDIR), true); //$NON-NLS-1$
718 						script.printAttribute("includes", path.toString() + "/**", true); //$NON-NLS-1$ //$NON-NLS-2$
719 						script.println("/>"); //$NON-NLS-1$
720 					}
721 				}
722 				script.printEndTag("eclipse.gatherBundle"); //$NON-NLS-1$
723 			}
724 		}
725 		script.printTargetEnd();
726 	}
727 
getCompiledLocations()728 	private String[] getCompiledLocations() {
729 		int count = 0;
730 		String[] fileSetValues = new String[compiledJarNames.size()];
731 		for (Iterator<CompiledEntry> iter = compiledJarNames.iterator(); iter.hasNext();) {
732 			CompiledEntry entry = iter.next();
733 			String formatedName = entry.getName(false) + (entry.getType() == CompiledEntry.FOLDER ? "/" : ""); //$NON-NLS-1$//$NON-NLS-2$
734 			if (dotOnTheClasspath && formatedName.startsWith(EXPANDED_DOT)) {
735 				continue;
736 			}
737 			fileSetValues[count++] = formatedName;
738 		}
739 		return fileSetValues;
740 	}
741 
742 	/**
743 	 * Add the <code>gather.bin.parts</code> target to the given Ant script.
744 	 *
745 	 * @throws CoreException
746 	 */
generateGatherBinPartsTarget()747 	private void generateGatherBinPartsTarget() throws CoreException {
748 		script.println();
749 		script.printTargetDeclaration(TARGET_GATHER_BIN_PARTS, TARGET_INIT, PROPERTY_DESTINATION_TEMP_FOLDER, null, null);
750 		IPath destination = new Path(Utils.getPropertyFormat(PROPERTY_DESTINATION_TEMP_FOLDER));
751 		destination = destination.append(fullName);
752 		String root = destination.toString();
753 		script.printMkdirTask(root);
754 
755 		Map<String, String> params = null;
756 		if (customBuildCallbacks != null) {
757 			params = new HashMap<>(3);
758 			params.put(PROPERTY_TARGET_FOLDER, root);
759 			params.put(PROPERTY_BUILD_RESULT_FOLDER, Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER));
760 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_PRE + TARGET_GATHER_BIN_PARTS, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
761 		}
762 
763 		generateGatherBinParts(destination);
764 
765 		if (customBuildCallbacks != null) {
766 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_POST + TARGET_GATHER_BIN_PARTS, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
767 		}
768 
769 		script.printTargetEnd();
770 	}
771 
generateGatherBinParts(IPath destination)772 	private void generateGatherBinParts(IPath destination) throws CoreException {
773 		String root = destination.toString();
774 		List<IPath> destinations = new ArrayList<>(5);
775 		destinations.add(destination);
776 		String include = (String) getBuildProperties().get(PROPERTY_BIN_INCLUDES);
777 		String exclude = (String) getBuildProperties().get(PROPERTY_BIN_EXCLUDES);
778 
779 		//Copy only the jars that has been compiled and are listed in the includes
780 		String[] splitIncludes = Utils.getArrayFromString(include);
781 		String[] fileSetValues = getCompiledLocations();
782 
783 		boolean dotIncluded = false; //This flag indicates if . should be gathered
784 		int pos = Utils.isStringIn(splitIncludes, EXPANDED_DOT + '/');
785 		if (pos != -1) {
786 			splitIncludes[pos] = null;
787 			dotIncluded = true;
788 		}
789 
790 		if (fileSetValues.length > 0 && fileSetValues[0] != null) {
791 			FileSet fileSet = new FileSet(Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER), null, Utils.getStringFromArray(fileSetValues, ","), null, replaceVariables(exclude, true), null, null); //$NON-NLS-1$
792 			script.printCopyTask(null, root, new FileSet[] {fileSet}, true, false);
793 		}
794 		//Dot on the classpath need to be copied in a special way
795 		if (dotIncluded) {
796 			FileSet fileSet = new FileSet(Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER) + '/' + EXPANDED_DOT, null, "**", null, replaceVariables(exclude, true), null, null); //$NON-NLS-1$
797 			script.printCopyTask(null, root, new FileSet[] {fileSet}, true, false);
798 		}
799 		//General copy of the files listed in the includes
800 		if (include != null || exclude != null) {
801 			String includeSet = replaceVariables(Utils.getStringFromArray(splitIncludes, ","), true); //$NON-NLS-1$
802 			if (includeSet != null && includeSet.length() > 0) {
803 				FileSet fileSet = new FileSet(Utils.getPropertyFormat(PROPERTY_BASEDIR), null, includeSet, null, replaceVariables(exclude, true), null, null);
804 				script.printCopyTask(null, root, new FileSet[] {fileSet}, true, true);
805 			}
806 		}
807 
808 		if (Utils.isSourceBundle(model)) {
809 			Set<BundleDescription> pluginsToGatherSourceFrom = getPluginSourceProviders();
810 			if (pluginsToGatherSourceFrom != null) {
811 				for (Iterator<BundleDescription> iter = pluginsToGatherSourceFrom.iterator(); iter.hasNext();) {
812 					BundleDescription plugin = iter.next();
813 					IPath location = Utils.makeRelative(new Path(getLocation(plugin)), new Path(getLocation(model)));
814 					Map<String, String> taskParams = new HashMap<>(1);
815 					taskParams.put(PROPERTY_DESTINATION_TEMP_FOLDER, root);
816 					script.printAntTask(DEFAULT_BUILD_SCRIPT_FILENAME, location.toOSString(), TARGET_GATHER_INDIVIDUAL_SOURCES, null, null, taskParams);
817 				}
818 			}
819 		}
820 
821 		generatePermissionProperties(root);
822 		genarateIdReplacementCall(destination.toString());
823 		generateAPIToolsCall(fileSetValues, dotIncluded, root);
824 	}
825 
getPluginSourceProviders()826 	private Set<BundleDescription> getPluginSourceProviders() throws CoreException {
827 		Set<BundleDescription> pluginSet = featureGenerator.sourceToGather.getElementEntries().get(model.getSymbolicName());
828 		if (pluginSet != null && pluginSet.size() > 0)
829 			return pluginSet;
830 
831 		String sourceAttribute = getBuildProperties().getProperty(SOURCE_PLUGIN_ATTRIBUTE);
832 		if (Boolean.valueOf(sourceAttribute).booleanValue())
833 			return null;
834 
835 		String[] tokens = Utils.getArrayFromString(sourceAttribute, ";"); //$NON-NLS-1$
836 		pluginSet = new HashSet<>();
837 		for (int i = 0; i + 1 < tokens.length; i += 2) {
838 			BundleDescription fromPlugin = getSite(false).getRegistry().getBundle(tokens[i], tokens[i + 1], true);
839 			if (fromPlugin != null && !Utils.isBinary(fromPlugin))
840 				pluginSet.add(fromPlugin);
841 		}
842 		return pluginSet;
843 	}
844 
genarateIdReplacementCall(String location)845 	private void genarateIdReplacementCall(String location) {
846 		Properties bundleProperties = (Properties) model.getUserObject();
847 		if (bundleProperties == null)
848 			return;
849 
850 		String qualifier = bundleProperties.getProperty(PROPERTY_QUALIFIER);
851 		String sourceReference = getSourceReference(bundleProperties);
852 		if (qualifier == null && sourceReference == null)
853 			return;
854 
855 		Map<String, String> arguments = new HashMap<>();
856 		arguments.put("path", AntScript.getEscaped(location)); //$NON-NLS-1$
857 		if (qualifier != null)
858 			arguments.put("version", model.getVersion().toString()); //$NON-NLS-1$
859 		if (sourceReference != null)
860 			arguments.put("attributes", ECLIPSE_SOURCE_REF + '|' + sourceReference); //$NON-NLS-1$
861 		script.printElement("eclipse.versionReplacer", arguments); //$NON-NLS-1$
862 	}
863 
getSourceReference(Properties bundleProperties)864 	private String getSourceReference(Properties bundleProperties) {
865 		String reference = (String) bundleProperties.get(PROPERTY_SOURCE_REFERENCE);
866 		if (!sourceReferences || reference == null)
867 			return null;
868 
869 		String originalEntry = (String) bundleProperties.get(ECLIPSE_SOURCE_REF);
870 		if (originalEntry != null) {
871 			try {
872 				ManifestElement[] elements = ManifestElement.parseHeader(ECLIPSE_SOURCE_REF, originalEntry);
873 				StringBuffer newEntry = new StringBuffer();
874 				boolean changed = false;
875 				for (int i = 0; i < elements.length; i++) {
876 					if (i > 0)
877 						newEntry.append(',');
878 					if (elements[i].getValue().equals(PDE_SOURCE_REF)) {
879 						newEntry.append(reference);
880 						changed = true;
881 					} else
882 						newEntry.append(elements[i].toString());
883 				}
884 				return changed ? newEntry.toString() : null; //returning null is no change
885 			} catch (BundleException e) {
886 				// ignore
887 			}
888 		} else {
889 			return reference;
890 		}
891 		return null;
892 	}
893 
generatePermissionProperties(String directory)894 	private void generatePermissionProperties(String directory) throws CoreException {
895 		getPermissionProperties();
896 		for (Iterator<Entry<Object, Object>> iter = permissionProperties.entrySet().iterator(); iter.hasNext();) {
897 			Map.Entry<Object, Object> permission = iter.next();
898 			String instruction = (String) permission.getKey();
899 			String parameters = (String) permission.getValue();
900 			int index;
901 			if ((index = instruction.indexOf(PERMISSIONS)) != -1) {
902 				generateChmodInstruction(directory, instruction.substring(index + PERMISSIONS.length() + 1), parameters);
903 				continue;
904 			}
905 			if (instruction.startsWith(LINK)) {
906 				generateLinkInstruction(directory, parameters);
907 			}
908 		}
909 	}
910 
generateChmodInstruction(String dir, String rights, String files)911 	private void generateChmodInstruction(String dir, String rights, String files) {
912 		// TO CHECK We only consider rights specified with numbers
913 		if (rights.equals(EXECUTABLE)) {
914 			rights = "755"; //$NON-NLS-1$
915 		}
916 		script.printChmod(dir, rights, files);
917 	}
918 
generateLinkInstruction(String dir, String files)919 	private void generateLinkInstruction(String dir, String files) {
920 		String[] links = Utils.getArrayFromString(files, ","); //$NON-NLS-1$
921 		List<String> arguments = new ArrayList<>(2);
922 		for (int i = 0; i < links.length; i += 2) {
923 			arguments.add(links[i]);
924 			arguments.add(links[i + 1]);
925 			script.printExecTask("ln -s", dir, arguments, "Linux,FreeBSD"); //$NON-NLS-1$ //$NON-NLS-2$
926 			arguments.clear();
927 		}
928 	}
929 
getPermissionProperties()930 	protected Properties getPermissionProperties() throws CoreException {
931 		if (permissionProperties == null) {
932 			permissionProperties = readProperties(getLocation(model), PERMISSIONS_FILE, IStatus.INFO);
933 		}
934 		return permissionProperties;
935 	}
936 
937 	/**
938 	 * Add the <code>zip.plugin</code> target to the given Ant script.
939 	 */
generateZipPluginTarget()940 	private void generateZipPluginTarget() {
941 		script.println();
942 		script.printTargetDeclaration(TARGET_ZIP_PLUGIN, TARGET_INIT, null, null, NLS.bind(Messages.build_plugin_zipPlugin, model.getSymbolicName()));
943 		script.printDeleteTask(Utils.getPropertyFormat(PROPERTY_TEMP_FOLDER), null, null);
944 		script.printMkdirTask(Utils.getPropertyFormat(PROPERTY_TEMP_FOLDER));
945 		script.printAntCallTask(TARGET_BUILD_JARS, true, null);
946 		script.printAntCallTask(TARGET_BUILD_SOURCES, true, null);
947 		Map<String, String> params = new HashMap<>(1);
948 		params.put(PROPERTY_DESTINATION_TEMP_FOLDER, Utils.getPropertyFormat(PROPERTY_TEMP_FOLDER) + '/');
949 		script.printAntCallTask(TARGET_GATHER_BIN_PARTS, true, params);
950 		script.printAntCallTask(TARGET_GATHER_SOURCES, true, params);
951 		FileSet fileSet = new FileSet(Utils.getPropertyFormat(PROPERTY_TEMP_FOLDER), null, "**/*.bin" + Utils.getPropertyFormat(PROPERTY_LOG_EXTENSION), null, null, null, null); //$NON-NLS-1$
952 		script.printDeleteTask(null, null, new FileSet[] {fileSet});
953 		script.printZipTask(pluginZipDestination, Utils.getPropertyFormat(PROPERTY_TEMP_FOLDER), true, false, null);
954 		script.printDeleteTask(Utils.getPropertyFormat(PROPERTY_TEMP_FOLDER), null, null);
955 		script.printTargetEnd();
956 	}
957 
958 	/**
959 	 * Add the <code>build.update.jar</code> target to the given Ant script.
960 	 */
generateBuildUpdateJarTarget()961 	private void generateBuildUpdateJarTarget() {
962 		script.println();
963 		script.printTargetDeclaration(TARGET_BUILD_UPDATE_JAR, TARGET_INIT, null, null, NLS.bind(Messages.build_plugin_buildUpdateJar, model.getSymbolicName()));
964 		script.printDeleteTask(Utils.getPropertyFormat(PROPERTY_TEMP_FOLDER), null, null);
965 		script.printMkdirTask(Utils.getPropertyFormat(PROPERTY_TEMP_FOLDER));
966 		script.printAntCallTask(TARGET_BUILD_JARS, true, null);
967 		Map<String, String> params = new HashMap<>(1);
968 		params.put(PROPERTY_DESTINATION_TEMP_FOLDER, Utils.getPropertyFormat(PROPERTY_TEMP_FOLDER) + '/');
969 		script.printAntCallTask(TARGET_GATHER_BIN_PARTS, true, params);
970 		script.printJarTask(pluginUpdateJarDestination, Utils.getPropertyFormat(PROPERTY_TEMP_FOLDER) + '/' + fullName, null, "merge"); //$NON-NLS-1$
971 		script.printDeleteTask(Utils.getPropertyFormat(PROPERTY_TEMP_FOLDER), null, null);
972 		if (signJars)
973 			script.println("<eclipse.jarProcessor sign=\"" + Utils.getPropertyFormat(PROPERTY_SIGN) + "\" pack=\"" + Utils.getPropertyFormat(PROPERTY_PACK) + "\" unsign=\"" + Utils.getPropertyFormat(PROPERTY_UNSIGN) + "\" jar=\"" + AntScript.getEscaped(pluginUpdateJarDestination) + "\" alias=\"" + Utils.getPropertyFormat(PROPERTY_SIGN_ALIAS) + "\" keystore=\"" + Utils.getPropertyFormat(PROPERTY_SIGN_KEYSTORE) + "\" storepass=\"" + Utils.getPropertyFormat(PROPERTY_SIGN_STOREPASS) + "\"/>"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
974 		script.printTargetEnd();
975 	}
976 
977 	/**
978 	 * Add the <code>refresh</code> target to the given Ant script.
979 	 */
generateRefreshTarget()980 	private void generateRefreshTarget() {
981 		script.println();
982 		script.printTargetDeclaration(TARGET_REFRESH, TARGET_INIT, PROPERTY_ECLIPSE_RUNNING, null, Messages.build_plugin_refresh);
983 		script.printConvertPathTask(new Path(getLocation(model)).removeLastSegments(0).toOSString().replace('\\', '/'), PROPERTY_RESOURCE_PATH, false);
984 		script.printRefreshLocalTask(Utils.getPropertyFormat(PROPERTY_RESOURCE_PATH), "infinite"); //$NON-NLS-1$
985 		script.printTargetEnd();
986 	}
987 
988 	/**
989 	 * End the script by closing the project element.
990 	 */
generateEpilogue()991 	private void generateEpilogue() {
992 		script.println();
993 		script.printProjectEnd();
994 	}
995 
996 	/**
997 	 * Defines, the XML declaration, Ant project and targets init and initTemplate.
998 	 * @throws CoreException
999 	 */
generatePrologue()1000 	private void generatePrologue() throws CoreException {
1001 		script.printProjectDeclaration(model.getSymbolicName(), TARGET_BUILD_JARS, DOT);
1002 		script.println();
1003 
1004 		script.printProperty(PROPERTY_P2_BUILD_REPO, "file:" + Utils.getPropertyFormat(PROPERTY_BUILD_DIRECTORY) + "/buildRepo"); //$NON-NLS-1$ //$NON-NLS-2$
1005 		script.printProperty(PROPERTY_BASE_WS, Utils.getPropertyFormat(PROPERTY_WS));
1006 		script.printProperty(PROPERTY_BASE_OS, Utils.getPropertyFormat(PROPERTY_OS));
1007 		script.printProperty(PROPERTY_BASE_ARCH, Utils.getPropertyFormat(PROPERTY_ARCH));
1008 		script.printProperty(PROPERTY_BASE_NL, Utils.getPropertyFormat(PROPERTY_NL));
1009 		script.printProperty(PROPERTY_BUNDLE_ID, model.getSymbolicName());
1010 		script.printProperty(PROPERTY_BUNDLE_VERSION, model.getVersion().toString());
1011 		script.printProperty(PROPERTY_P2_PUBLISHONERROR, FALSE);
1012 		script.println();
1013 
1014 		if (customBuildCallbacks != null && !customBuildCallbacks.equals(FALSE)) {
1015 			script.printAvailableTask(PROPERTY_CUSTOM_BUILD_CALLBACKS, customCallbacksBuildpath + '/' + customBuildCallbacks, customBuildCallbacks);
1016 			script.println();
1017 		}
1018 
1019 		generateCompilerSettings();
1020 
1021 		script.printTargetDeclaration(TARGET_INIT, TARGET_PROPERTIES, null, null, null);
1022 		script.printConditionIsSet(PROPERTY_PLUGIN_TEMP, Utils.getPropertyFormat(PROPERTY_BUILD_TEMP) + '/' + DEFAULT_PLUGIN_LOCATION, PROPERTY_BUILD_TEMP);
1023 		script.printProperty(PROPERTY_PLUGIN_TEMP, Utils.getPropertyFormat(PROPERTY_BASEDIR));
1024 		script.printConditionIsSet(PROPERTY_BUILD_RESULT_FOLDER, Utils.getPropertyFormat(PROPERTY_PLUGIN_TEMP) + '/' + getNormalizedName(model), PROPERTY_BUILD_TEMP);
1025 		script.printProperty(PROPERTY_BUILD_RESULT_FOLDER, Utils.getPropertyFormat(PROPERTY_BASEDIR));
1026 		script.printProperty(PROPERTY_TEMP_FOLDER, Utils.getPropertyFormat(PROPERTY_BASEDIR) + '/' + PROPERTY_TEMP_FOLDER);
1027 		script.printProperty(PROPERTY_PLUGIN_DESTINATION, Utils.getPropertyFormat(PROPERTY_BASEDIR));
1028 		script.printConditionIsTrue(PROPERTY_P2_PUBLISH_PARTS, TRUE, Utils.getPropertyFormat(PROPERTY_P2_GATHERING));
1029 		script.printProperty(PROPERTY_COMPILE_PROBLEM_MARKER, Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER) + '/' + "compilation.problem"); //$NON-NLS-1$
1030 
1031 		script.printConditionStart(PROPERTY_COMPILE_PROBLEM_MARKER_EXISTS, TRUE, null);
1032 		script.printStartTag("and"); //$NON-NLS-1$
1033 		script.printAvailableTask(null, Utils.getPropertyFormat(PROPERTY_COMPILE_PROBLEM_MARKER));
1034 		script.printIsFalse(Utils.getPropertyFormat(PROPERTY_P2_PUBLISHONERROR));
1035 		script.printEndTag("and"); //$NON-NLS-1$
1036 		script.printEndCondition();
1037 
1038 		script.printTargetEnd();
1039 		script.println();
1040 		script.printTargetDeclaration(TARGET_PROPERTIES, null, PROPERTY_ECLIPSE_RUNNING, null, null);
1041 		script.printProperty(PROPERTY_BUILD_COMPILER, JDT_COMPILER_ADAPTER);
1042 		script.println();
1043 
1044 		script.printTargetEnd();
1045 	}
1046 
generateCompilerSettings()1047 	private void generateCompilerSettings() throws CoreException {
1048 		String javacSource = null;
1049 		String javacTarget = null;
1050 		String bootClasspath = null;
1051 		String jreProfile = null;
1052 		try {
1053 			Properties properties = getBuildProperties();
1054 			javacSource = properties.getProperty(IBuildPropertiesConstants.PROPERTY_JAVAC_SOURCE);
1055 			javacTarget = properties.getProperty(IBuildPropertiesConstants.PROPERTY_JAVAC_TARGET);
1056 			bootClasspath = properties.getProperty(IBuildPropertiesConstants.PROPERTY_BOOT_CLASSPATH);
1057 			jreProfile = properties.getProperty(IBuildPropertiesConstants.PROPERTY_JRE_COMPILATION_PROFILE);
1058 		} catch (CoreException e) {
1059 			//ignore
1060 		}
1061 
1062 		script.printComment(Messages.build_compilerSetting);
1063 		script.printProperty(PROPERTY_JAVAC_FAIL_ON_ERROR, "false"); //$NON-NLS-1$
1064 		script.printProperty(PROPERTY_JAVAC_DEBUG_INFO, "on"); //$NON-NLS-1$
1065 		script.printProperty(PROPERTY_JAVAC_VERBOSE, "false"); //$NON-NLS-1$
1066 		script.printProperty(PROPERTY_LOG_EXTENSION, ".log"); //$NON-NLS-1$
1067 		script.printProperty(PROPERTY_JAVAC_COMPILERARG, ""); //$NON-NLS-1$
1068 		script.printProperty(PROPERTY_PREREQ_COMPILE_LOG, Utils.getPropertyFormat(PROPERTY_BUILD_DIRECTORY) + "/prereqErrors.log"); //$NON-NLS-1$
1069 
1070 		if (javacSource == null)
1071 			script.printProperty(IXMLConstants.PROPERTY_JAVAC_SOURCE, "1.3"); //$NON-NLS-1$
1072 		if (javacTarget == null)
1073 			script.printProperty(IXMLConstants.PROPERTY_JAVAC_TARGET, "1.2"); //$NON-NLS-1$
1074 		if (bootClasspath == null) {
1075 			script.println("<condition property=\"dir_bootclasspath\" value=\"${java.home}/../Classes\">");//$NON-NLS-1$
1076 			script.println("\t<and>"); //$NON-NLS-1$
1077 			script.println("\t\t<os family=\"mac\"/>");//$NON-NLS-1$
1078 			script.println("\t\t<available file=\"${java.home}/../Classes\" type=\"dir\"/>"); //$NON-NLS-1$
1079 			script.println("\t</and>"); //$NON-NLS-1$
1080 			script.println("</condition>");//$NON-NLS-1$
1081 			script.println("<property name=\"dir_bootclasspath\" value=\"${java.home}/lib\"/>");//$NON-NLS-1$
1082 			script.println("<path id=\"path_bootclasspath\">");//$NON-NLS-1$
1083 			script.println("\t<fileset dir=\"${dir_bootclasspath}\">");//$NON-NLS-1$
1084 			script.println("\t\t<include name=\"*.jar\"/>");//$NON-NLS-1$
1085 			script.println("\t</fileset>");//$NON-NLS-1$
1086 			script.println("</path>");//$NON-NLS-1$
1087 			script.printPropertyRefid(PROPERTY_BOOTCLASSPATH, "path_bootclasspath"); //$NON-NLS-1$
1088 		}
1089 
1090 		Properties environmentMappings = getExecutionEnvironmentMappings();
1091 		if (jreProfile != null && !environmentMappings.containsKey(jreProfile + '.' + IXMLConstants.PROPERTY_JAVAC_SOURCE)) {
1092 			if (reportResolutionErrors) {
1093 				IStatus status = new Status(IStatus.ERROR, model.getSymbolicName(), IStatus.ERROR, NLS.bind(Messages.build_plugin_unrecognizedJRE, jreProfile), null);
1094 				BundleHelper.getDefault().getLog().log(status);
1095 			}
1096 			jreProfile = null;
1097 		}
1098 
1099 		if (javacSource != null)
1100 			script.printProperty(PROPERTY_BUNDLE_JAVAC_SOURCE, javacSource);
1101 		if (javacTarget != null)
1102 			script.printProperty(PROPERTY_BUNDLE_JAVAC_TARGET, javacTarget);
1103 		if (bootClasspath != null)
1104 			script.printProperty(PROPERTY_BUNDLE_BOOTCLASSPATH, bootClasspath);
1105 
1106 		String source, target = null;
1107 		String[] modelEnvironments = model.getExecutionEnvironments();
1108 		String[] environments = null;
1109 		if (jreProfile != null) {
1110 			environments = new String[modelEnvironments.length + 1];
1111 			environments[0] = jreProfile;
1112 			System.arraycopy(modelEnvironments, 0, environments, 1, modelEnvironments.length);
1113 		} else {
1114 			environments = modelEnvironments;
1115 		}
1116 
1117 		ProfileManager profileManager = getSite(false).getRegistry().getProfileManager();
1118 		for (int i = 0; i < environments.length; i++) {
1119 			if (bootClasspath == null)
1120 				script.printConditionIsSet(PROPERTY_BUNDLE_BOOTCLASSPATH, Utils.getPropertyFormat(environments[i]), environments[i]);
1121 
1122 			source = profileManager.getJavacSource(environments[i]);
1123 			if (source == null)
1124 				source = (String) environmentMappings.get(environments[i] + '.' + IXMLConstants.PROPERTY_JAVAC_SOURCE);
1125 			target = profileManager.getJavacTarget(environments[i]);
1126 			if (target == null)
1127 				target = (String) environmentMappings.get(environments[i] + '.' + IXMLConstants.PROPERTY_JAVAC_TARGET);
1128 			if (javacSource == null && source != null)
1129 				script.printConditionIsSet(PROPERTY_BUNDLE_JAVAC_SOURCE, source, environments[i]);
1130 			if (javacTarget == null && target != null)
1131 				script.printConditionIsSet(PROPERTY_BUNDLE_JAVAC_TARGET, target, environments[i]);
1132 		}
1133 
1134 		if (javacSource == null)
1135 			script.printProperty(PROPERTY_BUNDLE_JAVAC_SOURCE, Utils.getPropertyFormat(IXMLConstants.PROPERTY_JAVAC_SOURCE));
1136 		if (javacTarget == null)
1137 			script.printProperty(PROPERTY_BUNDLE_JAVAC_TARGET, Utils.getPropertyFormat(IXMLConstants.PROPERTY_JAVAC_TARGET));
1138 		if (bootClasspath == null)
1139 			script.printProperty(PROPERTY_BUNDLE_BOOTCLASSPATH, Utils.getPropertyFormat(PROPERTY_BOOTCLASSPATH));
1140 		script.println();
1141 	}
1142 
1143 	/**
1144 	 * Sets the PluginModel to generate script from.
1145 	 *
1146 	 * @param model
1147 	 * @throws CoreException
1148 	 */
setModel(BundleDescription model)1149 	public void setModel(BundleDescription model) throws CoreException {
1150 		if (model == null) {
1151 			throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_ELEMENT_MISSING, Messages.error_missingElement, null));
1152 		}
1153 		model = getSite(false).getRegistry().getVersionReplacement(model);
1154 		this.model = model;
1155 		if (getBuildProperties() == AbstractScriptGenerator.MissingProperties.getInstance()) {
1156 			//if there were no build.properties, then it is a binary plugin
1157 			binaryPlugin = true;
1158 		} else {
1159 			getCompiledElements().add(getNormalizedName(model));
1160 		}
1161 		Properties bundleProperties = (Properties) model.getUserObject();
1162 		if (bundleProperties == null) {
1163 			bundleProperties = new Properties();
1164 			model.setUserObject(bundleProperties);
1165 		}
1166 		bundleProperties.put(IS_COMPILED, binaryPlugin ? Boolean.FALSE : Boolean.TRUE);
1167 	}
1168 
1169 	/**
1170 	 * Sets model to generate scripts from.
1171 	 *
1172 	 * @param modelId
1173 	 * @throws CoreException
1174 	 */
setModelId(String modelId, String modelVersion)1175 	public void setModelId(String modelId, String modelVersion) throws CoreException {
1176 		BundleDescription newModel = getModel(modelId, modelVersion);
1177 		if (newModel == null) {
1178 			String message = NLS.bind(Messages.exception_missingElement, modelId);
1179 			throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_ELEMENT_MISSING, message, null));
1180 		}
1181 		setModel(newModel);
1182 	}
1183 
1184 	/**
1185 	 * Add the <code>build.zips</code> target to the given Ant script.
1186 	 *
1187 	 * @throws CoreException
1188 	 */
generateBuildZipsTarget()1189 	private void generateBuildZipsTarget() throws CoreException {
1190 		StringBuffer zips = new StringBuffer();
1191 		Properties props = getBuildProperties();
1192 		for (Iterator<Entry<Object, Object>> iterator = props.entrySet().iterator(); iterator.hasNext();) {
1193 			Map.Entry<Object, Object> entry = iterator.next();
1194 			String key = (String) entry.getKey();
1195 			if (key.startsWith(PROPERTY_SOURCE_PREFIX) && key.endsWith(PROPERTY_ZIP_SUFFIX)) {
1196 				String zipName = key.substring(PROPERTY_SOURCE_PREFIX.length());
1197 				zips.append(',');
1198 				zips.append(zipName);
1199 				generateZipIndividualTarget(zipName, (String) entry.getValue());
1200 			}
1201 		}
1202 		script.println();
1203 		script.printTargetDeclaration(TARGET_BUILD_ZIPS, TARGET_INIT + zips.toString(), null, null, null);
1204 		script.printTargetEnd();
1205 	}
1206 
1207 	/**
1208 	 * Sets the featureGenerator.
1209 	 * @param featureGenerator The featureGenerator to set
1210 	 */
setFeatureGenerator(BuildDirector featureGenerator)1211 	public void setFeatureGenerator(BuildDirector featureGenerator) {
1212 		this.featureGenerator = featureGenerator;
1213 	}
1214 
1215 	/**
1216 	 * Add the "build.jars" target to the given Ant script using the specified plug-in model.
1217 	 *
1218 	 * @param pluginModel the plug-in model to reference
1219 	 * @throws CoreException
1220 	 */
generateBuildJarsTarget(BundleDescription pluginModel)1221 	private void generateBuildJarsTarget(BundleDescription pluginModel) throws CoreException {
1222 		Properties properties = getBuildProperties();
1223 		CompiledEntry[] availableJars = extractEntriesToCompile(properties);
1224 		compiledJarNames = new ArrayList<>(availableJars.length);
1225 		Map<String, CompiledEntry> jars = new HashMap<>(availableJars.length);
1226 		for (int i = 0; i < availableJars.length; i++)
1227 			jars.put(availableJars[i].getName(false), availableJars[i]);
1228 
1229 		// Put the jars in a correct compile order
1230 		String jarOrder = (String) getBuildProperties().get(PROPERTY_JAR_ORDER);
1231 		IClasspathComputer classpath = new ClasspathComputer3_0(this);
1232 
1233 		if (jarOrder != null) {
1234 			String[] order = Utils.getArrayFromString(jarOrder);
1235 			for (int i = 0; i < order.length; i++) {
1236 				CompiledEntry jar = jars.get(order[i]);
1237 				if (jar == null)
1238 					continue;
1239 
1240 				compiledJarNames.add(jar);
1241 				generateCompilationTarget(classpath.getClasspath(pluginModel, jar), jar);
1242 				generateSRCTarget(jar);
1243 				jars.remove(order[i]);
1244 			}
1245 		}
1246 		for (Iterator<CompiledEntry> iterator = jars.values().iterator(); iterator.hasNext();) {
1247 			CompiledEntry jar = iterator.next();
1248 			compiledJarNames.add(jar);
1249 			generateCompilationTarget(classpath.getClasspath(pluginModel, jar), jar);
1250 			generateSRCTarget(jar);
1251 		}
1252 		script.println();
1253 		script.printTargetDeclaration(TARGET_BUILD_JARS, TARGET_INIT, null, null, NLS.bind(Messages.build_plugin_buildJars, pluginModel.getSymbolicName()));
1254 		script.printDeleteTask(null, Utils.getPropertyFormat(PROPERTY_COMPILE_PROBLEM_MARKER), TRUE, null);
1255 
1256 		Map<String, String> params = null;
1257 		if (customBuildCallbacks != null) {
1258 			params = new HashMap<>(1);
1259 			params.put(PROPERTY_BUILD_RESULT_FOLDER, Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER));
1260 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_PRE + TARGET_BUILD_JARS, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
1261 		}
1262 		for (Iterator<CompiledEntry> iter = compiledJarNames.iterator(); iter.hasNext();) {
1263 			String name = iter.next().getName(false);
1264 			script.printAvailableTask(name, replaceVariables(getJARLocation(name), true));
1265 			script.printAntCallTask(name, true, null);
1266 		}
1267 		if (customBuildCallbacks != null) {
1268 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_POST + TARGET_BUILD_JARS, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
1269 		}
1270 		script.printTargetEnd();
1271 		script.println();
1272 
1273 		generateCheckCompilationTask(pluginModel);
1274 
1275 		script.printTargetDeclaration(TARGET_BUILD_SOURCES, TARGET_INIT, null, null, null);
1276 		if (customBuildCallbacks != null) {
1277 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_PRE + TARGET_BUILD_SOURCES, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
1278 		}
1279 		for (Iterator<CompiledEntry> iter = compiledJarNames.iterator(); iter.hasNext();) {
1280 			String jarName = iter.next().getName(false);
1281 			String srcName = getSRCName(jarName);
1282 			script.printAvailableTask(srcName, getSRCLocation(jarName));
1283 			script.printAntCallTask(srcName, true, null);
1284 		}
1285 		if (customBuildCallbacks != null) {
1286 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_POST + TARGET_BUILD_SOURCES, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, null);
1287 		}
1288 		script.printTargetEnd();
1289 	}
1290 
generateCheckCompilationTask(BundleDescription pluginModel)1291 	private void generateCheckCompilationTask(BundleDescription pluginModel) throws CoreException {
1292 		script.printTargetDeclaration(TARGET_CHECK_COMPILATION_RESULTS, null, PROPERTY_COMPILATION_ERROR, null, null);
1293 		script.printEchoTask(Utils.getPropertyFormat(PROPERTY_COMPILE_PROBLEM_MARKER), getNormalizedName(pluginModel) + "${line.separator}" + PROPERTY_COMPILATION_ERROR + "=" + Utils.getPropertyFormat(PROPERTY_COMPILATION_ERROR)); //$NON-NLS-1$ //$NON-NLS-2$
1294 
1295 		Map<String, String> arguments = new HashMap<>();
1296 		arguments.put("bundle", getNormalizedName(pluginModel)); //$NON-NLS-1$
1297 		arguments.put("log", Utils.getPropertyFormat(PROPERTY_PREREQ_COMPILE_LOG)); //$NON-NLS-1$
1298 		script.printStartTag("eclipse.logCompileError", arguments); //$NON-NLS-1$
1299 		script.incrementIdent();
1300 		arguments.clear();
1301 		for (Iterator<Object> iter = getPrequisitePaths().iterator(); iter.hasNext();) {
1302 			arguments.put("name", iter.next().toString()); //$NON-NLS-1$
1303 			script.printElement("include", arguments); //$NON-NLS-1$
1304 		}
1305 		script.decrementIdent();
1306 		script.printEndTag("eclipse.logCompileError"); //$NON-NLS-1$
1307 
1308 		script.printTargetEnd();
1309 		script.println();
1310 	}
1311 
getPrequisitePaths()1312 	private List<Object> getPrequisitePaths() throws CoreException {
1313 		Properties properties = (Properties) model.getUserObject();
1314 		List<Object> results = new ArrayList<>();
1315 		if (properties != null) {
1316 			String required = properties.getProperty(PROPERTY_REQUIRED_BUNDLE_IDS);
1317 			if (required != null) {
1318 				State state = getSite(false).getRegistry().getState();
1319 				String[] ids = Utils.getArrayFromString(required, ":"); //$NON-NLS-1$
1320 				for (int i = 0; i < ids.length; i++) {
1321 					try {
1322 						BundleDescription bundle = state.getBundle(Long.valueOf(ids[i]).longValue());
1323 						if (bundle != null && !Utils.isBinary(bundle)) {
1324 							Path bundleLocation = new Path(bundle.getLocation());
1325 							results.add(bundleLocation.append("compilation.problem")); //$NON-NLS-1$
1326 							results.add(Utils.getPropertyFormat(PROPERTY_PLUGIN_TEMP) + '/' + getNormalizedName(bundle) + "/compilation.problem"); //$NON-NLS-1$
1327 						}
1328 					} catch (NumberFormatException e) {
1329 						//ignore
1330 					}
1331 				}
1332 			}
1333 		}
1334 		return results;
1335 	}
1336 
1337 	/**
1338 	 * generate compile settings for compiling this entry
1339 	 * warning levels, default encoding, custom encodings
1340 	 * @param javac
1341 	 * @param entry
1342 	 */
generateCompilerSettings(JavacTask javac, CompiledEntry entry, List<Object> classpath)1343 	private void generateCompilerSettings(JavacTask javac, CompiledEntry entry, List<Object> classpath) {
1344 		final String ADAPTER_ENCODING = "#ADAPTER#ENCODING#"; //$NON-NLS-1$
1345 		final String ADAPTER_ACCESS = "#ADAPTER#ACCESS#"; //$NON-NLS-1$
1346 
1347 		Properties properties = null;
1348 		try {
1349 			properties = getBuildProperties();
1350 		} catch (CoreException e) {
1351 			return;
1352 		}
1353 		if (properties == null && classpath.size() == 0)
1354 			return;
1355 
1356 		String name = entry.getName(false);
1357 
1358 		String excludes = properties.getProperty(PROPERTY_EXCLUDE_PREFIX + name);
1359 		if (excludes != null) {
1360 			javac.setExcludes(Utils.getArrayFromString(excludes, ",")); //$NON-NLS-1$
1361 		}
1362 		if (name.equals(EXPANDED_DOT))
1363 			name = DOT;
1364 
1365 		// Bug 303960 potentially use a custom compiler adapter
1366 		String compilerAdapter = properties.getProperty(PROPERTY_COMPILER_ADAPTER);
1367 		if (compilerAdapter != null) {
1368 			javac.setCompilerAdapter(compilerAdapter);
1369 			javac.setAdapterUseLog(Boolean.valueOf(properties.getProperty(PROPERTY_ADAPTER_USELOG, TRUE)).booleanValue());
1370 			javac.setAdapterArgFile(Boolean.valueOf(properties.getProperty(PROPERTY_ADAPTER_USEARGFILE, TRUE)).booleanValue());
1371 		}
1372 
1373 		// Bug 303960 get compilerArg property
1374 		String compilerArg = properties.getProperty(PROPERTY_JAVAC_COMPILERARG);
1375 		if (compilerArg != null)
1376 			javac.setSpecificCompileArgs(compilerArg);
1377 
1378 		String defaultEncodingVal = properties.getProperty(PROPERTY_JAVAC_DEFAULT_ENCODING_PREFIX + name);
1379 		if (defaultEncodingVal != null)
1380 			javac.setEncoding(defaultEncodingVal);
1381 
1382 		String customEncodingsVal = properties.getProperty(PROPERTY_JAVAC_CUSTOM_ENCODINGS_PREFIX + name);
1383 		String warningLevels = properties.getProperty(PROPERTY_JAVAC_WARNINGS_PREFIX + name);
1384 		String errorLevels = properties.getProperty(PROPERTY_JAVAC_ERRORS_PREFIX + name);
1385 
1386 		if (customEncodingsVal == null && warningLevels == null && errorLevels == null && classpath.size() == 0) {
1387 			return;
1388 		}
1389 
1390 		String root = getLocation(model);
1391 		File file = new File(root, "javaCompiler." + name.replaceAll("[\\\\/]", "_") + ".args"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
1392 		if (file.exists()) {
1393 			file.delete();
1394 		}
1395 		Writer writer = null;
1396 		try {
1397 			try {
1398 				//only create the file if we are going to write something in it
1399 				if (warningLevels != null || customEncodingsVal != null || errorLevels != null)
1400 					writer = new BufferedWriter(new FileWriter(file));
1401 
1402 				if (warningLevels != null) {
1403 					writer.write("-warn:" + warningLevels + "\n"); //$NON-NLS-1$//$NON-NLS-2$
1404 				}
1405 
1406 				if (errorLevels != null) {
1407 					writer.write("-err:" + errorLevels + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
1408 				}
1409 
1410 				if (customEncodingsVal != null) {
1411 					String[] encodings = customEncodingsVal.split(","); //$NON-NLS-1$
1412 					if (encodings.length > 0) {
1413 						for (int i = 0; i < encodings.length; i++) {
1414 							writer.write(ADAPTER_ENCODING + encodings[i] + "\n"); //$NON-NLS-1$
1415 						}
1416 					}
1417 				}
1418 				//handle access rules if we are using ClasspathComputer3_0
1419 				Properties data = (Properties) model.getUserObject();
1420 				if (data == null || !data.containsKey(PROPERTY_CONVERTED_MANIFEST)) {
1421 					if (classpath.size() > 0 && classpath.get(0) instanceof ClasspathElement) {
1422 						for (Iterator<Object> iterator = classpath.iterator(); iterator.hasNext();) {
1423 							ClasspathElement element = (ClasspathElement) iterator.next();
1424 							if (element.getPath() != null && element.getAccessRules().length() > 0) {
1425 								String path = null;
1426 								if (element.getSubPath() == null)
1427 									path = element.getPath();
1428 								else
1429 									path = featureGenerator.getExtractedRoot(element) + '/' + element.getSubPath();
1430 
1431 								if (path.startsWith(Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER))) {
1432 									//remove leading ${build.result.folder}/
1433 									path = path.substring(Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER).length() + 1);
1434 								}
1435 								//remove leading ../../..
1436 								path = path.replaceFirst("^(\\.\\.[\\\\/])*", ""); //$NON-NLS-1$//$NON-NLS-2$
1437 								if (writer == null)
1438 									writer = new BufferedWriter(new FileWriter(file));
1439 								writer.write(ADAPTER_ACCESS + path + element.getAccessRules() + "\n"); //$NON-NLS-1$
1440 							}
1441 						}
1442 					}
1443 				}
1444 				if (writer != null)
1445 					javac.setCompileArgsFile(Utils.getPropertyFormat(PROPERTY_BASEDIR) + "/" + file.getName()); //$NON-NLS-1$
1446 			} finally {
1447 				if (writer != null)
1448 					writer.close();
1449 			}
1450 		} catch (IOException e1) {
1451 			//ignore
1452 		}
1453 	}
1454 
1455 	/**
1456 	 * Add a target to extract any nested jars we need to compile against
1457 	 * @param classpath
1458 	 * @param entry
1459 	 * @return a new classpath list containing the extracted locations
1460 	 */
generateExtractNestedJars(List<Object> classpath, CompiledEntry entry)1461 	private List<Object> generateExtractNestedJars(List<Object> classpath, CompiledEntry entry) {
1462 		script.printTargetDeclaration(entry.getName(false) + TARGET_NESTED_JARS, null, null, null, null);
1463 
1464 		if (classpath == null || classpath.size() == 0 || !(classpath.get(0) instanceof ClasspathElement)) {
1465 			script.printTargetEnd();
1466 			return classpath;
1467 		}
1468 
1469 		List<Object> extracted = new ArrayList<>(classpath.size());
1470 		for (Iterator<Object> iterator = classpath.iterator(); iterator.hasNext();) {
1471 			ClasspathElement element = (ClasspathElement) iterator.next();
1472 
1473 			if (element.getSubPath() == null)
1474 				extracted.add(element);
1475 			else {
1476 				String destPath = featureGenerator.getExtractedRoot(element);
1477 				String destDir = Utils.getPropertyFormat(PROPERTY_BUILD_DIRECTORY) + '/' + "nestedJars" + '/' + destPath.toString(); //$NON-NLS-1$
1478 				script.printMkdirTask(destDir);
1479 				script.printUnzipTask(element.getPath(), destDir, false, element.getSubPath(), null);
1480 				extracted.add(destDir + '/' + element.getSubPath());
1481 			}
1482 		}
1483 		script.printTargetEnd();
1484 
1485 		return extracted;
1486 	}
1487 
1488 	/**
1489 	 * Add the "jar" target to the given Ant script using the given classpath and
1490 	 * jar as parameters.
1491 	 *
1492 	 * @param classpath the classpath for the jar command
1493 	 * @param entry
1494 	 */
generateCompilationTarget(List<Object> classpath, CompiledEntry entry)1495 	private void generateCompilationTarget(List<Object> classpath, CompiledEntry entry) {
1496 		script.println();
1497 		String name = entry.getName(false);
1498 
1499 		//extract nested jars and update the classpath with the new locations
1500 		List<Object> extractedPath = generateExtractNestedJars(classpath, entry);
1501 
1502 		String depends = TARGET_INIT + "," + name + TARGET_NESTED_JARS; //$NON-NLS-1$
1503 		script.printTargetDeclaration(name, depends, null, entry.getName(true), NLS.bind(Messages.build_plugin_jar, model.getSymbolicName() + ' ' + name));
1504 		String destdir = (entry.getType() == CompiledEntry.FOLDER) ? getJARLocation(entry.getName(true)) : getTempJARFolderLocation(entry.getName(true));
1505 		script.printDeleteTask(destdir, null, null);
1506 		script.printMkdirTask(destdir);
1507 		script.printPathStructure("path", name + PROPERTY_CLASSPATH, extractedPath); //$NON-NLS-1$
1508 
1509 		String[] sources = entry.getSource();
1510 		Map<String, String> params = null, references = null;
1511 		if (customBuildCallbacks != null) {
1512 			params = new HashMap<>(2);
1513 			params.put(PROPERTY_TARGET_FOLDER, destdir);
1514 			for (int i = 1; i <= sources.length; i++) {
1515 				params.put(PROPERTY_SOURCE_FOLDER + i, sources[i - 1]);
1516 			}
1517 
1518 			references = new HashMap<>(1);
1519 			references.put(name + PROPERTY_CLASSPATH, null);
1520 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_PRE + name, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, references);
1521 		}
1522 
1523 		FileSet[] workspaceFiles = null;
1524 		String outputKey = name.equals(EXPANDED_DOT) ? DOT : name;
1525 		if (workspaceOutputFolders != null && workspaceOutputFolders.containsKey(outputKey)) {
1526 			// this is a no-op when using p2Gathering on folders GatherBundleTask will collect the class files from where they are.
1527 			// unless the class files are in a nested jar, or we are using custom callbacks, then we need to gather everything as before
1528 			boolean isFolder = (entry.getType() == CompiledEntry.FOLDER);
1529 			if (!BuildDirector.p2Gathering || !isFolder || customBuildCallbacks != null) {
1530 				Set<IPath> paths = workspaceOutputFolders.get(outputKey);
1531 				workspaceFiles = new FileSet[paths.size()];
1532 
1533 				int i = 0;
1534 				for (Iterator<IPath> iterator = paths.iterator(); iterator.hasNext();) {
1535 					IPath path = iterator.next();
1536 					workspaceFiles[i++] = new FileSet(Utils.getPropertyFormat(PROPERTY_BASEDIR) + "/" + path.toOSString(), null, null, null, "**/package.htm*", null, null); //$NON-NLS-1$ //$NON-NLS-2$
1537 				}
1538 
1539 				//if entry is a folder, copy over the class files, otherwise they will be jarred from where they are.
1540 				if (isFolder) {
1541 					script.printCopyTask(null, destdir, workspaceFiles, true, false);
1542 				}
1543 			}
1544 		} else {
1545 			script.printComment("compile the source code"); //$NON-NLS-1$
1546 			JavacTask javac = new JavacTask();
1547 			javac.setClasspathId(name + PROPERTY_CLASSPATH);
1548 			String[] executionEnvironments = model.getExecutionEnvironments();
1549 			boolean isModular = false;
1550 			// 1 execution env associated with the model
1551 			if (executionEnvironments.length == 1) {
1552 				String ee = executionEnvironments[0];
1553 				ProfileManager profileManager = null;
1554 				try {
1555 					profileManager = getSite(false).getRegistry().getProfileManager();
1556 				} catch (CoreException e) {
1557 					//nothing to do, will assume non-modular
1558 				}
1559 				String source = null;
1560 				if (profileManager != null)
1561 					source = profileManager.getJavacSource(ee);
1562 				int parseInt = -1;
1563 				try {
1564 					parseInt = Integer.parseInt(source);
1565 				} catch (NumberFormatException ne) {
1566 					//by default non-modular for 1.8 etc and below
1567 				}
1568 				if (parseInt >= 9)
1569 					isModular = true;
1570 			}
1571 			javac.setBootClasspath(isModular == true ? null : Utils.getPropertyFormat(PROPERTY_BUNDLE_BOOTCLASSPATH));
1572 			javac.setDestdir(destdir);
1573 			javac.setFailOnError(Utils.getPropertyFormat(PROPERTY_JAVAC_FAIL_ON_ERROR));
1574 			javac.setDebug(Utils.getPropertyFormat(PROPERTY_JAVAC_DEBUG_INFO));
1575 			javac.setVerbose(Utils.getPropertyFormat(PROPERTY_JAVAC_VERBOSE));
1576 			javac.setIncludeAntRuntime("no"); //$NON-NLS-1$
1577 			javac.setSource(Utils.getPropertyFormat(PROPERTY_BUNDLE_JAVAC_SOURCE));
1578 			javac.setTarget(Utils.getPropertyFormat(PROPERTY_BUNDLE_JAVAC_TARGET));
1579 			javac.setCompileArgs(Utils.getPropertyFormat(PROPERTY_JAVAC_COMPILERARG));
1580 			javac.setSrcdir(sources);
1581 			javac.setLogExtension(Utils.getPropertyFormat(PROPERTY_LOG_EXTENSION));
1582 			if (warningProperties != null)
1583 				javac.setWarningProperties(Utils.getPropertyFormat(PROPERTY_BASEDIR) + '/' + warningProperties);
1584 			if (generateErrorPropertyAttribute)
1585 				javac.setErrorProperty(PROPERTY_COMPILATION_ERROR);
1586 			generateCompilerSettings(javac, entry, classpath);
1587 
1588 			script.print(javac);
1589 		}
1590 
1591 		script.printAntCallTask(TARGET_CHECK_COMPILATION_RESULTS, true, null);
1592 
1593 		script.printComment("Copy necessary resources"); //$NON-NLS-1$
1594 		FileSet[] fileSets = new FileSet[sources.length];
1595 		for (int i = 0; i < sources.length; i++) {
1596 			String excludes = getFormattedSourceFileExtensions();
1597 			if (excludes.length() > 0) {
1598 				excludes += ", **/package.htm*"; //$NON-NLS-1$
1599 			} else {
1600 				excludes = "**/package.htm*"; //$NON-NLS-1$
1601 			}
1602 			String excludedFromJar = entry.getExcludedFromJar();
1603 			if (excludedFromJar != null)
1604 				excludes += ',' + excludedFromJar;
1605 
1606 			fileSets[i] = new FileSet(sources[i], null, null, null, excludes, null, null);
1607 		}
1608 
1609 		script.printCopyTask(null, destdir, fileSets, true, false);
1610 
1611 		if (customBuildCallbacks != null) {
1612 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_POST_COMPILE + name, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, references);
1613 		}
1614 
1615 		String jarLocation = getJARLocation(entry.getName(true));
1616 		if (entry.getType() != CompiledEntry.FOLDER) {
1617 			script.printMkdirTask(new Path(jarLocation).removeLastSegments(1).toString());
1618 			if (workspaceFiles != null)
1619 				script.printJarTask(jarLocation, destdir, workspaceFiles, getEmbeddedManifestFile(entry, destdir), null, "preserve"); //$NON-NLS-1$
1620 			else
1621 				script.printJarTask(jarLocation, destdir, getEmbeddedManifestFile(entry, destdir));
1622 			script.printDeleteTask(destdir, null, null);
1623 		}
1624 
1625 		if (customBuildCallbacks != null) {
1626 			params.clear();
1627 			params.put(PROPERTY_JAR_LOCATION, jarLocation);
1628 			script.printSubantTask(Utils.getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS), PROPERTY_POST + name, customCallbacksBuildpath, customCallbacksFailOnError, customCallbacksInheritAll, params, references);
1629 		}
1630 		script.printTargetEnd();
1631 	}
1632 
1633 	/*
1634 	 * The "errorProperty" attribute on the javac task requires ant 1.7.1 or greater
1635 	 */
shouldGenerateErrorAttribute()1636 	private boolean shouldGenerateErrorAttribute() {
1637 		//When exporting from the UI it is hard to know the ant version, for now don't generate the attribute
1638 		if (havePDEUIState())
1639 			return false;
1640 
1641 		//version string should look something like: "Apache Ant version 1.7.1 compiled on June 27 2008"
1642 		String versionString = getImmutableAntProperty(IBuildPropertiesConstants.PROPERTY_ANT_VERSION);
1643 		if (versionString != null) {
1644 			int idx = versionString.indexOf("version"); //$NON-NLS-1$
1645 			if (idx > 0) {
1646 				versionString = versionString.substring(idx + 7).trim();
1647 				idx = 0;
1648 				int segment = 0;
1649 				//try and be flexible, find the first 3 segments of numbers, stop at any other character
1650 				for (char c = versionString.charAt(idx); idx < versionString.length() && segment < 3; c = versionString.charAt(++idx)) {
1651 					if (c == '.')
1652 						segment++;
1653 					else if (!Character.isDigit(c))
1654 						break;
1655 				}
1656 				if (idx > 0) {
1657 					try {
1658 						Version antVersion = new Version(versionString.substring(0, idx));
1659 						if (antVersion.compareTo(new Version(1, 7, 1)) >= 0)
1660 							return true;
1661 
1662 						IStatus status = new Status(IStatus.WARNING, PI_PDEBUILD, WARNING_OLD_ANT, NLS.bind(Messages.warning_ant171Required, PROPERTY_P2_PUBLISHONERROR), null);
1663 						BundleHelper.getDefault().getLog().log(status);
1664 						return false;
1665 					} catch (IllegalArgumentException e) {
1666 						// shouldn't really happen, but catch just in case
1667 					}
1668 				}
1669 			}
1670 		}
1671 		//we don't know a version, assume someone knew what they were doing with their setup.
1672 		return true;
1673 	}
1674 
getEmbeddedManifestFile(CompiledEntry jarEntry, String destdir)1675 	private String getEmbeddedManifestFile(CompiledEntry jarEntry, String destdir) {
1676 		try {
1677 			String manifestName = getBuildProperties().getProperty(PROPERTY_MANIFEST_PREFIX + jarEntry.getName(true));
1678 			if (manifestName == null)
1679 				return null;
1680 			return destdir + '/' + manifestName;
1681 		} catch (CoreException e) {
1682 			return null;
1683 		}
1684 	}
1685 
1686 	/**
1687 	 *
1688 	 * @param properties
1689 	 * @return JAR[]
1690 	 */
extractEntriesToCompile(Properties properties)1691 	protected CompiledEntry[] extractEntriesToCompile(Properties properties) throws CoreException {
1692 		return extractEntriesToCompile(properties, model);
1693 	}
1694 
extractEntriesToCompile(Properties properties, BundleDescription model)1695 	public static CompiledEntry[] extractEntriesToCompile(Properties properties, BundleDescription model) throws CoreException {
1696 		List<CompiledEntry> result = new ArrayList<>(5);
1697 		int prefixLength = PROPERTY_SOURCE_PREFIX.length();
1698 		for (Iterator<Entry<Object, Object>> iterator = properties.entrySet().iterator(); iterator.hasNext();) {
1699 			Map.Entry<Object, Object> entry = iterator.next();
1700 			String key = (String) entry.getKey();
1701 			if (!(key.startsWith(PROPERTY_SOURCE_PREFIX)))
1702 				continue;
1703 			key = key.substring(prefixLength);
1704 			String[] source = Utils.getArrayFromString((String) entry.getValue());
1705 			if (source.length == 0) {
1706 				String message = NLS.bind(Messages.error_missingSourceFolder, model.getSymbolicName(), entry.getKey());
1707 				throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_GENERIC, message, null));
1708 			}
1709 			String[] output = Utils.getArrayFromString(properties.getProperty(PROPERTY_OUTPUT_PREFIX + key));
1710 			String[] extraClasspath = Utils.getArrayFromString(properties.getProperty(PROPERTY_EXTRAPATH_PREFIX + key));
1711 			String excludedFromJar = properties.getProperty(PROPERTY_EXCLUDE_PREFIX + key);
1712 			CompiledEntry newEntry = new CompiledEntry(key, source, output, extraClasspath, excludedFromJar, key.endsWith(PROPERTY_JAR_SUFFIX) ? CompiledEntry.JAR : CompiledEntry.FOLDER);
1713 			result.add(newEntry);
1714 		}
1715 		return result.toArray(new CompiledEntry[result.size()]);
1716 	}
1717 
1718 	/**
1719 	 * Add the "src" target to the given Ant script.
1720 	 *
1721 	 * @param jar
1722 	 */
generateSRCTarget(CompiledEntry jar)1723 	private void generateSRCTarget(CompiledEntry jar) {
1724 		script.println();
1725 		String name = jar.getName(false);
1726 		String srcName = getSRCName(name);
1727 		script.printTargetDeclaration(srcName, TARGET_INIT, null, srcName, null);
1728 		String[] sources = jar.getSource();
1729 		filterNonExistingSourceFolders(sources);
1730 		FileSet[] fileSets = new FileSet[sources.length];
1731 		int count = 0;
1732 		for (int i = 0; i < sources.length; i++) {
1733 			if (sources[i] != null)
1734 				fileSets[count++] = new FileSet(sources[i], null, getFormattedSourceFileExtensions(), null, null, null, null);
1735 		}
1736 
1737 		String srcLocation = getSRCLocation(name);
1738 		String srcParent = new Path(srcLocation).removeLastSegments(1).toString();
1739 		script.printMkdirTask(srcParent);
1740 		script.printAntCallTask("zip." + srcName, true, null); //$NON-NLS-1$
1741 		script.printTargetEnd();
1742 
1743 		script.printTargetDeclaration("zip." + srcName, null, null, null, null); //$NON-NLS-1$
1744 		if (count != 0)
1745 			script.printZipTask(srcLocation, null, false, false, fileSets);
1746 		script.printTargetEnd();
1747 
1748 		script.printTargetDeclaration("copy." + srcName, null, null, null, null); //$NON-NLS-1$
1749 		if (count != 0) {
1750 			String dest = null;
1751 			if (srcName.equals(SRC_ZIP))
1752 				dest = new Path(srcName).removeLastSegments(1).toString(); //src.zip can go in the root
1753 			else
1754 				dest = srcName.substring(0, srcName.length() - 4); //remove .zip, the rest go in folders
1755 			String toDir = Utils.getPropertyFormat(PROPERTY_SOURCE_DESTINATION_FOLDER) + '/' + dest;
1756 			script.printCopyTask(null, toDir, fileSets, true, true);
1757 		}
1758 		script.printTargetEnd();
1759 	}
1760 
1761 	/**
1762 	 * @return list of source extensions recognized by the bundle
1763 	 */
getFormattedSourceFileExtensions()1764 	private String getFormattedSourceFileExtensions() {
1765 		StringBuffer sb = new StringBuffer();
1766 		for (int i = 0; i < sourceFileExtensions.length; i++) {
1767 			if (i > 0) {
1768 				sb.append(", "); //$NON-NLS-1$
1769 			}
1770 			sb.append("**/").append(sourceFileExtensions[i]); //$NON-NLS-1$
1771 		}
1772 		return sb.toString();
1773 	}
1774 
filterNonExistingSourceFolders(String[] sources)1775 	private void filterNonExistingSourceFolders(String[] sources) {
1776 		File pluginRoot;
1777 		pluginRoot = new File(getLocation(model));
1778 		for (int i = 0; i < sources.length; i++) {
1779 			File file = new File(pluginRoot, sources[i]);
1780 			if (!file.exists()) {
1781 				sources[i] = null;
1782 				IStatus status = new Status(IStatus.WARNING, PI_PDEBUILD, EXCEPTION_SOURCE_LOCATION_MISSING, NLS.bind(Messages.warning_cannotLocateSource, file.getAbsolutePath()), null);
1783 				BundleHelper.getDefault().getLog().log(status);
1784 			}
1785 		}
1786 	}
1787 
1788 	/**
1789 	 * Return the name of the zip file for the source for the jar with
1790 	 * the given name.
1791 	 *
1792 	 * @param jarName the name of the jar file
1793 	 * @return String
1794 	 */
getSRCLocation(String jarName)1795 	protected String getSRCLocation(String jarName) {
1796 		return getJARLocation(getSRCName(jarName));
1797 	}
1798 
1799 	/**
1800 	 * Return the location for a temporary file for the jar file with
1801 	 * the given name.
1802 	 *
1803 	 * @param jarName the name of the jar file
1804 	 * @return String
1805 	 */
getTempJARFolderLocation(String jarName)1806 	protected String getTempJARFolderLocation(String jarName) {
1807 		IPath destination = new Path(Utils.getPropertyFormat(PROPERTY_TEMP_FOLDER));
1808 		destination = destination.append(jarName + ".bin"); //$NON-NLS-1$
1809 		return destination.toString();
1810 	}
1811 
1812 	/**
1813 	 * Return the full location of the jar file.
1814 	 *
1815 	 * @param jarName the name of the jar file
1816 	 * @return String
1817 	 */
getJARLocation(String jarName)1818 	protected String getJARLocation(String jarName) {
1819 		return new Path(Utils.getPropertyFormat(PROPERTY_BUILD_RESULT_FOLDER)).append(jarName).toString();
1820 	}
1821 
getClasspathEntries(BundleDescription lookedUpModel)1822 	protected String[] getClasspathEntries(BundleDescription lookedUpModel) throws CoreException {
1823 		return getSite(false).getRegistry().getExtraData().get(Long.valueOf(lookedUpModel.getBundleId()));
1824 	}
1825 
1826 	@Override
getBuildProperties()1827 	protected Properties getBuildProperties() throws CoreException {
1828 		if (buildProperties == null)
1829 			return buildProperties = readProperties(model.getLocation(), propertiesFileName, isIgnoreMissingPropertiesFile() ? IStatus.OK : IStatus.WARNING);
1830 
1831 		return buildProperties;
1832 	}
1833 
1834 	/**
1835 	 * Return the name of the zip file for the source from the given jar name.
1836 	 *
1837 	 * @param jarName the name of the jar file
1838 	 * @return String
1839 	 */
getSRCName(String jarName)1840 	public static String getSRCName(String jarName) {
1841 		if (jarName.endsWith(".jar")) { //$NON-NLS-1$
1842 			return jarName.substring(0, jarName.length() - 4) + SRC_ZIP;
1843 		}
1844 		if (jarName.equals(EXPANDED_DOT) || jarName.equals(DOT))
1845 			return SRC_ZIP;
1846 		return jarName.replace('/', '.') + SRC_ZIP;
1847 	}
1848 
1849 	/**
1850 	 * If the model defines its own custom script, we do not generate a new one
1851 	 * but we do try to update the version number.
1852 	 */
updateExistingScript()1853 	private void updateExistingScript() throws CoreException {
1854 		String root = getLocation(model);
1855 		File buildFile = new File(root, buildScriptFileName);
1856 		if (!buildFile.exists()) {
1857 			String message = NLS.bind(Messages.error_missingCustomBuildFile, buildFile);
1858 			throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_WRITING_SCRIPT, message, null));
1859 		}
1860 		try {
1861 			Utils.updateVersion(buildFile, PROPERTY_VERSION_SUFFIX, model.getVersion().toString());
1862 		} catch (IOException e) {
1863 			String message = NLS.bind(Messages.exception_writeScript, buildFile);
1864 			throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_WRITING_SCRIPT, message, e));
1865 		}
1866 		return;
1867 	}
1868 
1869 	/**
1870 	 * Substitute the value of an element description variable (variables that
1871 	 * are found in files like plugin.xml, e.g. $ws$) by an Ant property.
1872 	 *
1873 	 * @param sourceString
1874 	 * @return String
1875 	 */
replaceVariables(String sourceString, boolean compiledElement)1876 	static protected String replaceVariables(String sourceString, boolean compiledElement) {
1877 		if (sourceString == null)
1878 			return null;
1879 
1880 		int i = -1;
1881 		String result = sourceString;
1882 		while ((i = result.indexOf(DESCRIPTION_VARIABLE_WS)) >= 0)
1883 			result = result.substring(0, i) + "ws/" + Utils.getPropertyFormat(compiledElement ? PROPERTY_WS : PROPERTY_BASE_WS) + result.substring(i + DESCRIPTION_VARIABLE_WS.length()); //$NON-NLS-1$
1884 		while ((i = result.indexOf(DESCRIPTION_VARIABLE_OS)) >= 0)
1885 			result = result.substring(0, i) + "os/" + Utils.getPropertyFormat(compiledElement ? PROPERTY_OS : PROPERTY_BASE_OS) + result.substring(i + DESCRIPTION_VARIABLE_OS.length()); //$NON-NLS-1$
1886 		while ((i = result.indexOf(DESCRIPTION_VARIABLE_ARCH)) >= 0)
1887 			result = result.substring(0, i) + "arch/" + Utils.getPropertyFormat(compiledElement ? PROPERTY_ARCH : PROPERTY_BASE_ARCH) + result.substring(i + DESCRIPTION_VARIABLE_OS.length()); //$NON-NLS-1$
1888 		while ((i = result.indexOf(DESCRIPTION_VARIABLE_NL)) >= 0)
1889 			result = result.substring(0, i) + "nl/" + Utils.getPropertyFormat(compiledElement ? PROPERTY_NL : PROPERTY_BASE_NL) + result.substring(i + DESCRIPTION_VARIABLE_NL.length()); //$NON-NLS-1$
1890 		return result;
1891 	}
1892 
getModel()1893 	public BundleDescription getModel() {
1894 		return model;
1895 	}
1896 
getPropertiesFileName()1897 	public String getPropertiesFileName() {
1898 		return propertiesFileName;
1899 	}
1900 
setPropertiesFileName(String propertyFileName)1901 	public void setPropertiesFileName(String propertyFileName) {
1902 		this.propertiesFileName = propertyFileName;
1903 	}
1904 
getBuildScriptFileName()1905 	public String getBuildScriptFileName() {
1906 		return buildScriptFileName;
1907 	}
1908 
setBuildScriptFileName(String buildScriptFileName)1909 	public void setBuildScriptFileName(String buildScriptFileName) {
1910 		this.buildScriptFileName = buildScriptFileName;
1911 	}
1912 
1913 	/**
1914 	 * Sets whether or not to sign any constructed jars.
1915 	 *
1916 	 * @param value whether or not to sign any constructed JARs
1917 	 */
setSignJars(boolean value)1918 	public void setSignJars(boolean value) {
1919 		signJars = value;
1920 	}
1921 
1922 	/**
1923 	 * Returns the model object which is associated with the given identifier.
1924 	 * Returns <code>null</code> if the model object cannot be found.
1925 	 *
1926 	 * @param modelId the identifier of the model object to lookup
1927 	 * @return the model object or <code>null</code>
1928 	 */
getModel(String modelId, String modelVersion)1929 	protected BundleDescription getModel(String modelId, String modelVersion) throws CoreException {
1930 		if (modelVersion == null)
1931 			return getSite(false).getRegistry().getResolvedBundle(modelId);
1932 		return getSite(false).getRegistry().getResolvedBundle(modelId, modelVersion);
1933 	}
1934 
getAssociatedEntry()1935 	public FeatureEntry getAssociatedEntry() {
1936 		return associatedEntry;
1937 	}
1938 
setAssociatedEntry(FeatureEntry associatedEntry)1939 	public void setAssociatedEntry(FeatureEntry associatedEntry) {
1940 		this.associatedEntry = associatedEntry;
1941 	}
1942 
setWorkspaceOutputFolders(Map<String, Set<IPath>> folders)1943 	protected void setWorkspaceOutputFolders(Map<String, Set<IPath>> folders) {
1944 		this.workspaceOutputFolders = folders;
1945 	}
1946 
setGenerateSourceReferences(boolean sourceReferences)1947 	public void setGenerateSourceReferences(boolean sourceReferences) {
1948 		this.sourceReferences = sourceReferences;
1949 	}
1950 }
1951