| /******************************************************************************* |
| * Copyright (c) 2017 SSI Schaefer IT Solutions GmbH 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: |
| * SSI Schaefer IT Solutions GmbH |
| *******************************************************************************/ |
| package org.eclipse.tea.library.build.model; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.Writer; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.TreeMap; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.osgi.service.resolver.VersionRange; |
| import org.eclipse.tea.library.build.util.StringHelper; |
| import org.osgi.framework.Version; |
| |
| /** |
| * Stores useful information about a RCP plugin. |
| */ |
| public class PluginData extends BundleData { |
| |
| /** |
| * the Eclipse plugin project |
| */ |
| protected final IProject project; |
| |
| protected final ParameterValue[] dependencies; |
| protected final ParameterValue[] mavenDependencies; |
| protected final ParameterValue[] imports; |
| protected ParameterValue[] exports; |
| protected final String platformFilter; |
| protected String[] classPath; |
| protected final String[] requiredExecutionEnvironment; |
| |
| /** |
| * the fragment host, or {@code null} if no fragment host is defined |
| */ |
| protected final ParameterValue fragmentHost; |
| |
| protected final Properties buildProperties; |
| protected final Map<String, List<String>> sourceFolders, binaryFolders; |
| |
| protected final String[] binaryIncludes; |
| |
| protected final String description; |
| |
| /** |
| * Creates the plugin data for a source distribution. |
| * |
| * @param project |
| * Eclipse project |
| */ |
| public PluginData(IProject project) { |
| this(project.getName(), project.getLocation().toFile(), true, null, project); |
| } |
| |
| /** |
| * Creates the plugin data for a binary distribution. |
| * |
| * @param binaryDistribution |
| * JAR file or directory of an extracted JAR |
| */ |
| public static PluginData createFromBinaryDistribution(File binaryDistribution) { |
| if (binaryDistribution.isFile()) { |
| String jarName = binaryDistribution.getName().toLowerCase(); |
| if (jarName.endsWith(".jar")) { |
| return new PluginData(null, null, false, binaryDistribution, null); |
| } |
| throw new IllegalArgumentException("illegal JAR name: " + jarName); |
| } |
| if (binaryDistribution.isDirectory()) { |
| return new PluginData(null, binaryDistribution, false, null, null); |
| } |
| throw new IllegalArgumentException(binaryDistribution.getPath()); |
| } |
| |
| protected PluginData(String projectName, File bundleDir, boolean hasSource, File jarFile, IProject project) { |
| super(projectName, bundleDir, hasSource, jarFile); |
| |
| this.project = project; |
| |
| if (jarFile != null) { |
| buildProperties = readBuildPropertiesFromJar(jarFile); |
| } else { |
| buildProperties = readBuildPropertiesFromDirectory(bundleDir); |
| } |
| |
| final String[] binInc1; |
| if (manifest != null) { |
| dependencies = manifest.getDependencies(); |
| mavenDependencies = manifest.getMavenDependencies(); |
| imports = manifest.getImportPackages(); |
| exports = manifest.getExportPackages(); |
| classPath = manifest.getClassPath(); |
| requiredExecutionEnvironment = manifest.getRequiredExecutionEnvironment(); |
| fragmentHost = manifest.getFragmentHost(); |
| platformFilter = manifest.getPlatformFilter(); |
| description = manifest.getDescription(); |
| binInc1 = manifest.getBinaryInclude(); |
| } else { |
| dependencies = null; |
| mavenDependencies = null; |
| imports = null; |
| exports = null; |
| classPath = null; |
| requiredExecutionEnvironment = null; |
| fragmentHost = null; |
| platformFilter = null; |
| description = null; |
| binInc1 = EMPTY_STRINGS; |
| } |
| |
| final String[] binInc2; |
| if (buildProperties != null) { |
| sourceFolders = splitMap(buildProperties, "source."); |
| binaryFolders = splitMap(buildProperties, "output."); |
| binInc2 = splitList(buildProperties, "bin.includes"); |
| } else { |
| sourceFolders = Collections.emptyMap(); |
| binaryFolders = Collections.emptyMap(); |
| binInc2 = EMPTY_STRINGS; |
| } |
| |
| binaryIncludes = mergeLists(binInc1, binInc2); |
| } |
| |
| @Override |
| public final IProject getProject() { |
| return project; |
| } |
| |
| public boolean isBinary() { |
| // Note: DON'T cache this information here (so we don't need to |
| // reconstruct PluginData to get current information)! |
| return WorkspaceData.isBinaryProject(project); |
| } |
| |
| public final ParameterValue[] getDependencies() { |
| return dependencies; |
| } |
| |
| public final ParameterValue[] getMavenDependencies() { |
| return mavenDependencies; |
| } |
| |
| public final ParameterValue[] getPackageImports() { |
| if (imports == null) { |
| return new ParameterValue[0]; |
| } |
| return imports; |
| } |
| |
| public final ParameterValue[] getPackageExports() { |
| if (exports == null) { |
| return new ParameterValue[0]; |
| } |
| return exports; |
| } |
| |
| public final void setPackageExports(ParameterValue[] v) { |
| exports = v; |
| manifest.setExportPackages(v); |
| } |
| |
| public final String[] getClassPath() { |
| return classPath; |
| } |
| |
| public final void setClassPath(String[] cp) { |
| manifest.setClassPath(cp); // don't refresh our model |
| } |
| |
| public final String[] getRequiredExecutionEnvironment() { |
| return requiredExecutionEnvironment; |
| } |
| |
| public final void setRequiredExecutionEnvironment(String[] values) { |
| manifest.setRequiredExecutionEnvironment(values); |
| } |
| |
| @Override |
| public final String getBundleVersion() { |
| if (manifest == null) { |
| return null; |
| } |
| return manifest.getBundleVersion(); |
| } |
| |
| @Override |
| public final void setBundleVersion(String value) { |
| manifest.setBundleVersion(value); |
| } |
| |
| public final String getBundleVendor() { |
| return manifest.getBundleVendor(); |
| } |
| |
| public final void setBundleVendor(String value) { |
| manifest.setBundleVendor(value); |
| } |
| |
| public final String getBuddyPolicy() { |
| ParameterValue buddyPolicy = manifest.getBuddyPolicy(); |
| return buddyPolicy == null ? null : buddyPolicy.value; |
| } |
| |
| public final ParameterValue[] getBuddyRegistrations() { |
| return manifest.getBuddyRegistrations(); |
| } |
| |
| public final boolean isLazyActivationPolicy() { |
| return StringHelper.compare("lazy", manifest.getActivationPolicy()) == 0; |
| } |
| |
| public final void setLazyActivationPolicy() { |
| manifest.setLazyActivationPolicy(); |
| } |
| |
| /** |
| * Returns the fragment host, or {@code null} if no fragment host is |
| * defined. |
| */ |
| public final ParameterValue getFragmentHost() { |
| return fragmentHost; |
| } |
| |
| public final String[] getSourceFolders() { |
| return sourceFolders.values().stream().flatMap(List::stream).toArray(String[]::new); |
| } |
| |
| public final Map<String, List<String>> getBinaryFolders() { |
| return binaryFolders; |
| } |
| |
| public final String[] getBinaryIncludes() { |
| return binaryIncludes; |
| } |
| |
| public final String getPlatformFilter() { |
| return platformFilter; |
| } |
| |
| public String getBundleActivator() { |
| if (manifest == null) { |
| return null; |
| } |
| |
| return manifest.getActivator(); |
| } |
| |
| /** |
| * @param activator |
| * the activator to use, may be <code>null</code> to removed the |
| * header. |
| */ |
| public void setBundleActivator(String activator) { |
| manifest.setActivator(activator); |
| } |
| |
| public void setGitInfo(String repoUri, String projectPath, String commitId) { |
| manifest.setGitInfo(repoUri, projectPath, commitId); |
| } |
| |
| public List<String> getBinaryClassPath() { |
| if (jarFile != null) { |
| return Collections.singletonList(jarFile.getAbsolutePath()); |
| } |
| List<String> result = new ArrayList<>(); |
| for (String cp : classPath) { |
| if (".".equals(cp)) { |
| continue; |
| } |
| File f = new File(bundleDir, cp); |
| result.add(f.getAbsolutePath()); |
| } |
| return result; |
| } |
| |
| void writeHtmlListelement(Writer w) throws IOException { |
| w.write("<li>"); |
| w.write(getBundleName()); |
| if (dependencies != null) { |
| w.write("<br>Dependencies:\n<ul>\n"); |
| for (ParameterValue dep : dependencies) { |
| dep.writeHtmlListelement(w); |
| } |
| w.write("</ul>\n"); |
| } |
| if (mavenDependencies != null) { |
| w.write("<br>Maven JAR Dependencies:\n<ul>\n"); |
| for (ParameterValue dep : mavenDependencies) { |
| dep.writeHtmlListelement(w); |
| } |
| w.write("</ul>\n"); |
| } |
| w.write("</li>\n"); |
| } |
| |
| /** |
| * Checks whether this plugin exports a package with the given name. only |
| * call this if {@link BundleData#isMetadataOK()} returns true! |
| * |
| * @param id |
| * the id of the package to look for |
| */ |
| public boolean exportsPackage(String id, VersionRange range) { |
| if (exports == null) { |
| return false; |
| } |
| |
| for (ParameterValue val : exports) { |
| if (!val.value.equals(id)) { |
| continue; |
| } |
| |
| String exportVersion = val.getStringParameter("version"); |
| Version v; |
| if (exportVersion != null && !exportVersion.isEmpty()) { |
| v = Version.parseVersion(exportVersion); |
| } else { |
| v = Version.emptyVersion; |
| } |
| if (range == null || range.isIncluded(v)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public final ParameterValue[] getImportPackages() { |
| return imports; |
| } |
| |
| public ParameterValue getManifestHeader(String name) { |
| return manifest.getSingleAttribute(name); |
| } |
| |
| public ParameterValue[] getManifestHeaderList(String name) { |
| return manifest.getListAttribute(name); |
| } |
| |
| public final String getDescription() { |
| return description; |
| } |
| |
| public boolean migrateUnpackInformation() { |
| return manifest.migrateUnpackInformation(); |
| } |
| |
| private Map<String, String> getExternalizeClasspath() { |
| Map<String, String> result = new TreeMap<>(); |
| for (ParameterValue v : getManifestHeaderList("Externalize-ClassPath")) { |
| String from = v.value; |
| String to = v.getStringParameter("map"); |
| |
| result.put(from, to); |
| } |
| return result; |
| } |
| |
| /** |
| * @deprecated use non-WAMAS specifically named version |
| * ({@link #getExternalizeClasspath()}). |
| */ |
| @Deprecated |
| private Map<String, String> getWamasExternalizeClasspath() { |
| Map<String, String> result = new TreeMap<>(); |
| for (ParameterValue v : getManifestHeaderList("WAMAS-Externalize-ClassPath")) { |
| String from = v.value; |
| String to = v.getStringParameter("map"); |
| |
| result.put(from, to); |
| } |
| return result; |
| } |
| |
| String getSimpleManifestValue(String name) { |
| ParameterValue pv = getManifestHeader(name); |
| if (pv == null) { |
| return null; |
| } |
| return pv.value; |
| } |
| |
| /** |
| * @deprecated use non-WAMAS specifically named version |
| */ |
| @Deprecated |
| String getWamasPrefixNativeCode() { |
| return getSimpleManifestValue("WAMAS-Prefix-NativeCode"); |
| } |
| |
| String getPrefixNativeCode() { |
| return getSimpleManifestValue("Prefix-NativeCode"); |
| } |
| |
| /** |
| * ATTENTION: this method may ONLY be called while building JAR files. The |
| * MANIFEST.MF file MUST be backed up and restored after the operation. |
| */ |
| public void updateManifestForBinaryDeployment() { |
| if (getManifestFile() == null || manifest == null) { |
| return; |
| } |
| |
| // re-read the manifest, manipulate and write the changes. |
| ManifestHolder temp = readManifestFromDirectory(bundleDir); |
| Map<String, String> updates = getExternalizeClasspath(); |
| updates.putAll(getWamasExternalizeClasspath()); |
| |
| if (temp == null) { |
| return; |
| } |
| |
| String[] cp = manifest.getClassPath(); |
| if (!updates.isEmpty() && cp.length > 0) { |
| String[] target = new String[cp.length]; |
| System.arraycopy(cp, 0, target, 0, cp.length); |
| |
| for (int i = 0; i < cp.length; ++i) { |
| String replacement = updates.get(cp[i]); |
| if (replacement != null) { |
| target[i] = replacement; |
| } |
| } |
| |
| temp.setClassPath(target); |
| } |
| |
| String prefix = getWamasPrefixNativeCode(); |
| if (prefix == null) { |
| prefix = getPrefixNativeCode(); |
| } |
| ParameterValue[] nc = temp.getNativeCode(); |
| if (prefix != null && nc.length > 0) { |
| for (int i = 0; i < nc.length; ++i) { |
| nc[i].value = prefix + nc[i].value; |
| } |
| } |
| |
| try { |
| temp.write(getManifestFile()); |
| } catch (Exception e) { |
| throw new RuntimeException("cannot update manifest for binary deployment", e); |
| } |
| } |
| } |