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 de560dd00c..cb92e4f935 100644 --- a/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF +++ b/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF @@ -3,8 +3,9 @@ Bundle-ManifestVersion: 2 Bundle-Name: Generic UI components related to BND Bundle-SymbolicName: org.eclipse.pde.bnd.ui;singleton:=true Bundle-Vendor: Eclipse.org -Bundle-Version: 1.0.0.qualifier +Bundle-Version: 1.1.0.qualifier Export-Package: org.eclipse.pde.bnd.ui.autocomplete;version="1.0.0";x-friends:="org.eclipse.pde.ui", + org.eclipse.pde.bnd.ui.plugins;x-internal:=true, org.eclipse.pde.bnd.ui.preferences;version="1.0.0";x-friends:="org.eclipse.pde.ui", org.eclipse.pde.bnd.ui.quickfix;version="1.0.0";x-friends:="org.eclipse.pde.ui", org.eclipse.pde.bnd.ui.templating;version="1.0.0";x-friends:="org.eclipse.pde.ui", @@ -15,16 +16,30 @@ Import-Package: aQute.bnd.build;version="4.5.0", aQute.bnd.exceptions;version="3.0.0", aQute.bnd.header;version="2.6.0", aQute.bnd.http;version="2.0.0", + aQute.bnd.maven;version="[3.4.0,4.0.0]", + aQute.bnd.memoize;version="[2.0.0,3.0.0]", aQute.bnd.osgi;version="[7.0.0,8.0.0)", + aQute.bnd.osgi.repository;version="[3.1.0,4.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", aQute.bnd.service;version="4.8.0", + aQute.bnd.service.clipboard;version="[1.0.0,2.0.0]", + aQute.bnd.service.progress;version="[1.3.0,2.0.0]", + aQute.bnd.service.repository;version="[1.6.0,2.0.0]", + aQute.bnd.version;version="[2.3.0,3.0.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.api;version="[3.1.0,4.0.0]", + org.bndtools.headless.build.manager.api;version="[1.1.0,2.0.0]", org.bndtools.templating;version="[2.0.0,3.0.0)", org.bndtools.templating.util;version="[1.0.0,2.0.0)", + org.bndtools.versioncontrol.ignores.manager.api;version="[1.0.0,2.0.0]", + org.osgi.namespace.contract;version="[1.0.0,2.0.0]", + org.osgi.namespace.extender;version="[1.0.0,2.0.0]", + org.osgi.namespace.service;version="[1.0.0,2.0.0]", + org.osgi.service.event;version="[1.4.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)", @@ -37,11 +52,20 @@ Require-Bundle: org.eclipse.jdt.ui, org.eclipse.swt, org.eclipse.jface, org.eclipse.ui.workbench, - org.eclipse.core.expressions + org.eclipse.core.expressions, + org.eclipse.ui.forms, + org.eclipse.e4.core.services, + org.eclipse.ui;bundle-version="3.205.100", + org.eclipse.ui.ide;bundle-version="3.22.100", + org.eclipse.core.filesystem, + org.eclipse.team.core, + org.eclipse.core.databinding.observable Automatic-Module-Name: org.eclipse.pde.bnd.ui Bundle-Activator: org.eclipse.pde.bnd.ui.Resources Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Service-Component: OSGI-INF/org.bndtools.templating.repos.xml, OSGI-INF/org.eclipse.pde.bnd.ui.internal.Auxiliary.xml, - OSGI-INF/org.eclipse.pde.bnd.ui.internal.TemplateAdapter.xml + OSGI-INF/org.eclipse.pde.bnd.ui.internal.SWTClipboard.xml, + OSGI-INF/org.eclipse.pde.bnd.ui.internal.TemplateAdapter.xml, + OSGI-INF/org.eclipse.pde.bnd.ui.plugins.RepositoriesViewRefresher.xml diff --git a/ui/org.eclipse.pde.bnd.ui/plugin.xml b/ui/org.eclipse.pde.bnd.ui/plugin.xml index a4983a6807..f2ffd41f42 100644 --- a/ui/org.eclipse.pde.bnd.ui/plugin.xml +++ b/ui/org.eclipse.pde.bnd.ui/plugin.xml @@ -28,4 +28,12 @@ type="org.eclipse.core.resources.IProject"> + + + + + diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/Central.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/Central.java index 24ff747bd7..8c20deaf29 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/Central.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/Central.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013, 2022 bndtools project and others. + * Copyright (c) 2013, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -19,8 +19,9 @@ * Raymond Augé - ongoing enhancements * Fr Jeremy Krieg - ongoing enhancements * Jürgen Albert - ongoing enhancements + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.central; +package org.eclipse.pde.bnd.ui; import static aQute.bnd.exceptions.FunctionWithException.asFunction; @@ -28,22 +29,17 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.concurrent.Callable; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; import java.util.function.BooleanSupplier; -import java.util.function.Supplier; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.bndtools.api.BndtoolsConstants; -import org.bndtools.api.IStartupParticipant; import org.bndtools.api.ModelListener; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; @@ -52,6 +48,7 @@ import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -62,155 +59,27 @@ import org.eclipse.core.runtime.Status; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.swt.widgets.Display; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.ServiceRegistration; -import org.osgi.util.function.Consumer; -import org.osgi.util.promise.Deferred; -import org.osgi.util.promise.Promise; +import org.eclipse.pde.bnd.ui.plugins.RepositoriesViewRefresher; import org.osgi.util.promise.PromiseFactory; -import org.slf4j.LoggerFactory; -import aQute.bnd.annotation.plugin.InternalPluginDefinition; import aQute.bnd.build.Project; import aQute.bnd.build.Workspace; import aQute.bnd.exceptions.BiFunctionWithException; import aQute.bnd.exceptions.Exceptions; import aQute.bnd.exceptions.FunctionWithException; import aQute.bnd.exceptions.RunnableWithException; -import aQute.bnd.header.Attrs; -import aQute.bnd.memoize.Memoize; -import aQute.bnd.osgi.Constants; import aQute.bnd.osgi.Processor; import aQute.bnd.service.Refreshable; import aQute.bnd.service.RepositoryPlugin; import aQute.bnd.service.progress.ProgressPlugin.Task; import aQute.bnd.service.progress.TaskManager; -import aQute.lib.io.IO; -import aQute.libg.ints.IntCounter; import aQute.service.reporter.Reporter; -import bndtools.Plugin; -import bndtools.central.RepositoriesViewRefresher.RefreshModel; -import bndtools.preferences.BndPreferences; -public class Central implements IStartupParticipant { +public class Central { - private static final org.slf4j.Logger logger = LoggerFactory - .getLogger(Central.class); - private static volatile Central instance = null; - private static final Deferred anyWorkspaceDeferred = promiseFactory() - .deferred(); - private static volatile Deferred cnfWorkspaceDeferred = promiseFactory() - .deferred(); - private static final Memoize workspace = Memoize - .supplier(Central::createWorkspace); - - private static final Supplier eclipseWorkspaceRepository = Memoize - .supplier(EclipseWorkspaceRepository::new); - - private static Auxiliary auxiliary; - - static final AtomicBoolean indexValid = new AtomicBoolean(false); - - private final BundleContext bundleContext; - private final Map javaProjectToModel = new HashMap<>(); - private final List listeners = new CopyOnWriteArrayList<>(); - - private RepositoryListenerPluginTracker repoListenerTracker; - private final InternalPluginTracker internalPlugins; - - @SuppressWarnings("unused") - private static WorkspaceRepositoryChangeDetector workspaceRepositoryChangeDetector; - - private static RepositoriesViewRefresher repositoriesViewRefresher = new RepositoriesViewRefresher(); - private static BundleContext context; - private static ServiceRegistration workspaceService; - - static { - try { - context = FrameworkUtil.getBundle(Central.class) - .getBundleContext(); - Bundle bndlib = FrameworkUtil.getBundle(Workspace.class); - auxiliary = new Auxiliary(context, bndlib); - - } catch (Exception e) { - // ignore - } - } - - /** - * WARNING: Do not instantiate this class. It must be public to allow - * instantiation by the Eclipse registry, but it is not intended for direct - * creation by clients. Instead call Central.getInstance(). - */ - @Deprecated - public Central() { - bundleContext = FrameworkUtil.getBundle(Central.class) - .getBundleContext(); - internalPlugins = new InternalPluginTracker(bundleContext); - - } - - @Override - public void start() { - instance = this; - - repoListenerTracker = new RepositoryListenerPluginTracker(bundleContext); - repoListenerTracker.open(); - internalPlugins.open(); - } - - @Override - public void stop() { - repoListenerTracker.close(); - ServiceRegistration service = workspaceService; - if (service != null) { - service.unregister(); - } - instance = null; - - Workspace ws = workspace.peek(); - if (ws != null) { - ws.close(); - } - - if (auxiliary != null) - try { - auxiliary.close(); - } catch (Exception e) { - throw new RuntimeException(e); - } - internalPlugins.close(); - } - - public static Central getInstance() { - return instance; - } - - public Project getModel(IJavaProject project) { - try { - Project model = javaProjectToModel.get(project); - if (model == null) { - try { - model = getProject(project.getProject()); - } catch (IllegalArgumentException e) { - // initialiseWorkspace(); - // model = Central.getProject(projectDir); - return null; - } - if (model != null) { - javaProjectToModel.put(project, model); - } - } - return model; - } catch (Exception e) { - // TODO do something more useful here - throw new RuntimeException(e); - } - } + public static final String BNDTOOLS_NATURE = "bndtools.core.bndnature"; + + private final static List listeners = new CopyOnWriteArrayList<>(); public static IFile getWorkspaceBuildFile() throws Exception { IWorkspaceRoot wsroot = ResourcesPlugin.getWorkspace() @@ -221,203 +90,10 @@ public static IFile getWorkspaceBuildFile() throws Exception { return cnf.getFile(Workspace.BUILDFILE); } - public static EclipseWorkspaceRepository getEclipseWorkspaceRepository() { - return eclipseWorkspaceRepository.get(); - } - - public synchronized static RepositoryPlugin getWorkspaceRepository() throws Exception { - return getWorkspace().getWorkspaceRepository(); - } - - public static Workspace getWorkspaceIfPresent() { - try { - if (getInstance() == null) - return null; - return getWorkspace(); - } catch (IllegalStateException e) { - throw e; - } catch (Exception e) { - return null; - } - } - - public static Workspace getWorkspace() throws Exception { - if (getInstance() == null) { - throw new IllegalStateException("Central is not initialised"); - } - final Workspace ws; - Consumer afterLock = null; - synchronized (workspace) { - if (workspace.peek() == null) { // No workspace has been created - ws = workspace.get(); - // Resolve with new workspace - afterLock = tryResolve(anyWorkspaceDeferred); - if (!ws.isDefaultWorkspace()) { - afterLock = afterLock.andThen(tryResolve(cnfWorkspaceDeferred)); - } - } else { - ws = workspace.get(); - // get the parent directory of the "cnf" project, if there is - // one - File workspaceDirectory = getWorkspaceDirectory(); - // Check to see if we need to adjust it... - if (workspaceDirectory != null && !workspaceDirectory.equals(ws.getBase())) { - // There is a "cnf" project and the current workspace is - // not the same as the directory the cnf project is in, - // so switch the workspace to the directory - afterLock = Central::adjustWorkspace; - } else if (workspaceDirectory == null && !ws.isDefaultWorkspace()) { - // There is no "cnf" project and the current workspace is - // not the default, so switch the workspace to the default - afterLock = Central::adjustWorkspace; - } - } - } - if (afterLock != null) { // perform after lock action - afterLock.accept(ws); - } - return ws; - } - - private static void adjustWorkspace(Workspace ws) throws Exception { - // Get write lock on another thread - promiseFactory().submit(() -> { - Consumer afterLock = ws.writeLocked(() -> { - // get the parent directory of the "cnf" project, if there is - // one - File workspaceDirectory = getWorkspaceDirectory(); - // Check to see if we need to convert it... - if (workspaceDirectory != null && !workspaceDirectory.equals(ws.getBase())) { - // There is a "cnf" project and the current workspace is - // not the same as the directory the cnf project is in, - // so switch the workspace to the directory - ws.setFileSystem(workspaceDirectory, Workspace.CNFDIR); - ws.forceRefresh(); - ws.refresh(); - ws.refreshProjects(); - return tryResolve(cnfWorkspaceDeferred); - } else if (workspaceDirectory == null && !ws.isDefaultWorkspace()) { - // There is no "cnf" project and the current workspace is - // not the default, so switch the workspace to the default - cnfWorkspaceDeferred = promiseFactory().deferred(); - ws.setFileSystem(Workspace.BND_DEFAULT_WS, Workspace.CNFDIR); - ws.forceRefresh(); - ws.refresh(); - ws.refreshProjects(); - return null; - } - return null; - }); - if (afterLock != null) { // perform after lock action - afterLock.accept(ws); - } - return ws; - }); - } - - private static Consumer tryResolve(Deferred deferred) { - return value -> { - try { - deferred.resolve(value); - } catch (IllegalStateException e) { - // ignore race for already resolved - } - }; - } - - private static Workspace createWorkspace() { - Workspace ws = null; - try { - Workspace.setDriver(Constants.BNDDRIVER_ECLIPSE); - Workspace.addGestalt(Constants.GESTALT_INTERACTIVE, new Attrs()); - File workspaceDirectory = getWorkspaceDirectory(); - if (workspaceDirectory == null) { - // There is no "cnf" project so we create a default - // workspace - ws = Workspace.createDefaultWorkspace(); - } else { - // There is a "cnf" project so we create a normal - // workspace - ws = new Workspace(workspaceDirectory); - } - - ws.setOffline(new BndPreferences().isWorkspaceOffline()); - - ws.addBasicPlugin(new SWTClipboard()); - ws.addBasicPlugin(getInstance().repoListenerTracker); - ws.addBasicPlugin(getEclipseWorkspaceRepository()); - ws.addBasicPlugin(new JobProgress()); - - // Initialize projects in synchronized block - ws.getBuildOrder(); - - workspaceRepositoryChangeDetector = new WorkspaceRepositoryChangeDetector(ws); - workspaceService = context.registerService(Workspace.class, ws, null); - return ws; - } catch (Exception e) { - if (ws != null) { - ws.close(); - } - logger.error("Workspace creation failure", e); - throw Exceptions.duck(e); - } - } - - public static Promise onAnyWorkspace(Consumer callback) { - return callback(anyWorkspaceDeferred.getPromise(), callback, "onAnyWorkspace callback failed"); - } - - public static Promise onCnfWorkspace(Consumer callback) { - return callback(cnfWorkspaceDeferred.getPromise(), callback, "onCnfWorkspace callback failed"); - } - - private static Promise callback(Promise promise, Consumer callback, - String failureMessage) { - return promise.thenAccept(callback) - .onFailure(failure -> logger.error(failureMessage, failure)); - } - - public static Promise onAnyWorkspaceAsync(Consumer callback) { - return callbackAsync(anyWorkspaceDeferred.getPromise(), callback, "onAnyWorkspaceAsync callback failed"); - } - - public static Promise onCnfWorkspaceAsync(Consumer callback) { - return callbackAsync(cnfWorkspaceDeferred.getPromise(), callback, "onCnfWorkspaceAsync callback failed"); - } - - private static Promise callbackAsync(Promise promise, Consumer callback, - String failureMessage) { - return promise.then(resolved -> { - Workspace workspace = resolved.getValue(); - Deferred completion = promiseFactory().deferred(); - Display.getDefault() - .asyncExec(() -> { - try { - callback.accept(workspace); - completion.resolve(workspace); - } catch (Throwable e) { - completion.fail(e); - } - }); - return completion.getPromise(); - }) - .onFailure(failure -> logger.error(failureMessage, failure)); - } - public static PromiseFactory promiseFactory() { return Processor.getPromiseFactory(); } - public static boolean hasAnyWorkspace() { - return anyWorkspaceDeferred.getPromise() - .isDone(); - } - - public static boolean hasCnfWorkspace() { - return cnfWorkspaceDeferred.getPromise() - .isDone(); - } - /** * Returns the Bnd Workspace directory IF there is a "cnf" project * in the Eclipse workspace. @@ -448,7 +124,7 @@ private static File getWorkspaceDirectory() throws CoreException { * @return true if a workspace directory */ public static boolean isWorkspace(File directory) { - File build = IO.getFile(directory, "cnf/build.bnd"); + File build = new File(directory, "cnf/build.bnd"); return build.isFile(); } @@ -474,7 +150,7 @@ public void changed(Project model) { try { m.modelChanged(model); } catch (Exception e) { - logger.error("While notifying ModelListener {} of change to project {}", m, model, e); + ILog.get().error("While notifying ModelListener " + m + " of change to project " + model, e); } } } @@ -505,19 +181,21 @@ public static Optional getProject(Project model) { .findFirst(); } - public static IPath toPath(File file) throws Exception { + public static IPath toPath(File file, Workspace workspace) throws Exception { File absolute = file.getCanonicalFile(); return toFullPath(absolute).orElseGet(() -> { - try { - String workspacePath = getWorkspace().getBase() - .getAbsolutePath(); - String absolutePath = absolute.getPath(); - if (absolutePath.startsWith(workspacePath)) - return new Path(absolutePath.substring(workspacePath.length())); - return null; - } catch (Exception e) { - throw Exceptions.duck(e); + if (workspace != null) { + try { + String workspacePath = workspace.getBase().getAbsolutePath(); + String absolutePath = absolute.getPath(); + if (absolutePath.startsWith(workspacePath)) + return new Path(absolutePath.substring(workspacePath.length())); + return null; + } catch (Exception e) { + throw Exceptions.duck(e); + } } + return null; }); } @@ -561,13 +239,16 @@ public static void refresh(IPath path) { } } } catch (Exception e) { - logger.error("While refreshing path {}", path, e); + ILog.get().error("While refreshing path " + path, e); } } - public static void refreshPlugins() throws Exception { + public static void refreshPlugins(Workspace workspace) throws Exception { + if (workspace == null) { + return; + } List refreshedFiles = new ArrayList<>(); - List rps = getWorkspace().getPlugins(Refreshable.class); + List rps = workspace.getPlugins(Refreshable.class); boolean changed = false; boolean repoChanged = false; for (Refreshable rp : rps) { @@ -595,29 +276,32 @@ public static void refreshPlugins() throws Exception { } if (repoChanged) { - repositoriesViewRefresher.repositoriesRefreshed(); + RepositoriesViewRefresher.refreshRepositories(null); } - refreshProjects(); + refreshProjects(workspace); } } - public static void refreshPlugin(Refreshable plugin) throws Exception { - refreshPlugin(plugin, false); + public static void refreshPlugin(Workspace workspace, Refreshable plugin) throws Exception { + refreshPlugin(workspace, plugin, false); } - public static void refreshPlugin(Refreshable plugin, boolean force) throws Exception { + public static void refreshPlugin(Workspace workspace, Refreshable plugin, boolean force) throws Exception { boolean refresh = plugin.refresh(); if (refresh || force) { refreshFile(plugin.getRoot()); if (plugin instanceof RepositoryPlugin) { - repositoriesViewRefresher.repositoryRefreshed((RepositoryPlugin) plugin); + RepositoriesViewRefresher.refreshRepositories((RepositoryPlugin) plugin); } - refreshProjects(); + refreshProjects(workspace); } } - public static void refreshProjects() throws Exception { - Collection allProjects = getWorkspace().getAllProjects(); + public static void refreshProjects(Workspace workspace) throws Exception { + if (workspace == null) { + return; + } + Collection allProjects = workspace.getAllProjects(); // Mark all projects changed before we notify model listeners // since the listeners can take actions on project's other than // the specified project. @@ -625,11 +309,11 @@ public static void refreshProjects() throws Exception { p.setChanged(); } for (Project p : allProjects) { - for (ModelListener m : getInstance().listeners) { + for (ModelListener m : listeners) { try { m.modelChanged(p); } catch (Exception e) { - logger.error("While notifying ModelListener {} of change to project {}", m, p, e); + ILog.get().error("While notifying ModelListener " + m + " of change to project " + p, e); } } } @@ -660,32 +344,22 @@ public static void refresh(Project p) throws Exception { .refreshLocal(IResource.DEPTH_INFINITE, null); } - public void close() { - repositoriesViewRefresher.close(); - } - - public static void invalidateIndex() { - indexValid.set(false); - } - - public static boolean needsIndexing() { - return indexValid.compareAndSet(false, true); - } - public static Project getProject(File projectDir) throws Exception { - return getWorkspace().getProjectFromFile(projectDir); + public static Project getProject(Workspace workspace, File projectDir) throws Exception { + return workspace.getProjectFromFile(projectDir); } - public static Project getProject(IProject p) throws Exception { + @SuppressWarnings("resource") + public static Project getProject(Workspace workspace, IProject p) throws Exception { return Optional.ofNullable(p.getLocation()) .map(IPath::toFile) - .map(asFunction(Central::getProject)) + .map(asFunction(f -> getProject(workspace, f))) .orElse(null); } public static boolean isBndProject(IProject project) { return Optional.ofNullable(project) - .map(asFunction(p -> p.getNature(Plugin.BNDTOOLS_NATURE))) + .map(asFunction(p -> p.getNature(BNDTOOLS_NATURE))) .isPresent(); } @@ -745,7 +419,7 @@ public void abort() { } }; List after = new ArrayList<>(); - MultiStatus status = new MultiStatus(Plugin.PLUGIN_ID, 0, + MultiStatus status = new MultiStatus(Central.class, 0, "Errors occurred while calling bndCall after actions"); try { Callable with = () -> TaskManager.with(task, () -> callable.apply((name, runnable) -> after.add(() -> { @@ -795,48 +469,22 @@ public static IStatus toStatus(Processor processor, String message) { array, message, null); } - /** - * Register a viewer with repositories - */ - - public static void addRepositoriesViewer(TreeViewer viewer, RepositoriesViewRefresher.RefreshModel model) { - repositoriesViewRefresher.addViewer(viewer, model); - } - - /** - * Unregister a viewer with repositories - */ - public static void removeRepositoriesViewer(TreeViewer viewer) { - repositoriesViewRefresher.removeViewer(viewer); - } - - public static void setRepositories(TreeViewer viewer, RefreshModel model) { - repositoriesViewRefresher.setRepositories(viewer, model); - } - public static boolean refreshFiles(Reporter reporter, Collection files, IProgressMonitor monitor, boolean derived) { - IntCounter errors = new IntCounter(); + AtomicInteger errors = new AtomicInteger(); files.forEach(t -> { try { Central.refreshFile(t, monitor, derived); } catch (CoreException e) { - errors.inc(); + errors.incrementAndGet(); if (reporter != null) reporter.error("failed to refresh %s : %s", t, Exceptions.causes(e)); else throw Exceptions.duck(e); } }); - return errors.isZero(); + return errors.get() == 0; } - public static List getInternalPluginDefinitions() { - return instance.internalPlugins.getTracked() - .values() - .stream() - .flatMap(Collection::stream) - .collect(Collectors.toList()); - } } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/EditorUtils.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/EditorUtils.java index 6ccf0024fd..e15b42a068 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/EditorUtils.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/EditorUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2023 bndtools project and others. + * Copyright (c) 2010, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -13,12 +13,12 @@ * BJ Hargrave - ongoing enhancements * Christoph Rueger - ongoing enhancements * Peter Kriens - ongoing enhancements + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.utils; +package org.eclipse.pde.bnd.ui; import java.lang.reflect.InvocationTargetException; -import org.bndtools.core.ui.icons.Icons; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.IAction; @@ -73,7 +73,7 @@ public void run() { }; btn.setEnabled(true); btn.setToolTipText(tooltipText); - btn.setImageDescriptor(Icons.desc("help")); + btn.setImageDescriptor(Resources.getImageDescriptor("help.gif")); return btn; } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/FileExtensionFilter.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/FileExtensionFilter.java index 64cae5f7e9..94ba7f01b3 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/FileExtensionFilter.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/FileExtensionFilter.java @@ -12,7 +12,7 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.utils; +package org.eclipse.pde.bnd.ui; import java.util.Locale; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/FilterPanelPart.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/FilterPanelPart.java index 8077a1b839..715562147f 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/FilterPanelPart.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/FilterPanelPart.java @@ -15,7 +15,7 @@ * BJ Hargrave - ongoing enhancements * Peter Kriens - ongoing enhancements *******************************************************************************/ -package org.bndtools.utils.swt; +package org.eclipse.pde.bnd.ui; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HelpButtons.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HelpButtons.java index 1149f544e9..7848e8d67a 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HelpButtons.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HelpButtons.java @@ -11,10 +11,10 @@ * Contributors: * Christoph Rueger - initial API and implementation *******************************************************************************/ -package bndtools.editor.common; +package org.eclipse.pde.bnd.ui; -import static bndtools.utils.EditorUtils.createHelpButton; -import static bndtools.utils.EditorUtils.createHelpButtonWithText; +import static org.eclipse.pde.bnd.ui.EditorUtils.createHelpButton; +import static org.eclipse.pde.bnd.ui.EditorUtils.createHelpButtonWithText; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.ActionContributionItem; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HierarchicalLabel.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HierarchicalLabel.java index b4e620cddc..cc47381d97 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HierarchicalLabel.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HierarchicalLabel.java @@ -11,7 +11,7 @@ * Contributors: * Christoph Rueger - initial API and implementation *******************************************************************************/ -package bndtools.utils; +package org.eclipse.pde.bnd.ui; import java.util.ArrayList; import java.util.Arrays; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HierarchicalMenu.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HierarchicalMenu.java index 41e59f618d..2eb5c4a68e 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HierarchicalMenu.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HierarchicalMenu.java @@ -11,7 +11,7 @@ * Contributors: * Christoph Rueger - initial API and implementation *******************************************************************************/ -package bndtools.utils; +package org.eclipse.pde.bnd.ui; import java.util.ArrayList; import java.util.LinkedHashMap; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HyperlinkStyler.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HyperlinkStyler.java index 0930529ae0..548f9b8628 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HyperlinkStyler.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/HyperlinkStyler.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.viewers.StyledString.Styler; import org.eclipse.swt.SWT; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/LabelParser.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/LabelParser.java index 26e13d8a9c..fb3ddf36c6 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/LabelParser.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/LabelParser.java @@ -11,7 +11,7 @@ * Contributors: * Christoph Rueger - initial API and implementation *******************************************************************************/ -package bndtools.utils; +package org.eclipse.pde.bnd.ui; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/RefreshFileJob.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/RefreshFileJob.java index eebac70ad1..a2dd4a4d19 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/RefreshFileJob.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/RefreshFileJob.java @@ -14,7 +14,7 @@ * Carter Smithhart - ongoing enhancements * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.central; +package org.eclipse.pde.bnd.ui; import java.io.File; import java.util.Collections; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/RepositoryUtils.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/RepositoryUtils.java index 8ee63d86a0..0958979673 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/RepositoryUtils.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/RepositoryUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013, 2021 bndtools project and others. + * Copyright (c) 2013, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -15,8 +15,9 @@ * Sean Bright - ongoing enhancements * Peter Kriens - ongoing enhancements * Raymond Augé - ongoing enhancements + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.central; +package org.eclipse.pde.bnd.ui; import java.util.ArrayList; import java.util.Collection; @@ -53,17 +54,10 @@ public class RepositoryUtils { }, Objects::nonNull); } - public static List listRepositories(boolean hideCache) { - Workspace workspace; - try { - workspace = Central.getWorkspace(); - } catch (Exception e1) { + public static List listRepositories(final Workspace localWorkspace, final boolean hideCache) { + if (localWorkspace == null) { return Collections.emptyList(); } - return listRepositories(workspace, hideCache); - } - - public static List listRepositories(final Workspace localWorkspace, final boolean hideCache) { try { return localWorkspace.readLocked(() -> { List plugins = localWorkspace.getPlugins(RepositoryPlugin.class); @@ -72,9 +66,10 @@ public static List listRepositories(final Workspace localWorks // Add the workspace repo if the provided workspace == the // global bnd workspace - Workspace bndWorkspace = Central.getWorkspaceIfPresent(); - if ((bndWorkspace == localWorkspace) && !bndWorkspace.isDefaultWorkspace()) - repos.add(Central.getWorkspaceRepository()); + // TODO +// Workspace bndWorkspace = Central.getWorkspaceIfPresent(); +// if ((bndWorkspace == localWorkspace) && !bndWorkspace.isDefaultWorkspace()) +// repos.add(Central.getWorkspaceRepository()); // Add the repos from the provided workspace for (RepositoryPlugin plugin : plugins) { @@ -89,7 +84,7 @@ public static List listRepositories(final Workspace localWorks for (RepositoryPlugin repo : repos) { if (repo instanceof RegistryPlugin) { RegistryPlugin registry = (RegistryPlugin) repo; - registry.setRegistry(bndWorkspace); + registry.setRegistry(localWorkspace); } } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/ResourceUtils.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/ResourceUtils.java index 40f4f118b6..684e60d122 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/ResourceUtils.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/ResourceUtils.java @@ -16,7 +16,7 @@ * Rüdiger Herrmann - ongoing enhancements * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package org.bndtools.utils.resources; +package org.eclipse.pde.bnd.ui; import java.io.File; import java.net.MalformedURLException; @@ -95,7 +95,6 @@ public static Version getVersion(Resource resource) throws IllegalArgumentExcept return getVersion(getIdentityCapability(resource)); } - @SuppressWarnings("unused") public static Capability getContentCapability(Resource resource) throws IllegalArgumentException { List caps = resource.getCapabilities(ContentNamespace.CONTENT_NAMESPACE); 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 00dc960c4c..6953225c92 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2023 Christoph Läubrich and others. + * Copyright (c) 2023, 2024 Christoph Läubrich and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -13,17 +13,28 @@ *******************************************************************************/ package org.eclipse.pde.bnd.ui; +import java.net.URL; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.PlatformUI; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; +/** + * Manages resources that are bound to the life-cycle of the bundle like images + * or threads + */ public class Resources implements BundleActivator { private static ImageRegistry imageRegistry; + private static ScheduledExecutorService scheduler; + @Override public void start(BundleContext context) throws Exception { @@ -38,19 +49,53 @@ public synchronized static ImageDescriptor getImageDescriptor(String key) { ImageRegistry registry = getImageRegistry(); ImageDescriptor descriptor = registry.getDescriptor(key); if (descriptor == null) { - ImageDescriptor fromURL = ImageDescriptor.createFromURL(Resources.class.getResource(key)); + ImageDescriptor fromURL = ImageDescriptor.createFromURL(getImageUrl(key)); registry.put(key, fromURL); return fromURL; } return descriptor; } + private static URL getImageUrl(String key) { + URL resource = Resources.class.getResource(key); + if (resource != null) { + return resource; + } + resource = Resources.class.getResource("/icons/" + key); + if (resource != null) { + return resource; + } + resource = Resources.class.getResource("/icons/" + key + ".gif"); + if (resource != null) { + return resource; + } + resource = Resources.class.getResource("/icons/" + key + ".png"); + if (resource != null) { + return resource; + } + return null; + } + public synchronized static Image getImage(String key) { + if (key.startsWith("$")) { + try { + return PlatformUI.getWorkbench().getSharedImages().getImage(key); + } catch (IllegalStateException e) { + // don't care then... + } + } ImageRegistry registry = getImageRegistry(); getImageDescriptor(key); // make sure the descriptor is added! return registry.get(key); } + public synchronized static ScheduledExecutorService getScheduler() { + if (scheduler == null) { + scheduler = Executors.newScheduledThreadPool(4); + } + return scheduler; + } + private synchronized static ImageRegistry getImageRegistry() { if (imageRegistry == null) { imageRegistry = new ImageRegistry(Display.getCurrent()); @@ -63,6 +108,10 @@ private synchronized static void disposeResources() { imageRegistry.dispose(); imageRegistry = null; } + if (scheduler != null) { + scheduler.shutdownNow(); + scheduler = null; + } } } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/SWTUtil.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/SWTUtil.java index 23202c33f6..c4a1022035 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/SWTUtil.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/SWTUtil.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 org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.layout.PixelConverter; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/SelectionDragAdapter.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/SelectionDragAdapter.java index 75457c98b9..2b23f699e7 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/SelectionDragAdapter.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/SelectionDragAdapter.java @@ -13,7 +13,7 @@ * BJ Hargrave - ongoing enhancements * Raymond Augé - ongoing enhancements *******************************************************************************/ -package bndtools.utils; +package org.eclipse.pde.bnd.ui; import java.util.Iterator; @@ -21,14 +21,13 @@ import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.Viewer; +import org.eclipse.pde.bnd.ui.model.repo.RepositoryBundle; +import org.eclipse.pde.bnd.ui.model.repo.RepositoryBundleVersion; +import org.eclipse.pde.bnd.ui.model.repo.RepositoryResourceElement; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.swt.dnd.DragSourceListener; import org.eclipse.swt.dnd.TextTransfer; -import bndtools.model.repo.RepositoryBundle; -import bndtools.model.repo.RepositoryBundleVersion; -import bndtools.model.repo.RepositoryResourceElement; - public class SelectionDragAdapter implements DragSourceListener { private final LocalSelectionTransfer selectionTransfer = LocalSelectionTransfer.getTransfer(); diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/TeamUtils.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/TeamUtils.java index a8b422917f..aaa8fde5fa 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/TeamUtils.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/TeamUtils.java @@ -12,7 +12,7 @@ * Ferry Huberts - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.team; +package org.eclipse.pde.bnd.ui; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.team.core.RepositoryProvider; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/Workspaces.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/Workspaces.java new file mode 100644 index 0000000000..55c02c67c7 --- /dev/null +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/Workspaces.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2024 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; + +import java.io.File; +import java.util.Optional; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.Adapters; +import org.eclipse.core.runtime.IPath; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.util.tracker.ServiceTracker; + +import aQute.bnd.build.Project; +import aQute.bnd.build.Workspace; + +public class Workspaces { + + private static ServiceTracker tracker; + + public static Optional getWorkspace(IProject project) { + if (project != null) { + Project bndProject = Adapters.adapt(project, Project.class); + if (bndProject != null) { + return Optional.ofNullable(bndProject.getWorkspace()); + } else { + IFile bndFile = project.getFile(Project.BNDFILE); + if (bndFile.exists()) { + IPath location = bndFile.getLocation(); + if (location != null) { + File file = location.toFile(); + if (file != null) { + try { + Project nativeProject = Workspace.getProject(file.getParentFile()); + if (nativeProject != null) { + return Optional.ofNullable(nativeProject.getWorkspace()); + } + } catch (Exception e) { + } + } + } + } + } + } + return Optional.empty(); + } + + public static synchronized Optional getGlobalWorkspace() { + // TODO the UI should support display multiple workspaces and give the user a + // choice instead of simply using the highest ranked! + if (tracker == null) { + Bundle bundle = FrameworkUtil.getBundle(Workspaces.class); + if (bundle == null) { + return Optional.empty(); + } + BundleContext bundleContext = bundle.getBundleContext(); + if (bundleContext == null) { + return Optional.empty(); + } + tracker = new ServiceTracker<>(bundleContext, Workspace.class, null); + tracker.open(); + } + return Optional.ofNullable(tracker.getService()); + } + + public static String getName(Workspace workspace) { + if (workspace == null) { + return null; + } + String name = workspace.get("workspaceName"); + if (name != null && !name.isBlank()) { + return name; + } + return workspace.getBase().getName(); + } + + public static String getDescription(Workspace workspace) { + if (workspace == null) { + return null; + } + String name = workspace.get("workspaceDescription"); + if (name != null && !name.isBlank()) { + return name; + } + return String.format("Workspace at location %s", workspace.getBase().getAbsolutePath()); + } +} diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/BndDropTargetListener.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/BndDropTargetListener.java index 04e8bb547b..21f7911732 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/BndDropTargetListener.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/BndDropTargetListener.java @@ -12,7 +12,7 @@ * Raymond Augé - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.dnd.gav; +package org.eclipse.pde.bnd.ui.dnd; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.preferences.IPreferencesService; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/GAVDropTargetListener.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/GAVDropTargetListener.java index dcccf152df..1f5e65ed9f 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/GAVDropTargetListener.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/GAVDropTargetListener.java @@ -12,7 +12,7 @@ * Raymond Augé - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.dnd.gav; +package org.eclipse.pde.bnd.ui.dnd; import static java.util.Objects.requireNonNull; @@ -23,6 +23,7 @@ import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.pde.bnd.ui.model.repo.RepositoryBundle; import org.eclipse.pde.bnd.ui.model.repo.RepositoryBundleVersion; +import org.eclipse.pde.bnd.ui.model.repo.RepositoryResourceElement; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ST; import org.eclipse.swt.custom.StyledText; @@ -35,7 +36,6 @@ import org.osgi.resource.Resource; import aQute.bnd.service.RepositoryPlugin; -import bndtools.model.repo.RepositoryResourceElement; public abstract class GAVDropTargetListener implements DropTargetListener { diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/GAVIPageListener.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/GAVIPageListener.java index acb86b03d1..8ce1770921 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/GAVIPageListener.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/GAVIPageListener.java @@ -12,7 +12,7 @@ * Raymond Augé - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.dnd.gav; +package org.eclipse.pde.bnd.ui.dnd; import static org.eclipse.swt.dnd.DND.DROP_COPY; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/GradleDropTargetListener.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/GradleDropTargetListener.java index fc2b4ec8c9..7003784f90 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/GradleDropTargetListener.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/GradleDropTargetListener.java @@ -12,12 +12,7 @@ * Raymond Augé - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.dnd.gav; - -import static bndtools.dnd.gav.GradleDropTargetListener.Syntax.GRADLE_MAP; -import static bndtools.dnd.gav.GradleDropTargetListener.Syntax.GRADLE_MAP_NO_VERSION; -import static bndtools.dnd.gav.GradleDropTargetListener.Syntax.GRADLE_STRING; -import static bndtools.dnd.gav.GradleDropTargetListener.Syntax.GRADLE_STRING_NO_VERSION; +package org.eclipse.pde.bnd.ui.dnd; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.preferences.IPreferencesService; @@ -45,10 +40,11 @@ public GradleDropTargetListener(StyledText styledText) { void format(FormatEvent formatEvent) { if (formatEvent.isNoVersion()) { format(formatEvent.getResource(), - formatEvent.useAlternateSyntax() ? GRADLE_MAP_NO_VERSION : GRADLE_STRING_NO_VERSION, + formatEvent.useAlternateSyntax() ? Syntax.GRADLE_MAP_NO_VERSION : Syntax.GRADLE_STRING_NO_VERSION, formatEvent.getLineAtInsertionPoint(), formatEvent.getIndentPrefix(), indent(isTabs(), getSize())); } else { - format(formatEvent.getResource(), formatEvent.useAlternateSyntax() ? GRADLE_MAP : GRADLE_STRING, + format(formatEvent.getResource(), + formatEvent.useAlternateSyntax() ? Syntax.GRADLE_MAP : Syntax.GRADLE_STRING, formatEvent.getLineAtInsertionPoint(), formatEvent.getIndentPrefix(), indent(isTabs(), getSize())); } } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/MavenDropTargetListener.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/MavenDropTargetListener.java index 5066e77d77..3c02c6d819 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/MavenDropTargetListener.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/dnd/MavenDropTargetListener.java @@ -12,10 +12,7 @@ * Raymond Augé - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.dnd.gav; - -import static bndtools.dnd.gav.MavenDropTargetListener.Syntax.MAVEN; -import static bndtools.dnd.gav.MavenDropTargetListener.Syntax.MAVEN_NO_VERSION; +package org.eclipse.pde.bnd.ui.dnd; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.preferences.IPreferencesService; @@ -40,10 +37,10 @@ public MavenDropTargetListener(StyledText styledText) { @Override void format(FormatEvent formatEvent) { if (formatEvent.isNoVersion()) { - format(formatEvent.getResource(), MAVEN_NO_VERSION, formatEvent.getLineAtInsertionPoint(), + format(formatEvent.getResource(), Syntax.MAVEN_NO_VERSION, formatEvent.getLineAtInsertionPoint(), formatEvent.getIndentPrefix(), indent(isTabs(), getSize())); } else { - format(formatEvent.getResource(), MAVEN, formatEvent.getLineAtInsertionPoint(), + format(formatEvent.getResource(), Syntax.MAVEN, formatEvent.getLineAtInsertionPoint(), formatEvent.getIndentPrefix(), indent(isTabs(), getSize())); } } @@ -98,6 +95,13 @@ private void format(Resource resource, Syntax syntax, String lineAtInsertionPoin .append("") .append(identity) .append("\n"); + if (classifier!=null &&!classifier.isBlank()) { + sb.append(indentPrefix) + .append(indent) + .append("") + .append(version) + .append("\n"); + } switch (syntax) { case MAVEN : diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/internal/SWTClipboard.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/internal/SWTClipboard.java index 5739e7c5b7..89b94d1a7f 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/internal/SWTClipboard.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/internal/SWTClipboard.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2020, 2020 bndtools project and others. + * Copyright (c) 2020, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -10,8 +10,9 @@ * * Contributors: * Peter Kriens - initial API and implementation + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.central; +package org.eclipse.pde.bnd.ui.internal; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; @@ -20,9 +21,11 @@ import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.widgets.Display; +import org.osgi.service.component.annotations.Component; import aQute.bnd.service.clipboard.Clipboard; +@Component(service = Clipboard.class) public class SWTClipboard implements Clipboard { private static final Transfer[] TEXT_TRANSFER = new Transfer[] { TextTransfer.getInstance() diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/ContinueSearchElement.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/ContinueSearchElement.java index 1e83548046..0f46c508a9 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/ContinueSearchElement.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/ContinueSearchElement.java @@ -12,7 +12,7 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.model.repo; +package org.eclipse.pde.bnd.ui.model.repo; import java.net.URI; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/LoadingContentElement.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/LoadingContentElement.java index 360cc6e3eb..fa86e2e82a 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/LoadingContentElement.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/LoadingContentElement.java @@ -12,7 +12,7 @@ * Gregory Amerson - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.model.repo; +package org.eclipse.pde.bnd.ui.model.repo; public class LoadingContentElement { diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/ProjectBundle.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/ProjectBundle.java index 458c955ae0..f30d30a536 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/ProjectBundle.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/ProjectBundle.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2020 bndtools project and others. + * Copyright (c) 2010, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -14,24 +14,23 @@ * Neil Bartlett - ongoing enhancements * BJ Hargrave - ongoing enhancements * Peter Kriens - ongoing enhancements + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.model.repo; +package org.eclipse.pde.bnd.ui.model.repo; import java.io.File; import java.text.MessageFormat; - -mport org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.Path; -import org.eclipse.jface.util.ILogger; import aQute.bnd.build.Project; public class ProjectBundle implements IAdaptable { - private static final ILogger logger = Logger.getLogger(ProjectBundle.class); private final Project project; private final String bsn; @@ -70,8 +69,9 @@ public T getAdapter(Class adapter) { .getFileForLocation(path); } } catch (Exception e) { - logger.logError( - MessageFormat.format("Error retrieving bundle {0} from project {1}.", bsn, project.getName()), e); + ILog.get().error( + MessageFormat.format("Error retrieving bundle {0} from project {1}.", bsn, project.getName()), + e); } } return result; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryBundle.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryBundle.java index 7b6800f08a..5c2cd05443 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryBundle.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryBundle.java @@ -14,7 +14,7 @@ * Peter Kriens - ongoing enhancements * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.model.repo; +package org.eclipse.pde.bnd.ui.model.repo; import java.util.Map; import java.util.SortedSet; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryBundleVersion.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryBundleVersion.java index e08d04bbd5..fda8d22554 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryBundleVersion.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryBundleVersion.java @@ -17,7 +17,7 @@ * BJ Hargrave - ongoing enhancements * Raymond Augé - ongoing enhancements *******************************************************************************/ -package bndtools.model.repo; +package org.eclipse.pde.bnd.ui.model.repo; import java.util.Map; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryEntry.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryEntry.java index 3afd585a00..1e40ef1a98 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryEntry.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryEntry.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2021 bndtools project and others. + * Copyright (c) 2015, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -12,8 +12,9 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements * Raymond Augé - ongoing enhancements + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.model.repo; +package org.eclipse.pde.bnd.ui.model.repo; import java.io.File; import java.lang.reflect.InvocationTargetException; @@ -26,8 +27,8 @@ import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.Path; -import org.eclipse.jface.util.ILogger; import org.osgi.framework.namespace.IdentityNamespace; import org.osgi.resource.Resource; import org.osgi.service.repository.ExpressionCombiner; @@ -64,8 +65,6 @@ public String toString() { public abstract class RepositoryEntry implements IAdaptable, ResourceProvider { - private static final ILogger logger = Logger.getLogger(RepositoryEntry.class); - private final RepositoryPlugin repo; private final String bsn; private final VersionFinder versionFinder; @@ -121,7 +120,7 @@ public final boolean isLocal() { result = location == Location.local || location == Location.remote_cached; } } catch (Exception e) { - logger.logError(MessageFormat.format("Failed to query repository {0} for bundle {1} version {2}.", + ILog.get().error(MessageFormat.format("Failed to query repository {0} for bundle {1} version {2}.", repo.getName(), bsn, versionFinder), e); } return result; @@ -147,7 +146,7 @@ public final File getFile(boolean forceDownload) { } return repo.get(bsn, version, Collections.emptyMap()); } catch (Exception e) { - logger.logError(MessageFormat.format("Failed to query repository {0} for bundle {1} version {2}.", + ILog.get().error(MessageFormat.format("Failed to query repository {0} for bundle {1} version {2}.", repo.getName(), bsn, versionFinder), Exceptions.unrollCause(e, InvocationTargetException.class)); return null; } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryResourceElement.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryResourceElement.java index 58ce6b0c27..8e1e2f51ba 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryResourceElement.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryResourceElement.java @@ -16,12 +16,12 @@ * BJ Hargrave - ongoing enhancements * Christoph Rueger - ongoing enhancements *******************************************************************************/ -package bndtools.model.repo; +package org.eclipse.pde.bnd.ui.model.repo; import java.util.Objects; -import org.bndtools.utils.resources.ResourceUtils; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.pde.bnd.ui.ResourceUtils; import org.osgi.framework.Version; import org.osgi.resource.Resource; @@ -60,7 +60,6 @@ public Resource getResource() { return resource; } - @SuppressWarnings("unchecked") @Override public T getAdapter(Class adapter) { return repositoryBundleVersion.getAdapter(adapter); diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryTreeContentProvider.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryTreeContentProvider.java index 68937328a0..4c6137e8c6 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryTreeContentProvider.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryTreeContentProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2021 bndtools project and others. + * Copyright (c) 2010, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -16,8 +16,9 @@ * Gregory Amerson - ongoing enhancements * Raymond Augé - ongoing enhancements * Fr Jeremy Krieg - ongoing enhancements + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.model.repo; +package org.eclipse.pde.bnd.ui.model.repo; import java.text.MessageFormat; import java.util.ArrayList; @@ -34,14 +35,16 @@ import java.util.SortedSet; import java.util.stream.Stream; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.jface.util.ILogger; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.Viewer; +import org.eclipse.pde.bnd.ui.plugins.EclipseWorkspaceRepository; import org.eclipse.swt.widgets.Display; import org.osgi.resource.Capability; import org.osgi.resource.Requirement; @@ -56,14 +59,10 @@ import aQute.bnd.service.RepositoryPlugin; import aQute.bnd.service.ResolutionPhase; import aQute.bnd.version.Version; -import bndtools.central.Central; -import bndtools.central.EclipseWorkspaceRepository; public class RepositoryTreeContentProvider implements ITreeContentProvider { private static final String CACHE_REPOSITORY = "cache"; - private static final ILogger logger = Logger - .getLogger(RepositoryTreeContentProvider.class); private final EnumSet phases; @@ -187,8 +186,9 @@ private void addRepositoryPlugins(Collection result, Workspace workspace workspace.getErrors() .clear(); List repoPlugins = workspace.getPlugins(RepositoryPlugin.class); + ILog log = ILog.get(); for (String error : workspace.getErrors()) { - logger.logError(error, null); + log.error(error); } for (RepositoryPlugin repoPlugin : repoPlugins) { if (CACHE_REPOSITORY.equals(repoPlugin.getName())) @@ -246,7 +246,7 @@ Object[] getProjectBundles(Project project) { result[i++] = bundle; } } catch (Exception e) { - logger.logError(MessageFormat.format("Error querying sub-bundles for project {0}.", project.getName()), e); + ILog.get().error(MessageFormat.format("Error querying sub-bundles for project {0}.", project.getName()), e); } return result; } @@ -257,7 +257,7 @@ Object[] getRepositoryBundleVersions(RepositoryBundle bundle) { versions = bundle.getRepo() .versions(bundle.getBsn()); } catch (Exception e) { - logger.logError(MessageFormat.format("Error querying versions for bundle {0} in repository {1}.", + ILog.get().error(MessageFormat.format("Error querying versions for bundle {0} in repository {1}.", bundle.getBsn(), bundle.getRepo() .getName()), e); @@ -286,10 +286,11 @@ Object[] getRepositoryBundles(final RepositoryPlugin repoPlugin) { result = searchR5Repository(repoPlugin, (Repository) repoPlugin); } else if (repoPlugin instanceof WorkspaceRepository) { try { - EclipseWorkspaceRepository workspaceRepo = Central.getEclipseWorkspaceRepository(); + EclipseWorkspaceRepository workspaceRepo = EclipseWorkspaceRepository + .get(ResourcesPlugin.getWorkspace()); result = searchR5Repository(repoPlugin, workspaceRepo); } catch (Exception e) { - logger.logError("Error querying workspace repository", e); + ILog.get().error("Error querying workspace repository", e); } } return result; @@ -321,8 +322,8 @@ protected IStatus run(IProgressMonitor monitor) { bsns = repoPlugin.list(wildcardFilter); } catch (Exception e) { String message = MessageFormat.format("Error querying repository {0}.", repoPlugin.getName()); - logger.logError(message, e); - status = new Status(IStatus.ERROR, Plugin.PLUGIN_ID, message, e); + ILog.get().error(message, e); + status = Status.error(message, e); } if (bsns != null) { Collections.sort(bsns); diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryTreeLabelProvider.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryTreeLabelProvider.java index f2be8eb078..6f82c797ca 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryTreeLabelProvider.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/RepositoryTreeLabelProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2023 bndtools project and others. + * Copyright (c) 2010, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -15,15 +15,15 @@ * Sean Bright - ongoing enhancements * Gregory Amerson - ongoing enhancements * BJ Hargrave - ongoing enhancements + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.model.repo; +package org.eclipse.pde.bnd.ui.model.repo; -import org.bndtools.core.ui.icons.Icons; -import org.bndtools.core.ui.icons.Icons.IconBuilder; -import org.bndtools.utils.jface.HyperlinkStyler; import org.eclipse.jface.viewers.StyledCellLabelProvider; import org.eclipse.jface.viewers.StyledString; import org.eclipse.jface.viewers.ViewerCell; +import org.eclipse.pde.bnd.ui.HyperlinkStyler; +import org.eclipse.pde.bnd.ui.Resources; import org.eclipse.swt.graphics.Image; import aQute.bnd.build.Project; @@ -34,11 +34,11 @@ public class RepositoryTreeLabelProvider extends StyledCellLabelProvider implements org.eclipse.jface.viewers.ILabelProvider { - final Image arrowImg = Icons.image("arrow_down"); - final Image bundleImg = Icons.image("bundle"); - final Image matchImg = Icons.image("match"); - final Image projectImg = Icons.image("project"); - final Image loadingImg = Icons.image("loading"); + final Image arrowImg = Resources.getImage("arrow_down.png"); + final Image bundleImg = Resources.getImage("bundle.png"); + final Image matchImg = Resources.getImage("star-small.png"); + final Image projectImg = Resources.getImage("$IMG_OBJ_PROJECT"); + final Image loadingImg = Resources.getImage("loading_16x16.gif"); private final boolean showRepoId; @@ -65,20 +65,11 @@ public void update(ViewerCell cell) { name = repo.getName(); label.append(name); - IconBuilder ib = Icons.builder(repo.getIcon()); - if (repo.canWrite()) { - ib.bottomLeft("writable_decorator"); - } - if (repo.isRemote()) { - ib.bottomRight("remote_decorator"); - } - if (status != null) { - ib.topLeft("error_decorator"); label.append(" : "); label.append(status, StyledString.QUALIFIER_STYLER); } - image = ib.build(); + image = Resources.getImage(repo.getIcon()); } } else if (element instanceof Project) { if (index == 0) { @@ -158,7 +149,7 @@ public void update(ViewerCell cell) { } } catch (Exception e) { label.append("error: " + Exceptions.causes(e)); - image = Icons.image("error"); + image = Resources.getImage("error"); } cell.setText(label.getString()); diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/ResourceProvider.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/ResourceProvider.java index 07f64d2c67..1fa044e9e0 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/ResourceProvider.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/ResourceProvider.java @@ -11,7 +11,7 @@ * Contributors: * Raymond Augé - initial API and implementation *******************************************************************************/ -package bndtools.model.repo; +package org.eclipse.pde.bnd.ui.model.repo; import org.osgi.resource.Resource; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/SearchableRepositoryTreeContentProvider.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/SearchableRepositoryTreeContentProvider.java index b164fe35a5..7eafb0689d 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/SearchableRepositoryTreeContentProvider.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/model/repo/SearchableRepositoryTreeContentProvider.java @@ -12,7 +12,7 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.model.repo; +package org.eclipse.pde.bnd.ui.model.repo; import aQute.bnd.service.RepositoryPlugin; import aQute.bnd.service.repository.SearchableRepository; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/plugins/EclipseWorkspaceRepository.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/plugins/EclipseWorkspaceRepository.java index a3c081678d..95d036dd69 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/plugins/EclipseWorkspaceRepository.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/plugins/EclipseWorkspaceRepository.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2020, 2021 bndtools project and others. + * Copyright (c) 2020, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -10,52 +10,66 @@ * * Contributors: * BJ Hargrave - initial API and implementation + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.central; +package org.eclipse.pde.bnd.ui.plugins; import static aQute.bnd.exceptions.SupplierWithException.asSupplierOrElse; import static java.util.stream.Collectors.toList; import java.io.BufferedReader; import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiFunction; import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.runtime.Adapters; import aQute.bnd.build.Project; -import aQute.bnd.build.Workspace; import aQute.bnd.osgi.Constants; import aQute.bnd.osgi.repository.AbstractIndexingRepository; import aQute.bnd.osgi.repository.WorkspaceRepositoryMarker; import aQute.bnd.osgi.resource.ResourceBuilder; -import aQute.lib.io.IO; public class EclipseWorkspaceRepository extends AbstractIndexingRepository implements WorkspaceRepositoryMarker { - EclipseWorkspaceRepository() { - super(); - Central.onCnfWorkspace(this::initialize); + + private static final Map repositoryMap = new ConcurrentHashMap<>(); + private boolean initialized; + private IWorkspace workspace; + + EclipseWorkspaceRepository(IWorkspace workspace) { + this.workspace = workspace; } - private void initialize(Workspace workspace) throws Exception { - List projects = Arrays.stream(ResourcesPlugin.getWorkspace() + synchronized void initialize() throws Exception { + if (initialized) { + return; + } + initialized = true; + List projects = Arrays.stream(workspace .getRoot() .getProjects()) - .filter(this::isValid) .collect(toList()); for (IProject project : projects) { - Project model = Central.getProject(project); + Project model = Adapters.adapt(project, Project.class); + if (model == null) { + continue; + } File target = model.getTargetDir(); File buildfiles = new File(target, Constants.BUILDFILES); if (buildfiles.isFile()) { index(project, asSupplierOrElse(() -> { - try (BufferedReader rdr = IO.reader(buildfiles)) { + try (BufferedReader rdr = Files.newBufferedReader(buildfiles.toPath(), StandardCharsets.UTF_8)) { return rdr.lines() - .map(line -> IO.getFile(target, line.trim())) + .map(line -> new File(target, line.trim())) .filter(File::isFile) .collect(toList()); } @@ -67,7 +81,7 @@ private void initialize(Workspace workspace) throws Exception { @Override protected boolean isValid(IProject project) { try { - return project.isOpen() && (Central.getProject(project) != null); + return project.isOpen() && (Adapters.adapt(project, Project.class) != null); } catch (Exception e) { return false; } @@ -92,4 +106,11 @@ protected BiFunction indexer(IProject pr public String toString() { return NAME; } + + public static EclipseWorkspaceRepository get(IWorkspace workspace) throws Exception { + EclipseWorkspaceRepository repository = repositoryMap.computeIfAbsent(workspace, + EclipseWorkspaceRepository::new); + repository.initialize(); + return repository; + } } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/plugins/RepositoriesViewRefresher.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/plugins/RepositoriesViewRefresher.java index 1b94f35180..e6004b8a41 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/plugins/RepositoriesViewRefresher.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/plugins/RepositoriesViewRefresher.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2023 bndtools project and others. + * Copyright (c) 2015, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -15,8 +15,9 @@ * Gregory Amerson - ongoing enhancements * Raymond Augé - ongoing enhancements * Jürgen Albert - ongoing enhancements + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.central; +package org.eclipse.pde.bnd.ui.plugins; import java.io.File; import java.util.Collection; @@ -29,8 +30,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; -import org.bndtools.utils.swt.SWTConcurrencyUtil; import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; @@ -40,26 +41,22 @@ import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.viewers.TreePath; import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.pde.bnd.ui.plugins.RepositoriesViewRefresher.RefreshModel; import org.eclipse.swt.widgets.Display; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Component; import aQute.bnd.build.Workspace; import aQute.bnd.osgi.Jar; import aQute.bnd.service.RepositoryListenerPlugin; import aQute.bnd.service.RepositoryPlugin; +@Component(service = RepositoryListenerPlugin.class) public class RepositoriesViewRefresher implements RepositoryListenerPlugin { public interface RefreshModel { List getRepositories(); - } - // private static final ILogger logger = - // Logger.getLogger(RepositoriesViewRefresher.class); + Workspace getWorkspace(); + } enum State { IDLE, @@ -67,24 +64,10 @@ enum State { REDO; } - private final AtomicReference state = new AtomicReference<>(State.IDLE); - private final ServiceRegistration registration; - private final Map viewers = new ConcurrentHashMap<>(); - private final BundleContext context; - - RepositoriesViewRefresher() { - ServiceRegistration reg = null; - Bundle bundle = FrameworkUtil.getBundle(RepositoriesViewRefresher.class); - if (bundle != null) { - context = bundle.getBundleContext(); - if (context != null) - reg = context.registerService(RepositoryListenerPlugin.class, this, null); - } else - context = null; - this.registration = reg; - } + private static final AtomicReference state = new AtomicReference<>(State.IDLE); + private static final Map viewers = new ConcurrentHashMap<>(); - public void refreshRepositories(final RepositoryPlugin target) { + public static void refreshRepositories(final RepositoryPlugin target) { if (state.updateAndGet(current -> (current == State.IDLE) ? State.BUSY : State.REDO) == State.REDO) { return; } @@ -92,57 +75,61 @@ public void refreshRepositories(final RepositoryPlugin target) { // // Since this can delay, we move this to the background // - Central.onAnyWorkspace(ws -> { new WorkspaceJob("Updating repositories content") { @Override public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { if (monitor == null) monitor = new NullProgressMonitor(); - Set repos = new HashSet<>(); - if (target != null) - repos.add(target); - else { - for (RefreshModel m : viewers.values()) { - repos.addAll(m.getRepositories()); + Map> map = viewers.entrySet().stream() + .map(entry -> { + Workspace workspace = entry.getValue().getWorkspace(); + return new WorkspaceTreeViewerRefreshModel(workspace, entry.getKey(), entry.getValue()); + }).filter(m -> m.workspace() != null).collect(Collectors.groupingBy(m -> m.workspace())); + for (Entry> wsentry : map.entrySet()) { + + Set repos = new HashSet<>(); + if (target != null) + repos.add(target); + else { + for (WorkspaceTreeViewerRefreshModel m : wsentry.getValue()) { + repos.addAll(m.model().getRepositories()); + } } - } + ensureLoaded(monitor, repos, wsentry.getKey()); - ensureLoaded(monitor, repos, ws); + final Map> entryRepos = new HashMap<>(); - final Map, List> entryRepos = new HashMap<>(); - - for (Map.Entry entry : viewers.entrySet()) { - entryRepos.put(entry, entry.getValue() - .getRepositories()); - } + for (WorkspaceTreeViewerRefreshModel entry : wsentry.getValue()) { + entryRepos.put(entry, entry.model().getRepositories()); + } - state.set(State.BUSY); + state.set(State.BUSY); - for (Map.Entry entry : viewers.entrySet()) { + for (WorkspaceTreeViewerRefreshModel entry : wsentry.getValue()) { - TreeViewer viewer = entry.getKey(); - viewer.getControl() + TreeViewer viewer = entry.viewer(); + viewer.getControl() .getDisplay() .asyncExec(() -> { TreePath[] expandedTreePaths = viewer.getExpandedTreePaths(); viewer.setInput(entryRepos.get(entry)); - if (expandedTreePaths != null && expandedTreePaths.length > 0) + if (expandedTreePaths != null && expandedTreePaths.length > 0) viewer.setExpandedTreePaths(expandedTreePaths); }); - } - if (state.getAndSet(State.IDLE) == State.REDO) { - refreshRepositories(null); + } + if (state.getAndSet(State.IDLE) == State.REDO) { + refreshRepositories(null); + } } return Status.OK_STATUS; } }.schedule(1000); - }); } - private IStatus ensureLoaded(IProgressMonitor monitor, Collection repos, Workspace ws) { + private static IStatus ensureLoaded(IProgressMonitor monitor, Collection repos, Workspace ws) { int n = 0; try { final RepositoryPlugin workspaceRepo = ws.getWorkspaceRepository(); @@ -160,19 +147,22 @@ private IStatus ensureLoaded(IProgressMonitor monitor, Collection workspaceRepo.list(null), monitor::isCanceled); } catch (TimeoutException | InterruptedException e) { - return new Status(IStatus.ERROR, Plugin.PLUGIN_ID, - "Unable to acquire lock to refresh repository " + repo.getName(), e); + return Status.error("Unable to acquire lock to refresh repository " + repo.getName(), e); } } } catch (Exception e) { - return new Status(IStatus.ERROR, Plugin.PLUGIN_ID, "Exception refreshing repositories", e); + return Status.error("Exception refreshing repositories", e); } return Status.OK_STATUS; } - public void addViewer(TreeViewer viewer, RefreshModel model) { - this.viewers.put(viewer, model); - Central.onAnyWorkspace(workspace -> new Job("Updating repositories") { + public static void addViewer(TreeViewer viewer, RefreshModel model) { + viewers.put(viewer, model); + refreshViewer(viewer, model); + } + + public static void refreshViewer(TreeViewer viewer, RefreshModel model) { + new Job("Updating repositories") { @Override protected IStatus run(IProgressMonitor monitor) { List repositories = model.getRepositories(); @@ -180,11 +170,11 @@ protected IStatus run(IProgressMonitor monitor) { .asyncExec(() -> viewer.setInput(repositories)); return Status.OK_STATUS; } - }.schedule()); + }.schedule(); } - public void removeViewer(TreeViewer viewer) { - this.viewers.remove(viewer); + public static void removeViewer(TreeViewer viewer) { + viewers.remove(viewer); } @Override @@ -207,34 +197,9 @@ public void repositoriesRefreshed() { refreshRepositories(null); } - public void close() { - if (registration != null) - registration.unregister(); - } + private static final record WorkspaceTreeViewerRefreshModel(Workspace workspace, TreeViewer viewer, + RefreshModel model) { - public void setRepositories(final TreeViewer viewer, final RefreshModel refresh) { - if (state.updateAndGet(current -> (current == State.IDLE) ? State.BUSY : State.REDO) == State.REDO) { - return; - } - Central.onAnyWorkspace(ws -> { - new WorkspaceJob("Setting repositories") { - @Override - public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { - if (monitor == null) - monitor = new NullProgressMonitor(); - - ensureLoaded(monitor, refresh.getRepositories(), ws); - - SWTConcurrencyUtil.execForControl(viewer.getControl(), true, () -> { - viewer.setInput(refresh.getRepositories()); - - if (state.getAndSet(State.IDLE) == State.REDO) { - refreshRepositories(null); - } - }); - return Status.OK_STATUS; - } - }.schedule(); - }); } + } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/BndPreferences.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/BndPreferences.java index f18df6ee36..aad5aaa97f 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/BndPreferences.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/BndPreferences.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2021 bndtools project and others. + * Copyright (c) 2012, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -15,8 +15,9 @@ * Sean Bright - ongoing enhancements * BJ Hargrave - ongoing enhancements * Fr Jeremy Krieg - ongoing enhancements + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.preferences; +package org.eclipse.pde.bnd.ui.preferences; import java.io.Closeable; import java.util.Arrays; @@ -26,6 +27,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.TreeMap; import java.util.function.Consumer; @@ -33,59 +35,80 @@ import org.bndtools.api.NamedPlugin; import org.bndtools.headless.build.manager.api.HeadlessBuildManager; import org.bndtools.versioncontrol.ignores.manager.api.VersionControlIgnoresManager; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.Adapters; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.pde.bnd.ui.TeamUtils; import aQute.bnd.build.Workspace; -import bndtools.Plugin; -import bndtools.central.Central; -import bndtools.team.TeamUtils; public class BndPreferences { - private static final String PREF_ENABLE_SUB_BUNDLES = "enableSubBundles"; - private static final String PREF_NOASK_PACKAGEINFO = "noAskPackageInfo"; - private static final String PREF_USE_ALIAS_REQUIREMENTS = "useAliasRequirements"; - private static final String PREF_HIDE_INITIALISE_CNF_WIZARD = "hideInitialiseCnfWizard"; - private static final String PREF_HIDE_INITIALISE_CNF_ADVICE = "hideInitialiseCnfAdvice"; - private static final String PREF_WARN_EXISTING_LAUNCH = "warnExistingLaunch"; - private static final String PREF_HIDE_WARNING_EXTERNAL_FILE = "hideExternalFileWarning"; - private static final String PREF_BUILD_LOGGING = "buildLogging"; - private static final String PREF_EDITOR_OPEN_SOURCE_TAB = "editorOpenSourceTab"; - private static final String PREF_HEADLESS_BUILD_CREATE = "headlessBuildCreate"; - private static final String PREF_HEADLESS_BUILD_PLUGINS = "headlessBuildPlugins"; - private static final String PREF_VCS_IGNORES_CREATE = "versionControlIgnoresCreate"; - private static final String PREF_VCS_IGNORES_PLUGINS = "versionControlIgnoresPlugins"; - private static final String PREF_BUILDBEFORELAUNCH = "buildBeforeLaunch"; - private static final String PREF_ENABLE_TEMPLATE_REPO = "enableTemplateRepo"; - private static final String PREF_TEMPLATE_REPO_URI_LIST = "templateRepoUriList"; - private static final String PREF_EXPLORER_PROMPT = "prompt"; - private static final String PREF_PARALLEL = "parallel"; - - static final String PREF_WORKSPACE_OFFLINE = "workspaceIsOffline"; + private static final boolean DEFAULT_PREF_USE_ALIAS_REQUIREMENTS = true; + private static final boolean DEFAULT_PREF_PARALLEL = false; + private static final boolean DEFAULT_PREF_WORKSPACE_OFFLINE = false; + private static final String DEFAULT_PREF_TEMPLATE_REPO_URI_LIST = "https://raw.githubusercontent.com/bndtools/bundle-hub/master/index.xml.gz"; + private static final boolean DEFAULT_PREF_ENABLE_TEMPLATE_REPO = false; + private static final boolean DEFAULT_PREF_VCS_IGNORES_CREATE = true; + private static final String DEFAULT_PREF_HEADLESS_BUILD_PLUGINS = ""; + private static final boolean DEFAULT_PREF_HEADLESS_BUILD_CREATE = true; + private static final boolean DEFAULT_PREF_BUILDBEFORELAUNCH = true; + private static final boolean DEFAULT_PREF_WARN_EXISTING_LAUNCH = true; + private static final String DEFAULT_PREF_VCS_IGNORES_PLUGINS = ""; + private static final String DEFAULT_PREF_EXPLORER_PROMPT = ""; + private static final String PREF_ENABLE_SUB_BUNDLES = "enableSubBundles"; + private static final String PREF_NOASK_PACKAGEINFO = "noAskPackageInfo"; + private static final String PREF_USE_ALIAS_REQUIREMENTS = "useAliasRequirements"; + private static final String PREF_HIDE_INITIALISE_CNF_WIZARD = "hideInitialiseCnfWizard"; + private static final String PREF_HIDE_INITIALISE_CNF_ADVICE = "hideInitialiseCnfAdvice"; + private static final String PREF_WARN_EXISTING_LAUNCH = "warnExistingLaunch"; + private static final String PREF_HIDE_WARNING_EXTERNAL_FILE = "hideExternalFileWarning"; + private static final String PREF_BUILD_LOGGING = "buildLogging"; + private static final String PREF_EDITOR_OPEN_SOURCE_TAB = "editorOpenSourceTab"; + private static final String PREF_HEADLESS_BUILD_CREATE = "headlessBuildCreate"; + private static final String PREF_HEADLESS_BUILD_PLUGINS = "headlessBuildPlugins"; + private static final String PREF_VCS_IGNORES_CREATE = "versionControlIgnoresCreate"; + private static final String PREF_VCS_IGNORES_PLUGINS = "versionControlIgnoresPlugins"; + private static final String PREF_BUILDBEFORELAUNCH = "buildBeforeLaunch"; + private static final String PREF_ENABLE_TEMPLATE_REPO = "enableTemplateRepo"; + private static final String PREF_TEMPLATE_REPO_URI_LIST = "templateRepoUriList"; + private static final String PREF_EXPLORER_PROMPT = "prompt"; + private static final String PREF_PARALLEL = "parallel"; + + static final String PREF_WORKSPACE_OFFLINE = "workspaceIsOffline"; + private static final boolean DEFAULT_PREF_NOASK_PACKAGEINFO = false; + private static final boolean DEFAULT_PREF_HIDE_INITIALISE_CNF_WIZARD = false; + private static final String DEFAULT_PREF_ENABLE_SUB_BUNDLES = null; + private static final int DEFAULT_PREF_BUILD_LOGGING = 0; + private static final boolean DEFAULT_PREF_HIDE_INITIALISE_CNF_ADVICE = false; + private static final boolean DEFAULT_PREF_HIDE_WARNING_EXTERNAL_FILE = false; + private static final boolean DEFAULT_PREF_EDITOR_OPEN_SOURCE_TAB = false; private final IPreferenceStore store; - - public BndPreferences() { - store = Plugin.getDefault() - .getPreferenceStore(); - - // Defaults... - store.setDefault(PREF_WARN_EXISTING_LAUNCH, true); - store.setDefault(PREF_BUILDBEFORELAUNCH, true); - store.setDefault(PREF_HEADLESS_BUILD_CREATE, true); - store.setDefault(PREF_HEADLESS_BUILD_PLUGINS, ""); - store.setDefault(PREF_VCS_IGNORES_CREATE, true); - store.setDefault(PREF_VCS_IGNORES_PLUGINS, ""); - store.setDefault(PREF_ENABLE_TEMPLATE_REPO, false); - store.setDefault(PREF_TEMPLATE_REPO_URI_LIST, - "https://raw.githubusercontent.com/bndtools/bundle-hub/master/index.xml.gz"); - store.setDefault(PREF_WORKSPACE_OFFLINE, false); - store.setDefault(PREF_PARALLEL, false); - store.setDefault(PREF_USE_ALIAS_REQUIREMENTS, true); - store.setDefault(QuickFixVersioning.PREFERENCE_KEY, QuickFixVersioning.DEFAULT.toString()); - store.setDefault(PREF_EXPLORER_PROMPT, ""); + private IProject project; + + public BndPreferences(IProject project, IPreferenceStore store) { + this.store = store; + this.project = project; + if (store != null) { + // Defaults... + store.setDefault(PREF_WARN_EXISTING_LAUNCH, DEFAULT_PREF_WARN_EXISTING_LAUNCH); + store.setDefault(PREF_BUILDBEFORELAUNCH, DEFAULT_PREF_BUILDBEFORELAUNCH); + store.setDefault(PREF_HEADLESS_BUILD_CREATE, DEFAULT_PREF_HEADLESS_BUILD_CREATE); + store.setDefault(PREF_HEADLESS_BUILD_PLUGINS, DEFAULT_PREF_HEADLESS_BUILD_PLUGINS); + store.setDefault(PREF_VCS_IGNORES_CREATE, DEFAULT_PREF_VCS_IGNORES_CREATE); + store.setDefault(PREF_VCS_IGNORES_PLUGINS, DEFAULT_PREF_VCS_IGNORES_PLUGINS); + store.setDefault(PREF_ENABLE_TEMPLATE_REPO, DEFAULT_PREF_ENABLE_TEMPLATE_REPO); + store.setDefault(PREF_TEMPLATE_REPO_URI_LIST, + DEFAULT_PREF_TEMPLATE_REPO_URI_LIST); + store.setDefault(PREF_WORKSPACE_OFFLINE, DEFAULT_PREF_WORKSPACE_OFFLINE); + store.setDefault(PREF_PARALLEL, DEFAULT_PREF_PARALLEL); + store.setDefault(PREF_USE_ALIAS_REQUIREMENTS, DEFAULT_PREF_USE_ALIAS_REQUIREMENTS); + store.setDefault(QuickFixVersioning.PREFERENCE_KEY, QuickFixVersioning.DEFAULT.toString()); + store.setDefault(PREF_EXPLORER_PROMPT, DEFAULT_PREF_EXPLORER_PROMPT); + } } private String mapToPreference(Map names) { @@ -142,83 +165,143 @@ private Map preferenceToMap(String preference, } public void setNoAskPackageInfo(boolean noAskPackageInfo) { + if (store == null) { + return; + } store.setValue(PREF_NOASK_PACKAGEINFO, noAskPackageInfo); } public void setUseAliasRequirements(boolean useAliases) { + if (store == null) { + return; + } store.setValue(PREF_USE_ALIAS_REQUIREMENTS, useAliases); } public boolean getNoAskPackageInfo() { + if (store == null) { + return DEFAULT_PREF_NOASK_PACKAGEINFO; + } return store.getBoolean(PREF_NOASK_PACKAGEINFO); } public boolean getUseAliasRequirements() { + if (store == null) { + return DEFAULT_PREF_USE_ALIAS_REQUIREMENTS; + } return store.getBoolean(PREF_USE_ALIAS_REQUIREMENTS); } public void setHideInitCnfWizard(boolean hide) { + if (store == null) { + return; + } store.setValue(PREF_HIDE_INITIALISE_CNF_WIZARD, hide); } public boolean getHideInitCnfWizard() { + if (store == null) { + return DEFAULT_PREF_HIDE_INITIALISE_CNF_WIZARD; + } return store.getBoolean(PREF_HIDE_INITIALISE_CNF_WIZARD); } public void setWarnExistingLaunch(boolean warnExistingLaunch) { + if (store == null) { + return; + } store.setValue(PREF_WARN_EXISTING_LAUNCH, warnExistingLaunch); } public boolean getWarnExistingLaunches() { + if (store == null) { + return DEFAULT_PREF_WARN_EXISTING_LAUNCH; + } return store.getBoolean(PREF_WARN_EXISTING_LAUNCH); } public void setEnableSubBundles(String enableSubs) { + if (store == null) { + return; + } store.setValue(PREF_ENABLE_SUB_BUNDLES, enableSubs); } public String getEnableSubBundles() { + if (store == null) { + return DEFAULT_PREF_ENABLE_SUB_BUNDLES; + } return store.getString(PREF_ENABLE_SUB_BUNDLES); } public void setBuildLogging(int buildLogging) { + if (store == null) { + return; + } store.setValue(PREF_BUILD_LOGGING, buildLogging); } public int getBuildLogging() { + if (store == null) { + return DEFAULT_PREF_BUILD_LOGGING; + } return store.getInt(PREF_BUILD_LOGGING); } public void setHideInitCnfAdvice(boolean hide) { + if (store == null) { + return; + } store.setValue(PREF_HIDE_INITIALISE_CNF_ADVICE, hide); } public boolean getHideInitCnfAdvice() { + if (store == null) { + return DEFAULT_PREF_HIDE_INITIALISE_CNF_ADVICE; + } return store.getBoolean(PREF_HIDE_INITIALISE_CNF_ADVICE); } public void setHideWarningExternalFile(boolean hide) { + if (store == null) { + return; + } store.setValue(PREF_HIDE_WARNING_EXTERNAL_FILE, hide); } public boolean getHideWarningExternalFile() { + if (store == null) { + return DEFAULT_PREF_HIDE_WARNING_EXTERNAL_FILE; + } return store.getBoolean(PREF_HIDE_WARNING_EXTERNAL_FILE); } public boolean getEnableTemplateRepo() { + if (store == null) { + return DEFAULT_PREF_ENABLE_TEMPLATE_REPO; + } return store.getBoolean(PREF_ENABLE_TEMPLATE_REPO); } public void setEnableTemplateRepo(boolean enable) { + if (store == null) { + return; + } store.setValue(PREF_ENABLE_TEMPLATE_REPO, enable); } public List getTemplateRepoUriList() { + if (store == null) { + return List.of(DEFAULT_PREF_TEMPLATE_REPO_URI_LIST); + } String urisStr = store.getString(PREF_TEMPLATE_REPO_URI_LIST); return Arrays.asList(urisStr.split("\\s")); } public void setTemplateRepoUriList(List uris) { + if (store == null) { + return; + } StringBuilder sb = new StringBuilder(); for (Iterator i = uris.iterator(); i.hasNext();) { sb.append(i.next()); @@ -233,28 +316,43 @@ public IPreferenceStore getStore() { } public void setEditorOpenSourceTab(boolean editorOpenSourceTab) { + if (store == null) { + return; + } store.setValue(PREF_EDITOR_OPEN_SOURCE_TAB, editorOpenSourceTab); } public boolean getEditorOpenSourceTab() { + if (store == null) { + return DEFAULT_PREF_EDITOR_OPEN_SOURCE_TAB; + } return store.getBoolean(PREF_EDITOR_OPEN_SOURCE_TAB); } public void setHeadlessBuildCreate(boolean headlessCreate) { + if (store == null) { + return; + } store.setValue(PREF_HEADLESS_BUILD_CREATE, headlessCreate); } public boolean getHeadlessBuildCreate() { + if (store == null) { + return DEFAULT_PREF_HEADLESS_BUILD_CREATE; + } return store.getBoolean(PREF_HEADLESS_BUILD_CREATE); } public void setHeadlessBuildPlugins(Map names) { + if (store == null) { + return; + } store.setValue(PREF_HEADLESS_BUILD_PLUGINS, mapToPreference(names)); } public Map getHeadlessBuildPlugins(Collection allPluginsInformation, boolean onlyEnabled) { - if (!getHeadlessBuildCreate()) { + if (!getHeadlessBuildCreate() || store == null) { return Collections.emptyMap(); } @@ -283,20 +381,29 @@ public Set getHeadlessBuildPluginsEnabled(HeadlessBuildManager manager, } public void setVersionControlIgnoresCreate(boolean versionControlIgnoresCreate) { + if (store == null) { + return; + } store.setValue(PREF_VCS_IGNORES_CREATE, versionControlIgnoresCreate); } public boolean getVersionControlIgnoresCreate() { + if (store == null) { + return DEFAULT_PREF_VCS_IGNORES_CREATE; + } return store.getBoolean(PREF_VCS_IGNORES_CREATE); } public void setVersionControlIgnoresPlugins(Map names) { + if (store == null) { + return; + } store.setValue(PREF_VCS_IGNORES_PLUGINS, mapToPreference(names)); } public Map getVersionControlIgnoresPlugins(Collection allPluginsInformation, boolean onlyEnabled) { - if (!getVersionControlIgnoresCreate()) { + if (!getVersionControlIgnoresCreate() || store == null) { return Collections.emptyMap(); } @@ -304,10 +411,16 @@ public Map getVersionControlIgnoresPlugins(Collection listener) { } public void setParallel(boolean parallel) { + if (store == null) { + return; + } store.setValue(PREF_PARALLEL, parallel); } public boolean isParallel() { + if (store == null) { + return DEFAULT_PREF_PARALLEL; + } return store.getBoolean(PREF_PARALLEL); } public Closeable onString(String key, Consumer listener) { + if (store == null) { + return () -> { + }; + } IPropertyChangeListener l = e -> { if (e.getProperty() .equals(key)) @@ -361,11 +484,14 @@ public Set getVersionControlIgnoresPluginsEnabled(VersionControlIgnoresM if (project != null) { String repositoryProviderId = TeamUtils.getProjectRepositoryProviderId(project); if (repositoryProviderId != null) { - Set managingPlugins = Plugin.getDefault() - .getVersionControlIgnoresManager() - .getPluginsForProjectRepositoryProviderId(repositoryProviderId); - if (managingPlugins != null && !managingPlugins.isEmpty()) { - return managingPlugins; + VersionControlIgnoresManager versionControlIgnoresManager = Adapters.adapt(project.getProject(), + VersionControlIgnoresManager.class); + if (versionControlIgnoresManager != null) { + Set managingPlugins = versionControlIgnoresManager + .getPluginsForProjectRepositoryProviderId(repositoryProviderId); + if (managingPlugins != null && !managingPlugins.isEmpty()) { + return managingPlugins; + } } } } @@ -374,18 +500,30 @@ public Set getVersionControlIgnoresPluginsEnabled(VersionControlIgnoresM } public boolean getBuildBeforeLaunch() { + if (store == null) { + return DEFAULT_PREF_BUILDBEFORELAUNCH; + } return store.getBoolean(PREF_BUILDBEFORELAUNCH); } public void setBuildBeforeLaunch(boolean b) { + if (store == null) { + return; + } store.setValue(PREF_BUILDBEFORELAUNCH, b); } public QuickFixVersioning getQuickFixVersioning() { + if (store == null) { + return QuickFixVersioning.DEFAULT; + } return QuickFixVersioning.parse(store.getString(QuickFixVersioning.PREFERENCE_KEY)); } public void setQuickFixVersioning(QuickFixVersioning qfv) { + if (store == null) { + return; + } if (qfv == null) { qfv = QuickFixVersioning.DEFAULT; } @@ -393,14 +531,20 @@ public void setQuickFixVersioning(QuickFixVersioning qfv) { } public boolean isWorkspaceOffline() { + if (store == null) { + return DEFAULT_PREF_WORKSPACE_OFFLINE; + } return store.getBoolean(PREF_WORKSPACE_OFFLINE); } public void setWorkspaceOffline(boolean b) { - Workspace workspace = Central.getWorkspaceIfPresent(); + Workspace workspace = Adapters.adapt(project, Workspace.class); if (workspace != null) { workspace.setOffline(b); } + if (store == null) { + return; + } store.setValue(PREF_WORKSPACE_OFFLINE, b); } @@ -411,4 +555,21 @@ public void addPropertyChangeListener(IPropertyChangeListener listener) { public void removePropertyChangeListener(IPropertyChangeListener listener) { store.removePropertyChangeListener(listener); } + + @Override + public int hashCode() { + return Objects.hash(project, store); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BndPreferences other = (BndPreferences) obj; + return Objects.equals(project, other.project) && Objects.equals(store, other.store); + } } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/QuickFixVersioning.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/QuickFixVersioning.java index 60db3b20fc..72d4b2eb30 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/QuickFixVersioning.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/QuickFixVersioning.java @@ -11,7 +11,7 @@ * Contributors: * Fr Jeremy Krieg - initial API and implementation *******************************************************************************/ -package bndtools.preferences; +package org.eclipse.pde.bnd.ui.preferences; public enum QuickFixVersioning { diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/WorkspaceOfflineChangeAdapter.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/WorkspaceOfflineChangeAdapter.java index 304e99f399..2705d2a7e7 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/WorkspaceOfflineChangeAdapter.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/WorkspaceOfflineChangeAdapter.java @@ -12,7 +12,7 @@ * Sean Bright - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.preferences; +package org.eclipse.pde.bnd.ui.preferences; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/WorkspaceOfflineChangeListener.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/WorkspaceOfflineChangeListener.java index 6a1dbb0d5d..c938dd84f0 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/WorkspaceOfflineChangeListener.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/preferences/WorkspaceOfflineChangeListener.java @@ -12,7 +12,7 @@ * Sean Bright - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.preferences; +package org.eclipse.pde.bnd.ui.preferences; public interface WorkspaceOfflineChangeListener { void workspaceOfflineChanged(boolean offline); diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/ViewEventTopics.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/ViewEventTopics.java index a9190c5f48..5bca3a6ca0 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/ViewEventTopics.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/ViewEventTopics.java @@ -11,7 +11,7 @@ * Contributors: * Christoph Rueger - initial API and implementation *******************************************************************************/ -package bndtools.views; +package org.eclipse.pde.bnd.ui.views; /** * Topics for the EventBroker which is used for communication between different diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/AdvancedSearchDialog.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/AdvancedSearchDialog.java index 4e6024c6ce..2eace202da 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/AdvancedSearchDialog.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/AdvancedSearchDialog.java @@ -13,7 +13,7 @@ * BJ Hargrave - ongoing enhancements * Christoph Rueger - ongoing enhancements *******************************************************************************/ -package bndtools.views.repository; +package org.eclipse.pde.bnd.ui.views.repository; import java.beans.PropertyChangeListener; import java.util.LinkedHashMap; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/ArbitraryNamespaceSearchPanel.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/ArbitraryNamespaceSearchPanel.java index 66bc22139a..d9aebab4b4 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/ArbitraryNamespaceSearchPanel.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/ArbitraryNamespaceSearchPanel.java @@ -12,7 +12,7 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.views.repository; +package org.eclipse.pde.bnd.ui.views.repository; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/FilteredViewPart.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/FilteredViewPart.java index e99bf03689..d290851916 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/FilteredViewPart.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/FilteredViewPart.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2021 bndtools project and others. + * Copyright (c) 2010, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -12,14 +12,15 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements * Peter Kriens - ongoing enhancements + * Christoph Läubrich - adjust to pde code base *******************************************************************************/ -package bndtools.views.repository; +package org.eclipse.pde.bnd.ui.views.repository; -import org.bndtools.core.ui.icons.Icons; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.pde.bnd.ui.FilterPanelPart; +import org.eclipse.pde.bnd.ui.Resources; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.layout.GridData; @@ -34,8 +35,7 @@ */ public abstract class FilteredViewPart extends ViewPart { - private final FilterPanelPart filterPanel = new FilterPanelPart(Plugin.getDefault() - .getScheduler()); + private final FilterPanelPart filterPanel = new FilterPanelPart(Resources.getScheduler()); private Action filterAction; @@ -120,7 +120,7 @@ protected void fillToolBar(IToolBarManager toolBar) { private class FilterAction extends Action { public FilterAction() { super("Filter", IAction.AS_CHECK_BOX); - setImageDescriptor(Icons.desc("/icons/filter.gif")); + setImageDescriptor(Resources.getImageDescriptor("/icons/filter.gif")); } @Override diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/PackageSearchPanel.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/PackageSearchPanel.java index 9caa7a4001..54e56e0b6e 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/PackageSearchPanel.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/PackageSearchPanel.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2021 bndtools project and others. + * Copyright (c) 2015, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -12,10 +12,11 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements * Peter Kriens - ongoing enhancements + * Christoph Läubrich - adapt to pde code base *******************************************************************************/ -package bndtools.views.repository; +package org.eclipse.pde.bnd.ui.views.repository; -import org.bndtools.core.ui.icons.Icons; +import org.eclipse.pde.bnd.ui.Resources; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.Image; @@ -78,7 +79,6 @@ public Control createControl(Composite parent) { private void validate() { try { - String filter = null; if (packageName == null || packageName.trim() .isEmpty()) { @@ -87,11 +87,10 @@ private void validate() { return; } - VersionRange versionRange = null; if (versionRangeStr != null && versionRangeStr.trim() .length() > 0) { try { - versionRange = new VersionRange(versionRangeStr); + new VersionRange(versionRangeStr); } catch (Exception e) { throw new IllegalArgumentException("Invalid version range: " + e.getMessage()); } @@ -112,7 +111,7 @@ public void setFocus() { @Override public Image createImage(Device device) { - return Icons.image("package"); + return Resources.getImage("package"); } @Override diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/RepoDownloadJob.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/RepoDownloadJob.java index 7d5bd7f576..218ed2391a 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/RepoDownloadJob.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/RepoDownloadJob.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2019 bndtools project and others. + * Copyright (c) 2015, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -11,8 +11,9 @@ * Contributors: * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.views.repository; +package org.eclipse.pde.bnd.ui.views.repository; import java.util.Collection; import java.util.Collections; @@ -29,6 +30,8 @@ import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.pde.bnd.ui.model.repo.RepositoryBundle; +import org.eclipse.pde.bnd.ui.model.repo.RepositoryBundleVersion; import aQute.bnd.service.RemoteRepositoryPlugin; import aQute.bnd.service.RepositoryPlugin; @@ -36,9 +39,6 @@ import aQute.bnd.service.ResourceHandle.Location; import aQute.bnd.service.Strategy; import aQute.bnd.version.Version; -import bndtools.Plugin; -import bndtools.model.repo.RepositoryBundle; -import bndtools.model.repo.RepositoryBundleVersion; public class RepoDownloadJob extends Job { @@ -63,8 +63,7 @@ protected IStatus run(IProgressMonitor progress) { boolean locked = LOCK.tryLock(); try { while (!locked) { - monitor.setBlocked(new Status(IStatus.INFO, Plugin.PLUGIN_ID, 0, - "Waiting for other download jobs to complete.", null)); + monitor.setBlocked(Status.info("Waiting for other download jobs to complete.")); if (progress.isCanceled()) return Status.CANCEL_STATUS; @@ -74,7 +73,7 @@ protected IStatus run(IProgressMonitor progress) { } monitor.clearBlocked(); - MultiStatus status = new MultiStatus(Plugin.PLUGIN_ID, 0, + MultiStatus status = new MultiStatus(RepoDownloadJob.class, 0, "One or more repository files failed to download.", null); monitor.setTaskName("Expanding repository contents"); List rbvs = new LinkedList<>(); @@ -87,7 +86,7 @@ protected IStatus run(IProgressMonitor progress) { } rbvs.addAll(bundleVersions); } catch (Exception e) { - return new Status(IStatus.ERROR, Plugin.PLUGIN_ID, 0, "Error listing repository contents", e); + return Status.error("Error listing repository contents", e); } monitor.setWorkRemaining(rbvs.size()); @@ -108,8 +107,8 @@ protected IStatus run(IProgressMonitor progress) { handle.request(); } } catch (Exception e) { - status.add(new Status(IStatus.ERROR, Plugin.PLUGIN_ID, 0, - String.format("Download of %s:%s with remote name %s failed", rbv.getBsn(), rbv.getVersion(), + status.add(Status.error(String.format("Download of %s:%s with remote name %s failed", rbv.getBsn(), + rbv.getVersion(), resourceName), e)); } finally { diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/RepositoriesView.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/RepositoriesView.java index 6fec0e3a20..d910cf5c81 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/RepositoriesView.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/RepositoriesView.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2023 bndtools project and others. + * Copyright (c) 2010, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -24,8 +24,9 @@ * Juergen Albert * Raymond Augé * Christoph Rueger + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.views.repository; +package org.eclipse.pde.bnd.ui.views.repository; import java.io.CharArrayWriter; import java.io.File; @@ -35,27 +36,32 @@ import java.lang.reflect.Method; import java.net.URI; import java.net.URL; +import java.nio.file.Files; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Set; import java.util.jar.JarFile; -import javax.swing.event.HyperlinkEvent; - -import org.bndtools.core.ui.icons.Icons; +import org.eclipse.core.databinding.observable.IChangeListener; +import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.WritableValue; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileStore; -import org.eclipse.core.internal.resources.Resource; import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.WorkspaceJob; +import org.eclipse.core.runtime.Adapters; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -65,30 +71,47 @@ import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.e4.core.services.events.IEventBroker; -import org.eclipse.jdt.internal.ui.util.SWTUtil; import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.ControlContribution; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.util.ILogger; +import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.util.LocalSelectionTransfer; import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerDropAdapter; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.pde.bnd.ui.Central; import org.eclipse.pde.bnd.ui.FilterPanelPart; +import org.eclipse.pde.bnd.ui.HelpButtons; +import org.eclipse.pde.bnd.ui.HierarchicalLabel; +import org.eclipse.pde.bnd.ui.HierarchicalMenu; +import org.eclipse.pde.bnd.ui.RepositoryUtils; +import org.eclipse.pde.bnd.ui.Resources; +import org.eclipse.pde.bnd.ui.SWTUtil; +import org.eclipse.pde.bnd.ui.SelectionDragAdapter; +import org.eclipse.pde.bnd.ui.Workspaces; +import org.eclipse.pde.bnd.ui.dnd.GAVIPageListener; import org.eclipse.pde.bnd.ui.model.repo.RepositoryBundle; import org.eclipse.pde.bnd.ui.model.repo.RepositoryBundleVersion; import org.eclipse.pde.bnd.ui.model.repo.RepositoryEntry; +import org.eclipse.pde.bnd.ui.model.repo.RepositoryTreeLabelProvider; +import org.eclipse.pde.bnd.ui.model.repo.SearchableRepositoryTreeContentProvider; +import org.eclipse.pde.bnd.ui.plugins.RepositoriesViewRefresher; +import org.eclipse.pde.bnd.ui.preferences.BndPreferences; +import org.eclipse.pde.bnd.ui.preferences.WorkspaceOfflineChangeAdapter; +import org.eclipse.pde.bnd.ui.views.ViewEventTopics; +import org.eclipse.pde.bnd.ui.wizards.AddFilesToRepositoryWizard; import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DropTargetEvent; @@ -105,21 +128,24 @@ import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Tree; import org.eclipse.ui.IActionBars; -import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.ISelectionService; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.XMLMemento; import org.eclipse.ui.actions.ActionFactory; -import org.eclipse.ui.forms.events.HyperlinkAdapter; -import org.eclipse.ui.forms.widgets.FormText; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.part.ResourceTransfer; import org.eclipse.ui.part.ViewPart; import org.osgi.resource.Requirement; +import org.osgi.service.event.Event; import org.osgi.service.repository.Repository; import aQute.bnd.build.Workspace; @@ -131,34 +157,12 @@ import aQute.bnd.service.RemoteRepositoryPlugin; import aQute.bnd.service.RepositoryPlugin; import aQute.bnd.service.clipboard.Clipboard; -import aQute.lib.converter.Converter; -import aQute.lib.io.IO; -import bndtools.central.Central; -import bndtools.central.RepositoriesViewRefresher; -import bndtools.central.RepositoryUtils; -import bndtools.dnd.gav.GAVIPageListener; -import bndtools.editor.common.HelpButtons; -import bndtools.model.repo.RepositoryTreeLabelProvider; -import bndtools.model.repo.SearchableRepositoryTreeContentProvider; -import bndtools.preferences.BndPreferences; -import bndtools.preferences.WorkspaceOfflineChangeAdapter; -import bndtools.utils.HierarchicalLabel; -import bndtools.utils.HierarchicalMenu; -import bndtools.utils.SelectionDragAdapter; -import bndtools.views.ViewEventTopics; -import bndtools.wizards.workspace.AddFilesToRepositoryWizard; -import bndtools.wizards.workspace.WorkspaceSetupWizard; public class RepositoriesView extends ViewPart implements RepositoriesViewRefresher.RefreshModel { private static final String DROP_TARGET = "dropTarget"; - private static final ILogger logger = Logger - .getLogger(RepositoriesView.class); - - private final FilterPanelPart filterPart = new FilterPanelPart( - Plugin.getDefault() - .getScheduler()); + private final FilterPanelPart filterPart = new FilterPanelPart(Resources.getScheduler()); private SearchableRepositoryTreeContentProvider contentProvider; private TreeViewer viewer; private Control filterPanel; @@ -175,41 +179,24 @@ public class RepositoriesView extends ViewPart implements RepositoriesViewRefres .getService(IEventBroker.class); - private final BndPreferences prefs = new BndPreferences(); - - private final WorkspaceOfflineChangeAdapter workspaceOfflineListener = new WorkspaceOfflineChangeAdapter() { - @Override - public void workspaceOfflineChanged( - boolean offline) { - configureOfflineAction(); - - if (!offline) { - // Fire - // a - // fake - // selection - // event - // so - // that - // repo - // plugins - // can - // do - // what - // they - // would - // do - // if - // they - // were - // already - // online - viewer.setSelection( - viewer.getSelection(), - false); - } - } - }; + private final WorkspaceOfflineChangeAdapter workspaceOfflineListener = new WorkspaceOfflineChangeAdapter() { + @Override + public void workspaceOfflineChanged(boolean offline) { + updateOfflineAction(offline); + if (!offline) { + // Fire a fake selection event so that repo plugins can do what they would do if + // they were already online + viewer.setSelection(viewer.getSelection(), false); + } + } + }; + + private BndPreferences preferences; + + private Workspace workspace; + + private IObservableValue workspaceName = new WritableValue<>(); + private IObservableValue workspaceDescription = new WritableValue<>(); @Override public void createPartControl(final Composite parent) { @@ -224,27 +211,6 @@ public void createPartControl(final Composite parent) { fill.marginHeight = 5; fill.marginWidth = 5; defaultParent.setLayout(fill); - - if (!Central.hasWorkspaceDirectory()) { - FormText form = toolkit.createFormText(defaultParent, true); - form.setText("

