1 /*******************************************************************************
2  * Copyright (c) 2009, 2017 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *     Compuware Corporation - Sebastien Angers <sebastien.angers@compuware.com>
14  *     		- Enabled additional mirror slicingOptions in Headless PDE Build
15  *     		- Enabled 'raw' attribute for mirror step in Headless PDE Build
16  *     		- https://bugs.eclipse.org/338878
17  *******************************************************************************/
18 
19 package org.eclipse.pde.internal.build;
20 
21 import java.io.*;
22 import java.net.URI;
23 import java.util.*;
24 import org.eclipse.core.runtime.*;
25 import org.eclipse.equinox.internal.p2.publisher.eclipse.ProductFile;
26 import org.eclipse.osgi.service.resolver.BundleDescription;
27 import org.eclipse.osgi.service.resolver.VersionRange;
28 import org.eclipse.pde.internal.build.ant.FileSet;
29 import org.eclipse.pde.internal.build.builder.BuildDirector;
30 import org.eclipse.pde.internal.build.builder.ModelBuildScriptGenerator;
31 import org.eclipse.pde.internal.build.site.BuildTimeFeature;
32 import org.osgi.framework.Version;
33 
34 public class P2ConfigScriptGenerator extends AssembleConfigScriptGenerator {
35 	private static final VersionRange OLD_EXECUTABLE_RANGE = new VersionRange(Version.emptyVersion, true, new Version(3, 3, 200, "v20090306-1900"), false); //$NON-NLS-1$
36 	private AssemblyInformation assemblyInformation = null;
37 	private boolean assembling = false;
38 	private boolean versionsList = false;
39 
P2ConfigScriptGenerator(AssemblyInformation assemblyInformation, boolean assembling)40 	public P2ConfigScriptGenerator(AssemblyInformation assemblyInformation, boolean assembling) {
41 		this.assemblyInformation = assemblyInformation;
42 		this.assembling = assembling;
43 	}
44 
initialize(String directoryName, String feature)45 	public void initialize(String directoryName, String feature) {
46 		this.directory = directoryName;
47 		this.featureId = feature;
48 	}
49 
50 	@Override
generate()51 	public void generate() {
52 		initializeCollections();
53 
54 		try {
55 			String prefix = assembling ? "assemble." : "package."; //$NON-NLS-1$ //$NON-NLS-2$
56 			openScript(directory, prefix + featureId + ".p2.xml"); //$NON-NLS-1$
57 		} catch (CoreException e) {
58 			return;
59 		}
60 		generatePrologue();
61 		generateMainBegin();
62 		generateGatherCalls();
63 		generateMetadataCalls();
64 		generateMainEnd();
65 
66 		generateGatherBinPartsTarget();
67 		generateCustomAssemblyTarget();
68 		generateSigningTarget();
69 		generateMetadataTarget();
70 		generateEpilogue();
71 		closeScript();
72 	}
73 
initializeCollections()74 	protected void initializeCollections() {
75 		Collection<Object> p = new LinkedHashSet<>();
76 		Collection<Object> f = new LinkedHashSet<>();
77 		Collection<BuildTimeFeature> r = new LinkedHashSet<>();
78 		for (Iterator<Config> iterator = getConfigInfos().iterator(); iterator.hasNext();) {
79 			Config config = iterator.next();
80 			p.addAll(assemblyInformation.getPlugins(config));
81 			f.addAll(assemblyInformation.getFeatures(config));
82 			r.addAll(assemblyInformation.getRootFileProviders(config));
83 		}
84 
85 		this.plugins = p.toArray(new BundleDescription[p.size()]);
86 		this.features = f.toArray(new BuildTimeFeature[f.size()]);
87 		this.rootFileProviders = r;
88 	}
89 
90 	@Override
generatePrologue()91 	protected void generatePrologue() {
92 		script.printProjectDeclaration("Publish p2 metadata", TARGET_MAIN, null); //$NON-NLS-1$
93 		ProductFile product = getProductFile();
94 		if (product != null) {
95 			String launcherName = product.getLauncherName() != null ? product.getLauncherName() : "eclipse"; //$NON-NLS-1$
96 			script.printProperty(PROPERTY_LAUNCHER_NAME, launcherName);
97 			script.printProperty(PROPERTY_LAUNCHER_PROVIDER, FEATURE_EQUINOX_EXECUTABLE);
98 		}
99 		script.printProperty(PROPERTY_P2_BUILD_REPO, "file:" + Utils.getPropertyFormat(PROPERTY_BUILD_DIRECTORY) + "/buildRepo"); //$NON-NLS-1$ //$NON-NLS-2$
100 		script.printProperty(PROPERTY_ASSEMBLY_TMP, Utils.getPropertyFormat(PROPERTY_BUILD_DIRECTORY) + "/tmp"); //$NON-NLS-1$
101 		script.printProperty(PROPERTY_SIGN, (signJars ? Boolean.TRUE : Boolean.FALSE).toString());
102 		script.printAvailableTask(PROPERTY_CUSTOM_ASSEMBLY, "${builder}/customAssembly.xml", "${builder}/customAssembly.xml"); //$NON-NLS-1$ //$NON-NLS-2$
103 
104 		if (productQualifier != null)
105 			script.printProperty(PROPERTY_P2_PRODUCT_QUALIFIER, productQualifier);
106 
107 		script.printProperty(PROPERTY_P2_MIRROR_RAW, FALSE);
108 		script.printProperty(PROPERTY_P2_MIRROR_SLICING_FILTER, ""); //$NON-NLS-1$
109 		script.printProperty(PROPERTY_P2_MIRROR_SLICING_FOLLOW_ONLY_FILTERED_REQS, FALSE);
110 		script.printProperty(PROPERTY_P2_MIRROR_SLICING_FOLLOW_STRICT, FALSE);
111 		script.printProperty(PROPERTY_P2_MIRROR_SLICING_INCLUDE_FEATURES, TRUE);
112 		script.printProperty(PROPERTY_P2_MIRROR_SLICING_INCLUDE_NON_GREEDY, FALSE);
113 		script.printProperty(PROPERTY_P2_MIRROR_SLICING_INCLUDE_OPTIONAL, havePDEUIState() ? FALSE : TRUE);
114 		script.printProperty(PROPERTY_P2_MIRROR_SLICING_LATEST_VERSION_ONLY, FALSE);
115 		script.printProperty(PROPERTY_P2_MIRROR_SLICING_PLATFORM_FILTER, ""); //$NON-NLS-1$
116 
117 		script.println();
118 		generateCustomGatherMacro();
119 	}
120 
121 	@Override
generateMainEnd()122 	protected void generateMainEnd() {
123 		script.printTargetEnd();
124 		script.println();
125 	}
126 
generateMetadataCalls()127 	protected void generateMetadataCalls() {
128 		script.printAntCallTask(TARGET_P2_METADATA, true, null);
129 	}
130 
131 	@Override
generateGatherCalls()132 	protected void generateGatherCalls() {
133 		super.generateGatherCalls();
134 
135 		if (signJars)
136 			script.printAntCallTask(TARGET_P2_SIGN_REPO, true, null);
137 		script.println();
138 	}
139 
140 	@Override
generateBrandingCalls()141 	protected void generateBrandingCalls() {
142 		ProductFile product = getProductFile();
143 		if (product != null) {
144 			List<Config> configs = getConfigInfos();
145 			for (Iterator<Config> iterator = configs.iterator(); iterator.hasNext();) {
146 				Config config = iterator.next();
147 				if (Config.genericConfig().equals(config))
148 					continue;
149 				script.printTab();
150 				script.print("<eclipse.brand.p2.artifacts "); //$NON-NLS-1$
151 				script.printAttribute("launcherName", Utils.getPropertyFormat(PROPERTY_LAUNCHER_NAME), true); //$NON-NLS-1$
152 				script.printAttribute("config", config.toString("."), true); //$NON-NLS-1$ //$NON-NLS-2$
153 				script.printAttribute("iconsList", computeIconsList(config.getOs()), true); //$NON-NLS-1$
154 				script.printAttribute("launcherProvider", Utils.getPropertyFormat(PROPERTY_LAUNCHER_PROVIDER), true); //$NON-NLS-1$
155 				script.printAttribute("productId", product.getId(), true); //$NON-NLS-1$
156 				script.printAttribute("productVersion", getReplacedProductVersion(), true); //$NON-NLS-1$
157 				script.printAttribute("repository", Utils.getPropertyFormat(PROPERTY_P2_BUILD_REPO), true); //$NON-NLS-1$
158 				script.printAttribute("tempDirectory", Utils.getPropertyFormat(PROPERTY_ASSEMBLY_TMP), true); //$NON-NLS-1$
159 				script.println("/>"); //$NON-NLS-1$
160 			}
161 		}
162 		script.printDeleteTask(Utils.getPropertyFormat(PROPERTY_ASSEMBLY_TMP) + "/p2.branding", null, null); //$NON-NLS-1$
163 		script.println();
164 	}
165 
generateSigningTarget()166 	protected void generateSigningTarget() {
167 		script.printTargetDeclaration(TARGET_P2_SIGN_REPO, null, null, null, null);
168 		if (signJars && plugins.length + features.length > 0) {
169 			script.printTab();
170 			script.print("<p2.process.artifacts"); //$NON-NLS-1$
171 			script.printAttribute("repositoryPath", Utils.getPropertyFormat(PROPERTY_P2_BUILD_REPO), true); //$NON-NLS-1$
172 			script.println(">"); //$NON-NLS-1$
173 			script.printTab();
174 			script.print("\t<sign"); //$NON-NLS-1$
175 			script.printAttribute("keystore", Utils.getPropertyFormat(PROPERTY_SIGN_KEYSTORE), true); //$NON-NLS-1$
176 			script.printAttribute("storepass", Utils.getPropertyFormat(PROPERTY_SIGN_STOREPASS), true); //$NON-NLS-1$
177 			script.printAttribute("keypass", Utils.getPropertyFormat(PROPERTY_SIGN_KEYPASS), true); //$NON-NLS-1$
178 			script.printAttribute("alias", Utils.getPropertyFormat(PROPERTY_SIGN_ALIAS), true); //$NON-NLS-1$
179 			script.printAttribute("unsign", Utils.getPropertyFormat(PROPERTY_UNSIGN), true); //$NON-NLS-1$
180 			script.print(" />\n"); //$NON-NLS-1$
181 			for (int i = 0; i < plugins.length; i++) {
182 				script.printTab();
183 				script.print("\t<plugin"); //$NON-NLS-1$
184 				script.printAttribute("id", plugins[i].getSymbolicName(), true); //$NON-NLS-1$
185 				script.printAttribute("version", plugins[i].getVersion().toString(), true); //$NON-NLS-1$
186 				script.print(" /> \n"); //$NON-NLS-1$
187 			}
188 			for (int i = 0; i < features.length; i++) {
189 				script.printTab();
190 				script.print("\t<feature"); //$NON-NLS-1$
191 				script.printAttribute("id", features[i].getId(), true); //$NON-NLS-1$
192 				script.printAttribute("version", features[i].getVersion(), true); //$NON-NLS-1$
193 				script.print(" />\n"); //$NON-NLS-1$
194 			}
195 			script.println("</p2.process.artifacts>"); //$NON-NLS-1$
196 		}
197 		script.printTargetEnd();
198 		script.println();
199 	}
200 
generateMetadataTarget()201 	protected void generateMetadataTarget() {
202 		script.printTargetDeclaration(TARGET_P2_METADATA, null, null, null, null);
203 		script.printProperty(PROPERTY_P2_FLAVOR, "tooling"); //$NON-NLS-1$
204 		generateBrandingCalls();
205 
206 		ProductFile product = getProductFile();
207 		if (product != null) {
208 
209 			String productDir = getWorkingDirectory() + '/' + DEFAULT_FEATURE_LOCATION + '/' + CONTAINER_FEATURE + "/product"; //$NON-NLS-1$
210 			File productFile = product.getLocation();
211 			String newProduct = new File(productDir, productFile.getName()).getAbsolutePath();
212 			script.printCopyFileTask(productFile.getPath(), newProduct, true);
213 
214 			if (!generateProductP2Inf(productFile, productDir)) {
215 				//if we didn't generate the file, copy over the provided one
216 				File parent = productFile.getParentFile();
217 				File p2Inf = new File(parent, "p2.inf"); //$NON-NLS-1$
218 				if (p2Inf.exists())
219 					script.printCopyTask(p2Inf.getAbsolutePath(), productDir, null, false, true);
220 			}
221 
222 			script.printTab();
223 			script.print("<replace "); //$NON-NLS-1$
224 			script.printAttribute("file", new File(productDir, "p2.inf").getAbsolutePath(), true); //$NON-NLS-1$ //$NON-NLS-2$
225 			script.printAttribute("token", "@FLAVOR@", true); //$NON-NLS-1$ //$NON-NLS-2$
226 			script.printAttribute("value", Utils.getPropertyFormat(PROPERTY_P2_FLAVOR), true); //$NON-NLS-1$
227 			script.println("/>"); //$NON-NLS-1$
228 			generateCopyConfigs(product, productDir);
229 			generateProductReplaceTask(product, newProduct, assemblyInformation);
230 
231 			script.printTab();
232 			script.print("<p2.publish.product"); //$NON-NLS-1$
233 			script.printAttribute("flavor", Utils.getPropertyFormat(PROPERTY_P2_FLAVOR), true); //$NON-NLS-1$
234 			script.printAttribute("repository", Utils.getPropertyFormat(PROPERTY_P2_BUILD_REPO), true); //$NON-NLS-1$
235 			script.printAttribute("productFile", newProduct, true); //$NON-NLS-1$
236 			script.println(">"); //$NON-NLS-1$
237 
238 			URI[] metadata = getContextMetadata();
239 			URI[] artifacts = getContextArtifacts();
240 			for (int i = 0; metadata != null && i < metadata.length; i++) {
241 				script.printTab();
242 				script.print("\t<contextRepository"); //$NON-NLS-1$
243 				script.printAttribute("location", URIUtil.toUnencodedString(metadata[i]), true); //$NON-NLS-1$
244 				script.printAttribute("metadata", TRUE, true); //$NON-NLS-1$
245 				script.println("/>"); //$NON-NLS-1$
246 			}
247 			for (int i = 0; artifacts != null && i < artifacts.length; i++) {
248 				script.printTab();
249 				script.print("\t<contextRepository"); //$NON-NLS-1$
250 				script.printAttribute("location", URIUtil.toUnencodedString(artifacts[i]), true); //$NON-NLS-1$
251 				script.printAttribute("artifact", TRUE, true); //$NON-NLS-1$
252 				script.println("/>"); //$NON-NLS-1$
253 			}
254 
255 			for (Iterator<Config> iterator = getConfigInfos().iterator(); iterator.hasNext();) {
256 				Config config = iterator.next();
257 				if (Config.genericConfig().equals(config))
258 					continue;
259 
260 				script.printTab();
261 				script.print("\t<config"); //$NON-NLS-1$
262 				script.printAttribute("os", config.getOs(), true); //$NON-NLS-1$
263 				script.printAttribute("ws", config.getWs(), true); //$NON-NLS-1$
264 				script.printAttribute("arch", config.getArch(), true); //$NON-NLS-1$
265 				script.println("/>"); //$NON-NLS-1$
266 			}
267 			if (versionsList) {
268 				script.printTab();
269 				script.print("\t<advice"); //$NON-NLS-1$
270 				script.printAttribute("kind", "featureVersions", true); //$NON-NLS-1$ //$NON-NLS-2$
271 				script.printAttribute("file", getWorkingDirectory() + '/' + DEFAULT_FEATURE_VERSION_FILENAME_PREFIX + PROPERTIES_FILE_SUFFIX, true); //$NON-NLS-1$
272 				script.println("/>"); //$NON-NLS-1$
273 				script.printTab();
274 				script.print("\t<advice"); //$NON-NLS-1$
275 				script.printAttribute("kind", "pluginVersions", true); //$NON-NLS-1$ //$NON-NLS-2$
276 				script.printAttribute("file", getWorkingDirectory() + '/' + DEFAULT_PLUGIN_VERSION_FILENAME_PREFIX + PROPERTIES_FILE_SUFFIX, true); //$NON-NLS-1$
277 				script.println("/>"); //$NON-NLS-1$
278 			}
279 			script.println("</p2.publish.product>"); //$NON-NLS-1$
280 		}
281 
282 		script.println();
283 		generateSynchContext();
284 		script.printTargetEnd();
285 	}
286 
generateCopyConfigs(ProductFile product, String productDir)287 	protected void generateCopyConfigs(ProductFile product, String productDir) {
288 		if (!product.haveCustomConfig())
289 			return;
290 		for (Iterator<Config> iterator = getConfigInfos().iterator(); iterator.hasNext();) {
291 			Config config = iterator.next();
292 			String entry = product.getConfigIniPath(config.getOs());
293 			if (entry == null)
294 				continue;
295 			File entryFile = new File(entry);
296 			if (entryFile.exists() && entryFile.isAbsolute())
297 				continue;
298 			String path = findConfigFile(product, config.getOs());
299 			if (path != null) {
300 				//non-null path exists, but isn't necessarily absolute
301 				File configFile = new File(path);
302 				script.printCopyFileTask(configFile.getAbsolutePath(), productDir + '/' + entry, true);
303 			}
304 		}
305 	}
306 
generateSynchContext()307 	protected void generateSynchContext() {
308 		ProductFile product = getProductFile();
309 		ArrayList<BuildTimeFeature> binaryFeatures = null;
310 		if (product == null) {
311 			binaryFeatures = new ArrayList<>();
312 			for (int i = 0; i < features.length; i++) {
313 				BuildTimeFeature feature = features[i];
314 				if (feature.isBinary())
315 					binaryFeatures.add(feature);
316 			}
317 		}
318 
319 		if (product == null && (binaryFeatures == null || binaryFeatures.size() == 0))
320 			return;
321 
322 		Map<String, String> args = new HashMap<>();
323 		// note that if the raw attribute (p2.mirror.raw) has not been set in the build.properties, then the default was set in #generatePrologue()
324 		args.put("raw", Utils.getPropertyFormat(PROPERTY_P2_MIRROR_RAW)); //$NON-NLS-1$
325 		script.printStartTag("p2.mirror", args); //$NON-NLS-1$
326 
327 		script.printTab();
328 		// note that if a slicingOption has not been set in the build.properties, then the default was set in #generatePrologue()
329 		script.print("\t<slicingOptions"); //$NON-NLS-1$
330 		script.printAttribute("includeNonGreedy", Utils.getPropertyFormat(PROPERTY_P2_MIRROR_SLICING_INCLUDE_NON_GREEDY), true); //$NON-NLS-1$
331 		script.printAttribute("filter", Utils.getPropertyFormat(PROPERTY_P2_MIRROR_SLICING_FILTER), true); //$NON-NLS-1$
332 		script.printAttribute("followOnlyFilteredRequirements", Utils.getPropertyFormat(PROPERTY_P2_MIRROR_SLICING_FOLLOW_ONLY_FILTERED_REQS), true); //$NON-NLS-1$
333 		script.printAttribute("followStrict", Utils.getPropertyFormat(PROPERTY_P2_MIRROR_SLICING_FOLLOW_STRICT), true); //$NON-NLS-1$
334 		script.printAttribute("includeFeatures", Utils.getPropertyFormat(PROPERTY_P2_MIRROR_SLICING_INCLUDE_FEATURES), true); //$NON-NLS-1$
335 		script.printAttribute("includeOptional", Utils.getPropertyFormat(PROPERTY_P2_MIRROR_SLICING_INCLUDE_OPTIONAL), true); //$NON-NLS-1$
336 		script.printAttribute("latestVersionOnly", Utils.getPropertyFormat(PROPERTY_P2_MIRROR_SLICING_LATEST_VERSION_ONLY), true); //$NON-NLS-1$
337 		script.printAttribute("platformFilter", Utils.getPropertyFormat(PROPERTY_P2_MIRROR_SLICING_PLATFORM_FILTER), true); //$NON-NLS-1$
338 		script.println("/>"); //$NON-NLS-1$
339 
340 		script.printTab();
341 		script.print("\t<source"); //$NON-NLS-1$
342 		script.printAttribute("location", Utils.getPropertyFormat(PROPERTY_P2_BUILD_REPO), true); //$NON-NLS-1$
343 		script.println("/>"); //$NON-NLS-1$
344 
345 		URI[] context = getContextMetadata();
346 		for (int i = 0; context != null && i < context.length; i++) {
347 			script.printTab();
348 			script.print("\t<source"); //$NON-NLS-1$
349 			script.printAttribute("location", URIUtil.toUnencodedString(context[i]), true); //$NON-NLS-1$
350 			script.printAttribute("optional", TRUE, true); //$NON-NLS-1$
351 			script.printAttribute("kind", "metadata", true); //$NON-NLS-1$ //$NON-NLS-2$
352 			script.println("/>"); //$NON-NLS-1$
353 		}
354 		URI[] artifacts = getContextArtifacts();
355 		for (int i = 0; artifacts != null && i < artifacts.length; i++) {
356 			script.printTab();
357 			script.print("\t<source"); //$NON-NLS-1$
358 			script.printAttribute("location", URIUtil.toUnencodedString(artifacts[i]), true); //$NON-NLS-1$
359 			script.printAttribute("optional", TRUE, true); //$NON-NLS-1$
360 			script.printAttribute("kind", "artifact", true); //$NON-NLS-1$ //$NON-NLS-2$
361 			script.println("/>"); //$NON-NLS-1$
362 		}
363 
364 		script.printTab();
365 		script.print("\t<destination "); //$NON-NLS-1$
366 		script.printAttribute("location", Utils.getPropertyFormat(PROPERTY_P2_BUILD_REPO), true); //$NON-NLS-1$
367 		script.printAttribute("kind", "metadata", true); //$NON-NLS-1$ //$NON-NLS-2$
368 		script.println("/>"); //$NON-NLS-1$
369 		script.print("\t<destination "); //$NON-NLS-1$
370 		script.printAttribute("location", Utils.getPropertyFormat(PROPERTY_P2_BUILD_REPO), true); //$NON-NLS-1$
371 		script.printAttribute("kind", "artifact", true); //$NON-NLS-1$ //$NON-NLS-2$
372 		script.println("/>"); //$NON-NLS-1$
373 		script.printTab();
374 
375 		if (product != null) {
376 			String version = product.getVersion();
377 			if (version.endsWith(PROPERTY_QUALIFIER)) {
378 				Version oldVersion = new Version(version);
379 				version = oldVersion.getMajor() + "." + oldVersion.getMinor() + "." + oldVersion.getMicro() + "." + Utils.getPropertyFormat(PROPERTY_P2_PRODUCT_QUALIFIER); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
380 			}
381 			script.print("\t<iu"); //$NON-NLS-1$
382 			script.printAttribute(ID, product.getId(), true);
383 			script.printAttribute(VERSION, version, true);
384 			script.println("/>"); //$NON-NLS-1$
385 		} else {
386 			for (int i = 0; i < features.length; i++) {
387 				BuildTimeFeature feature = features[i];
388 				if (feature.isBinary()) {
389 					binaryFeatures.add(feature);
390 					script.print("\t<iu"); //$NON-NLS-1$
391 					script.printAttribute(ID, getFeatureGroupId(feature), true);
392 					script.printAttribute(VERSION, feature.getVersion(), true);
393 					script.println("/>"); //$NON-NLS-1$
394 				}
395 			}
396 		}
397 		script.printEndTag("p2.mirror"); //$NON-NLS-1$
398 	}
399 
generateProductP2Inf(File productFile, String root)400 	private boolean generateProductP2Inf(File productFile, String root) {
401 		ProductGenerator generator = new ProductGenerator();
402 		generator.setProduct(productFile.getAbsolutePath());
403 		generator.setBuildSiteFactory(siteFactory);
404 		generator.setRoot(root);
405 		generator.setWorkingDirectory(getWorkingDirectory());
406 		generator.setAssemblyInfo(assemblyInformation);
407 		generator.setFeatureId(featureId);
408 		try {
409 			return generator.generateP2Info();
410 		} catch (CoreException e) {
411 			//problem with the .product file
412 			return false;
413 		}
414 	}
415 
generateEpilogue()416 	protected void generateEpilogue() {
417 		script.printProjectEnd();
418 	}
419 
420 	@Override
generateCustomGatherMacro()421 	protected void generateCustomGatherMacro() {
422 		List<String> attributes = new ArrayList<>(5);
423 		attributes.add("dir"); //$NON-NLS-1$
424 		attributes.add("propertyName"); //$NON-NLS-1$
425 		attributes.add("propertyValue"); //$NON-NLS-1$
426 		attributes.add("subFolder"); //$NON-NLS-1$
427 		attributes.add(PROPERTY_PROJECT_NAME);
428 		script.printMacroDef(PROPERTY_CUSTOM_GATHER, attributes);
429 
430 		Map<String, String> params = new HashMap<>();
431 		params.put("@{propertyName}", "@{propertyValue}"); //$NON-NLS-1$//$NON-NLS-2$
432 		script.printAntTask(DEFAULT_BUILD_SCRIPT_FILENAME, "@{dir}", TARGET_PUBLISH_BIN_PARTS, null, null, params); //$NON-NLS-1$
433 
434 		params.put(PROPERTY_PROJECT_LOCATION, "${basedir}/@{dir}"); //$NON-NLS-1$
435 		params.put(PROPERTY_PROJECT_NAME, "@{projectName}"); //$NON-NLS-1$
436 		params.put(PROPERTY_TARGET_FOLDER, "@{propertyValue}@{subFolder}"); //$NON-NLS-1$
437 		printCustomAssemblyAntCall(TARGET_GATHER_BIN_PARTS, params);
438 
439 		script.printEndMacroDef();
440 		script.println();
441 	}
442 
443 	@Override
generateGatherBinPartsTarget()444 	protected void generateGatherBinPartsTarget() {
445 		BuildTimeFeature oldExecutableFeature = null;
446 		ArrayList<FileSet> binaryFeatures = new ArrayList<>();
447 		ArrayList<FileSet> binaryBundles = new ArrayList<>();
448 		script.printTargetDeclaration(TARGET_GATHER_BIN_PARTS, null, null, null, null);
449 		for (int i = 0; i < plugins.length; i++) {
450 			BundleDescription plugin = plugins[i];
451 			Path pluginLocation = new Path(plugin.getLocation());
452 			if (Utils.isBinary(plugin))
453 				binaryBundles.add(new FileSet(pluginLocation.removeLastSegments(1).toOSString(), null, pluginLocation.lastSegment(), null, null, null, null));
454 			else
455 				printCustomGatherCall(ModelBuildScriptGenerator.getNormalizedName(plugin), Utils.makeRelative(pluginLocation, new Path(workingDirectory)).toOSString(), PROPERTY_DESTINATION_TEMP_FOLDER, Utils.getPropertyFormat(PROPERTY_ECLIPSE_PLUGINS), null);
456 		}
457 
458 		Set<BuildTimeFeature> featureSet = BuildDirector.p2Gathering ? new HashSet<>() : null;
459 		for (int i = 0; i < features.length; i++) {
460 			BuildTimeFeature feature = features[i];
461 			IPath featureLocation = new Path(feature.getRootLocation());
462 			if (feature.isBinary()) {
463 				binaryFeatures.add(new FileSet(featureLocation.removeLastSegments(1).toOSString(), null, featureLocation.lastSegment(), null, null, null, null));
464 			} else {
465 				String featureFullName = feature.getId() + "_" + feature.getVersion(); //$NON-NLS-1$
466 				printCustomGatherCall(featureFullName, Utils.makeRelative(featureLocation, new Path(workingDirectory)).toOSString(), PROPERTY_FEATURE_BASE, Utils.getPropertyFormat(PROPERTY_ECLIPSE_BASE), '/' + DEFAULT_FEATURE_LOCATION);
467 				featureSet.add(feature);
468 			}
469 		}
470 
471 		//This will generate gather.bin.parts call to features that provides files for the root
472 		for (Iterator<BuildTimeFeature> iter = rootFileProviders.iterator(); iter.hasNext();) {
473 			BuildTimeFeature feature = iter.next();
474 			if (featureSet.contains(feature))
475 				continue;
476 			if (isOldExecutableFeature(feature)) {
477 				oldExecutableFeature = feature;
478 				script.printAntCallTask(TARGET_P2_COMPATIBILITY_GATHER_EXECUTABLE, true, null);
479 			} else {
480 				IPath featureLocation = new Path(feature.getRootLocation());
481 				String featureFullName = feature.getId() + "_" + feature.getVersion(); //$NON-NLS-1$
482 				printCustomGatherCall(featureFullName, Utils.makeRelative(featureLocation, new Path(workingDirectory)).toOSString(), PROPERTY_FEATURE_BASE, Utils.getPropertyFormat(PROPERTY_ECLIPSE_BASE), '/' + DEFAULT_FEATURE_LOCATION);
483 			}
484 		}
485 
486 		String repo = Utils.getPropertyFormat(PROPERTY_P2_BUILD_REPO);
487 		URI[] context = getContextMetadata();
488 		script.printP2PublishFeaturesAndBundles(repo, repo, binaryBundles.toArray(new FileSet[binaryBundles.size()]), binaryFeatures.toArray(new FileSet[binaryFeatures.size()]), Utils.getPropertyFormat(PROPERTY_P2_CATEGORY_SITE), Utils.getPropertyFormat(PROPERTY_P2_CATEGORY_PREFIX), Utils.getPropertyFormat(PROPERTY_P2_CATEGORY_DEFINITION), Utils.getPropertyFormat(PROPERTY_P2_CATEGORY_VERSION), context);
489 
490 		script.printTargetEnd();
491 		script.println();
492 
493 		if (oldExecutableFeature != null) {
494 			generateCompatibilityGatherExecutable(oldExecutableFeature);
495 		}
496 	}
497 
isOldExecutableFeature(BuildTimeFeature feature)498 	private boolean isOldExecutableFeature(BuildTimeFeature feature) {
499 		if (!feature.getId().equals(FEATURE_EQUINOX_EXECUTABLE))
500 			return false;
501 
502 		if (feature.isBinary() || !OLD_EXECUTABLE_RANGE.isIncluded(new Version(feature.getVersion())))
503 			return false;
504 
505 		Properties properties = getFeatureBuildProperties(feature);
506 		return properties != null && Boolean.valueOf((String) properties.get(PROPERTY_CUSTOM)).booleanValue();
507 	}
508 
generateCompatibilityGatherExecutable(BuildTimeFeature executableFeature)509 	private void generateCompatibilityGatherExecutable(BuildTimeFeature executableFeature) {
510 		IPath featureLocation = new Path(executableFeature.getRootLocation());
511 		String featureFullName = executableFeature.getId() + "_" + executableFeature.getVersion(); //$NON-NLS-1$
512 
513 		File productDir = new File(getWorkingDirectory(), DEFAULT_FEATURE_LOCATION + '/' + CONTAINER_FEATURE + "/product"); //$NON-NLS-1$
514 		productDir.mkdirs();
515 		File overridesFile = new File(productDir, "overrides.properties"); //$NON-NLS-1$
516 		Properties overrides = Utils.getOldExecutableRootOverrides();
517 		OutputStream outputStream = null;
518 		try {
519 			outputStream = new BufferedOutputStream(new FileOutputStream(overridesFile));
520 			overrides.store(outputStream, "Overrides for org.eclipse.equinox.executable"); //$NON-NLS-1$
521 		} catch (IOException e) {
522 			//
523 		} finally {
524 			Utils.close(outputStream);
525 		}
526 
527 		script.printTargetDeclaration(TARGET_P2_COMPATIBILITY_GATHER_EXECUTABLE, null, null, null, null);
528 		script.printTab();
529 		script.print("<eclipse.gatherFeature"); //$NON-NLS-1$
530 		script.printAttribute("metadataRepository", Utils.getPropertyFormat(PROPERTY_P2_BUILD_REPO), true); //$NON-NLS-1$
531 		script.printAttribute("artifactRepository", Utils.getPropertyFormat(PROPERTY_P2_BUILD_REPO), true); //$NON-NLS-1$
532 		script.printAttribute("buildResultFolder", executableFeature.getRootLocation(), true); //$NON-NLS-1$
533 		script.printAttribute("baseDirectory", executableFeature.getRootLocation(), true); //$NON-NLS-1$
534 		script.printAttribute("overrides", overridesFile.getAbsolutePath(), true); //$NON-NLS-1$
535 		script.println("/>"); //$NON-NLS-1$
536 
537 		Map<String, String> params = new HashMap<>();
538 		params.put(PROPERTY_PROJECT_LOCATION, "${basedir}/" + Utils.makeRelative(featureLocation, new Path(workingDirectory)).toOSString()); //$NON-NLS-1$
539 		params.put(PROPERTY_FEATURE_BASE, Utils.getPropertyFormat(PROPERTY_ECLIPSE_BASE));
540 		params.put(PROPERTY_PROJECT_NAME, featureFullName);
541 		params.put(PROPERTY_TARGET_FOLDER, Utils.getPropertyFormat(PROPERTY_ECLIPSE_BASE) + '/' + DEFAULT_FEATURE_LOCATION);
542 		printCustomAssemblyAntCall(TARGET_GATHER_BIN_PARTS, params);
543 		script.printTargetEnd();
544 		script.println();
545 	}
546 
setVersionsList(boolean versionsList)547 	public void setVersionsList(boolean versionsList) {
548 		this.versionsList = versionsList;
549 	}
550 }
551