| /******************************************************************************* |
| * Copyright (c) 2009, 2018 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.pde.internal.build.fetch; |
| |
| import java.io.File; |
| import java.util.*; |
| import java.util.Map.Entry; |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.pde.build.IAntScript; |
| import org.eclipse.pde.build.IFetchFactory; |
| import org.eclipse.pde.internal.build.*; |
| |
| /** |
| * Factory which interprets a p2IU entry in a map file for a build contribution. |
| * |
| * @since 1.0 |
| */ |
| public class P2IUFetchFactory implements IFetchFactory { |
| |
| private static class IUFetchInfo { |
| String id, version; |
| |
| public IUFetchInfo(String id, String version) { |
| this.id = id; |
| this.version = version; |
| } |
| |
| @Override |
| public int hashCode() { |
| final int prime = 31; |
| int result = 1; |
| result = prime * result + ((id == null) ? 0 : id.hashCode()); |
| result = prime * result + ((version == null) ? 0 : version.hashCode()); |
| return result; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) |
| return true; |
| if (obj == null || getClass() != obj.getClass()) |
| return false; |
| |
| IUFetchInfo other = (IUFetchInfo) obj; |
| if (id == null) { |
| if (other.id != null) |
| return false; |
| } else if (!id.equals(other.id)) |
| return false; |
| if (version == null) { |
| if (other.version != null) |
| return false; |
| } else if (!version.equals(other.version)) |
| return false; |
| return true; |
| } |
| } |
| |
| private static final String ATTRIBUTE_DESTINATION = "destination"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_ID = "id"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_SOURCE = "source"; //$NON-NLS-1$ |
| private static final String ATTRIBUTE_VERSION = "version"; //$NON-NLS-1$ |
| private static final String KEY_REPOSITORY = "repository"; //$NON-NLS-1$ |
| private static final String KEY_ID = "id"; //$NON-NLS-1$ |
| private static final String KEY_VERSION = "version"; //$NON-NLS-1$ |
| private static final String SEPARATOR = ","; //$NON-NLS-1$ |
| private static final String TASK_IU = "iu"; //$NON-NLS-1$ |
| private static final String TASK_REPO2RUNNABLE = "p2.repo2runnable"; //$NON-NLS-1$ |
| private static final String TARGET_GET_IUS_FROM_REPO = "FetchIUsFromRepo"; //$NON-NLS-1$ |
| |
| private final Map<String, ArrayList<IUFetchInfo>> iusToFetchBySource = new LinkedHashMap<>(2); |
| |
| /* |
| * Helper method to throw an exception with the given message. |
| */ |
| private static void throwException(String message, Exception e) throws CoreException { |
| throw new CoreException(new Status(IStatus.ERROR, IPDEBuildConstants.PI_PDEBUILD, 0, message, e)); |
| } |
| |
| @Override |
| public void addTargets(IAntScript script) { |
| // single target to fetch all IUs from different repos |
| // |
| // <p2.repo2runnable source="source1" destination="${trasnformedRepoLocation}"> |
| // <iu id="aBundle" version="1" /> |
| // ... |
| // </p2.repo2runnable> |
| // <p2.repo2runnable source="source2" destination="${transformedRepoLocation}"> |
| // <iu id="bBundle" version="2" /> |
| // ... |
| // </p2.repo2runnable> |
| // ... |
| script.println(); |
| script.printTargetDeclaration(TARGET_GET_IUS_FROM_REPO, null, null, null, null); |
| |
| Map<String, String> args = new LinkedHashMap<>(2); |
| for (Iterator<Entry<String, ArrayList<IUFetchInfo>>> stream = iusToFetchBySource.entrySet().iterator(); stream.hasNext();) { |
| Entry<String, ArrayList<IUFetchInfo>> entry = stream.next(); |
| String sourceRepository = entry.getKey(); |
| ArrayList<IUFetchInfo> iusToFetch = entry.getValue(); |
| |
| script.printEchoTask(null, NLS.bind(Messages.fetching_p2Repo, new String[] {sourceRepository, Utils.getPropertyFormat(IBuildPropertiesConstants.PROPERTY_TRANSFORMED_REPO)}), "info"); //$NON-NLS-1$ |
| args.clear(); |
| args.put(ATTRIBUTE_SOURCE, sourceRepository); |
| args.put(ATTRIBUTE_DESTINATION, Utils.getPropertyFormat(IBuildPropertiesConstants.PROPERTY_TRANSFORMED_REPO)); |
| script.printStartTag(TASK_REPO2RUNNABLE, args); |
| script.incrementIdent(); |
| |
| for (Iterator<IUFetchInfo> stream2 = iusToFetch.iterator(); stream2.hasNext();) { |
| IUFetchInfo iuFetchInfo = stream2.next(); |
| args.clear(); |
| args.put(ATTRIBUTE_ID, iuFetchInfo.id); |
| args.put(ATTRIBUTE_VERSION, iuFetchInfo.version); |
| script.printElement(TASK_IU, args); |
| } |
| |
| script.decrementIdent(); |
| script.printEndTag(TASK_REPO2RUNNABLE); |
| script.println(); |
| |
| } |
| |
| script.printTargetEnd(); |
| script.println(); |
| |
| // clear the map |
| iusToFetchBySource.clear(); |
| } |
| |
| @Override |
| public void generateRetrieveElementCall(Map<String, Object> entryInfos, IPath destination, IAntScript script) { |
| // generate at most one fetch call |
| if (iusToFetchBySource.isEmpty()) { |
| // <antcall target="FetchIUsFromRepo" /> |
| script.printAntCallTask(TARGET_GET_IUS_FROM_REPO, true, null); |
| } |
| |
| // collect the IU and repo to fetch from for single fetch call later |
| String sourceRepository = (String) entryInfos.get(KEY_REPOSITORY); |
| |
| if (!iusToFetchBySource.containsKey(sourceRepository)) { |
| iusToFetchBySource.put(sourceRepository, new ArrayList<IUFetchInfo>()); |
| } |
| |
| IUFetchInfo iuFetchInfo = new IUFetchInfo((String) entryInfos.get(KEY_ID), (String) entryInfos.get(KEY_VERSION)); |
| |
| List<IUFetchInfo> iusToFetch = iusToFetchBySource.get(sourceRepository); |
| if (!iusToFetch.contains(iuFetchInfo)) |
| iusToFetch.add(iuFetchInfo); |
| |
| } |
| |
| @Override |
| public void generateRetrieveFilesCall(Map<String, Object> entryInfos, IPath destination, String[] files, IAntScript script) { |
| Map<String, String> args = new HashMap<>(); |
| args.put(ATTRIBUTE_SOURCE, (String) entryInfos.get(KEY_REPOSITORY)); |
| args.put(ATTRIBUTE_DESTINATION, destination.toOSString()); |
| script.printStartTag(TASK_REPO2RUNNABLE, args); |
| script.incrementIdent(); |
| args.clear(); |
| args.put(ATTRIBUTE_ID, (String) entryInfos.get(KEY_ID)); |
| args.put(ATTRIBUTE_VERSION, (String) entryInfos.get(KEY_VERSION)); |
| script.printElement(TASK_IU, args); |
| script.decrementIdent(); |
| script.printEndTag(TASK_REPO2RUNNABLE); |
| script.println(); |
| |
| //create a dummy build.properties file which will be overwritten if the feature actually contains one |
| args.clear(); |
| args.put("message", "#empty"); //$NON-NLS-1$ //$NON-NLS-2$ |
| args.put("file", new File(destination.toFile(), "build.properties").getAbsolutePath()); //$NON-NLS-1$//$NON-NLS-2$ |
| script.printElement("echo", args); //$NON-NLS-1$ |
| |
| //move the files to the destination |
| args.clear(); |
| args.put("todir", destination.toOSString()); //$NON-NLS-1$ |
| args.put("flatten", "true"); //$NON-NLS-1$ //$NON-NLS-2$ |
| script.printStartTag("move", args); //$NON-NLS-1$ |
| script.incrementIdent(); |
| args.clear(); |
| args.put("dir", destination.toOSString()); //$NON-NLS-1$ |
| for (int i = 0; i < files.length; i++) { |
| args.put("includes", "features/*/" + files[i]); //$NON-NLS-1$ //$NON-NLS-2$ |
| script.printElement("fileset", args); //$NON-NLS-1$ |
| } |
| script.decrementIdent(); |
| script.printEndTag("move"); //$NON-NLS-1$ |
| } |
| |
| @Override |
| public void parseMapFileEntry(String rawEntry, Properties overrideTags, Map<String, Object> entryInfos) throws CoreException { |
| String[] arguments = Utils.getArrayFromStringWithBlank(rawEntry, SEPARATOR); |
| |
| // build up the table of arguments in the map file entry |
| Map<String, String> table = new HashMap<>(); |
| for (int i = 0; i < arguments.length; i++) { |
| String arg = arguments[i]; |
| // if we have at least one arg without an equals sign then we are malformed and should bail |
| int index = arg.indexOf('='); |
| if (index == -1) |
| throwException(NLS.bind(Messages.error_incorrectDirectoryEntry, entryInfos.get(KEY_ELEMENT_NAME)), null); |
| String key = arg.substring(0, index); |
| String value = arg.substring(index + 1); |
| table.put(key, value); |
| } |
| |
| entryInfos.put(KEY_ID, table.get(KEY_ID)); |
| if (table.containsKey(KEY_VERSION)) |
| entryInfos.put(KEY_VERSION, table.get(KEY_VERSION)); |
| else |
| entryInfos.put(KEY_VERSION, ""); //$NON-NLS-1$ |
| entryInfos.put(KEY_REPOSITORY, table.get(KEY_REPOSITORY)); |
| |
| // we need an IU id, and repository |
| if (entryInfos.get(KEY_ID) == null || entryInfos.get(KEY_REPOSITORY) == null) |
| throwException(NLS.bind(Messages.error_directoryEntryRequiresIdAndRepo, entryInfos.get(KEY_ELEMENT_NAME)), null); |
| } |
| |
| } |