diff --git a/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF index 3e48203ac8..71b9288c49 100644 --- a/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF +++ b/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF @@ -10,19 +10,32 @@ Import-Package: aQute.bnd.build;version="4.5.0", aQute.bnd.build.model.clauses;version="2.5.0", aQute.bnd.exceptions;version="3.0.0", aQute.bnd.header;version="2.6.0", - aQute.bnd.osgi, + aQute.bnd.http;version="2.0.0", + aQute.bnd.osgi;version="[7.0.0,8.0.0)", + aQute.bnd.osgi.resource;version="[5.0.0,6)", + aQute.bnd.repository.osgi;version="[1.1.1,2)", aQute.bnd.result;version="2.0.0", - jakarta.xml.bind;version="4.0.1", - jakarta.xml.bind.annotation;version="4.0.1" + aQute.bnd.service;version="4.8.0", + aQute.service.reporter;version="[1.2.0,2.0.0)", + jakarta.xml.bind;version="[4.0.0,5.0.0)", + jakarta.xml.bind.annotation;version="[4.0.0,5.0.0)", + org.bndtools.templating;version="[2.0.0,3.0.0)", + org.bndtools.templating.util;version="[1.0.0,2.0.0)", + org.osgi.service.metatype;version="[1.4.1,2)", + org.osgi.service.repository;version="[1.1.0,2.0.0)", + org.osgi.util.function;version="[1.2.0,2)", + org.osgi.util.promise;version="[1.3.0,2.0.0)" Require-Bundle: org.eclipse.jdt.ui, org.eclipse.jdt.core, org.eclipse.core.resources, org.eclipse.core.runtime;bundle-version="3.30.0", org.eclipse.jface.text, org.eclipse.swt, - org.eclipse.jface + org.eclipse.jface, + org.eclipse.ui.workbench Automatic-Module-Name: org.eclipse.pde.bnd.ui Bundle-Activator: org.eclipse.pde.bnd.ui.Resources Bundle-RequiredExecutionEnvironment: JavaSE-17 -Service-Component: OSGI-INF/org.eclipse.pde.bnd.ui.internal.Auxiliary.xml +Service-Component: OSGI-INF/org.bndtools.templating.repos.xml, + OSGI-INF/org.eclipse.pde.bnd.ui.internal.Auxiliary.xml Bundle-ActivationPolicy: lazy diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/AddRemoveButtonBarPart.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/AddRemoveButtonBarPart.java index 7b896c41b8..5f65ff22f3 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/AddRemoveButtonBarPart.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/AddRemoveButtonBarPart.java @@ -12,7 +12,7 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package org.bndtools.utils.swt; +package org.eclipse.pde.bnd.ui; import java.util.ArrayList; import java.util.List; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/BoldStyler.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/BoldStyler.java index 5d5ae536f7..4901c92979 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/BoldStyler.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/BoldStyler.java @@ -12,7 +12,7 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package org.bndtools.utils.jface; +package org.eclipse.pde.bnd.ui; import org.eclipse.jface.preference.JFacePreferences; import org.eclipse.jface.resource.ColorRegistry; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/OBRLink.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/OBRLink.java index 694a1c4641..9c387bab2d 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/OBRLink.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/OBRLink.java @@ -12,7 +12,7 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.shared; +package org.eclipse.pde.bnd.ui; import org.eclipse.jface.viewers.StyledString; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/Resources.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/Resources.java index fb77846e36..8b89bfcbf0 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/Resources.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/Resources.java @@ -21,11 +21,20 @@ public void stop(BundleContext context) throws Exception { disposeResources(); } - public synchronized static Image getImage(String key) { + public synchronized static ImageDescriptor getImageDescriptor(String key) { ImageRegistry registry = getImageRegistry(); - if (registry.getDescriptor(key) == null) { - registry.put(key, ImageDescriptor.createFromURL(Resources.class.getResource(key))); + ImageDescriptor descriptor = registry.getDescriptor(key); + if (descriptor == null) { + ImageDescriptor fromURL = ImageDescriptor.createFromURL(Resources.class.getResource(key)); + registry.put(key, fromURL); + return fromURL; } + return descriptor; + } + + public synchronized static Image getImage(String key) { + ImageRegistry registry = getImageRegistry(); + getImageDescriptor(key); // make sure the descriptor is added! return registry.get(key); } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/URLDialog.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/URLDialog.java index b6f630992e..c062612643 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/URLDialog.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/URLDialog.java @@ -13,7 +13,7 @@ * Neil Bartlett - ongoing enhancements * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.shared; +package org.eclipse.pde.bnd.ui; import java.io.File; import java.net.URI; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/URLLabelProvider.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/URLLabelProvider.java index 155e46e6ba..9dc8ce692c 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/URLLabelProvider.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/URLLabelProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2021 bndtools project and others. + * Copyright (c) 2010, 2023 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -12,22 +12,19 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements * Peter Kriens - ongoing enhancements + * Christoph Läubrich - adapt to PDE code base *******************************************************************************/ -package bndtools.shared; +package org.eclipse.pde.bnd.ui; -import org.bndtools.core.ui.icons.Icons; import org.eclipse.jface.viewers.StyledCellLabelProvider; import org.eclipse.jface.viewers.StyledString; import org.eclipse.jface.viewers.ViewerCell; -import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.Image; public class URLLabelProvider extends StyledCellLabelProvider { - private final static Image linkImg = Icons.image("link"); - private final static Image fileImg = Icons.image("file"); - - public URLLabelProvider(Device display) {} + private final static Image linkImg = Resources.getImage("/icons/link.png"); + private final static Image fileImg = Resources.getImage("/icon/file.png"); @Override public void update(ViewerCell cell) { diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/ReposPreference.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/ReposPreference.java new file mode 100644 index 0000000000..570fd06855 --- /dev/null +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/ReposPreference.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2023 Christoph Läubrich and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.pde.bnd.ui.preferences; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +public interface ReposPreference { + + public static final String KEY_TEMPLATE_REPO_URI_LIST = "templateRepoUriList"; + + public static final boolean DEF_ENABLE_TEMPLATE_REPOSITORIES = false; + + public static final String KEY_ENABLE_TEMPLATE_REPOSITORIES = "enableTemplateRepositories"; + + public static final String TEMPLATE_LOADER_NODE = "repoTemplateLoader"; + + public static final Function> TEMPLATE_REPOSITORIES_PARSER = s -> s == null || s.isBlank() + ? List.of() + : Arrays.asList(s.split("\\s")); +} \ No newline at end of file diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/ReposPreferencePage.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/ReposPreferencePage.java index a051e5bb6a..0e8abd9357 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/ReposPreferencePage.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/ReposPreferencePage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2019 bndtools project and others. + * Copyright (c) 2015, 2023 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -12,22 +12,28 @@ * Neil Bartlett - initial API and implementation * Sean Bright - ongoing enhancements * BJ Hargrave - ongoing enhancements + * Christoph Läubrich - adapt to PDE code base *******************************************************************************/ -package bndtools.preferences.ui; +package org.eclipse.pde.bnd.ui.preferences; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; -import org.bndtools.utils.swt.AddRemoveButtonBarPart; -import org.bndtools.utils.swt.AddRemoveButtonBarPart.AddRemoveListener; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.jface.fieldassist.ControlDecoration; import org.eclipse.jface.fieldassist.FieldDecorationRegistry; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.window.Window; +import org.eclipse.pde.bnd.ui.AddRemoveButtonBarPart; +import org.eclipse.pde.bnd.ui.AddRemoveButtonBarPart.AddRemoveListener; +import org.eclipse.pde.bnd.ui.URLDialog; +import org.eclipse.pde.bnd.ui.URLLabelProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; @@ -43,23 +49,26 @@ import org.eclipse.swt.widgets.Table; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; +import org.osgi.framework.FrameworkUtil; +import org.osgi.service.prefs.BackingStoreException; -import bndtools.preferences.BndPreferences; -import bndtools.shared.URLDialog; -import bndtools.shared.URLLabelProvider; -public class ReposPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { +public class ReposPreferencePage extends PreferencePage implements IWorkbenchPreferencePage, ReposPreference { + private static final String REPO_DEFAULT = "https://raw.githubusercontent.com/bndtools/bundle-hub/master/index.xml.gz"; private boolean enableTemplateRepo; private List templateRepos; private TableViewer vwrRepos; + private IEclipsePreferences preferences; @Override public void init(IWorkbench workbench) { - BndPreferences prefs = new BndPreferences(); - - enableTemplateRepo = prefs.getEnableTemplateRepo(); - templateRepos = new ArrayList<>(prefs.getTemplateRepoUriList()); + preferences = (IEclipsePreferences) InstanceScope.INSTANCE + .getNode(FrameworkUtil.getBundle(ReposPreferencePage.class).getSymbolicName()) + .node(TEMPLATE_LOADER_NODE); + enableTemplateRepo = preferences.getBoolean(KEY_ENABLE_TEMPLATE_REPOSITORIES, DEF_ENABLE_TEMPLATE_REPOSITORIES); + templateRepos = TEMPLATE_REPOSITORIES_PARSER.apply(preferences.get(KEY_TEMPLATE_REPO_URI_LIST, + REPO_DEFAULT)); } @Override @@ -96,7 +105,7 @@ protected Control createContents(Composite parent) { final Table tblRepos = new Table(group, SWT.BORDER | SWT.MULTI); vwrRepos = new TableViewer(tblRepos); vwrRepos.setContentProvider(ArrayContentProvider.getInstance()); - vwrRepos.setLabelProvider(new URLLabelProvider(tblRepos.getDisplay())); + vwrRepos.setLabelProvider(new URLLabelProvider()); vwrRepos.setInput(templateRepos); GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false); @@ -185,11 +194,22 @@ private void validate() { @Override public boolean performOk() { - BndPreferences prefs = new BndPreferences(); - - prefs.setEnableTemplateRepo(enableTemplateRepo); - prefs.setTemplateRepoUriList(templateRepos); - + String repoList = templateRepos.stream().collect(Collectors.joining("\t")); + if (enableTemplateRepo == DEF_ENABLE_TEMPLATE_REPOSITORIES) { + preferences.remove(KEY_ENABLE_TEMPLATE_REPOSITORIES); + if (REPO_DEFAULT.equals(repoList)) { + preferences.remove(KEY_TEMPLATE_REPO_URI_LIST); + } else { + preferences.put(KEY_TEMPLATE_REPO_URI_LIST, repoList); + } + } else { + preferences.putBoolean(KEY_ENABLE_TEMPLATE_REPOSITORIES, enableTemplateRepo); + preferences.put(KEY_TEMPLATE_REPO_URI_LIST, repoList); + } + try { + preferences.flush(); + } catch (BackingStoreException e) { + } return true; } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/BuiltInServiceTemplate.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/BuiltInServiceTemplate.java index 9b92833534..d48c57fb2e 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/BuiltInServiceTemplate.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/BuiltInServiceTemplate.java @@ -11,7 +11,7 @@ * Contributors: * Scott Lewis - initial API and implementation *******************************************************************************/ -package org.bndtools.core.ui.wizards.shared; +package org.eclipse.pde.bnd.ui.templating; import java.net.URL; import java.nio.file.Path; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/BuiltInTemplate.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/BuiltInTemplate.java index 3f8799d73b..dce29173aa 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/BuiltInTemplate.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/BuiltInTemplate.java @@ -12,7 +12,7 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package org.bndtools.core.ui.wizards.shared; +package org.eclipse.pde.bnd.ui.templating; import java.io.IOException; import java.net.URI; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/BundleLocator.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/BundleLocator.java index da45d517e7..214c772e4c 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/BundleLocator.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/BundleLocator.java @@ -12,7 +12,7 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package org.bndtools.core.templating.repobased; +package org.eclipse.pde.bnd.ui.templating; import java.io.File; import java.net.URI; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/CapabilityBasedTemplate.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/CapabilityBasedTemplate.java index dde677e633..28c5deac52 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/CapabilityBasedTemplate.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/CapabilityBasedTemplate.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2020 bndtools project and others. + * Copyright (c) 2015, 2023 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -11,41 +11,45 @@ * Contributors: * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements + * Christoph Läubrich - adapt to PDE codebase *******************************************************************************/ -package org.bndtools.core.templating.repobased; - +package org.eclipse.pde.bnd.ui.templating; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URI; -import java.util.ArrayList; -import java.util.Iterator; +import java.nio.charset.Charset; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.NoSuchElementException; import java.util.Objects; +import java.util.function.Function; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarInputStream; +import java.util.stream.Collectors; -import org.apache.felix.metatype.AD; -import org.apache.felix.metatype.MetaData; -import org.apache.felix.metatype.MetaDataReader; -import org.apache.felix.metatype.OCD; import org.bndtools.templating.BytesResource; import org.bndtools.templating.FolderResource; import org.bndtools.templating.Resource; import org.bndtools.templating.ResourceMap; +import org.bndtools.templating.ResourceType; import org.bndtools.templating.Template; import org.bndtools.templating.TemplateEngine; import org.bndtools.templating.util.AttributeDefinitionImpl; import org.bndtools.templating.util.CompositeOCD; import org.bndtools.templating.util.ObjectClassDefinitionImpl; +import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.Status; +import org.eclipse.pde.osgi.xmlns.metatype.v1_4.Tmetadata; +import org.eclipse.pde.osgi.xmlns.metatype.v1_4.Tocd; import org.osgi.framework.Version; import org.osgi.framework.namespace.IdentityNamespace; import org.osgi.resource.Capability; @@ -54,32 +58,29 @@ import org.osgi.service.repository.ContentNamespace; import aQute.bnd.osgi.resource.ResourceUtils; -import aQute.lib.io.IO; -import bndtools.Plugin; public class CapabilityBasedTemplate implements Template { - private static final String DEFAULT_DIR = "template/"; + private static final String DEFAULT_DIR = "template/"; - private final Capability capability; - private final BundleLocator locator; - private final TemplateEngine engine; + private final Capability capability; + private final BundleLocator locator; + private final TemplateEngine engine; - private final String name; - private final String category; - private final String description; - private final Version version; + private final String name; + private final String category; + private final String description; + private final Version version; - private final String dir; - private final URI iconUri; + private final String dir; + private final URI iconUri; - private final String metaTypePath; - private final String ocdRef; + private final String metaTypePath; + private final String ocdRef; - private final String helpPath; + private final String helpPath; - private File _bundleFile = null; - private ResourceMap _inputResources = null; + private File _bundleFile = null; public CapabilityBasedTemplate(Capability capability, BundleLocator locator, TemplateEngine engine) { this.capability = capability; @@ -91,8 +92,7 @@ public CapabilityBasedTemplate(Capability capability, BundleLocator locator, Tem Object nameObj = attrs.get("name"); this.name = nameObj instanceof String ? (String) nameObj : "<>"; - this.description = "from " + ResourceUtils.getIdentityCapability(capability.getResource()) - .osgi_identity(); + this.description = "from " + ResourceUtils.getIdentityCapability(capability.getResource()).osgi_identity(); Object categoryObj = attrs.get("category"); category = categoryObj instanceof String ? (String) categoryObj : null; @@ -154,8 +154,7 @@ public Version getVersion() { @Override public int getRanking() { - Object rankingObj = capability.getAttributes() - .get("ranking"); + Object rankingObj = capability.getAttributes().get("ranking"); return rankingObj instanceof Number ? ((Number) rankingObj).intValue() : 0; } @@ -166,52 +165,51 @@ public ObjectClassDefinition getMetadata() throws Exception { @Override public ObjectClassDefinition getMetadata(IProgressMonitor monitor) throws Exception { - String resourceId = ResourceUtils.getIdentityCapability(capability.getResource()) - .osgi_identity(); - + String resourceId = ResourceUtils.getIdentityCapability(capability.getResource()).osgi_identity(); +// final CompositeOCD compositeOcd = new CompositeOCD(name, description, null); - +// if (metaTypePath != null) { try (JarFile bundleJarFile = new JarFile(fetchBundle())) { JarEntry metaTypeEntry = bundleJarFile.getJarEntry(metaTypePath); try (InputStream entryInput = bundleJarFile.getInputStream(metaTypeEntry)) { - MetaData metaData = new MetaDataReader().parse(entryInput); - - @SuppressWarnings("rawtypes") - Map ocdMap = metaData.getObjectClassDefinitions(); - if (ocdMap != null) { - if (ocdMap.size() == 1) { - @SuppressWarnings("unchecked") - Entry entry = (Entry) ocdMap.entrySet() - .iterator() - .next(); - // There is exactly one OCD, but if the capability - // specified the 'ocd' property then it must - // match. - if (ocdRef == null || ocdRef.equals(entry.getKey())) { - compositeOcd.addDelegate(new FelixOCDAdapter(entry.getValue())); - } else { - log(IStatus.WARNING, String.format( - "MetaType entry '%s' from resource '%s' did not contain an Object Class Definition with id '%s'", - metaTypePath, resourceId, ocdRef), null); - } - } else { - // There are multiple OCDs in the MetaType record, - // so the capability must have specified the - // 'ocd' property. - if (ocdRef != null) { - OCD felixOcd = (OCD) ocdMap.get(ocdRef); - if (felixOcd != null) { - compositeOcd.addDelegate(new FelixOCDAdapter(felixOcd)); + Tmetadata metaData = JaxbMetatype.readMetaType(entryInput); + if (metaData != null) { + + Map ocdMap = metaData.getOCDOrDesignateOrAny().stream() + .filter(Tocd.class::isInstance).map(Tocd.class::cast) + .collect(Collectors.toMap(Tocd::getId, Function.identity())); + if (!ocdMap.isEmpty()) { + if (ocdMap.size() == 1) { + Entry entry = ocdMap.entrySet().iterator().next(); + // There is exactly one OCD, but if the capability + // specified the 'ocd' property then it must + // match. + if (ocdRef == null || ocdRef.equals(entry.getKey())) { + compositeOcd.addDelegate(new JaxbObjectClassDefinition(entry.getValue())); } else { - log(IStatus.WARNING, String.format( - "MetaType entry '%s' from resource '%s' did not contain an Object Class Definition with id '%s'", - metaTypePath, resourceId, ocdRef), null); + ILog.get().warn(String.format( + "MetaType entry '%s' from resource '%s' did not contain an Object Class Definition with id '%s'", + metaTypePath, resourceId, ocdRef), null); } } else { - log(IStatus.WARNING, String.format( - "MetaType entry '%s' from resource '%s' contains multiple Object Class Definitions, and no 'ocd' property was specified.", - metaTypePath, resourceId), null); + // There are multiple OCDs in the MetaType record, + // so the capability must have specified the + // 'ocd' property. + if (ocdRef != null) { + Tocd felixOcd = ocdMap.get(ocdRef); + if (felixOcd != null) { + compositeOcd.addDelegate(new JaxbObjectClassDefinition(felixOcd)); + } else { + ILog.get().warn(String.format( + "MetaType entry '%s' from resource '%s' did not contain an Object Class Definition with id '%s'", + metaTypePath, resourceId, ocdRef), null); + } + } else { + ILog.get().warn(String.format( + "MetaType entry '%s' from resource '%s' contains multiple Object Class Definitions, and no 'ocd' property was specified.", + metaTypePath, resourceId), null); + } } } } @@ -227,11 +225,9 @@ public ObjectClassDefinition getMetadata(IProgressMonitor monitor) throws Except Map params = engine.getTemplateParameters(inputs, monitor); for (Entry entry : params.entrySet()) { AttributeDefinitionImpl ad = new AttributeDefinitionImpl(entry.getKey(), entry.getKey(), 0, - AttributeDefinition.STRING); + AttributeDefinition.STRING); if (entry.getValue() != null) - ad.setDefaultValue(new String[] { - entry.getValue() - }); + ad.setDefaultValue(new String[] { entry.getValue() }); ocdImpl.addAttribute(ad, true); } compositeOcd.addDelegate(ocdImpl); @@ -246,7 +242,7 @@ public ResourceMap generateOutputs(Map> parameters) throws @Override public ResourceMap generateOutputs(Map> parameters, IProgressMonitor monitor) - throws Exception { + throws Exception { ResourceMap inputs = getInputSources(); return engine.generateOutputs(inputs, parameters, monitor); } @@ -258,46 +254,97 @@ public URI getIcon() { @Override public URI getHelpContent() { - URI uri = null; if (helpPath != null) { try { File f = fetchBundle(); - uri = new URI("jar:" + f.toURI() - .toURL() + "!/" + helpPath); + if (f.isFile()) { + return new URI("jar:" + f.toURI().toURL() + "!/" + helpPath); + } + if (f.isDirectory()) { + return new File(f, helpPath).toURI(); + } } catch (Exception e) { // ignore } } - return uri; + return null; } private synchronized ResourceMap getInputSources() throws IOException { File bundleFile = fetchBundle(); - _inputResources = new ResourceMap(); - try (JarInputStream in = new JarInputStream(IO.stream(bundleFile))) { - JarEntry jarEntry = in.getNextJarEntry(); - while (jarEntry != null) { - String entryPath = jarEntry.getName() - .trim(); - if (entryPath.startsWith(dir)) { - String relativePath = entryPath.substring(dir.length()); - if (!relativePath.isEmpty()) { // skip the root folder - Resource resource; - if (relativePath.endsWith("/")) { - // strip the trailing slash - relativePath.substring(0, relativePath.length()); - resource = new FolderResource(); - } else { - // cannot use IO.collect() because it closes the - // whole JarInputStream - resource = BytesResource.loadFrom(in); - } - _inputResources.put(relativePath, resource); + ResourceMap _inputResources = new ResourceMap(); + if (bundleFile.isDirectory()) { + Path basePath = bundleFile.toPath().resolve(dir); + Files.walkFileTree(basePath, new FileVisitor() { + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + String relativePath = basePath.relativize(dir).toString(); + if (!relativePath.isBlank()) { + _inputResources.put(relativePath, new FolderResource()); } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + String relativePath = basePath.relativize(file).toString(); + _inputResources.put(relativePath, new Resource() { + + @Override + public ResourceType getType() { + return ResourceType.File; + } + + @Override + public InputStream getContent() throws IOException { + return Files.newInputStream(file); + } + + @Override + public String getTextEncoding() { + return Charset.defaultCharset().name(); + } + + }); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + return FileVisitResult.CONTINUE; + } + }); + } else { + try (JarInputStream in = new JarInputStream(new FileInputStream(bundleFile))) { + JarEntry jarEntry = in.getNextJarEntry(); + while (jarEntry != null) { + String entryPath = jarEntry.getName().trim(); + if (entryPath.startsWith(dir)) { + String relativePath = entryPath.substring(dir.length()); + if (!relativePath.isEmpty()) { // skip the root folder + Resource resource; + if (relativePath.endsWith("/")) { + // strip the trailing slash + relativePath.substring(0, relativePath.length()); + resource = new FolderResource(); + } else { + // cannot use IO.collect() because it closes the + // whole JarInputStream + resource = BytesResource.loadFrom(in); + } + _inputResources.put(relativePath, resource); + } + } + jarEntry = in.getNextJarEntry(); } - jarEntry = in.getNextJarEntry(); } } return _inputResources; @@ -307,18 +354,12 @@ private synchronized File fetchBundle() throws IOException { if (_bundleFile != null && _bundleFile.exists()) return _bundleFile; - Capability idCap = capability.getResource() - .getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE) - .get(0); - String id = (String) idCap.getAttributes() - .get(IdentityNamespace.IDENTITY_NAMESPACE); + Capability idCap = capability.getResource().getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE).get(0); + String id = (String) idCap.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE); - Capability contentCap = capability.getResource() - .getCapabilities(ContentNamespace.CONTENT_NAMESPACE) - .get(0); + Capability contentCap = capability.getResource().getCapabilities(ContentNamespace.CONTENT_NAMESPACE).get(0); URI location; - Object locationObj = contentCap.getAttributes() - .get("url"); + Object locationObj = contentCap.getAttributes().get("url"); if (locationObj instanceof URI) location = (URI) locationObj; else if (locationObj instanceof String) @@ -327,15 +368,14 @@ else if (locationObj instanceof String) throw new IOException("Template repository entry is missing url attribute"); if ("file".equals(location.getScheme())) { - _bundleFile = IO.getFile(location.getPath()); + _bundleFile = new File(location); return _bundleFile; } // Try to locate from the workspace and/or repositories if a // BundleLocator was provide if (locator != null) { - String hashStr = (String) contentCap.getAttributes() - .get(ContentNamespace.CONTENT_NAMESPACE); + String hashStr = (String) contentCap.getAttributes().get(ContentNamespace.CONTENT_NAMESPACE); try { _bundleFile = locator.locate(id, hashStr, "SHA-256", location); if (_bundleFile != null) @@ -372,176 +412,4 @@ public void close() throws IOException { // nothing to do } - private static void log(int level, String message, Throwable e) { - Plugin.getDefault() - .getLog() - .log(new Status(level, Plugin.PLUGIN_ID, 0, message, e)); - } - - private static class FelixADAdapter implements AttributeDefinition { - - private final AD ad; - - public FelixADAdapter(AD ad) { - this.ad = ad; - } - - @Override - public String getName() { - return ad.getName(); - } - - @Override - public String getID() { - return ad.getID(); - } - - @Override - public String getDescription() { - return ad.getDescription(); - } - - @Override - public int getCardinality() { - return ad.getCardinality(); - } - - @Override - public int getType() { - return ad.getType(); - } - - @Override - public String[] getOptionValues() { - return ad.getOptionValues(); - } - - @Override - public String[] getOptionLabels() { - return ad.getOptionLabels(); - } - - @Override - public String validate(String value) { - return ad.validate(value); - } - - @Override - public String[] getDefaultValue() { - return ad.getDefaultValue(); - } - } - - private static class FelixOCDAdapter implements ObjectClassDefinition { - - private final OCD ocd; - - public FelixOCDAdapter(OCD ocd) { - if (ocd == null) - throw new NullPointerException(); - this.ocd = ocd; - } - - @Override - public String getName() { - return ocd.getName(); - } - - @Override - public String getID() { - return ocd.getID(); - } - - @Override - public String getDescription() { - return ocd.getDescription(); - } - - @SuppressWarnings("unchecked") - @Override - public AttributeDefinition[] getAttributeDefinitions(int filter) { - if (ocd.getAttributeDefinitions() == null) - return null; - - Iterator iter = ocd.getAttributeDefinitions() - .values() - .iterator(); - if (filter == ObjectClassDefinition.OPTIONAL || filter == ObjectClassDefinition.REQUIRED) { - boolean required = (filter == ObjectClassDefinition.REQUIRED); - iter = new RequiredFilterIterator(iter, required); - } else if (filter != ObjectClassDefinition.ALL) { - return null; - } - - if (!iter.hasNext()) - return null; - - List result = new ArrayList<>(); - while (iter.hasNext()) { - result.add(new FelixADAdapter(iter.next())); - } - return result.toArray(new AttributeDefinition[0]); - } - - @Override - public InputStream getIcon(int size) throws IOException { - // TODO - return null; - } - - @SuppressWarnings("rawtypes") - private static class RequiredFilterIterator implements Iterator { - - private final Iterator base; - - private final boolean required; - - private AD next; - - private RequiredFilterIterator(Iterator base, boolean required) { - this.base = base; - this.required = required; - this.next = seek(); - } - - @Override - public boolean hasNext() { - return next != null; - } - - @Override - public Object next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - - AD toReturn = next; - next = seek(); - return toReturn; - } - - @Override - public void remove() { - throw new UnsupportedOperationException("remove"); - } - - private AD seek() { - if (base.hasNext()) { - AD next; - do { - next = (AD) base.next(); - } while (next.isRequired() != required && base.hasNext()); - - if (next.isRequired() == required) { - return next; - } - } - - // nothing found any more - return null; - } - - } - } - -} +} \ No newline at end of file diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/DirectDownloadBundleLocator.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/DirectDownloadBundleLocator.java index 2b518eee8a..c3d0d06dc7 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/DirectDownloadBundleLocator.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/DirectDownloadBundleLocator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2019 bndtools project and others. + * Copyright (c) 2016, 2023 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -11,24 +11,29 @@ * Contributors: * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements + * Christoph Läubrich - adapt to PDE codebase *******************************************************************************/ -package org.bndtools.core.templating.repobased; +package org.eclipse.pde.bnd.ui.templating; import java.io.File; +import java.io.InputStream; import java.net.URI; - -import aQute.lib.io.IO; +import java.nio.file.Files; +import java.nio.file.Path; // TODO need to use some kind of cache to avoid repeated downloads public class DirectDownloadBundleLocator implements BundleLocator { @Override public File locate(String bsn, String hash, String algo, URI location) throws Exception { - File tempFile = File.createTempFile("download", "jar"); - tempFile.deleteOnExit(); + + Path tempFile = Files.createTempFile("download", "jar"); + tempFile.toFile().deleteOnExit(); - IO.copy(location.toURL(), tempFile); - return tempFile; + try (InputStream stream = location.toURL().openStream()) { + Files.copy(stream, tempFile); + } + return tempFile.toFile(); } } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/JaxbAttributeDefinition.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/JaxbAttributeDefinition.java new file mode 100644 index 0000000000..61128faa4e --- /dev/null +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/JaxbAttributeDefinition.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2023 Christoph Läubrich and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.pde.bnd.ui.templating; + +import org.eclipse.pde.osgi.xmlns.metatype.v1_4.Tad; +import org.eclipse.pde.osgi.xmlns.metatype.v1_4.Toption; +import org.osgi.service.metatype.AttributeDefinition; + +class JaxbAttributeDefinition implements AttributeDefinition { + + private final Tad ad; + + public JaxbAttributeDefinition(Tad ad) { + this.ad = ad; + } + + @Override + public String getName() { + return ad.getName(); + } + + @Override + public String getID() { + return ad.getId(); + } + + @Override + public String getDescription() { + return ad.getDescription(); + } + + @Override + public int getCardinality() { + return ad.getCardinality(); + } + + @Override + public int getType() { + return ad.getType().ordinal() + 1; + } + + @Override + public String[] getOptionValues() { + return ad.getOptionOrAny().stream().filter(Toption.class::isInstance).map(Toption.class::cast) + .map(Toption::getValue).toArray(String[]::new); + } + + @Override + public String[] getOptionLabels() { + return ad.getOptionOrAny().stream().filter(Toption.class::isInstance).map(Toption.class::cast) + .map(Toption::getLabel).toArray(String[]::new); + } + + @Override + public String validate(String value) { + return null; + } + + @Override + public String[] getDefaultValue() { + return new String[] { ad.getDefault() }; + } +} \ No newline at end of file diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/JaxbMetatype.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/JaxbMetatype.java new file mode 100644 index 0000000000..7dc40905c7 --- /dev/null +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/JaxbMetatype.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2023 Christoph Läubrich and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.pde.bnd.ui.templating; + +import java.io.InputStream; + +import org.eclipse.core.runtime.ILog; +import org.eclipse.pde.osgi.xmlns.metatype.v1_4.ObjectFactory; +import org.eclipse.pde.osgi.xmlns.metatype.v1_4.Tmetadata; + +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.JAXBElement; +import jakarta.xml.bind.JAXBException; + +class JaxbMetatype { + + private static JAXBContext jaxbContext; + + private static boolean loaded; + + + static Tmetadata readMetaType(InputStream entryInput) throws JAXBException { + JAXBContext context = getJaxbContext(); + if (context == null) { + return null; + } + Object unmarshal = context.createUnmarshaller().unmarshal(entryInput); + if (unmarshal instanceof Tmetadata metadata) { + return metadata; + } + if (unmarshal instanceof JAXBElement elem) { + Object value = elem.getValue(); + if (value instanceof Tmetadata metadata) { + return metadata; + } + } + return null; + } + + + public static JAXBContext getJaxbContext() { + if (!loaded && jaxbContext == null) { + try { + jaxbContext = JAXBContext.newInstance(ObjectFactory.class); + } catch (JAXBException e) { + ILog.get().warn("Can't load JAXBContext, bnd template processing might be incomplete!", e); + } + loaded = true; + } + return jaxbContext; + } +} diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/JaxbObjectClassDefinition.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/JaxbObjectClassDefinition.java new file mode 100644 index 0000000000..2b2489559e --- /dev/null +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/JaxbObjectClassDefinition.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2023 Christoph Läubrich and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.pde.bnd.ui.templating; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.eclipse.pde.osgi.xmlns.metatype.v1_4.Tad; +import org.eclipse.pde.osgi.xmlns.metatype.v1_4.Ticon; +import org.eclipse.pde.osgi.xmlns.metatype.v1_4.Tocd; +import org.osgi.service.metatype.AttributeDefinition; +import org.osgi.service.metatype.ObjectClassDefinition; + +class JaxbObjectClassDefinition implements ObjectClassDefinition { + + private final Tocd ocd; + + public JaxbObjectClassDefinition(Tocd ocd) { + if (ocd == null) + throw new NullPointerException(); + this.ocd = ocd; + } + + @Override + public String getName() { + return ocd.getName(); + } + + @Override + public String getID() { + return ocd.getId(); + } + + @Override + public String getDescription() { + return ocd.getDescription(); + } + + @Override + public AttributeDefinition[] getAttributeDefinitions(int filter) { + Stream stream = ocd.getADOrIconOrAny().stream().filter(Tad.class::isInstance).map(Tad.class::cast); + if (filter == ObjectClassDefinition.OPTIONAL) { + stream = stream.filter(Predicate.not(Tad::isRequired)); + } else if (filter == ObjectClassDefinition.REQUIRED) { + stream = stream.filter(Tad::isRequired); + } else if (filter != ObjectClassDefinition.ALL) { + return null; + } + AttributeDefinition[] definitions = stream.toArray(AttributeDefinition[]::new); + if (definitions.length == 0) { + return null; + } + return definitions; + } + + @Override + public InputStream getIcon(int size) throws IOException { + List icons = ocd.getADOrIconOrAny().stream().filter(Ticon.class::isInstance).map(Ticon.class::cast) + .toList(); + if (icons.isEmpty()) { + throw new FileNotFoundException(); + } + for (Ticon icon : icons) { + if (icon.getSize().intValue() == size) { + return new URL(icon.getResource()).openStream(); + } + } + return new URL(icons.get(0).getResource()).openStream(); + } + +} \ No newline at end of file diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/LatestTemplateFilter.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/LatestTemplateFilter.java index 4dc4b74cf1..bfa49e83ed 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/LatestTemplateFilter.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/LatestTemplateFilter.java @@ -12,7 +12,7 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package org.bndtools.core.ui.wizards.shared; +package org.eclipse.pde.bnd.ui.templating; import java.util.LinkedHashMap; import java.util.Map; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoPluginsBundleLocator.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoPluginsBundleLocator.java index 2e994e95d9..bd9d4aa5ee 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoPluginsBundleLocator.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoPluginsBundleLocator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2019 bndtools project and others. + * Copyright (c) 2015, 2023 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -11,17 +11,20 @@ * Contributors: * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements + * Christoph Läubrich - adapt to PDE codebase *******************************************************************************/ -package org.bndtools.core.templating.repobased; +package org.eclipse.pde.bnd.ui.templating; import java.io.File; +import java.io.InputStream; import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.HashMap; import java.util.List; import java.util.Map; import aQute.bnd.service.RepositoryPlugin; -import aQute.lib.io.IO; public class RepoPluginsBundleLocator implements BundleLocator { @@ -51,11 +54,13 @@ public File locate(String bsn, String hash, String algo, URI location) throws Ex // Fall back to direct download // TODO: need some kind of download/cache service to avoid repeated // downloads - File tempFile = File.createTempFile("download", "jar"); - tempFile.deleteOnExit(); + Path tempFile = Files.createTempFile("download", "jar"); + tempFile.toFile().deleteOnExit(); - IO.copy(location.toURL(), tempFile); - return tempFile; + try (InputStream stream = location.toURL().openStream()) { + Files.copy(stream, tempFile); + } + return tempFile.toFile(); } } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoTemplateContentProvider.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoTemplateContentProvider.java index ae9bfab8f3..24b600f303 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoTemplateContentProvider.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoTemplateContentProvider.java @@ -12,7 +12,7 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package org.bndtools.core.ui.wizards.shared; +package org.eclipse.pde.bnd.ui.templating; import java.util.Arrays; import java.util.Collection; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoTemplateLabelProvider.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoTemplateLabelProvider.java index 0779513a55..8961796584 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoTemplateLabelProvider.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoTemplateLabelProvider.java @@ -13,16 +13,16 @@ * Sean Bright - ongoing enhancements * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package org.bndtools.core.ui.wizards.shared; +package org.eclipse.pde.bnd.ui.templating; import java.util.Map; import org.bndtools.templating.Category; import org.bndtools.templating.Template; -import org.bndtools.utils.jface.BoldStyler; import org.eclipse.jface.viewers.StyledCellLabelProvider; import org.eclipse.jface.viewers.StyledString; import org.eclipse.jface.viewers.ViewerCell; +import org.eclipse.pde.bnd.ui.BoldStyler; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/ReposTemplateLoader.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/ReposTemplateLoader.java index 78cda296ba..07253f1d87 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/ReposTemplateLoader.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/ReposTemplateLoader.java @@ -13,9 +13,9 @@ * BJ Hargrave - ongoing enhancements * Raymond Auge - ongoing enhancements * Fr Jeremy Krieg - ongoing enhancements + * Christoph Läubrich - adapt to PDE codebase *******************************************************************************/ -package org.bndtools.core.templating.repobased; - +package org.eclipse.pde.bnd.ui.templating; import static java.util.stream.Collectors.toList; import java.util.ArrayList; @@ -27,12 +27,18 @@ import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.stream.Collectors; import org.bndtools.templating.Template; import org.bndtools.templating.TemplateEngine; import org.bndtools.templating.TemplateLoader; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.IScopeContext; +import org.eclipse.pde.bnd.ui.preferences.ReposPreference; +import org.eclipse.pde.bnd.ui.preferences.ReposPreferencePage; import org.osgi.framework.Constants; import org.osgi.framework.namespace.IdentityNamespace; import org.osgi.resource.Capability; @@ -55,10 +61,8 @@ import aQute.bnd.osgi.resource.ResourceUtils; import aQute.bnd.osgi.resource.ResourceUtils.IdentityCapability; import aQute.bnd.repository.osgi.OSGiRepository; -import aQute.lib.strings.Strings; +import aQute.bnd.service.RepositoryPlugin; import aQute.service.reporter.Reporter; -import bndtools.central.Central; -import bndtools.preferences.BndPreferences; @Component(name = "org.bndtools.templating.repos", property = { "source=workspace", Constants.SERVICE_DESCRIPTION + "=Load templates from the Workspace and Repositories", @@ -72,12 +76,15 @@ public class ReposTemplateLoader implements TemplateLoader { private final ConcurrentMap engines = new ConcurrentHashMap<>(); - // for testing - Workspace workspace = null; + @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC) + private final List workspaces = new CopyOnWriteArrayList<>(); private PromiseFactory promiseFactory; private ExecutorService localExecutor = null; + @Reference(target = IScopeContext.BUNDLE_SCOPE_FILTER) + private IScopeContext bundleScope; + @Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY) void setExecutorService(ExecutorService executor) { this.promiseFactory = new PromiseFactory(Objects.requireNonNull(executor)); @@ -115,13 +122,15 @@ public Promise> findTemplates(String templateType, final Reporter .buildSyntheticRequirement(); // Try to get the repositories and BundleLocator from the workspace - List workspaceRepos; + List workspaceRepos = new ArrayList<>(); BundleLocator tmpLocator; try { - if (workspace == null) - workspace = Central.getWorkspace(); - workspaceRepos = workspace.getPlugins(Repository.class); - tmpLocator = new RepoPluginsBundleLocator(workspace.getRepositories()); + List wsRepo = new ArrayList<>(); + for (Workspace workspace : workspaces) { + workspaceRepos.addAll(workspace.getPlugins(Repository.class)); + wsRepo.addAll(workspace.getRepositories()); + } + tmpLocator = new RepoPluginsBundleLocator(wsRepo); } catch (Exception e) { workspaceRepos = Collections.emptyList(); tmpLocator = new DirectDownloadBundleLocator(); @@ -175,20 +184,19 @@ public Promise> findTemplates(String templateType, final Reporter } private void addPreferenceConfiguredRepos(List repos, Reporter reporter) { - BndPreferences bndPrefs = null; - try { - bndPrefs = new BndPreferences(); - } catch (Exception e) { - // e.printStackTrace(); - } - if (bndPrefs != null && bndPrefs.getEnableTemplateRepo()) { - List repoUris = bndPrefs.getTemplateRepoUriList(); - try { - OSGiRepository prefsRepo = loadRepo(repoUris, reporter); - repos.add(prefsRepo); - } catch (Exception ex) { - reporter.exception(ex, "Error loading preference repository: %s", repoUris); + IEclipsePreferences preferences = bundleScope.getNode(ReposPreference.TEMPLATE_LOADER_NODE); + if (preferences.getBoolean(ReposPreferencePage.KEY_ENABLE_TEMPLATE_REPOSITORIES, + ReposPreference.DEF_ENABLE_TEMPLATE_REPOSITORIES)) { + List list = ReposPreference.TEMPLATE_REPOSITORIES_PARSER + .apply(preferences.get(ReposPreference.KEY_TEMPLATE_REPO_URI_LIST, "")); + if (!list.isEmpty()) { + try { + OSGiRepository prefsRepo = loadRepo(list, reporter); + repos.add(prefsRepo); + } catch (Exception ex) { + reporter.exception(ex, "Error loading preference repository: %s", list); + } } } } @@ -196,6 +204,7 @@ private void addPreferenceConfiguredRepos(List repos, Reporter repor private OSGiRepository loadRepo(List uris, Reporter reporter) throws Exception { OSGiRepository repo = new OSGiRepository(); repo.setReporter(reporter); + Workspace workspace = workspaces.stream().findFirst().orElse(null); if (workspace != null) { repo.setRegistry(workspace); } else { @@ -204,8 +213,8 @@ private OSGiRepository loadRepo(List uris, Reporter reporter) throws Exc repo.setRegistry(p); } Map map = new HashMap<>(); - map.put("locations", Strings.join(uris)); + map.put("locations", uris.stream().collect(Collectors.joining(","))); repo.setProperties(map); return repo; } -} +} \ No newline at end of file diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/ProjectTemplateParam.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/ProjectTemplateParam.java index 1e4d44bd1e..c4913f27b9 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/ProjectTemplateParam.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/ProjectTemplateParam.java @@ -12,7 +12,7 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.wizards.project; +package org.eclipse.pde.bnd.ui.wizards; public enum ProjectTemplateParam { diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/TemplateParamsWizardPage.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/TemplateParamsWizardPage.java index d76a6307e6..bbc5fc7859 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/TemplateParamsWizardPage.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/TemplateParamsWizardPage.java @@ -13,8 +13,9 @@ * BJ Hargrave - ongoing enhancements * Fr Jeremy Krieg - ongoing enhancements * Scott Lewis - ongoing enhancements + * Christoph Läubrich - Adjust to PDE codebase *******************************************************************************/ -package org.bndtools.core.ui.wizards.shared; +package org.eclipse.pde.bnd.ui.wizards; import java.util.HashMap; import java.util.HashSet; @@ -24,11 +25,13 @@ import java.util.Set; import org.bndtools.templating.Template; +import org.eclipse.core.runtime.ILog; import org.eclipse.jface.fieldassist.ControlDecoration; import org.eclipse.jface.fieldassist.FieldDecorationRegistry; import org.eclipse.jface.preference.JFacePreferences; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.pde.bnd.ui.Resources; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; @@ -39,9 +42,7 @@ import org.osgi.service.metatype.AttributeDefinition; import org.osgi.service.metatype.ObjectClassDefinition; -import bndtools.Plugin; - -public class TemplateParamsWizardPage extends WizardPage implements ISkippableWizardPage { +public class TemplateParamsWizardPage extends WizardPage { private final Set fixedAttribs = new HashSet<>(); @@ -65,7 +66,7 @@ public TemplateParamsWizardPage(String[] fixedAttribs) { @Override public void createControl(Composite parent) { setTitle("Template Parameters"); - setImageDescriptor(Plugin.imageDescriptorFromPlugin("icons/bndtools-wizban.png")); //$NON-NLS-1$ + setImageDescriptor(Resources.getImageDescriptor("/icons/bndtools-wizban.png")); //$NON-NLS-1$ container = new Composite(parent, SWT.NONE); setControl(container); @@ -139,6 +140,7 @@ void updateUI() { for (Control fieldControl : fieldControls) { fieldControl.setEnabled(false); } + ILog.get().error("Error loading template metadata: ", e); } } currentPanel = panel; @@ -236,7 +238,6 @@ private boolean isToBeReplaced(String defaultValue) { return (defaultValue != null && defaultValue.startsWith("<") && defaultValue.endsWith(">")) ? true : false; } - @Override public boolean shouldSkip() { return skip; } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/ObjectFactory.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/ObjectFactory.java index c8de4c9645..1ab1eb2dc5 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/ObjectFactory.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/ObjectFactory.java @@ -29,6 +29,7 @@ * content can consist of schema derived interfaces and classes representing the * binding of schema type definitions, element declarations and model groups. * Factory methods for each of these are provided in this class. + *

* */ @XmlRegistry diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tad.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tad.java index 539f9b9c4a..9e01dc7598 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tad.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tad.java @@ -33,10 +33,6 @@ import jakarta.xml.bind.annotation.XmlType; /** - *

Java-Klasse für Tad complex type. - * - *

Das folgende Schemafragment gibt den erwarteten Content an, der in dieser Klasse enthalten ist. - * *

  * <complexType name="Tad">
  *   <complexContent>
diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tattribute.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tattribute.java
index 3e8e5f47cc..40e1184226 100644
--- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tattribute.java
+++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tattribute.java
@@ -33,10 +33,6 @@
 import jakarta.xml.bind.annotation.XmlType;
 
 /**
- * 

Java-Klasse für Tattribute complex type. - * - *

Das folgende Schemafragment gibt den erwarteten Content an, der in dieser Klasse enthalten ist. - * *

  * <complexType name="Tattribute">
  *   <complexContent>
diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tdesignate.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tdesignate.java
index 8d8475ec8f..45694c41d1 100644
--- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tdesignate.java
+++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tdesignate.java
@@ -32,10 +32,6 @@
 import jakarta.xml.bind.annotation.XmlType;
 
 /**
- * 

Java-Klasse für Tdesignate complex type. - * - *

Das folgende Schemafragment gibt den erwarteten Content an, der in dieser Klasse enthalten ist. - * *

  * <complexType name="Tdesignate">
  *   <complexContent>
diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Ticon.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Ticon.java
index 87e7b23aab..45390c2cb0 100644
--- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Ticon.java
+++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Ticon.java
@@ -33,10 +33,6 @@
 import jakarta.xml.bind.annotation.XmlType;
 
 /**
- * 

Java-Klasse für Ticon complex type. - * - *

Das folgende Schemafragment gibt den erwarteten Content an, der in dieser Klasse enthalten ist. - * *

  * <complexType name="Ticon">
  *   <complexContent>
diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tmetadata.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tmetadata.java
index 421834c774..e187012f20 100644
--- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tmetadata.java
+++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tmetadata.java
@@ -34,10 +34,6 @@
 import jakarta.xml.bind.annotation.XmlType;
 
 /**
- * 

Java-Klasse für Tmetadata complex type. - * - *

Das folgende Schemafragment gibt den erwarteten Content an, der in dieser Klasse enthalten ist. - * *

  * <complexType name="Tmetadata">
  *   <complexContent>
diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tobject.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tobject.java
index 6c7d27d87f..ee8771c96d 100644
--- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tobject.java
+++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tobject.java
@@ -33,10 +33,6 @@
 import jakarta.xml.bind.annotation.XmlType;
 
 /**
- * 

Java-Klasse für Tobject complex type. - * - *

Das folgende Schemafragment gibt den erwarteten Content an, der in dieser Klasse enthalten ist. - * *

  * <complexType name="Tobject">
  *   <complexContent>
diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tocd.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tocd.java
index a3b594ddcf..c121570580 100644
--- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tocd.java
+++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tocd.java
@@ -34,10 +34,6 @@
 import jakarta.xml.bind.annotation.XmlType;
 
 /**
- * 

Java-Klasse für Tocd complex type. - * - *

Das folgende Schemafragment gibt den erwarteten Content an, der in dieser Klasse enthalten ist. - * *

  * <complexType name="Tocd">
  *   <complexContent>
diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Toption.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Toption.java
index 6cd8d6c00e..b681ff3c31 100644
--- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Toption.java
+++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Toption.java
@@ -31,10 +31,6 @@
 import jakarta.xml.bind.annotation.XmlType;
 
 /**
- * 

Java-Klasse für Toption complex type. - * - *

Das folgende Schemafragment gibt den erwarteten Content an, der in dieser Klasse enthalten ist. - * *

  * <complexType name="Toption">
  *   <complexContent>
diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tscalar.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tscalar.java
index 29d41cdd9a..1757f90728 100644
--- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tscalar.java
+++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/osgi/xmlns/metatype/v1_4/Tscalar.java
@@ -20,10 +20,6 @@
 
 
 /**
- * 

Java-Klasse für Tscalar. - * - *

Das folgende Schemafragment gibt den erwarteten Content an, der in dieser Klasse enthalten ist. - *

*

  * <simpleType name="Tscalar">
  *   <restriction base="{http://www.w3.org/2001/XMLSchema}string">