No workspace configuration found. Create a new Bnd workspace...

", - true, false); - form.addHyperlinkListener(new HyperlinkAdapter() { - @Override - public void linkActivated(HyperlinkEvent e) { - IWorkbench workbench = PlatformUI.getWorkbench(); - IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); - - WorkspaceSetupWizard wizard = new WorkspaceSetupWizard(); - wizard.init(workbench, StructuredSelection.EMPTY); - WizardDialog dialog = new WizardDialog(window.getShell(), wizard); - dialog.open(); - } - }); - } else { - toolkit.createLabel(defaultParent, "Repositories are loading, please wait..."); - } - stackLayout.topControl = defaultParent; parent.layout(); @@ -272,9 +238,7 @@ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { advancedSearchAction.setEnabled(true); refreshAction.setEnabled(true); collapseAllAction.setEnabled(true); - - configureOfflineAction(); - + setPrefrences(getPreferences()); parent.layout(); } } @@ -284,7 +248,7 @@ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { viewer.setLabelProvider(new RepositoryTreeLabelProvider(false)); getViewSite().setSelectionProvider(viewer); - Central.addRepositoriesViewer(viewer, RepositoriesView.this); + RepositoriesViewRefresher.addViewer(viewer, RepositoriesView.this); // LISTENERS filterPart.addPropertyChangeListener(event -> { @@ -364,7 +328,7 @@ public boolean performDrop(Object data) { File tmp = File.createTempFile("dwnl", ".jar"); try (HttpClient client = new HttpClient()) { - IO.copy(client.connect(url), tmp); + Files.copy(client.connect(url), tmp.toPath()); } if (isJarFile(tmp)) { @@ -478,52 +442,96 @@ protected IStatus run(IProgressMonitor monitor) { createActions(); fillToolBar(getViewSite().getActionBars() .getToolBarManager()); + IActionBars actionBars = getViewSite().getActionBars(); + actionBars.setGlobalActionHandler(ActionFactory.REFRESH.getId(), refreshAction); + + // Event subscription + eventBroker.subscribe(ViewEventTopics.REPOSITORIESVIEW_OPEN_ADVANCED_SEARCH.topic(), + event -> handleOpenAdvancedSearch(event)); + ISelectionService selectionService = getSite().getWorkbenchWindow().getSelectionService(); - prefs.addPropertyChangeListener(workspaceOfflineListener); + selectionService.addSelectionListener(new ISelectionListener() { - // synthenic call to "refresh" so that we can get the repositories to - // show up in the UI - new WorkspaceJob("Load repositories") { @Override - public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { - try { - Central.refreshPlugins(); - } catch (Exception e) { - // ignore errors there may be no workspace yet + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + if (getSite().getPart() == part) { + return; } - return Status.OK_STATUS; + updateSelection(selection); } - }.schedule(); + }); + updateSelection(selectionService.getSelection()); + } - IActionBars actionBars = getViewSite().getActionBars(); - actionBars.setGlobalActionHandler(ActionFactory.REFRESH.getId(), refreshAction); + private void updateSelection(ISelection selection) { + IProject project = getProject(selection); + Workspace ws = Workspaces.getWorkspace(project).or(() -> Workspaces.getGlobalWorkspace()).orElse(null); + if (this.workspace != ws) { + this.workspace = ws; + RepositoriesViewRefresher.refreshViewer(viewer, this); + workspaceName.setValue(Workspaces.getName(ws)); + workspaceDescription.setValue(Workspaces.getDescription(ws)); + } + BndPreferences pref = Adapters.adapt(project, BndPreferences.class); + setPrefrences(pref); + } - // Event subscription - eventBroker.subscribe(ViewEventTopics.REPOSITORIESVIEW_OPEN_ADVANCED_SEARCH.topic(), - event -> handleOpenAdvancedSearch(event)); + protected IProject getProject(ISelection selection) { + if (selection instanceof IStructuredSelection structured) { + Object firstElement = structured.getFirstElement(); + IProject project = Adapters.adapt(firstElement, IProject.class); + if (project != null) { + return project; + } + IResource resource = Adapters.adapt(firstElement, IResource.class); + if (resource != null) { + return resource.getProject(); + } + return null; + } + if (selection instanceof ITextSelection) { + IEditorPart editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + if (editor != null) { + IEditorInput editorInput = editor.getEditorInput(); + if (editorInput instanceof IFileEditorInput fileInput) { + return fileInput.getFile().getProject(); + } + } + } + return null; } - private void configureOfflineAction() { - Workspace workspace = Central.getWorkspaceIfPresent(); - if (workspace == null) { + private void setPrefrences(BndPreferences preferences) { + if (Objects.equals(this.preferences, preferences)) { + return; + } + if (this.preferences!=null) { + this.preferences.removePropertyChangeListener(workspaceOfflineListener); + } + this.preferences = preferences; + if (preferences == null) { offlineAction.setChecked(false); offlineAction.setToolTipText("Go Offline"); - offlineAction.setImageDescriptor(Icons.desc("connected")); - offlineAction.setDisabledImageDescriptor(Icons.desc("connected.disabled")); + offlineAction.setImageDescriptor(Resources.getImageDescriptor("connect.png")); + offlineAction.setDisabledImageDescriptor(Resources.getImageDescriptor("connect_d.png")); offlineAction.setEnabled(false); return; } + preferences.addPropertyChangeListener(workspaceOfflineListener); + updateOfflineAction(preferences.isWorkspaceOffline()); + } - if (prefs.isWorkspaceOffline()) { + protected void updateOfflineAction(boolean offline) { + if (offline) { offlineAction.setChecked(true); offlineAction.setToolTipText("Go Online"); - offlineAction.setImageDescriptor(Icons.desc("disconnected")); - offlineAction.setDisabledImageDescriptor(Icons.desc("disconnected.disabled")); + offlineAction.setImageDescriptor(Resources.getImageDescriptor("disconnect.png")); + offlineAction.setDisabledImageDescriptor(Resources.getImageDescriptor("disconnect_d.png")); } else { offlineAction.setChecked(false); offlineAction.setToolTipText("Go Offline"); - offlineAction.setImageDescriptor(Icons.desc("connected")); - offlineAction.setDisabledImageDescriptor(Icons.desc("connected.disabled")); + offlineAction.setImageDescriptor(Resources.getImageDescriptor("connect.png")); + offlineAction.setDisabledImageDescriptor(Resources.getImageDescriptor("connect_d.png")); } offlineAction.setEnabled(true); } @@ -535,7 +543,7 @@ protected void openURI(URI uri) { .getStore(uri); IDE.openEditorOnFileStore(page, fileStore); } catch (PartInitException e) { - logger.logError("Error opening editor for " + uri, e); + ILog.get().error("Error opening editor for " + uri, e); } } @@ -580,13 +588,16 @@ public void dispose() { .getActiveWorkbenchWindow() .getPartService() .removePartListener(dndgaviPageListener); - Central.removeRepositoriesViewer(viewer); - prefs.removePropertyChangeListener(workspaceOfflineListener); + RepositoriesViewRefresher.removeViewer(viewer); + BndPreferences preferences = getPreferences(); + if (preferences != null) { + preferences.removePropertyChangeListener(workspaceOfflineListener); + } super.dispose(); } boolean addFilesToRepository(RepositoryPlugin repo, File[] files) { - AddFilesToRepositoryWizard wizard = new AddFilesToRepositoryWizard(repo, files); + AddFilesToRepositoryWizard wizard = new AddFilesToRepositoryWizard(getWorkspace(), repo, files); WizardDialog dialog = new WizardDialog(getViewSite().getShell(), wizard); dialog.open(); viewer.refresh(repo); @@ -610,8 +621,8 @@ public void run() { collapseAllAction.setEnabled(false); collapseAllAction.setText("Collapse All"); collapseAllAction.setToolTipText("Collapse All"); - collapseAllAction.setImageDescriptor(Icons.desc("collapse")); - collapseAllAction.setDisabledImageDescriptor(Icons.desc("collapse.disabled")); + collapseAllAction.setImageDescriptor(Resources.getImageDescriptor("collapseall.png")); + collapseAllAction.setDisabledImageDescriptor(Resources.getImageDescriptor("collapseall_d.png")); refreshAction = new Action() { @Override @@ -627,13 +638,13 @@ public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { try { refreshAction.setEnabled(false); - Central.refreshPlugins(); + Central.refreshPlugins(getWorkspace()); } catch (Exception e) { Throwable t = Exceptions.unrollCause(e, InvocationTargetException.class); - logger.logError("Unexpected error in refreshing plugns", t); + ILog.get().error("Unexpected error in refreshing plugns", t); - return new Status(IStatus.ERROR, Plugin.PLUGIN_ID, "Failed to refresh plugins", t); + return Status.error("Failed to refresh plugins", t); } finally { refreshAction.setEnabled(true); } @@ -645,8 +656,8 @@ public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { refreshAction.setEnabled(false); refreshAction.setText("Refresh"); refreshAction.setToolTipText("Refresh Repositories Tree"); - refreshAction.setImageDescriptor(Icons.desc("refresh")); - refreshAction.setDisabledImageDescriptor(Icons.desc("refresh.disabled")); + refreshAction.setImageDescriptor(Resources.getImageDescriptor("arrow_refresh.png")); + refreshAction.setDisabledImageDescriptor(Resources.getImageDescriptor("arrow_refresh_d.png")); addBundlesAction = new Action() { @Override @@ -656,7 +667,8 @@ public void run() { if (element != null && element instanceof RepositoryPlugin) { RepositoryPlugin repo = (RepositoryPlugin) element; if (repo.canWrite()) { - AddFilesToRepositoryWizard wizard = new AddFilesToRepositoryWizard(repo, new File[0]); + AddFilesToRepositoryWizard wizard = new AddFilesToRepositoryWizard(getWorkspace(), repo, + new File[0]); WizardDialog dialog = new WizardDialog(getViewSite().getShell(), wizard); dialog.open(); @@ -668,8 +680,8 @@ public void run() { addBundlesAction.setEnabled(false); addBundlesAction.setText("Add"); addBundlesAction.setToolTipText("Add Bundles to Repository"); - addBundlesAction.setImageDescriptor(Icons.desc("add")); - addBundlesAction.setDisabledImageDescriptor(Icons.desc("add.disabled")); + addBundlesAction.setImageDescriptor(Resources.getImageDescriptor("add_obj.png")); + addBundlesAction.setDisabledImageDescriptor(Resources.getImageDescriptor("add_obj_d.png")); advancedSearchAction = new Action("Advanced Search", IAction.AS_CHECK_BOX) { @Override @@ -681,7 +693,7 @@ public void run() { XMLMemento memento = XMLMemento.createReadRoot(new StringReader(advancedSearchState)); dialog.restoreState(memento); } catch (Exception e) { - logger.logError("Failed to load dialog state", e); + ILog.get().error("Failed to load dialog state", e); } } @@ -703,7 +715,7 @@ public void run() { memento.save(writer); advancedSearchState = writer.toString(); } catch (Exception e) { - logger.logError("Failed to save dialog state", e); + ILog.get().error("Failed to save dialog state", e); } } else { contentProvider.setRequirementFilter(null); @@ -715,8 +727,8 @@ public void run() { advancedSearchAction.setEnabled(false); advancedSearchAction.setText("Advanced Search"); advancedSearchAction.setToolTipText("Toggle Advanced Search"); - advancedSearchAction.setImageDescriptor(Icons.desc("search")); - advancedSearchAction.setDisabledImageDescriptor(Icons.desc("search.disabled")); + advancedSearchAction.setImageDescriptor(Resources.getImageDescriptor("search.png")); + advancedSearchAction.setDisabledImageDescriptor(Resources.getImageDescriptor("search_d.png")); downloadAction = new Action() { @Override @@ -766,22 +778,22 @@ private List selectionByType(IStructuredSelection selection, Class typ }; downloadAction.setEnabled(false); downloadAction.setText("Download Repository Content"); - downloadAction.setImageDescriptor(Icons.desc("download")); - downloadAction.setDisabledImageDescriptor(Icons.desc("download.disabled")); + downloadAction.setImageDescriptor(Resources.getImageDescriptor("download.png")); + downloadAction.setDisabledImageDescriptor(Resources.getImageDescriptor("download_d.png")); offlineAction = new Action("Online/Offline Mode", IAction.AS_CHECK_BOX) { @Override public void run() { - Workspace workspace = Central.getWorkspaceIfPresent(); - if (workspace != null) { - prefs.setWorkspaceOffline(offlineAction.isChecked()); + BndPreferences preferences = getPreferences(); + if (preferences != null) { + preferences.setWorkspaceOffline(offlineAction.isChecked()); } } }; offlineAction.setEnabled(false); offlineAction.setToolTipText("Go Offline"); - offlineAction.setImageDescriptor(Icons.desc("connected")); - offlineAction.setDisabledImageDescriptor(Icons.desc("connected.disabled")); + offlineAction.setImageDescriptor(Resources.getImageDescriptor("connect.png")); + offlineAction.setDisabledImageDescriptor(Resources.getImageDescriptor("connect_d.png")); viewer.addSelectionChangedListener(event -> { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); @@ -865,6 +877,50 @@ void createContextMenu() { } private void fillToolBar(IToolBarManager toolBar) { + toolBar.add(new ControlContribution("label") { + + @Override + protected Control createControl(Composite parent) { + final Composite composite = new Composite(parent, SWT.NONE); + composite.setLayout(new FillLayout()); + // TODO maybe make this a combo so the user can choose other namespaces eg: + // - active selection + // - any of the ones registered at OSGi + CLabel label = new CLabel(composite, SWT.CENTER); + + IChangeListener labelListener = e -> { + String text = label.getText(); + String newText = getLabelText(); + if (Objects.equals(text, newText)) { + return; + } + label.setText(newText); + label.setToolTipText(workspaceDescription.getValue()); + toolBar.update(true); + }; + IChangeListener tooltipListener = e -> { + String text = label.getToolTipText(); + String newText = workspaceDescription.getValue(); + if (Objects.equals(text, newText)) { + return; + } + label.setToolTipText(newText); + }; + label.addDisposeListener(e -> { + workspaceDescription.removeChangeListener(tooltipListener); + workspaceName.removeChangeListener(labelListener); + }); + workspaceName.addChangeListener(labelListener); + workspaceDescription.addChangeListener(tooltipListener); + label.setText(getLabelText()); + label.setToolTipText(workspaceDescription.getValue()); + return composite; + } + + private String getLabelText() { + return Objects.requireNonNullElse(workspaceName.getValue(), ""); + } + }); toolBar.add(advancedSearchAction); toolBar.add(downloadAction); toolBar.add(new Separator()); @@ -929,7 +985,7 @@ boolean performDrop(Object target, TransferData data, Object dropped) { RepositoryPlugin repositoryPlugin = getRepositoryPlugin(target); if (repositoryPlugin != null && repositoryPlugin instanceof Refreshable) - Central.refreshPlugin((Refreshable) repositoryPlugin); + Central.refreshPlugin(getWorkspace(), (Refreshable) repositoryPlugin); return true; } catch (Exception e) { e.printStackTrace(); @@ -942,8 +998,8 @@ private Object toJava(Object dropped) { IStructuredSelection selection = (IStructuredSelection) dropped; if (!selection.isEmpty()) { Object firstElement = selection.getFirstElement(); - if (firstElement instanceof Resource) { - Resource resource = (Resource) firstElement; + if (firstElement instanceof IResource) { + IResource resource = (IResource) firstElement; IPath path = resource.getRawLocation(); if (path != null) { File file = path.toFile(); @@ -1032,13 +1088,18 @@ Object toJava(TransferData data) throws Exception { } } if (URLTransfer.getInstance() - .isSupportedType(data)) - return Converter.cnv(URI.class, URLTransfer.getInstance() - .nativeToJava(data)); - else if (FileTransfer.getInstance() .isSupportedType(data)) { - return Converter.cnv(File[].class, FileTransfer.getInstance() - .nativeToJava(data)); + Object nativeUrl = URLTransfer.getInstance().nativeToJava(data); + if (nativeUrl instanceof String s) { + return new URI(s); + } + } else if (FileTransfer.getInstance() + .isSupportedType(data)) { + Object nativeFiles = FileTransfer.getInstance() + .nativeToJava(data); + if (nativeFiles instanceof String[] str) { + return Arrays.stream(str).map(File::new).toArray(File[]::new); + } } else if (TextTransfer.getInstance() .isSupportedType(data)) { return TextTransfer.getInstance() @@ -1066,7 +1127,7 @@ else if (element instanceof RepositoryBundleVersion) @Override public List getRepositories() { - return RepositoryUtils.listRepositories(true); + return RepositoryUtils.listRepositories(getWorkspace(), true); } private static boolean isJarFile(File candidate) { @@ -1090,13 +1151,9 @@ protected IStatus run(IProgressMonitor monitor) { try { r.run(); if (rp != null && rp instanceof Refreshable) - Central.refreshPlugin((Refreshable) rp, true); + Central.refreshPlugin(getWorkspace(), (Refreshable) rp, true); } catch (final Exception e) { - IStatus status = new Status(IStatus.ERROR, Plugin.PLUGIN_ID, - "Error executing: " + getName(), e); - Plugin.getDefault() - .getLog() - .log(status); + ILog.get().error("Error executing: " + getName(), e); } monitor.done(); return Status.OK_STATUS; @@ -1130,7 +1187,7 @@ public void done(IJobChangeEvent event) { private void addCopyToClipboardSubMenueEntries(Actionable act, final RepositoryPlugin rp, HierarchicalMenu hmenu) { - final Registry registry = Central.getWorkspaceIfPresent(); + final Registry registry = getWorkspace(); if (registry == null) { return; } @@ -1273,4 +1330,13 @@ private void handleOpenAdvancedSearch(Event event) { } } + @Override + public Workspace getWorkspace() { + return this.workspace; + } + + private BndPreferences getPreferences() { + return this.preferences; + } + } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/SearchPanel.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/SearchPanel.java index 07584e768d..1ade7b2120 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/SearchPanel.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/SearchPanel.java @@ -12,7 +12,7 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements *******************************************************************************/ -package bndtools.views.repository; +package org.eclipse.pde.bnd.ui.views.repository; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; @@ -75,7 +75,7 @@ protected void setRequirement(Requirement requirement) { propSupport.firePropertyChange(PROP_VALUE, oldRequiremenmt, requirement); } - public Image createImage(@SuppressWarnings("unused") Device device) { + public Image createImage(Device device) { return null; } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/ServiceSearchPanel.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/ServiceSearchPanel.java index 41ec20be3c..98e309d32e 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/ServiceSearchPanel.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/views/repository/ServiceSearchPanel.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2021 bndtools project and others. + * Copyright (c) 2015, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -12,10 +12,11 @@ * Neil Bartlett - initial API and implementation * BJ Hargrave - ongoing enhancements * Peter Kriens - ongoing enhancements + * Christoph Läubrich - adapt to pde code base *******************************************************************************/ -package bndtools.views.repository; +package org.eclipse.pde.bnd.ui.views.repository; -import org.bndtools.core.ui.icons.Icons; +import org.eclipse.pde.bnd.ui.Resources; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.Image; @@ -82,7 +83,7 @@ public void setFocus() { @Override public Image createImage(Device device) { - return Icons.image("service"); + return Resources.getImage("service"); } @Override diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/AddFilesToRepositoryWizard.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/AddFilesToRepositoryWizard.java index 141894f1e2..83b4d9f939 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/AddFilesToRepositoryWizard.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/AddFilesToRepositoryWizard.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2021 bndtools project and others. + * Copyright (c) 2010, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -14,18 +14,22 @@ * PK Søreide - ongoing enhancements * Gregory Amerson - ongoing enhancements * BJ Hargrave - ongoing enhancements + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.wizards.workspace; +package org.eclipse.pde.bnd.ui.wizards; import java.io.BufferedInputStream; import java.io.File; import java.io.InputStream; import java.net.URI; +import java.nio.file.Files; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.CoreException; @@ -35,30 +39,30 @@ import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.jface.wizard.Wizard; +import org.eclipse.pde.bnd.ui.Central; +import org.eclipse.pde.bnd.ui.RefreshFileJob; +import aQute.bnd.build.Workspace; import aQute.bnd.osgi.Jar; import aQute.bnd.service.Refreshable; import aQute.bnd.service.RepositoryPlugin; -import aQute.lib.io.IO; -import bndtools.Plugin; -import bndtools.central.Central; -import bndtools.central.RefreshFileJob; -import bndtools.types.Pair; public class AddFilesToRepositoryWizard extends Wizard { private RepositoryPlugin repository; private final File[] files; - private List> selectedBundles; + private List> selectedBundles; private final LocalRepositorySelectionPage repoSelectionPage; private final AddFilesToRepositoryWizardPage fileSelectionPage; + private Workspace workspace; - public AddFilesToRepositoryWizard(RepositoryPlugin repository, File[] initialFiles) { + public AddFilesToRepositoryWizard(Workspace workspace, RepositoryPlugin repository, File[] initialFiles) { + this.workspace = workspace; this.repository = repository; this.files = initialFiles; - repoSelectionPage = new LocalRepositorySelectionPage("repoSelectionPage", repository); + repoSelectionPage = new LocalRepositorySelectionPage(workspace, "repoSelectionPage", repository); fileSelectionPage = new AddFilesToRepositoryWizardPage("fileSelectionPage"); fileSelectionPage.setFiles(files); @@ -79,7 +83,8 @@ public boolean performFinish() { WorkspaceJob job = new WorkspaceJob("Adding files to repository") { @Override public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { - MultiStatus status = new MultiStatus(Plugin.PLUGIN_ID, 0, "Failed to install one or more bundles", + MultiStatus status = new MultiStatus(AddFilesToRepositoryWizard.class, 0, + "Failed to install one or more bundles", null); List files = fileSelectionPage.getFiles(); List refresh = new ArrayList<>(); @@ -89,15 +94,14 @@ public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { try (Jar jar = new Jar(file)) { String bsn = jar.getBsn(); String version = jar.getVersion(); - selectedBundles.add(Pair.newInstance(bsn, (version != null) ? version : "0")); + selectedBundles.add(Map.entry(bsn, (version != null) ? version : "0")); } catch (Exception e) { - status.add(new Status(IStatus.ERROR, Plugin.PLUGIN_ID, 0, - MessageFormat.format("Failed to analyse JAR: {0}", file.getPath()), e)); + status.add(Status.error(MessageFormat.format("Failed to analyze JAR: {0}", file.getPath()), e)); progress.worked(1); continue; } - try (InputStream in = new BufferedInputStream(IO.stream(file))) { + try (InputStream in = new BufferedInputStream(Files.newInputStream(file.toPath()))) { RepositoryPlugin.PutResult result = repository.put(in, new RepositoryPlugin.PutOptions()); URI artifact = result.artifact; if ((artifact != null) && artifact.getScheme() @@ -105,11 +109,11 @@ public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { refresh.add(new File(artifact)); } if (repository instanceof Refreshable) { - Central.refreshPlugin((Refreshable) repository, true); + Central.refreshPlugin(workspace, (Refreshable) repository, true); } } catch (Exception e) { - status.add(new Status(IStatus.ERROR, Plugin.PLUGIN_ID, 0, - MessageFormat.format("Failed to add JAR to repository: {0}", file.getPath()), e)); + status.add(Status.error( + MessageFormat.format("Failed to add JAR to repository: {0}", file.getPath()), e)); progress.worked(1); continue; } @@ -126,7 +130,7 @@ public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { return true; } - public List> getSelectedBundles() { + public List> getSelectedBundles() { return Collections.unmodifiableList(selectedBundles); } } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/AddFilesToRepositoryWizardPage.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/AddFilesToRepositoryWizardPage.java index 03aefe1c6e..42f968c586 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/AddFilesToRepositoryWizardPage.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/AddFilesToRepositoryWizardPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2021 bndtools project and others. + * Copyright (c) 2010, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -13,8 +13,9 @@ * Ferry Huberts - ongoing enhancements * BJ Hargrave - ongoing enhancements * Peter Kriens - ongoing enhancements + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.wizards.workspace; +package org.eclipse.pde.bnd.ui.wizards; import java.io.File; import java.util.ArrayList; @@ -22,15 +23,14 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.jar.Attributes; import org.bndtools.api.ILogger; import org.bndtools.api.Logger; -import org.bndtools.core.ui.icons.Icons; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.ArrayContentProvider; @@ -41,6 +41,8 @@ import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.pde.bnd.ui.FileExtensionFilter; +import org.eclipse.pde.bnd.ui.Resources; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; @@ -59,20 +61,17 @@ import org.osgi.framework.Constants; import aQute.bnd.osgi.Jar; -import bndtools.Plugin; -import bndtools.types.Pair; -import bndtools.utils.FileExtensionFilter; public class AddFilesToRepositoryWizardPage extends WizardPage { private static final ILogger logger = Logger .getLogger(AddFilesToRepositoryWizardPage.class); - private final static Image jarImg = Icons.image("jar"); - private final static Image warnImg = Icons.image("/icons/warning_obj.gif"); - private final static Image errorImg = Icons.image("/icons/error.gif"); - private final static Image okayImg = Icons.image("/icons/tick.png"); + private final static Image jarImg = Resources.getImage("jar.gif"); + private final static Image warnImg = Resources.getImage("warning_obj.gif"); + private final static Image errorImg = Resources.getImage("error.gif"); + private final static Image okayImg = Resources.getImage("tick.png"); - private final Map> bsnMap = new HashMap<>(); + private final Map> bsnMap = new HashMap<>(); private final List files = new ArrayList<>(1); private TableViewer viewer; @@ -106,14 +105,13 @@ void analyseFile(File file) { String bsn = attribs.getValue(Constants.BUNDLE_SYMBOLICNAME); String version = attribs.getValue(Constants.BUNDLE_VERSION); - bsnMap.put(file, Pair.newInstance(bsn, version)); + bsnMap.put(file, Map.entry(bsn, version)); } catch (Exception e) { logger.logError("Error reading JAR file content", e); } } @Override - @SuppressWarnings("unused") public void createControl(Composite parent) { setTitle("Add Files to Repository"); @@ -139,7 +137,7 @@ public void createControl(Composite parent) { @Override public void update(ViewerCell cell) { File file = (File) cell.getElement(); - Pair bundleId = bsnMap.get(file); + Entry bundleId = bsnMap.get(file); int index = cell.getColumnIndex(); if (index == 0) { @@ -160,8 +158,8 @@ public void update(ViewerCell cell) { cell.setImage(errorImg); cell.setText("Not a JAR file"); } else { - String bsn = bundleId.getFirst(); - String version = bundleId.getSecond(); + String bsn = bundleId.getKey(); + String version = bundleId.getValue(); if (bsn == null) { cell.setImage(warnImg); cell.setText("Not a Bundle JAR"); @@ -227,9 +225,9 @@ void doAdd() { new WorkbenchContentProvider()); dialog.setValidator(selection -> { if (selection.length > 0 && selection[0] instanceof IFile) { - return new Status(IStatus.OK, Plugin.PLUGIN_ID, IStatus.OK, "", null); //$NON-NLS-1$ + return Status.OK_STATUS; } - return new Status(IStatus.ERROR, Plugin.PLUGIN_ID, IStatus.ERROR, "", null); //$NON-NLS-1$ + return Status.error(""); //$NON-NLS-1$ }); dialog.setAllowMultiple(true); dialog.setTitle("JAR File Selection"); @@ -298,11 +296,11 @@ void validate() { String warning = null; for (File file : files) { - Pair pair = bsnMap.get(file); + Entry pair = bsnMap.get(file); if (pair == null) { error = "One or more selected files is not a JAR."; } else { - String bsn = pair.getFirst(); + String bsn = pair.getKey(); if (bsn == null) { warning = "One or more selected files is not a Bundle JAR"; } diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/LocalRepositorySelectionPage.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/LocalRepositorySelectionPage.java index 8ee91001cf..f6acb07e51 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/LocalRepositorySelectionPage.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/wizards/LocalRepositorySelectionPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2020 bndtools project and others. + * Copyright (c) 2010, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -12,8 +12,9 @@ * Neil Bartlett - initial API and implementation * Ferry Huberts - ongoing enhancements * BJ Hargrave - ongoing enhancements + * Christoph Läubrich - Adapt to PDE codebase *******************************************************************************/ -package bndtools.wizards.workspace; +package org.eclipse.pde.bnd.ui.wizards; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; @@ -28,15 +29,14 @@ import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.pde.bnd.ui.model.repo.RepositoryTreeContentProvider; +import org.eclipse.pde.bnd.ui.model.repo.RepositoryTreeLabelProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; import aQute.bnd.build.Workspace; import aQute.bnd.service.RepositoryPlugin; -import bndtools.central.Central; -import bndtools.model.repo.RepositoryTreeContentProvider; -import bndtools.model.repo.RepositoryTreeLabelProvider; class LocalRepositorySelectionPage extends WizardPage { private static final ILogger logger = Logger.getLogger(LocalRepositorySelectionPage.class); @@ -46,12 +46,15 @@ class LocalRepositorySelectionPage extends WizardPage { private final PropertyChangeSupport propSupport = new PropertyChangeSupport(this); private RepositoryPlugin selectedRepository = null; - LocalRepositorySelectionPage(String pageName) { - this(pageName, null); + private Workspace workspace; + + LocalRepositorySelectionPage(Workspace workspace, String pageName) { + this(workspace, pageName, null); } - LocalRepositorySelectionPage(String pageName, RepositoryPlugin selectedRepository) { + LocalRepositorySelectionPage(Workspace workspace, String pageName, RepositoryPlugin selectedRepository) { super(pageName); + this.workspace = workspace; this.selectedRepository = selectedRepository; } @@ -73,7 +76,6 @@ public boolean select(Viewer viewer, Object parentElement, Object element) { }); try { - Workspace workspace = Central.getWorkspace(); viewer.setInput(workspace); if (selectedRepository != null) viewer.setSelection(new StructuredSelection(selectedRepository)); diff --git a/ui/org.eclipse.pde.core/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.core/META-INF/MANIFEST.MF index 8b137beabd..34b4361af1 100644 --- a/ui/org.eclipse.pde.core/META-INF/MANIFEST.MF +++ b/ui/org.eclipse.pde.core/META-INF/MANIFEST.MF @@ -87,8 +87,11 @@ Import-Package: aQute.bnd.build;version="[4.4.0,5.0.0)", aQute.bnd.osgi.resource;version="[4.3.0,6.0.0)", aQute.bnd.properties;version="[2.0.0,3.0.0)", aQute.bnd.service;version="[4.7.0,5.0.0)", + aQute.bnd.service.clipboard;version="[1.0.0,2.0.0]", + aQute.bnd.service.progress;version="[1.3.0,2.0.0]", aQute.bnd.version;version="[2.2.0,3.0.0)", aQute.service.reporter;version="[1.2.0,2.0.0)", + org.bndtools.versioncontrol.ignores.manager.api;version="[1.0.0,2.0.0]", org.eclipse.equinox.internal.p2.publisher.eclipse, org.eclipse.equinox.p2.publisher, org.eclipse.equinox.p2.publisher.eclipse, diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDECore.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDECore.java index 5b02694e50..9fe9dc2dc2 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDECore.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDECore.java @@ -57,6 +57,8 @@ import org.osgi.util.tracker.ServiceTracker; import aQute.bnd.build.Workspace; +import aQute.bnd.service.RepositoryListenerPlugin; +import aQute.bnd.service.clipboard.Clipboard; public class PDECore extends Plugin implements DebugOptionsListener { public static final String PLUGIN_ID = "org.eclipse.pde.core"; //$NON-NLS-1$ @@ -201,6 +203,10 @@ public static void logException(Throwable e, String message) { private ServiceTracker classpathContributorServiceTracker; + private ServiceTracker clipBoardsServiceTracker; + + private ServiceTracker repositoryListenerServiceTracker; + public PDECore() { inst = this; } @@ -463,4 +469,28 @@ public synchronized Stream getClasspathContributors() { } return classpathContributorServiceTracker.getTracked().values().stream(); } + + public synchronized Clipboard getClipboardPlugin() { + if (fBundleContext == null) { + return null; + } + if (clipBoardsServiceTracker == null) { + clipBoardsServiceTracker = new ServiceTracker<>(fBundleContext, Clipboard.class, null); + clipBoardsServiceTracker.open(); + } + return clipBoardsServiceTracker.getService(); + } + + public synchronized Stream getRepositoryListenerPlugins() { + if (fBundleContext == null) { + return Stream.empty(); + } + if (repositoryListenerServiceTracker == null) { + repositoryListenerServiceTracker = new ServiceTracker<>(fBundleContext, RepositoryListenerPlugin.class, + null); + repositoryListenerServiceTracker.open(); + } + return repositoryListenerServiceTracker.getTracked().values().stream(); + + } } diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/BndProjectManager.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/BndProjectManager.java index c9b448053f..7b28d5aeac 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/BndProjectManager.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/BndProjectManager.java @@ -97,7 +97,13 @@ static synchronized Workspace getWorkspace() throws Exception { run.setProperty(Constants.STANDALONE, TRUE); IPath path = PDECore.getDefault().getStateLocation().append(Project.BNDCNF); workspace = Workspace.createStandaloneWorkspace(run, path.toFile().toURI()); + workspace.set("workspaceName", Messages.BndProjectManager_WorkspaceName); //$NON-NLS-1$ + workspace.set("workspaceDescription", Messages.BndProjectManager_WorkspaceDescription); //$NON-NLS-1$ workspace.addBasicPlugin(TargetRepository.getTargetRepository()); + workspace.addBasicPlugin(new JobProgress()); + workspace.addBasicPlugin(new SupplierClipboard(() -> PDECore.getDefault().getClipboardPlugin())); + workspace.addBasicPlugin( + new DelegateRepositoryListener(() -> PDECore.getDefault().getRepositoryListenerPlugins())); workspace.refresh(); } } diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/DelegateRepositoryListener.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/DelegateRepositoryListener.java new file mode 100644 index 0000000000..98f057a120 --- /dev/null +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/DelegateRepositoryListener.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2024 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.internal.core.bnd; + +import java.io.File; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import aQute.bnd.osgi.Jar; +import aQute.bnd.service.RepositoryListenerPlugin; +import aQute.bnd.service.RepositoryPlugin; + +public class DelegateRepositoryListener implements RepositoryListenerPlugin { + + private Supplier> delegateSupplier; + + public DelegateRepositoryListener(Supplier> delegateSupplier) { + this.delegateSupplier = delegateSupplier; + } + + @Override + public void bundleAdded(RepositoryPlugin repository, Jar jar, File file) { + delegateSupplier.get().forEach(listener -> listener.bundleAdded(repository, jar, file)); + + } + + @Override + public void bundleRemoved(RepositoryPlugin repository, Jar jar, File file) { + delegateSupplier.get().forEach(listener -> listener.bundleRemoved(repository, jar, file)); + } + + @Override + public void repositoryRefreshed(RepositoryPlugin repository) { + delegateSupplier.get().forEach(listener -> listener.repositoryRefreshed(repository)); + + } + + @Override + public void repositoriesRefreshed() { + delegateSupplier.get().forEach(listener -> listener.repositoriesRefreshed()); + } + +} diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/JobProgress.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/JobProgress.java index e0fe4dfacf..be576e63b1 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/JobProgress.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/JobProgress.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2019 bndtools project and others. + * Copyright (c) 2016, 2024 bndtools project and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -11,23 +11,20 @@ * Contributors: * Gregory Amerson - initial API and implementation * BJ Hargrave - ongoing enhancements + * Christoph Läubrich - adapt to pde codebase *******************************************************************************/ -package bndtools.central; +package org.eclipse.pde.internal.core.bnd; import java.util.concurrent.atomic.AtomicReference; -import org.bndtools.api.ILogger; -import org.bndtools.api.Logger; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import aQute.bnd.service.progress.ProgressPlugin; -import bndtools.Plugin; public class JobProgress implements ProgressPlugin { - static final ILogger logger = Logger.getLogger(JobProgress.class); @Override public Task startTask(String name, int size) { @@ -46,7 +43,6 @@ private static class TaskJob extends Job implements Task { super(name); this.name = name; this.size = size; - logger.logInfo(name, null); } @Override @@ -60,8 +56,7 @@ protected IStatus run(IProgressMonitor monitor) { Thread.sleep(100); } catch (InterruptedException e) { monitor.setCanceled(true); - status.compareAndSet(null, - new Status(IStatus.CANCEL, Plugin.PLUGIN_ID, "InterruptedException", e)); + status.compareAndSet(null, Status.CANCEL_STATUS); Thread.currentThread() .interrupt(); } @@ -78,7 +73,7 @@ protected IStatus run(IProgressMonitor monitor) { private boolean isCanceled(IProgressMonitor m) { boolean canceled = m.isCanceled(); if (canceled) { - status.compareAndSet(null, new Status(IStatus.CANCEL, Plugin.PLUGIN_ID, "Canceled")); + status.compareAndSet(null, Status.CANCEL_STATUS); } return canceled; } @@ -94,8 +89,11 @@ public void worked(int units) { @Override public void done(String message, Throwable error) { - status.compareAndSet(null, - new Status(error == null ? IStatus.OK : IStatus.ERROR, Plugin.PLUGIN_ID, message, error)); + if (error == null) { + status.compareAndSet(null, Status.OK_STATUS); + } else { + status.compareAndSet(null, Status.error(message, error)); + } } @Override diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/Messages.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/Messages.java new file mode 100644 index 0000000000..aa9cc220af --- /dev/null +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/Messages.java @@ -0,0 +1,16 @@ +package org.eclipse.pde.internal.core.bnd; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + private static final String BUNDLE_NAME = Messages.class.getPackageName() + ".messages"; //$NON-NLS-1$ + public static String BndProjectManager_WorkspaceDescription; + public static String BndProjectManager_WorkspaceName; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/PdeBndAdapter.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/PdeBndAdapter.java index 444c1c360b..b7730d2041 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/PdeBndAdapter.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/PdeBndAdapter.java @@ -13,17 +13,24 @@ *******************************************************************************/ package org.eclipse.pde.internal.core.bnd; +import org.bndtools.versioncontrol.ignores.manager.api.VersionControlIgnoresManager; import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.AdapterTypes; import org.eclipse.core.runtime.IAdapterFactory; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; import aQute.bnd.build.Project; -@Component(service = IAdapterFactory.class, property = { - IAdapterFactory.SERVICE_PROPERTY_ADAPTABLE_CLASS + "=org.eclipse.core.resources.IProject", - IAdapterFactory.SERVICE_PROPERTY_ADAPTER_NAMES + "=aQute.bnd.build.Project" }) +@Component(service = IAdapterFactory.class) +@AdapterTypes(adaptableClass = IProject.class, adapterNames = { Project.class, VersionControlIgnoresManager.class }) public class PdeBndAdapter implements IAdapterFactory { + @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC) + private volatile VersionControlIgnoresManager versionControlIgnoresManager; + @Override public T getAdapter(Object adaptableObject, Class adapterType) { if (adapterType == Project.class) { @@ -36,12 +43,10 @@ public T getAdapter(Object adaptableObject, Class adapterType) { } } } + if (adapterType == VersionControlIgnoresManager.class) { + return adapterType.cast(versionControlIgnoresManager); + } return null; } - @Override - public Class[] getAdapterList() { - return new Class[] { Project.class }; - } - } \ No newline at end of file diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/SupplierClipboard.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/SupplierClipboard.java new file mode 100644 index 0000000000..07c4354fdf --- /dev/null +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/SupplierClipboard.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2024 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.internal.core.bnd; + +import java.util.Optional; +import java.util.function.Supplier; + +import aQute.bnd.service.clipboard.Clipboard; + +public class SupplierClipboard implements Clipboard { + + private Supplier supplier; + + public SupplierClipboard(Supplier supplier) { + this.supplier = supplier; + } + + @Override + public boolean copy(T content) { + Clipboard clipboard = supplier.get(); + if (clipboard != null) { + return clipboard.copy(content); + } + return false; + } + + @Override + public Optional paste(Class type) { + return Optional.ofNullable(supplier.get()).flatMap(clipboard -> clipboard.paste(type)); + } + +} diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/messages.properties b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/messages.properties new file mode 100644 index 0000000000..e8505c0ca4 --- /dev/null +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/bnd/messages.properties @@ -0,0 +1,2 @@ +BndProjectManager_WorkspaceDescription=The PDE Automatic Manifest Workspace +BndProjectManager_WorkspaceName=PDE diff --git a/ui/org.eclipse.pde.ui/.project b/ui/org.eclipse.pde.ui/.project index dedc0515a2..b6a6ee4543 100644 --- a/ui/org.eclipse.pde.ui/.project +++ b/ui/org.eclipse.pde.ui/.project @@ -25,6 +25,11 @@ + + org.eclipse.pde.ds.core.builder + + + org.eclipse.jdt.core.javanature diff --git a/ui/org.eclipse.pde.ui/.settings/org.eclipse.pde.ds.annotations.prefs b/ui/org.eclipse.pde.ui/.settings/org.eclipse.pde.ds.annotations.prefs new file mode 100644 index 0000000000..5faf08b7d5 --- /dev/null +++ b/ui/org.eclipse.pde.ui/.settings/org.eclipse.pde.ds.annotations.prefs @@ -0,0 +1,7 @@ +dsVersion=V1_4 +eclipse.preferences.version=1 +enabled=true +generateBundleActivationPolicyLazy=true +path=OSGI-INF +validationErrorLevel=error +validationErrorLevel.missingImplicitUnbindMethod=error diff --git a/ui/org.eclipse.pde.ui/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.ui/META-INF/MANIFEST.MF index 94edf9a43f..654ad2bd39 100644 --- a/ui/org.eclipse.pde.ui/META-INF/MANIFEST.MF +++ b/ui/org.eclipse.pde.ui/META-INF/MANIFEST.MF @@ -120,6 +120,7 @@ Require-Bundle: org.eclipse.equinox.security;bundle-version="[1.4.100,2.0.0)", org.eclipse.pde.bnd.ui;bundle-version="1.0.0", org.eclipse.pde.ds.core;bundle-version="1.3.300" +Service-Component: OSGI-INF/org.eclipse.pde.internal.ui.BndPreferencesAdapter.xml Import-Package: aQute.bnd.build;version="4.5.0", aQute.bnd.build.model;version="[4.2.0,5.0.0)", aQute.bnd.build.model.clauses;version="2.5.0", @@ -142,3 +143,4 @@ Import-Package: aQute.bnd.build;version="4.5.0", Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Automatic-Module-Name: org.eclipse.pde.ui + diff --git a/ui/org.eclipse.pde.ui/OSGI-INF/.gitignore b/ui/org.eclipse.pde.ui/OSGI-INF/.gitignore new file mode 100644 index 0000000000..b878e882ac --- /dev/null +++ b/ui/org.eclipse.pde.ui/OSGI-INF/.gitignore @@ -0,0 +1 @@ +/*.xml diff --git a/ui/org.eclipse.pde.ui/build.properties b/ui/org.eclipse.pde.ui/build.properties index cf3100634e..50ecc9c392 100644 --- a/ui/org.eclipse.pde.ui/build.properties +++ b/ui/org.eclipse.pde.ui/build.properties @@ -17,7 +17,8 @@ bin.includes = plugin.properties,\ plugin.xml,\ about.html,\ META-INF/,\ - css/ + css/,\ + OSGI-INF/ src.includes = about.html,\ schema/ source.. = src/,\ diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/BndPreferencesAdapter.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/BndPreferencesAdapter.java new file mode 100644 index 0000000000..e6db037c5c --- /dev/null +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/BndPreferencesAdapter.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2024 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.internal.ui; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.AdapterTypes; +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.pde.bnd.ui.preferences.BndPreferences; +import org.eclipse.pde.internal.core.natures.BndProject; +import org.osgi.service.component.annotations.Component; + +@Component(service = IAdapterFactory.class) +@AdapterTypes(adaptableClass = IProject.class, adapterNames = BndPreferences.class) +public class BndPreferencesAdapter implements IAdapterFactory { + + @Override + public T getAdapter(Object adaptableObject, Class adapterType) { + if (adaptableObject instanceof IProject project) { + if (adapterType == BndPreferences.class) { + if (BndProject.isBndProject(project)) { + return adapterType.cast(new BndPreferences(project, PDEPlugin.getDefault().getPreferenceStore())); + } + } + } + return null; + } + +}