Merge pull request #2748 from apache/delivery

Sync delivery to release123 for NB 12.3-beta3
diff --git a/NOTICE b/NOTICE
index 8a60ef5..e09832b 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,5 +1,5 @@
 Apache NetBeans
-Copyright 2017-2020 The Apache Software Foundation
+Copyright 2017-2021 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/cpplite/cpplite.debugger/src/META-INF/debugger/BreakpointsView/org.netbeans.spi.viewmodel.NodeModel b/cpplite/cpplite.debugger/src/META-INF/debugger/BreakpointsView/org.netbeans.spi.viewmodel.NodeModel
deleted file mode 100644
index b2ec1a2..0000000
--- a/cpplite/cpplite.debugger/src/META-INF/debugger/BreakpointsView/org.netbeans.spi.viewmodel.NodeModel
+++ /dev/null
@@ -1 +0,0 @@
-org.netbeans.modules.cpplite.debugger.breakpoints.BreakpointModel
\ No newline at end of file
diff --git a/cpplite/cpplite.debugger/src/META-INF/debugger/CPPLiteSession/org.netbeans.spi.debugger.ActionsProvider b/cpplite/cpplite.debugger/src/META-INF/debugger/CPPLiteSession/org.netbeans.spi.debugger.ActionsProvider
deleted file mode 100644
index 948c17a..0000000
--- a/cpplite/cpplite.debugger/src/META-INF/debugger/CPPLiteSession/org.netbeans.spi.debugger.ActionsProvider
+++ /dev/null
@@ -1,2 +0,0 @@
-org.netbeans.modules.cpplite.debugger.CPPLiteDebugger
-org.netbeans.modules.cpplite.debugger.breakpoints.CPPLiteBreakpointActionProvider
\ No newline at end of file
diff --git a/cpplite/cpplite.debugger/src/META-INF/debugger/org.netbeans.api.debugger.LazyDebuggerManagerListener b/cpplite/cpplite.debugger/src/META-INF/debugger/org.netbeans.api.debugger.LazyDebuggerManagerListener
deleted file mode 100644
index b7903e7..0000000
--- a/cpplite/cpplite.debugger/src/META-INF/debugger/org.netbeans.api.debugger.LazyDebuggerManagerListener
+++ /dev/null
@@ -1,2 +0,0 @@
-org.netbeans.modules.cpplite.debugger.breakpoints.BreakpointAnnotationListener
-org.netbeans.modules.cpplite.debugger.breakpoints.PersistenceManager
\ No newline at end of file
diff --git a/cpplite/cpplite.debugger/src/META-INF/debugger/org.netbeans.api.debugger.Properties$Reader b/cpplite/cpplite.debugger/src/META-INF/debugger/org.netbeans.api.debugger.Properties$Reader
deleted file mode 100644
index 4ce300b..0000000
--- a/cpplite/cpplite.debugger/src/META-INF/debugger/org.netbeans.api.debugger.Properties$Reader
+++ /dev/null
@@ -1 +0,0 @@
-org.netbeans.modules.cpplite.debugger.breakpoints.BreakpointsReader
\ No newline at end of file
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/Bundle.properties b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/Bundle.properties
index fa230e4..5ccc602 100644
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/Bundle.properties
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/Bundle.properties
@@ -18,30 +18,3 @@
 OpenIDE-Module-Display-Category=C/C++
 OpenIDE-Module-Name=CPPLite Debugger
 
-# RunTargetsAction
-LBL_run_other_targets=Other Targets
-LBL_run_advanced=Advanced...
-TITLE_run_advanced=Debug Ant Target
-LBL_run_advanced_run=Debug
-LBL_run_advanced_cancel=Cancel
-
-# AdvancedActionsPanel
-AdvancedActionsPanel.targetLabel.text=Select &target(s) to debug\:
-AdvancedActionsPanel.targetDescriptionLabel.text=Target description\:
-AdvancedActionsPanel.propertiesLabel.text=Special Ant &properties\:
-AdvancedActionsPanel.verbosityLabel.text=&Verbosity level\:
-LBL_verbosity_warn=Quiet
-LBL_verbosity_info=Normal
-LBL_verbosity_verbose=Verbose
-LBL_verbosity_debug=Debug
-
-#org.netbeans.modules.debugger.jpda.ui.DebuggerAnnotation
-TOOLTIP_DISABLED_CONDITIONAL_BREAKPOINT=Disabled Conditional Breakpoint
-TOOLTIP_DISABLED_BREAKPOINT=Disabled Breakpoint
-TOOLTIP_CALLSITE=Call Stack Line
-TOOLTIP_BREAKPOINT=Breakpoint
-TOOLTIP_CONDITIONAL_BREAKPOINT=Conditional Breakpoint
-TOOLTIP_CURRENT_PC=Current Program Counter
-TOOLTIP_CURRENT_PC_2=Current Target
-
-CTL_WatchDisabled=>disabled<
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteActionsProvider.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteActionsProvider.java
new file mode 100644
index 0000000..8ce1378
--- /dev/null
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteActionsProvider.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.cpplite.debugger;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.netbeans.api.debugger.ActionsManager;
+import org.netbeans.spi.debugger.ActionsProvider;
+import org.netbeans.spi.debugger.ActionsProviderSupport;
+import org.netbeans.spi.debugger.ContextProvider;
+import org.openide.util.RequestProcessor;
+
+/**
+ * The CPP Lite Debugger's actions provider.
+ */
+@ActionsProvider.Registration(path="CPPLiteSession", actions={"start", "stepInto", "stepOver", "stepOut",
+                                                              "pause", "continue", "kill"})
+public final class CPPLiteActionsProvider extends ActionsProviderSupport {
+
+    private static final Logger LOGGER = Logger.getLogger(CPPLiteActionsProvider.class.getName());
+
+    private static final Set<Object> ACTIONS = new HashSet<>();
+    private static final Set<Object> ACTIONS_TO_DISABLE = new HashSet<>();
+
+    static {
+        ACTIONS.add (ActionsManager.ACTION_KILL);
+        ACTIONS.add (ActionsManager.ACTION_CONTINUE);
+        ACTIONS.add (ActionsManager.ACTION_PAUSE);
+        ACTIONS.add (ActionsManager.ACTION_START);
+        ACTIONS.add (ActionsManager.ACTION_STEP_INTO);
+        ACTIONS.add (ActionsManager.ACTION_STEP_OVER);
+        ACTIONS.add (ActionsManager.ACTION_STEP_OUT);
+        ACTIONS_TO_DISABLE.addAll(ACTIONS);
+        // Ignore the KILL action
+        ACTIONS_TO_DISABLE.remove(ActionsManager.ACTION_KILL);
+    }
+
+    /** The ReqeustProcessor used by action performers. */
+    private static RequestProcessor     actionsRequestProcessor;
+    private static RequestProcessor     killRequestProcessor;
+
+    private final CPPLiteDebugger debugger;
+
+    public CPPLiteActionsProvider(ContextProvider contextProvider) {
+        debugger = contextProvider.lookupFirst(null, CPPLiteDebugger.class);
+        // init actions
+        for (Object action : ACTIONS) {
+            setEnabled (action, true);
+        }
+    }
+
+    @Override
+    public Set getActions () {
+        return ACTIONS;
+    }
+
+    @Override
+    public void doAction (Object action) {
+        LOGGER.log(Level.FINE, "CPPLiteDebugger.doAction({0}), is kill = {1}", new Object[]{action, action == ActionsManager.ACTION_KILL});
+        if (action == ActionsManager.ACTION_KILL) {
+            debugger.finish();
+        } else
+        if (action == ActionsManager.ACTION_CONTINUE) {
+            debugger.resume();
+        } else
+        if (action == ActionsManager.ACTION_PAUSE) {
+            debugger.pause();
+        } else
+        if (action == ActionsManager.ACTION_START) {
+            return ;
+        } else
+        if ( action == ActionsManager.ACTION_STEP_INTO ||
+             action == ActionsManager.ACTION_STEP_OUT ||
+             action == ActionsManager.ACTION_STEP_OVER
+        ) {
+            debugger.doStep (action);
+        }
+    }
+
+    @Override
+    public void postAction(final Object action, final Runnable actionPerformedNotifier) {
+        if (action == ActionsManager.ACTION_KILL) {
+            synchronized (CPPLiteDebugger.class) {
+                if (killRequestProcessor == null) {
+                    killRequestProcessor = new RequestProcessor("CPPLite debugger finish RP", 1);
+                }
+            }
+            killRequestProcessor.post(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        doAction(action);
+                    } finally {
+                        actionPerformedNotifier.run();
+                    }
+                }
+            });
+            return ;
+        }
+        setDebugActionsEnabled(false);
+        synchronized (CPPLiteDebugger.class) {
+            if (actionsRequestProcessor == null) {
+                actionsRequestProcessor = new RequestProcessor("CPPLite debugger actions RP", 1);
+            }
+        }
+        actionsRequestProcessor.post(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    doAction(action);
+                } finally {
+                    actionPerformedNotifier.run();
+                    setDebugActionsEnabled(true);
+                }
+            }
+        });
+    }
+
+    private void setDebugActionsEnabled(boolean enabled) {
+        for (Object action : ACTIONS_TO_DISABLE) {
+            setEnabled(action, enabled);
+        }
+    }
+
+}
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java
index 0193378..87d6587 100644
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPLiteDebugger.java
@@ -19,6 +19,8 @@
 
 package org.netbeans.modules.cpplite.debugger;
 
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
@@ -27,10 +29,9 @@
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.EventListener;
-import java.util.Iterator;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Semaphore;
@@ -43,6 +44,7 @@
 import org.netbeans.api.debugger.DebuggerEngine;
 import org.netbeans.api.debugger.DebuggerInfo;
 import org.netbeans.api.debugger.DebuggerManager;
+import org.netbeans.api.debugger.DebuggerManagerAdapter;
 import org.netbeans.modules.cnd.debugger.gdb2.mi.MICommand;
 import org.netbeans.modules.cnd.debugger.gdb2.mi.MICommandInjector;
 import org.netbeans.modules.cnd.debugger.gdb2.mi.MIConst;
@@ -54,7 +56,6 @@
 import org.netbeans.modules.nativeexecution.api.ExecutionEnvironmentFactory;
 import org.netbeans.modules.nativeexecution.api.pty.Pty;
 import org.netbeans.modules.nativeexecution.api.pty.PtySupport;
-import org.netbeans.spi.debugger.ActionsProviderSupport;
 import org.netbeans.spi.debugger.ContextProvider;
 import org.netbeans.spi.debugger.DebuggerEngineProvider;
 import org.netbeans.spi.debugger.SessionProvider;
@@ -62,6 +63,7 @@
 
 import org.openide.filesystems.FileObject;
 import org.openide.filesystems.FileUtil;
+import org.openide.text.Annotatable;
 import org.openide.text.Line;
 import org.openide.util.Exceptions;
 import org.openide.util.Pair;
@@ -72,22 +74,19 @@
  *
  * @author  Honza
  */
-public class CPPLiteDebugger extends ActionsProviderSupport {
+public final class CPPLiteDebugger {
 
     private static final Logger LOGGER = Logger.getLogger(CPPLiteDebugger.class.getName());
 
-    /** The ReqeustProcessor used by action performers. */
-    private static RequestProcessor     actionsRequestProcessor;
-    private static RequestProcessor     killRequestProcessor;
-
     private CPPLiteDebuggerConfig       configuration;
     private CPPLiteDebuggerEngineProvider   engineProvider;
     private ContextProvider             contextProvider;
     private Process                     debuggee;
     private LiteMIProxy                 proxy;
-    private Object                      currentLine;
+    private volatile Object             currentLine;
     private volatile boolean            suspended = false;
     private final List<StateListener>   stateListeners = new CopyOnWriteArrayList<>();
+    private final BreakpointsHandler    breakpointsHandler = new BreakpointsHandler();
 
     private final ThreadsCollector      threadsCollector = new ThreadsCollector(this);
     private volatile CPPThread          currentThread;
@@ -98,10 +97,6 @@
         configuration = contextProvider.lookupFirst(null, CPPLiteDebuggerConfig.class);
         // init engineProvider
         engineProvider = (CPPLiteDebuggerEngineProvider) contextProvider.lookupFirst(null, DebuggerEngineProvider.class);
-        // init actions
-        for (Iterator it = actions.iterator(); it.hasNext(); ) {
-            setEnabled (it.next(), true);
-        }
     }
 
     void setDebuggee(Process debuggee) {
@@ -125,17 +120,7 @@
 
         proxy.waitStarted();
 
-        for (Breakpoint b : DebuggerManager.getDebuggerManager ().getBreakpoints ()) {
-            if (b instanceof CPPLiteBreakpoint) {
-                CPPLiteBreakpoint cpplineBreakpoint = (CPPLiteBreakpoint) b;
-                Line l = cpplineBreakpoint.getLine();
-                FileObject source = l.getLookup().lookup(FileObject.class);
-                File sourceFile = source != null ? FileUtil.toFile(source) : null;
-                if (sourceFile != null) {
-                    proxy.send(new Command("-break-insert " + sourceFile.getAbsolutePath() + ":" + (l.getLineNumber() + 1)));
-                }
-            }
-        }
+        breakpointsHandler.init();
 
         proxy.send(new Command("-gdb-set target-async"));
         //proxy.send(new Command("-gdb-set scheduler-locking on"));
@@ -143,55 +128,6 @@
         proxy.send(new Command("-exec-run"));
     }
 
-    // ActionsProvider .........................................................
-
-    private static final Set<Object> actions = new HashSet<>();
-    private static final Set<Object> actionsToDisable = new HashSet<>();
-    static {
-        actions.add (ActionsManager.ACTION_KILL);
-        actions.add (ActionsManager.ACTION_CONTINUE);
-        actions.add (ActionsManager.ACTION_PAUSE);
-        actions.add (ActionsManager.ACTION_START);
-        actions.add (ActionsManager.ACTION_STEP_INTO);
-        actions.add (ActionsManager.ACTION_STEP_OVER);
-        actions.add (ActionsManager.ACTION_STEP_OUT);
-        actionsToDisable.addAll(actions);
-        // Ignore the KILL action
-        actionsToDisable.remove(ActionsManager.ACTION_KILL);
-    }
-
-    @Override
-    public Set getActions () {
-        return actions;
-    }
-
-    @Override
-    public void doAction (Object action) {
-        LOGGER.log(Level.FINE, "CPPLiteDebugger.doAction({0}), is kill = {1}", new Object[]{action, action == ActionsManager.ACTION_KILL});
-        if (action == ActionsManager.ACTION_KILL) {
-            finish ();
-        } else
-        if (action == ActionsManager.ACTION_CONTINUE) {
-            CPPThread thread = currentThread;
-            if (thread != null) {
-                thread.notifyRunning();
-            }
-            proxy.send(new Command("-exec-continue --all"));
-        } else
-        if (action == ActionsManager.ACTION_PAUSE) {
-            proxy.send(new Command("-exec-interrupt --all"));
-        } else
-        if (action == ActionsManager.ACTION_START) {
-            return ;
-        } else
-        if ( action == ActionsManager.ACTION_STEP_INTO ||
-             action == ActionsManager.ACTION_STEP_OUT ||
-             action == ActionsManager.ACTION_STEP_OVER
-        ) {
-            doStep (action);
-        }
-    }
-
     private static class CPPLiteInjector implements MICommandInjector {
 
         private final OutputStream out;
@@ -218,51 +154,6 @@
 
     }
 
-    @Override
-    public void postAction(final Object action, final Runnable actionPerformedNotifier) {
-        if (action == ActionsManager.ACTION_KILL) {
-            synchronized (CPPLiteDebugger.class) {
-                if (killRequestProcessor == null) {
-                    killRequestProcessor = new RequestProcessor("CPPLite debugger finish RP", 1);
-                }
-            }
-            killRequestProcessor.post(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        doAction(action);
-                    } finally {
-                        actionPerformedNotifier.run();
-                    }
-                }
-            });
-            return ;
-        }
-        setDebugActionsEnabled(false);
-        synchronized (CPPLiteDebugger.class) {
-            if (actionsRequestProcessor == null) {
-                actionsRequestProcessor = new RequestProcessor("CPPLite debugger actions RP", 1);
-            }
-        }
-        actionsRequestProcessor.post(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    doAction(action);
-                } finally {
-                    actionPerformedNotifier.run();
-                    setDebugActionsEnabled(true);
-                }
-            }
-        });
-    }
-
-    private void setDebugActionsEnabled(boolean enabled) {
-        for (Object action : actionsToDisable) {
-            setEnabled(action, enabled);
-        }
-    }
-
     MIRecord sendAndGet(String command) throws InterruptedException {
         return sendAndGet(command, false);
     }
@@ -434,7 +325,7 @@
     /**
      * should define callStack based on callStackInternal & action.
      */
-    private void doStep (Object action) {
+    void doStep (Object action) {
         CPPThread thread = currentThread;
         String threadId = "";
         if (thread != null) {
@@ -450,12 +341,22 @@
         }
     }
 
-    private void finish () {
+    void pause() {
+        proxy.send(new Command("-exec-interrupt --all"));
+    }
+
+    void resume() {
+        threadsCollector.running("all");
+        proxy.send(new Command("-exec-continue --all"));
+    }
+
+    void finish () {
         LOGGER.fine("CPPLiteDebugger.finish()");
         if (finished) {
             LOGGER.fine("finish(): already finished.");
             return ;
         }
+        breakpointsHandler.dispose();
         proxy.send(new Command("-gdb-exit"));
         Utils.unmarkCurrent ();
         engineProvider.getDestructor().killEngine();
@@ -526,8 +427,10 @@
                                 if (frame != null) {
                                     Line currentLine = frame.location();
                                     if (currentLine != null) {
-                                        Utils.markCurrent(new Line[] {currentLine});
-                                        Utils.showLine(new Line[] {currentLine});
+                                        Annotatable[] lines = new Annotatable[] {currentLine};
+                                        CPPLiteDebugger.this.currentLine = lines;
+                                        Utils.markCurrent(lines);
+                                        Utils.showLine(lines);
                                     }
                                 }
                                 break;
@@ -645,7 +548,7 @@
 
     }
 
-    public static @NonNull Pair<CPPLiteDebugger, Process> startDebugging (CPPLiteDebuggerConfig configuration) throws IOException {
+    public static @NonNull Pair<DebuggerEngine, Process> startDebugging (CPPLiteDebuggerConfig configuration) throws IOException {
         DebuggerInfo di = DebuggerInfo.create (
             "CPPLiteDebuggerInfo",
             new Object[] {
@@ -702,7 +605,7 @@
         });
         debugger.setDebuggee(debuggee);
 
-        return Pair.of(debugger, new Process() {
+        return Pair.of(es[0], new Process() {
             @Override
             public OutputStream getOutputStream() {
                 return pty.getOutputStream();
@@ -734,4 +637,114 @@
             }
         });
     }
+
+    private class BreakpointsHandler extends DebuggerManagerAdapter implements PropertyChangeListener {
+
+        private final Map<String, CPPLiteBreakpoint> breakpointsById = new ConcurrentHashMap<>();
+        private final Map<CPPLiteBreakpoint, String> breakpointIds = new ConcurrentHashMap<>();
+
+        BreakpointsHandler() {
+        }
+
+        private void init() {
+            DebuggerManager.getDebuggerManager().addDebuggerListener(DebuggerManager.PROP_BREAKPOINTS, this);
+            for (Breakpoint b : DebuggerManager.getDebuggerManager().getBreakpoints()) {
+                if (b instanceof CPPLiteBreakpoint) {
+                    CPPLiteBreakpoint cpplineBreakpoint = (CPPLiteBreakpoint) b;
+                    addBreakpoint(cpplineBreakpoint);
+                }
+            }
+        }
+
+        void dispose() {
+            DebuggerManager.getDebuggerManager().removeDebuggerListener(DebuggerManager.PROP_BREAKPOINTS, this);
+            for (Breakpoint b : DebuggerManager.getDebuggerManager().getBreakpoints()) {
+                if (b instanceof CPPLiteBreakpoint) {
+                    b.removePropertyChangeListener(this);
+                }
+            }
+        }
+
+        @Override
+        public void breakpointAdded(Breakpoint breakpoint) {
+            if (breakpoint instanceof CPPLiteBreakpoint) {
+                addBreakpoint((CPPLiteBreakpoint) breakpoint);
+            }
+        }
+
+        @Override
+        public void breakpointRemoved(Breakpoint breakpoint) {
+            if (breakpoint instanceof CPPLiteBreakpoint) {
+                removeBreakpoint((CPPLiteBreakpoint) breakpoint);
+            }
+        }
+
+        @Override
+        public void propertyChange(PropertyChangeEvent evt) {
+            Object source = evt.getSource();
+            if (source instanceof CPPLiteBreakpoint) {
+                String id = breakpointIds.get((CPPLiteBreakpoint) source);
+                if (id != null) {
+                    String propertyName = evt.getPropertyName();
+                    switch (propertyName) {
+                        case Breakpoint.PROP_ENABLED:
+                            if (Boolean.TRUE.equals(evt.getNewValue())) {
+                                proxy.send(new Command("-break-enable " + id));
+                            } else {
+                                proxy.send(new Command("-break-disable " + id));
+                            }
+                            break;
+                    }
+                }
+            }
+        }
+
+        private void addBreakpoint(CPPLiteBreakpoint breakpoint) {
+            Line l = breakpoint.getLine();
+            FileObject source = l.getLookup().lookup(FileObject.class);
+            File sourceFile = source != null ? FileUtil.toFile(source) : null;
+            if (sourceFile != null) {
+                String disabled = breakpoint.isEnabled() ? "" : "-d ";
+                Command command = new Command("-break-insert " + disabled + sourceFile.getAbsolutePath() + ":" + (l.getLineNumber() + 1)) {
+                    @Override
+                    protected void onDone(MIRecord record) {
+                        MIValue bkpt = record.results().valueOf("bkpt");
+                        if (bkpt instanceof MITList) {
+                            breakpointResolved(breakpoint, (MITList) bkpt);
+                        }
+                        super.onDone(record);
+                    }
+
+                    @Override
+                    protected void onError(MIRecord record) {
+                        String msg = record.results().getConstValue("msg");
+                        breakpointError(breakpoint, msg);
+                        super.onError(record);
+                    }
+                };
+                proxy.send(command);
+            }
+            breakpoint.addPropertyChangeListener(this);
+        }
+
+        private void removeBreakpoint(CPPLiteBreakpoint breakpoint) {
+            String id = breakpointIds.remove(breakpoint);
+            if (id != null) {
+                breakpoint.removePropertyChangeListener(this);
+                Command command = new Command("-break-delete " + id);
+                proxy.send(command);
+            }
+        }
+
+        private void breakpointResolved(CPPLiteBreakpoint breakpoint, MITList list) {
+            breakpoint.setCPPValidity(Breakpoint.VALIDITY.VALID, null);
+            String id = list.getConstValue("number");
+            breakpointsById.put(id, breakpoint);
+            breakpointIds.put(breakpoint, id);
+        }
+
+        private void breakpointError(CPPLiteBreakpoint breakpoint, String msg) {
+            breakpoint.setCPPValidity(Breakpoint.VALIDITY.INVALID, msg);
+        }
+    }
 }
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPThread.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPThread.java
index b3e945c..6158f6e 100644
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPThread.java
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/CPPThread.java
@@ -258,6 +258,9 @@
 
     void notifyRunning() {
         synchronized (this) {
+            if (status == Status.RUNNING) {
+                return ;
+            }
             status = Status.RUNNING;
             topFrame = null;
             stack = null;
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerAnnotation.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerAnnotation.java
index c792b0c..3642570 100644
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerAnnotation.java
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerAnnotation.java
@@ -42,34 +42,33 @@
     /** Annotation type constant. */
     public static final String CALL_STACK_FRAME_ANNOTATION_TYPE = "CallSite";
 
-    private Annotatable annotatable;
-    private String      type;
-    
-    
+    private final String type;
+
     public DebuggerAnnotation (String type, Annotatable annotatable) {
         this.type = type;
-        this.annotatable = annotatable;
         attach (annotatable);
     }
-    
+
     @Override
     public String getAnnotationType () {
         return type;
     }
-    
+
     @Override
+    @NbBundle.Messages({"TTP_CurrentPC=Current Program Counter",
+                        "TTP_CurrentPC2=Current Target",
+                        "TTP_Callsite=Call Stack Line"})
     public String getShortDescription () {
-        if (type == CURRENT_LINE_ANNOTATION_TYPE)
-            return NbBundle.getMessage(DebuggerAnnotation.class, "TOOLTIP_CURRENT_PC");
-        else
-        if (type == CURRENT_LINE_ANNOTATION_TYPE2)
-            return NbBundle.getMessage(DebuggerAnnotation.class, "TOOLTIP_CURRENT_PC_2");
-        else
-        if (type == CURRENT_LINE_PART_ANNOTATION_TYPE)
-            return NbBundle.getMessage(DebuggerAnnotation.class, "TOOLTIP_CURRENT_PC");
-        else
-        if (type == CALL_STACK_FRAME_ANNOTATION_TYPE)
-            return NbBundle.getMessage(DebuggerAnnotation.class, "TOOLTIP_CALLSITE");
-        return null;
+        switch (type) {
+            case CURRENT_LINE_ANNOTATION_TYPE:
+            case CURRENT_LINE_PART_ANNOTATION_TYPE:
+                return Bundle.TTP_CurrentPC();
+            case CURRENT_LINE_ANNOTATION_TYPE2:
+                return Bundle.TTP_CurrentPC2();
+            case CALL_STACK_FRAME_ANNOTATION_TYPE:
+                return Bundle.TTP_Callsite();
+            default:
+                throw new IllegalStateException(type);
+        }
     }
 }
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerBreakpointAnnotation.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerBreakpointAnnotation.java
index bb51639..f5e90b3 100644
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerBreakpointAnnotation.java
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/DebuggerBreakpointAnnotation.java
@@ -19,7 +19,11 @@
 
 package org.netbeans.modules.cpplite.debugger;
 
+import java.util.LinkedList;
+import java.util.List;
+
 import org.netbeans.api.debugger.Breakpoint;
+import org.netbeans.api.debugger.Breakpoint.HIT_COUNT_FILTERING_STYLE;
 import org.netbeans.modules.cpplite.debugger.breakpoints.CPPLiteBreakpoint;
 import org.netbeans.spi.debugger.ui.BreakpointAnnotation;
 import org.openide.text.Annotatable;
@@ -42,41 +46,104 @@
     /** Annotation type constant. */
     public static final String DISABLED_CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE = "DisabledCondBreakpoint"; // NOI18N
 
-    private Annotatable annotatable;
-    private String      type;
-    private CPPLiteBreakpoint breakpoint;
-    
-    
+    private final String type;
+    private final CPPLiteBreakpoint breakpoint;
+
     public DebuggerBreakpointAnnotation (String type, CPPLiteBreakpoint b) {
         this.type = type;
-        this.annotatable = b.getLine ();
         this.breakpoint = b;
+        Annotatable annotatable = b.getLine ();
         attach (annotatable);
     }
-    
+
     @Override
     public String getAnnotationType () {
         return type;
     }
-    
+
     @Override
+    @NbBundle.Messages({"TTP_Breakpoint_Hits=Hits when:",
+                        "# {0} - hit count",
+                        "TTP_Breakpoint_HitsEqual=Hit count \\= {0}",
+                        "# {0} - hit count",
+                        "TTP_Breakpoint_HitsGreaterThan=Hit count > {0}",
+                        "# {0} - hit count",
+                        "TTP_Breakpoint_HitsMultipleOf=Hit count is multiple of {0}"})
     public String getShortDescription () {
-        if (type == BREAKPOINT_ANNOTATION_TYPE)
-            return NbBundle.getMessage 
-                (DebuggerBreakpointAnnotation.class, "TOOLTIP_BREAKPOINT");
-        else 
-        if (type == DISABLED_BREAKPOINT_ANNOTATION_TYPE)
-            return NbBundle.getMessage 
-                (DebuggerBreakpointAnnotation.class, "TOOLTIP_DISABLED_BREAKPOINT");
-        else 
-        if (type == CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE)
-            return NbBundle.getMessage 
-                (DebuggerBreakpointAnnotation.class, "TOOLTIP_CONDITIONAL_BREAKPOINT");
-        else
-        if (type == DISABLED_CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE)
-            return NbBundle.getMessage 
-                (DebuggerBreakpointAnnotation.class, "TOOLTIP_DISABLED_CONDITIONAL_BREAKPOINT");
-        return null;
+        List<String> list = new LinkedList<>();
+        //add condition if available
+        String condition = breakpoint.getCondition();
+        if (condition != null) {
+            list.add(condition);
+        }
+
+        // add hit count if available
+        HIT_COUNT_FILTERING_STYLE hitCountFilteringStyle = breakpoint.getHitCountFilteringStyle();
+        if (hitCountFilteringStyle != null) {
+            int hcf = breakpoint.getHitCountFilter();
+            String tooltip;
+            switch (hitCountFilteringStyle) {
+                case EQUAL:
+                    tooltip = Bundle.TTP_Breakpoint_HitsEqual(hcf);
+                    break;
+                case GREATER:
+                    tooltip = Bundle.TTP_Breakpoint_HitsGreaterThan(hcf);
+                    break;
+                case MULTIPLE:
+                    tooltip = Bundle.TTP_Breakpoint_HitsMultipleOf(hcf);
+                    break;
+                default:
+                    throw new IllegalStateException("Unknown HitCountFilteringStyle: "+hitCountFilteringStyle); // NOI18N
+            }
+            list.add(tooltip);
+        }
+
+        String typeDesc = getBPTypeDescription();
+        if (list.isEmpty()) {
+            return typeDesc;
+        }
+        StringBuilder result = new StringBuilder(typeDesc);
+        //append more information
+        result.append("\n");        // NOI18N
+        result.append(Bundle.TTP_Breakpoint_Hits());
+        for (String text : list) {
+            result.append("\n");    // NOI18N
+            result.append(text);
+        }
+        return result.toString();
+    }
+
+    @NbBundle.Messages({"TTP_Breakpoint=Breakpoint",
+                        "TTP_BreakpointDisabled=Disabled Breakpoint",
+                        "TTP_BreakpointConditional=Conditional Breakpoint",
+                        "TTP_BreakpointDisabledConditional=Disabled Conditional Breakpoint",
+                        "TTP_BreakpointBroken=Broken breakpoint - It is not possible to stop on this line.",
+                        "# {0} - Reason for being invalid",
+                        "TTP_BreakpointBrokenInvalid=Broken breakpoint: {0}",
+                        "TTP_BreakpointStroke=Deactivated breakpoint"})
+    private String getBPTypeDescription () {
+        if (type.endsWith("_broken")) {                                         // NOI18N
+            if (breakpoint.getValidity() == Breakpoint.VALIDITY.INVALID) {
+                String msg = breakpoint.getValidityMessage();
+                return Bundle.TTP_BreakpointBrokenInvalid(msg);
+            }
+            return Bundle.TTP_BreakpointBroken();
+        }
+        if (type.endsWith("_stroke")) {                                         // NOI18N
+            return Bundle.TTP_BreakpointStroke();
+        }
+        switch (type) {
+            case BREAKPOINT_ANNOTATION_TYPE:
+                return Bundle.TTP_Breakpoint();
+            case DISABLED_BREAKPOINT_ANNOTATION_TYPE:
+                return Bundle.TTP_BreakpointDisabled();
+            case CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE:
+                return Bundle.TTP_BreakpointConditional();
+            case DISABLED_CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE:
+                return Bundle.TTP_BreakpointDisabledConditional();
+            default:
+                throw new IllegalStateException(type);
+        }
     }
 
     @Override
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointAnnotationListener.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointAnnotationListener.java
deleted file mode 100644
index 44b20da..0000000
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointAnnotationListener.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.netbeans.modules.cpplite.debugger.breakpoints;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.util.HashMap;
-import java.util.Map;
-import org.netbeans.api.debugger.Breakpoint;
-import org.netbeans.api.debugger.DebuggerManager;
-
-import org.netbeans.api.debugger.DebuggerManagerAdapter;
-import org.netbeans.modules.cpplite.debugger.DebuggerBreakpointAnnotation;
-
-
-/**
- * Listens on {@org.netbeans.api.debugger.DebuggerManager} on
- * {@link org.netbeans.api.debugger.DebuggerManager#PROP_BREAKPOINTS}
- * property and annotates JPDA Debugger line breakpoints in NetBeans editor.
- *
- * @author Jan Jancura
- */
-public class BreakpointAnnotationListener extends DebuggerManagerAdapter 
-implements PropertyChangeListener {
-    
-    private Map<CPPLiteBreakpoint, DebuggerBreakpointAnnotation> breakpointToAnnotation = new HashMap<>();
-   
-    @Override
-    public String[] getProperties () {
-        return new String[] {DebuggerManager.PROP_BREAKPOINTS};
-    }
-
-    /**
-    * Called when some breakpoint is added.
-    *
-    * @param b breakpoint
-    */
-    @Override
-    public void breakpointAdded (Breakpoint b) {
-        if (! (b instanceof CPPLiteBreakpoint)) return;
-        addAnnotation ((CPPLiteBreakpoint) b);
-    }
-
-    /**
-    * Called when some breakpoint is removed.
-    *
-    * @param breakpoint
-    */
-    @Override
-    public void breakpointRemoved (Breakpoint b) {
-        if (! (b instanceof CPPLiteBreakpoint)) return;
-        removeAnnotation (b);
-    }
-
-    /**
-     * This method gets called when a bound property is changed.
-     * @param evt A PropertyChangeEvent object describing the event source 
-     *   	and the property that has changed.
-     */
-
-    @Override
-    public void propertyChange (PropertyChangeEvent evt) {
-        if (evt.getPropertyName () != Breakpoint.PROP_ENABLED) return;
-        removeAnnotation ((Breakpoint) evt.getSource ());
-        addAnnotation ((CPPLiteBreakpoint) evt.getSource ());
-    }
-    
-    private void addAnnotation (CPPLiteBreakpoint b) {
-        breakpointToAnnotation.put (
-            b,
-            new DebuggerBreakpointAnnotation (
-                b.isEnabled () ? 
-                    DebuggerBreakpointAnnotation.BREAKPOINT_ANNOTATION_TYPE :
-                    DebuggerBreakpointAnnotation.DISABLED_BREAKPOINT_ANNOTATION_TYPE, 
-                b
-            )
-        );
-        b.addPropertyChangeListener (
-            Breakpoint.PROP_ENABLED, 
-            this
-        );
-    }
-    
-    private void removeAnnotation (Breakpoint b) {
-        DebuggerBreakpointAnnotation annotation = (DebuggerBreakpointAnnotation) 
-            breakpointToAnnotation.remove (b);
-        if (annotation == null) return;
-        annotation.detach ();
-        b.removePropertyChangeListener (
-            Breakpoint.PROP_ENABLED, 
-            this
-        );
-    }
-}
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointAnnotationProvider.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointAnnotationProvider.java
new file mode 100644
index 0000000..aac9137
--- /dev/null
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointAnnotationProvider.java
@@ -0,0 +1,269 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.netbeans.modules.cpplite.debugger.breakpoints;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.netbeans.api.debugger.Breakpoint;
+import org.netbeans.api.debugger.Breakpoint.VALIDITY;
+import org.netbeans.api.debugger.DebuggerManager;
+import org.netbeans.api.debugger.DebuggerManagerAdapter;
+import org.netbeans.modules.cpplite.debugger.DebuggerBreakpointAnnotation;
+
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataObject;
+import org.openide.text.Annotation;
+import org.openide.text.AnnotationProvider;
+import org.openide.text.Line;
+import org.openide.util.Lookup;
+import org.openide.util.RequestProcessor;
+import org.openide.util.WeakListeners;
+import org.openide.util.WeakSet;
+
+
+/**
+ * This class is called when some file in editor is opened. It changes if
+ * some breakpoints are added or removed.
+ *
+ * @author Jan Jancura, Martin Entlicher
+ */
+@org.openide.util.lookup.ServiceProvider(service=org.openide.text.AnnotationProvider.class)
+public class BreakpointAnnotationProvider extends DebuggerManagerAdapter implements AnnotationProvider {
+
+    private final Map<CPPLiteBreakpoint, Set<Annotation>> breakpointToAnnotations = new IdentityHashMap<>();
+    private final Set<FileObject> annotatedFiles = new WeakSet<>();
+    private Set<PropertyChangeListener> dataObjectListeners;
+    private volatile boolean breakpointsActive = true;
+    private final RequestProcessor annotationProcessor = new RequestProcessor("CPP BP Annotation Refresh", 1);
+
+    public BreakpointAnnotationProvider() {
+        DebuggerManager.getDebuggerManager().addDebuggerListener(DebuggerManager.PROP_BREAKPOINTS, this);
+    }
+
+    @Override
+    public void annotate (Line.Set set, Lookup lookup) {
+        final FileObject fo = lookup.lookup(FileObject.class);
+        if (fo != null) {
+            DataObject dobj = lookup.lookup(DataObject.class);
+            if (dobj != null) {
+                PropertyChangeListener pchl = new PropertyChangeListener() {
+                    /** annotate renamed files. */
+                    @Override
+                    public void propertyChange(PropertyChangeEvent evt) {
+                        if (DataObject.PROP_PRIMARY_FILE.equals(evt.getPropertyName())) {
+                            DataObject dobj = (DataObject) evt.getSource();
+                            final FileObject newFO = dobj.getPrimaryFile();
+                            annotationProcessor.post(new Runnable() {
+                                @Override
+                                public void run() {
+                                    annotate(newFO);
+                                }
+                            });
+                        }
+                    }
+                };
+                dobj.addPropertyChangeListener(WeakListeners.propertyChange(pchl, dobj));
+                synchronized (this) {
+                    if (dataObjectListeners == null) {
+                        dataObjectListeners = new HashSet<>();
+                    }
+                    // Prevent from GC.
+                    dataObjectListeners.add(pchl);
+                }
+            }
+            annotate(fo);
+        }
+    }
+
+    private void annotate (final FileObject fo) {
+        synchronized (breakpointToAnnotations) {
+            for (Breakpoint breakpoint : DebuggerManager.getDebuggerManager().getBreakpoints()) {
+                if (breakpoint instanceof CPPLiteBreakpoint) {
+                    CPPLiteBreakpoint b = (CPPLiteBreakpoint) breakpoint;
+                    if (isAt(b, fo)) {
+                        if (!breakpointToAnnotations.containsKey(b)) {
+                            b.addPropertyChangeListener(this);
+                        }
+                        removeAnnotations(b);   // Remove any staled breakpoint annotations
+                        addAnnotationTo(b);
+                    }
+                }
+            }
+            annotatedFiles.add(fo);
+        }
+    }
+
+    private static boolean isAt(CPPLiteBreakpoint b, FileObject fo) {
+        FileObject bfo = (FileObject) b.getLine().getLookup().lookup(FileObject.class);
+        return fo.equals(bfo);
+    }
+
+    @Override
+    public void breakpointAdded(Breakpoint breakpoint) {
+        if (breakpoint instanceof CPPLiteBreakpoint) {
+            postAnnotationRefresh((CPPLiteBreakpoint) breakpoint, false, true);
+            breakpoint.addPropertyChangeListener (this);
+        }
+    }
+
+    @Override
+    public void breakpointRemoved(Breakpoint breakpoint) {
+        if (breakpoint instanceof CPPLiteBreakpoint) {
+            breakpoint.removePropertyChangeListener (this);
+            postAnnotationRefresh((CPPLiteBreakpoint) breakpoint, true, false);
+        }
+    }
+
+    @Override
+    public void propertyChange(PropertyChangeEvent evt) {
+        Object source = evt.getSource();
+        if (source instanceof CPPLiteBreakpoint) {
+            String propertyName = evt.getPropertyName ();
+            switch (propertyName) {
+                case Breakpoint.PROP_ENABLED:
+                case Breakpoint.PROP_VALIDITY:
+                case CPPLiteBreakpoint.PROP_CONDITION:
+                    postAnnotationRefresh((CPPLiteBreakpoint) source, true, true);
+            }
+        }
+    }
+
+    void setBreakpointsActive(boolean active) {
+        if (breakpointsActive == active) {
+            return ;
+        }
+        breakpointsActive = active;
+        annotationProcessor.post(new AnnotationRefresh(null, true, true));
+    }
+
+    private void postAnnotationRefresh(CPPLiteBreakpoint b, boolean remove, boolean add) {
+        annotationProcessor.post(new AnnotationRefresh(b, remove, add));
+    }
+
+    private final class AnnotationRefresh implements Runnable {
+
+        private final CPPLiteBreakpoint b;
+        private final boolean remove;
+        private final boolean add;
+
+        public AnnotationRefresh(CPPLiteBreakpoint b, boolean remove, boolean add) {
+            this.b = b;
+            this.remove = remove;
+            this.add = add;
+        }
+
+        @Override
+        public void run() {
+            synchronized (breakpointToAnnotations) {
+                if (b != null) {
+                    refreshAnnotation(b);
+                } else {
+                    List<CPPLiteBreakpoint> bpts = new ArrayList<>(breakpointToAnnotations.keySet());
+                    for (CPPLiteBreakpoint bp : bpts) {
+                        refreshAnnotation(bp);
+                    }
+                }
+            }
+        }
+
+        private void refreshAnnotation(CPPLiteBreakpoint b) {
+            assert Thread.holdsLock(breakpointToAnnotations);
+            removeAnnotations(b);
+            if (remove) {
+                if (!add) {
+                    breakpointToAnnotations.remove(b);
+                }
+            }
+            if (add) {
+                breakpointToAnnotations.put(b, new WeakSet<>());
+                for (FileObject fo : annotatedFiles) {
+                    if (isAt(b, fo)) {
+                        addAnnotationTo(b);
+                    }
+                }
+            }
+        }
+
+    }
+
+    private static String getAnnotationType(CPPLiteBreakpoint b, boolean isConditional,
+                                            boolean active) {
+        boolean isInvalid = b.getValidity() == VALIDITY.INVALID;
+        String annotationType = b.isEnabled() ?
+                (isConditional ? DebuggerBreakpointAnnotation.CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE :
+                                 DebuggerBreakpointAnnotation.BREAKPOINT_ANNOTATION_TYPE) :
+                (isConditional ? DebuggerBreakpointAnnotation.DISABLED_CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE :
+                                 DebuggerBreakpointAnnotation.DISABLED_BREAKPOINT_ANNOTATION_TYPE);
+        if (!active) {
+            annotationType += "_stroke";                    // NOI18N
+        } else if (isInvalid && b.isEnabled ()) {
+            annotationType += "_broken";                    // NOI18N
+        }
+        return annotationType;
+    }
+
+    private void addAnnotationTo(CPPLiteBreakpoint b) {
+        assert Thread.holdsLock(breakpointToAnnotations);
+        String condition = getCondition(b);
+        boolean isConditional = condition.trim().length() > 0 || b.getHitCountFilteringStyle() != null;
+        String annotationType = getAnnotationType(b, isConditional, breakpointsActive);
+        DebuggerBreakpointAnnotation annotation = new DebuggerBreakpointAnnotation (annotationType, b);
+        Set<Annotation> bpAnnotations = breakpointToAnnotations.get(b);
+        if (bpAnnotations == null) {
+            Set<Annotation> set = new WeakSet<>();
+            set.add(annotation);
+            breakpointToAnnotations.put(b, set);
+        } else {
+            bpAnnotations.add(annotation);
+            breakpointToAnnotations.put(b, bpAnnotations);
+        }
+    }
+
+    private void removeAnnotations(CPPLiteBreakpoint b) {
+        assert Thread.holdsLock(breakpointToAnnotations);
+        Set<Annotation> annotations = breakpointToAnnotations.remove(b);
+        if (annotations == null) {
+            return ;
+        }
+        for (Annotation a : annotations) {
+            a.detach();
+        }
+    }
+
+    /**
+     * Gets the condition of a breakpoint.
+     * @param b The breakpoint
+     * @return The condition or empty {@link String} if no condition is supported.
+     */
+    static String getCondition(Breakpoint b) {
+        if (b instanceof CPPLiteBreakpoint) {
+            return ""; // TODO
+        } else {
+            throw new IllegalStateException(b.toString());
+        }
+    }
+}
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointModel.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointModel.java
index 895f4d5..6939797 100644
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointModel.java
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointModel.java
@@ -19,12 +19,14 @@
 
 package org.netbeans.modules.cpplite.debugger.breakpoints;
 
-import java.util.Vector;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 import org.netbeans.api.debugger.DebuggerEngine;
 import org.netbeans.api.debugger.DebuggerManager;
 import org.netbeans.modules.cpplite.debugger.CPPLiteDebugger;
 import org.netbeans.modules.cpplite.debugger.Utils;
+import org.netbeans.spi.debugger.DebuggerServiceRegistration;
 import org.netbeans.spi.viewmodel.ModelEvent;
 import org.netbeans.spi.viewmodel.NodeModel;
 import org.netbeans.spi.viewmodel.ModelListener;
@@ -35,16 +37,17 @@
  *
  * @author   Jan Jancura
  */
+@DebuggerServiceRegistration(path="BreakpointsView", types={NodeModel.class})
 public class BreakpointModel implements NodeModel {
     
     public static final String      LINE_BREAKPOINT =
-        "org/netbeans/modules/debugger/resources/editor/Breakpoint";
+        "org/netbeans/modules/debugger/resources/breakpointsView/Breakpoint";
     public static final String      LINE_BREAKPOINT_PC =
-        "org/netbeans/modules/debugger/resources/editor/Breakpoint+PC";
+        "org/netbeans/modules/debugger/resources/breakpointsView/BreakpointHit";
     public static final String      DISABLED_LINE_BREAKPOINT =
-        "org/netbeans/modules/debugger/resources/editor/DisabledBreakpoint";
+        "org/netbeans/modules/debugger/resources/breakpointsView/DisabledBreakpoint";
     
-    private Vector<ModelListener>   listeners = new Vector<>();
+    private List<ModelListener>   listeners = new CopyOnWriteArrayList<>();
     
     
     // NodeModel implementation ................................................
@@ -138,10 +141,10 @@
         
      
     public void fireChanges () {
-        Vector<ModelListener> v = (Vector<ModelListener>)listeners.clone();
-        int i, k = v.size ();
-        for (i = 0; i < k; i++)
-            v.get(i).modelChanged(new ModelEvent.TreeChanged(this));
+        ModelEvent event = new ModelEvent.TreeChanged(this);
+        for (ModelListener l : listeners) {
+            l.modelChanged(event);
+        }
     }
     
     private static CPPLiteDebugger getDebugger () {
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointsReader.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointsReader.java
index 79339f4..e0d9020 100644
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointsReader.java
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/BreakpointsReader.java
@@ -23,6 +23,7 @@
 import java.net.URL;
 import org.netbeans.api.debugger.Breakpoint;
 import org.netbeans.api.debugger.Properties;
+import org.netbeans.spi.debugger.DebuggerServiceRegistration;
 import org.openide.cookies.LineCookie;
 import org.openide.filesystems.FileObject;
 import org.openide.filesystems.URLMapper;
@@ -35,6 +36,7 @@
  *
  * @author Jan Jancura
  */
+@DebuggerServiceRegistration(types={Properties.Reader.class})
 public class BreakpointsReader implements Properties.Reader {
     
     
@@ -67,6 +69,10 @@
             hitCountFilteringStyle = null;
         }
         b.setHitCountFilter(hitCountFilter, hitCountFilteringStyle);
+        String condition = properties.getString(CPPLiteBreakpoint.PROP_CONDITION, null);
+        if (condition != null && !condition.isEmpty()) {
+            b.setCondition(condition);
+        }
         if (properties.getBoolean (Breakpoint.PROP_ENABLED, true))
             b.enable ();
         else
@@ -77,21 +83,25 @@
     @Override
     public void write (Object object, Properties properties) {
         CPPLiteBreakpoint b = (CPPLiteBreakpoint) object;
-        FileObject fo = (FileObject) b.getLine ().getLookup ().
-            lookup (FileObject.class);
-            properties.setString("url", fo.toURL().toString());
-            properties.setInt (
-                "lineNumber", 
-                b.getLine ().getLineNumber ()
-            );
-            properties.setString (
-                Breakpoint.PROP_GROUP_NAME, 
-                b.getGroupName ()
-            );
-            properties.setBoolean (Breakpoint.PROP_ENABLED, b.isEnabled ());
-            properties.setInt(Breakpoint.PROP_HIT_COUNT_FILTER, b.getHitCountFilter());
-            Breakpoint.HIT_COUNT_FILTERING_STYLE style = b.getHitCountFilteringStyle();
-            properties.setInt(Breakpoint.PROP_HIT_COUNT_FILTER+"_style", style != null ? style.ordinal() : 0); // NOI18N
+        FileObject fo = (FileObject) b.getLine().getLookup().lookup(FileObject.class);
+        properties.setString("url", fo.toURL().toString());
+        properties.setInt (
+            "lineNumber", 
+            b.getLine ().getLineNumber ()
+        );
+        properties.setString (
+            Breakpoint.PROP_GROUP_NAME, 
+            b.getGroupName ()
+        );
+        properties.setBoolean (Breakpoint.PROP_ENABLED, b.isEnabled ());
+        properties.setInt(Breakpoint.PROP_HIT_COUNT_FILTER, b.getHitCountFilter());
+        Breakpoint.HIT_COUNT_FILTERING_STYLE style = b.getHitCountFilteringStyle();
+        properties.setInt(Breakpoint.PROP_HIT_COUNT_FILTER+"_style", style != null ? style.ordinal() : 0); // NOI18N
+        String condition = b.getCondition();
+        if (condition == null) {
+            condition = "";
+        }
+        properties.setString(CPPLiteBreakpoint.PROP_CONDITION, condition);
     }
     
 
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpoint.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpoint.java
index e340d84..6f063ce 100644
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpoint.java
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpoint.java
@@ -21,7 +21,10 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import org.netbeans.api.debugger.Breakpoint;
 import org.netbeans.api.debugger.DebuggerEngine;
 import org.netbeans.api.debugger.DebuggerManager;
@@ -41,13 +44,16 @@
  *
  * @author  Honza
  */
-public class CPPLiteBreakpoint extends Breakpoint {
+public final class CPPLiteBreakpoint extends Breakpoint {
 
-    private boolean enabled = true;
-    private Line    line;
+    public static final String PROP_CONDITION = "condition";                    // NOI18N
 
+    private volatile boolean enabled = true;
+    private final Map<CPPLiteDebugger, String> ids = new HashMap<>();
+    private final Line line;
+    private volatile String condition;
 
-    /*test?*/public CPPLiteBreakpoint (Line line) {
+    public CPPLiteBreakpoint (Line line) {
         this.line = line;
     }
 
@@ -64,7 +70,7 @@
     public boolean isEnabled () {
         return enabled;
     }
-    
+
     /**
      * Disables the breakpoint.
      */
@@ -74,7 +80,7 @@
         enabled = false;
         firePropertyChange (PROP_ENABLED, Boolean.TRUE, Boolean.FALSE);
     }
-    
+
     /**
      * Enables the breakpoint.
      */
@@ -85,18 +91,44 @@
         firePropertyChange (PROP_ENABLED, Boolean.FALSE, Boolean.TRUE);
     }
 
-    @Override
-    public GroupProperties getGroupProperties() {
-        return new AntGroupProperties();
+    /**
+     * Get the breakpoint condition, or <code>null</code>.
+     */
+    public String getCondition() {
+        return condition;
     }
 
-    private final class AntGroupProperties extends GroupProperties {
+    /**
+     * Set the breakpoint condition.
+     */
+    public void setCondition(String condition) {
+        String oldCondition;
+        synchronized (this) {
+            oldCondition = this.condition;
+            if (Objects.equals(oldCondition, condition)) {
+                return ;
+            }
+            this.condition = condition;
+        }
+        firePropertyChange (PROP_CONDITION, oldCondition, condition);
+    }
 
-        private AntEngineListener engineListener;
+    public void setCPPValidity(VALIDITY validity, String reason) {
+        setValidity(validity, reason);
+    }
+
+    @Override
+    public GroupProperties getGroupProperties() {
+        return new CPPGroupProperties();
+    }
+
+    private final class CPPGroupProperties extends GroupProperties {
+
+        private CPPEngineListener engineListener;
 
         @Override
         public String getLanguage() {
-            return "ANT";
+            return "C/C++";
         }
 
         @Override
@@ -140,7 +172,7 @@
         @Override
         public DebuggerEngine[] getEngines() {
             if (engineListener == null) {
-                engineListener = new AntEngineListener();
+                engineListener = new CPPEngineListener();
                 DebuggerManager.getDebuggerManager().addDebuggerListener(
                         WeakListeners.create(DebuggerManagerListener.class,
                                              engineListener,
@@ -151,7 +183,7 @@
                 return null;
             }
             if (engines.length == 1) {
-                if (isAntEngine(engines[0])) {
+                if (isCPPEngine(engines[0])) {
                     return engines;
                 } else {
                     return null;
@@ -160,9 +192,9 @@
             // Several running sessions
             List<DebuggerEngine> antEngines = null;
             for (DebuggerEngine e : engines) {
-                if (isAntEngine(e)) {
+                if (isCPPEngine(e)) {
                     if (antEngines == null) {
-                        antEngines = new ArrayList<DebuggerEngine>();
+                        antEngines = new ArrayList<>();
                     }
                     antEngines.add(e);
                 }
@@ -170,11 +202,11 @@
             if (antEngines == null) {
                 return null;
             } else {
-                return antEngines.toArray(new DebuggerEngine[]{});
+                return antEngines.toArray(new DebuggerEngine[antEngines.size()]);
             }
         }
 
-        private boolean isAntEngine(DebuggerEngine e) {
+        private boolean isCPPEngine(DebuggerEngine e) {
             return e.lookupFirst(null, CPPLiteDebugger.class) != null;
         }
 
@@ -183,19 +215,19 @@
             return false;
         }
 
-        private final class AntEngineListener extends DebuggerManagerAdapter {
+        private final class CPPEngineListener extends DebuggerManagerAdapter {
 
             @Override
             public void engineAdded(DebuggerEngine engine) {
-                if (isAntEngine(engine)) {
-                    firePropertyChange(PROP_GROUP_PROPERTIES, null, AntGroupProperties.this);
+                if (isCPPEngine(engine)) {
+                    firePropertyChange(PROP_GROUP_PROPERTIES, null, CPPGroupProperties.this);
                 }
             }
 
             @Override
             public void engineRemoved(DebuggerEngine engine) {
-                if (isAntEngine(engine)) {
-                    firePropertyChange(PROP_GROUP_PROPERTIES, null, AntGroupProperties.this);
+                if (isCPPEngine(engine)) {
+                    firePropertyChange(PROP_GROUP_PROPERTIES, null, CPPGroupProperties.this);
                 }
             }
 
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpointActionProvider.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpointActionProvider.java
index 8ef0cc8..c166e25 100644
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpointActionProvider.java
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/CPPLiteBreakpointActionProvider.java
@@ -25,11 +25,11 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
+
 import org.netbeans.api.debugger.ActionsManager;
 import org.netbeans.api.debugger.Breakpoint;
 import org.netbeans.api.debugger.DebuggerManager;
 import org.netbeans.spi.debugger.ActionsProvider.Registration;
-import org.netbeans.spi.debugger.ActionsProvider.Registrations;
 import org.netbeans.spi.debugger.ActionsProviderSupport;
 import org.netbeans.spi.debugger.ui.EditorContextDispatcher;
 import org.openide.filesystems.FileObject;
@@ -43,16 +43,16 @@
 @Registration(actions={"toggleBreakpoint"}, activateForMIMETypes={"text/X-c", "text/X-c++", "text/X-h", "text/X-h++"})
 public class CPPLiteBreakpointActionProvider extends ActionsProviderSupport
                                          implements PropertyChangeListener {
-    
+
     private static final String[] C_MIME_TYPES = new String[] {"text/X-c", "text/X-c++", "text/X-h", "text/X-h++"}; // NOI18N
     private static final Set<String> C_MIME_TYPES_SET = new HashSet<>(Arrays.asList(C_MIME_TYPES));
-    
-    private static final Set actions = Collections.singleton (
+
+    private static final Set ACTIONS = Collections.singleton (
         ActionsManager.ACTION_TOGGLE_BREAKPOINT
     );
-    
+
     EditorContextDispatcher context = EditorContextDispatcher.getDefault();
-    
+
     public CPPLiteBreakpointActionProvider () {
         for (String mimeType : C_MIME_TYPES) {
             context.addPropertyChangeListener(mimeType,
@@ -60,7 +60,7 @@
         }
         setEnabled (ActionsManager.ACTION_TOGGLE_BREAKPOINT, false);
     }
-    
+
     /**
      * Called when the action is called (action button is pressed).
      *
@@ -87,7 +87,7 @@
             );
         //S ystem.out.println("toggle");
     }
-    
+
     /**
      * Returns set of actions supported by this ActionsProvider.
      *
@@ -95,10 +95,9 @@
      */
     @Override
     public Set getActions () {
-        return actions;
+        return ACTIONS;
     }
-    
-    
+
     private static Line getCurrentLine () {
         FileObject fo = EditorContextDispatcher.getDefault().getCurrentFile();
         //System.out.println("n = "+n+", FO = "+fo+" => is ANT = "+isAntFile(fo));
@@ -107,8 +106,7 @@
         }
         return EditorContextDispatcher.getDefault().getCurrentLine();
     }
-    
-    
+
     private static boolean isCFile(FileObject fo) {
         if (fo == null) {
             return false;
@@ -116,12 +114,12 @@
             return C_MIME_TYPES_SET.contains(fo.getMIMEType());
         }
     }
-    
+
     @Override
     public void propertyChange(PropertyChangeEvent evt) {
         // We need to push the state there :-(( instead of wait for someone to be interested in...
         boolean enabled = getCurrentLine() != null;
         setEnabled (ActionsManager.ACTION_TOGGLE_BREAKPOINT, enabled);
     }
-    
+
 }
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/LoadBreakpoints.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/LoadBreakpoints.java
deleted file mode 100644
index 78cde77..0000000
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/LoadBreakpoints.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.netbeans.modules.cpplite.debugger.breakpoints;
-
-import org.netbeans.api.debugger.DebuggerManager;
-import org.openide.modules.OnStart;
-import org.openide.windows.WindowManager;
-
-/**
- *
- * @author lahvac
- */
-@OnStart
-public class LoadBreakpoints implements Runnable {
-
-    @Override
-    public void run() {
-        //to load and assign breakpoints
-        //XXX: there must be a better/cleaner way, right?
-        WindowManager.getDefault().invokeWhenUIReady(() -> 
-            DebuggerManager.getDebuggerManager ().getBreakpoints ()
-        );
-    }
-    
-}
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/PersistenceManager.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/PersistenceManager.java
index c296967..d467600 100644
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/PersistenceManager.java
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/breakpoints/PersistenceManager.java
@@ -30,6 +30,7 @@
 import org.netbeans.api.debugger.Properties;
 import org.netbeans.api.debugger.Session;
 import org.netbeans.api.debugger.Watch;
+import org.netbeans.spi.debugger.DebuggerServiceRegistration;
 
 /**
  * Listens on DebuggerManager and:
@@ -39,6 +40,7 @@
  *
  * @author Jan Jancura
  */
+@DebuggerServiceRegistration(types={LazyDebuggerManagerListener.class})
 public class PersistenceManager implements LazyDebuggerManagerListener {
     
     @Override
diff --git a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/debuggingview/DebuggingViewSupportImpl.java b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/debuggingview/DebuggingViewSupportImpl.java
index d657e09..b0e30d7 100644
--- a/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/debuggingview/DebuggingViewSupportImpl.java
+++ b/cpplite/cpplite.debugger/src/org/netbeans/modules/cpplite/debugger/debuggingview/DebuggingViewSupportImpl.java
@@ -85,7 +85,7 @@
 
     @Override
     public void resume() {
-        debugger.doAction(ActionsManager.ACTION_CONTINUE);
+        session.getCurrentEngine().getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
     }
 
     @Override
diff --git a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/AbstractDebugTest.java b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/AbstractDebugTest.java
new file mode 100644
index 0000000..2d9d4bd
--- /dev/null
+++ b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/AbstractDebugTest.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.cpplite.debugger;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Arrays;
+import junit.framework.Test;
+
+import org.netbeans.api.debugger.DebuggerEngine;
+import org.netbeans.junit.NbModuleSuite;
+import org.netbeans.junit.NbTestCase;
+
+public abstract class AbstractDebugTest extends NbTestCase {
+
+    protected DebuggerEngine engine;
+    protected CPPLiteDebugger debugger;
+
+    private final int[] suspendCount = new int[]{0};
+    private final int[] resumeCount = new int[]{0};
+
+    protected AbstractDebugTest(String s) {
+        super(s);
+    }
+
+    protected final static void compileC(String name, File wd) throws IOException, InterruptedException {
+        Process compile = new ProcessBuilder("gcc", "-o", name, "-g", name + ".c").directory(wd).start();
+        assertEquals(0, compile.waitFor());
+    }
+
+    protected final static void compileCPP(String name, File wd) throws IOException, InterruptedException {
+        Process compile = new ProcessBuilder("g++", "-o", name, "-g", name + ".cpp").directory(wd).start();
+        assertEquals(0, compile.waitFor());
+    }
+
+    protected final void startDebugging(String name, File wd) throws IOException {
+        engine = CPPLiteDebugger.startDebugging(new CPPLiteDebuggerConfig(Arrays.asList(new File(wd, name).getAbsolutePath()), wd)).first();
+        debugger = engine.lookupFirst(null, CPPLiteDebugger.class);
+        debugger.addStateListener(new CPPLiteDebugger.StateListener() {
+            @Override
+            public void suspended(boolean suspended) {
+                int[] count;
+                if (suspended) {
+                    count = suspendCount;
+                } else {
+                    count = resumeCount;
+                }
+                synchronized (count) {
+                    count[0]++;
+                    count.notifyAll();
+                }
+            }
+
+            @Override
+            public void finished() {
+            }
+
+            @Override
+            public void currentThread(CPPThread thread) {
+            }
+
+            @Override
+            public void currentFrame(CPPFrame frame) {
+            }
+        });
+    }
+
+    protected final void waitSuspended(int count) throws InterruptedException {
+        synchronized (suspendCount) {
+            while (suspendCount[0] < count) {
+                suspendCount.wait();
+            }
+        }
+    }
+
+    protected final void waitResumed(int count) throws InterruptedException {
+        synchronized (resumeCount) {
+            while (resumeCount[0] < count) {
+                resumeCount.wait();
+            }
+        }
+    }
+
+    protected final void assertStoppedAt(URI file, int line) {
+        CPPFrame currentFrame = debugger.getCurrentFrame();
+        assertNotNull(currentFrame);
+        assertEquals(file, currentFrame.getSourceURI());
+        assertEquals(line, currentFrame.getLine());
+    }
+
+    public static Test suite() {
+        return NbModuleSuite.emptyConfiguration().gui(false).suite();
+    }
+}
diff --git a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/BreakpointsTest.java b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/BreakpointsTest.java
new file mode 100644
index 0000000..f80bee8
--- /dev/null
+++ b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/BreakpointsTest.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.netbeans.modules.cpplite.debugger;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import junit.framework.Test;
+
+import org.netbeans.api.debugger.ActionsManager;
+import org.netbeans.api.debugger.DebuggerManager;
+import org.netbeans.junit.NbModuleSuite;
+import org.netbeans.modules.cpplite.debugger.breakpoints.CPPLiteBreakpoint;
+import org.openide.cookies.LineCookie;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.loaders.DataObject;
+
+/**
+ * Tests C/C++ debugger breakpoints.
+ */
+public class BreakpointsTest extends AbstractDebugTest {
+
+    public BreakpointsTest (String s) {
+        super (s);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        clearWorkDir();
+    }
+
+    public void testBreakpoints() throws Exception {
+        File wd = getWorkDir();
+        FileObject source = FileUtil.createData(FileUtil.toFileObject(wd), "breakpoints.c");
+        try (OutputStream os = source.getOutputStream();
+            Writer w = new OutputStreamWriter(os)) {
+            w.append("#include<stdio.h>\n" +
+                     "\n" +
+                     "long double loop(unsigned int N) {\n" +
+                     "    unsigned int i;\n" +
+                     "    long double f = 1;\n" +
+                     "    long double s = 0;\n" +
+                     "    for (i = 1; i <= N; i++) {\n" +
+                     "        f *= i;\n" +
+                     "        s += i;\n" +
+                     "        f /= s/i;\n" +
+                     "    }\n" +
+                     "    return f;\n" +
+                     "}\n" +
+                     "\n" +
+                     "int main(int argc, char** args) {\n" +
+                     "    int N = 100;\n" +
+                     "    long double r = loop(N);\n" +
+                     "    printf(\"Result(%d) = %.40Lg\\n\", N, r);\n" +
+                     "}");
+        }
+        compileC("breakpoints", wd);
+        LineCookie lc = DataObject.find(source).getLookup().lookup(LineCookie.class);
+        assertNotNull(lc);
+        CPPLiteBreakpoint bp8 = new CPPLiteBreakpoint(lc.getLineSet().getCurrent(7));
+        CPPLiteBreakpoint bp9 = new CPPLiteBreakpoint(lc.getLineSet().getCurrent(8));
+        bp9.disable();
+        DebuggerManager.getDebuggerManager().addBreakpoint(bp8);
+        DebuggerManager.getDebuggerManager().addBreakpoint(bp9);
+        startDebugging("breakpoints", wd);
+
+        waitSuspended(1);
+        assertStoppedAt(source.toURI(), 8);
+
+        engine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
+        waitResumed(1);
+        waitSuspended(2);
+        assertStoppedAt(source.toURI(), 8);
+
+        bp9.enable();
+
+        engine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
+        waitResumed(2);
+        waitSuspended(3);
+        assertStoppedAt(source.toURI(), 9);
+
+        CPPLiteBreakpoint bp10 = new CPPLiteBreakpoint(lc.getLineSet().getCurrent(9));
+        DebuggerManager.getDebuggerManager().addBreakpoint(bp10);
+
+        engine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
+        waitResumed(3);
+        waitSuspended(4);
+        assertStoppedAt(source.toURI(), 10);
+
+        DebuggerManager.getDebuggerManager().removeBreakpoint(bp8);
+        DebuggerManager.getDebuggerManager().removeBreakpoint(bp9);
+
+        engine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
+        waitResumed(4);
+        waitSuspended(5);
+        assertStoppedAt(source.toURI(), 10);
+
+        bp10.disable();
+
+        bp8 = new CPPLiteBreakpoint(lc.getLineSet().getCurrent(7));
+        DebuggerManager.getDebuggerManager().addBreakpoint(bp8);
+
+        engine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
+        waitResumed(5);
+        waitSuspended(6);
+        assertStoppedAt(source.toURI(), 8);
+
+        engine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
+        waitResumed(5);
+        waitSuspended(6);
+        assertStoppedAt(source.toURI(), 8);
+
+        bp8.disable();
+
+        engine.getActionsManager().doAction(ActionsManager.ACTION_CONTINUE);
+        waitResumed(6);
+
+        engine.getActionsManager().doAction(ActionsManager.ACTION_KILL);
+    }
+
+    public static Test suite() {
+        return NbModuleSuite.emptyConfiguration()
+                            .addTest(BreakpointsTest.class)
+                            .enableModules(".*", ".*")
+                            .gui(false)
+                            .suite();
+    }
+}
diff --git a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/StepTest.java b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/StepTest.java
index 0361a20..a2042dd 100644
--- a/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/StepTest.java
+++ b/cpplite/cpplite.debugger/test/unit/src/org/netbeans/modules/cpplite/debugger/StepTest.java
@@ -23,12 +23,11 @@
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.Writer;
-import java.util.Arrays;
 import junit.framework.Test;
+
 import org.netbeans.api.debugger.ActionsManager;
 import org.netbeans.api.debugger.DebuggerManager;
 import org.netbeans.junit.NbModuleSuite;
-import org.netbeans.junit.NbTestCase;
 import org.netbeans.modules.cpplite.debugger.breakpoints.CPPLiteBreakpoint;
 import org.openide.cookies.LineCookie;
 import org.openide.filesystems.FileObject;
@@ -40,7 +39,7 @@
  *
  * @author Jan Jancura
  */
-public class StepTest extends NbTestCase {
+public class StepTest extends AbstractDebugTest {
 
     public StepTest (String s) {
         super (s);
@@ -55,7 +54,7 @@
         File wd = getWorkDir();
         FileObject source = FileUtil.createData(FileUtil.toFileObject(wd), "main.cpp");
         try (OutputStream os = source.getOutputStream();
-             Writer w = new OutputStreamWriter(os)) {
+            Writer w = new OutputStreamWriter(os)) {
             w.append("#include <iostream>\n" +
                      "\n" +
                      "void test(void) {\n" +
@@ -70,69 +69,25 @@
                      "    std::cout << \"Hello, second time!\" << std::endl;\n" +
                      "}");
         }
-        Process compile = new ProcessBuilder("g++", "-o", "main", "-g", "main.cpp").directory(wd).start();
-        assertEquals(0, compile.waitFor());
+        compileCPP("main", wd);
         LineCookie lc = DataObject.find(source).getLookup().lookup(LineCookie.class);
         assertNotNull(lc);
         DebuggerManager.getDebuggerManager().addBreakpoint(new CPPLiteBreakpoint(lc.getLineSet().getCurrent(4)));
-        CPPLiteDebugger d = CPPLiteDebugger.startDebugging(new CPPLiteDebuggerConfig(Arrays.asList(new File(wd, "main").getAbsolutePath()), wd)).first();
-        int[] suspendCount = new int[1];
-        int[] resumeCount = new int[1];
-        d.addStateListener(new CPPLiteDebugger.StateListener() {
-            @Override
-            public void suspended(boolean suspended) {
-                int[] count;
-                if (suspended) {
-                    count = suspendCount;
-                } else {
-                    count = resumeCount;
-                }
-                synchronized (count) {
-                    count[0]++;
-                    count.notifyAll();
-                }
-            }
+        startDebugging("main", wd);
 
-            @Override
-            public void finished() {
-            }
+        waitSuspended(1);
 
-            @Override
-            public void currentThread(CPPThread thread) {
-            }
+        assertStoppedAt(source.toURI(), 5);
 
-            @Override
-            public void currentFrame(CPPFrame frame) {
-            }
-        });
+        engine.getActionsManager().doAction(ActionsManager.ACTION_STEP_OVER);
 
-        synchronized (suspendCount) {
-            while (suspendCount[0] < 1) {
-                suspendCount.wait();
-            }
-        }
+        waitResumed(1);
 
-        //on line 4, there is a breakpoint and the PC
-        assertEquals(2, lc.getLineSet().getCurrent(4).getAnnotationCount());
+        waitSuspended(2);
 
-        d.doAction(ActionsManager.ACTION_STEP_OVER);
+        assertStoppedAt(source.toURI(), 6);
 
-        synchronized (resumeCount) {
-            while (resumeCount[0] < 1) {
-                resumeCount.wait();
-            }
-        }
-
-        synchronized (suspendCount) {
-            while (suspendCount[0] < 2) {
-                suspendCount.wait();
-            }
-        }
-
-        //on line 4, there is a breakpoint
-        assertEquals(1, lc.getLineSet().getCurrent(4).getAnnotationCount());
-        //PC:
-        assertEquals(1, lc.getLineSet().getCurrent(5).getAnnotationCount());
+        engine.getActionsManager().doAction(ActionsManager.ACTION_KILL);
     }
 
     public static Test suite() {
diff --git a/extide/gradle/netbeans-gradle-tooling/build.gradle b/extide/gradle/netbeans-gradle-tooling/build.gradle
index a8db3ec..23412e7 100644
--- a/extide/gradle/netbeans-gradle-tooling/build.gradle
+++ b/extide/gradle/netbeans-gradle-tooling/build.gradle
@@ -26,7 +26,7 @@
 [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
 
 repositories {
-    jcenter()
+    mavenCentral()
 }
 
 dependencies {
diff --git a/extide/gradle/netbeans-gradle-tooling/src/test/data/multi/build.gradle b/extide/gradle/netbeans-gradle-tooling/src/test/data/multi/build.gradle
index 1c30cea..50ceec5 100644
--- a/extide/gradle/netbeans-gradle-tooling/src/test/data/multi/build.gradle
+++ b/extide/gradle/netbeans-gradle-tooling/src/test/data/multi/build.gradle
@@ -22,7 +22,7 @@
     apply plugin: 'jacoco'
     
     repositories {
-        jcenter()
+        mavenCentral()
     }
     
 }
diff --git a/extide/gradle/netbeans-gradle-tooling/src/test/data/simple-with-tests/build.gradle b/extide/gradle/netbeans-gradle-tooling/src/test/data/simple-with-tests/build.gradle
index 5e41a81..666569d 100644
--- a/extide/gradle/netbeans-gradle-tooling/src/test/data/simple-with-tests/build.gradle
+++ b/extide/gradle/netbeans-gradle-tooling/src/test/data/simple-with-tests/build.gradle
@@ -28,7 +28,7 @@
 apply plugin: 'groovy'
 
 repositories {
-    jcenter()
+    mavenCentral()
 }
 
 dependencies {
diff --git a/extide/gradle/netbeans-gradle-tooling/src/test/data/unresolvable/build.gradle b/extide/gradle/netbeans-gradle-tooling/src/test/data/unresolvable/build.gradle
index 857634f..38c7184 100644
--- a/extide/gradle/netbeans-gradle-tooling/src/test/data/unresolvable/build.gradle
+++ b/extide/gradle/netbeans-gradle-tooling/src/test/data/unresolvable/build.gradle
@@ -20,7 +20,7 @@
 apply plugin: 'java'
 
 repositories {
-    jcenter()
+    mavenCentral()
 }
 
 dependencies {
diff --git a/extide/gradle/src/org/netbeans/modules/gradle/GradleModuleFileCache21.java b/extide/gradle/src/org/netbeans/modules/gradle/GradleModuleFileCache21.java
index 86dc596..8ced737 100644
--- a/extide/gradle/src/org/netbeans/modules/gradle/GradleModuleFileCache21.java
+++ b/extide/gradle/src/org/netbeans/modules/gradle/GradleModuleFileCache21.java
@@ -247,7 +247,7 @@
         int firstColon = gav.indexOf(':');
         int lastColon = gav.lastIndexOf(':');
         if (firstColon == -1 || firstColon == lastColon) {
-            throw new IllegalArgumentException("Invalig GAV format: " + gav);
+            throw new IllegalArgumentException("Invalid GAV format: " + gav); //NOI18N
         }
         return new String[] {
             gav.substring(0, firstColon),
diff --git a/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProject.java b/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProject.java
index 49a4f14..3c2cd03 100644
--- a/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProject.java
+++ b/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProject.java
@@ -32,7 +32,7 @@
 import java.util.Map;
 import java.util.Set;
 import org.netbeans.api.project.Project;
-import org.openide.filesystems.FileUtil;
+import org.netbeans.modules.gradle.GradleModuleFileCache21;
 
 /**
  * This object holds the basic information of the Gradle project.
@@ -255,11 +255,8 @@
     }
 
     @Override
-    public Set<GradleDependency.ModuleDependency> findModules(String gav) {
-        String parts[] = GradleDependency.gavSplit(gav);
-        if (parts.length != 3) {
-            throw new IllegalArgumentException("Invalid gav filter: "  + gav);
-        }
+    public Set<GradleDependency.ModuleDependency> findModules(String gav) throws IllegalArgumentException {
+        String parts[] = GradleModuleFileCache21.gavSplit(gav);
         String groupId = parts[0].isEmpty() ? null : parts[0];
         String artifactId = parts[1].isEmpty() ? null : parts[1];
         String ver = parts[2].isEmpty() ? null : parts[2];
diff --git a/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProjectBuilder.java b/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProjectBuilder.java
index 1519aea..ede038d 100644
--- a/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProjectBuilder.java
+++ b/extide/gradle/src/org/netbeans/modules/gradle/api/GradleBaseProjectBuilder.java
@@ -196,8 +196,13 @@
                             conf.modules.add(dep);
                         } else {
                             dep = resolveModuleDependency(gradleUserHome, c);
-                            components.put(c, dep);
-                            conf.modules.add(dep);
+                            if (dep != null) {
+                                components.put(c, dep);
+                                conf.modules.add(dep);
+                            } else {
+                               // NETBEANS-5161: This could happen on composite projects
+                               // TODO: Implement composite project module dependency
+                            }
                         }
                     }
                 }
@@ -259,19 +264,24 @@
 
     private ModuleDependency resolveModuleDependency(File gradleUserHome, String c) {
         GradleModuleFileCache21 moduleCache = GradleModuleFileCache21.getGradleFileCache(gradleUserHome.toPath());
-        GradleModuleFileCache21.CachedArtifactVersion artVersion = moduleCache.resolveModule(c);
-        Set<File> binaries = artifactSore.getBinaries(c);
-        if (((binaries == null) || binaries.isEmpty()) && (artVersion.getBinary() != null)) {
-            binaries = Collections.singleton(artVersion.getBinary().getPath().toFile());
+        try {
+            GradleModuleFileCache21.CachedArtifactVersion artVersion = moduleCache.resolveModule(c);
+            Set<File> binaries = artifactSore.getBinaries(c);
+            if (((binaries == null) || binaries.isEmpty()) && (artVersion.getBinary() != null)) {
+                binaries = Collections.singleton(artVersion.getBinary().getPath().toFile());
+            }
+            ModuleDependency ret = new ModuleDependency(c, binaries);
+            if (artVersion.getSources() != null) {
+                ret.sources = Collections.singleton(artVersion.getSources().getPath().toFile());
+            }
+            if (artVersion.getJavaDoc() != null) {
+                ret.javadoc = Collections.singleton(artVersion.getJavaDoc().getPath().toFile());
+            }
+            return ret;
+        } catch (IllegalArgumentException iae) {
+            // NETBEANS-5161: This could happen on composite projects
+            return null;
         }
-        ModuleDependency ret = new ModuleDependency(c, binaries);
-        if (artVersion.getSources() != null) {
-            ret.sources = Collections.singleton(artVersion.getSources().getPath().toFile());
-        }
-        if (artVersion.getJavaDoc() != null) {
-            ret.javadoc = Collections.singleton(artVersion.getJavaDoc().getPath().toFile());
-        }
-        return ret;
     }
 
     private void processDependencyPlugins() {
diff --git a/extide/gradle/src/org/netbeans/modules/gradle/api/GradleConfiguration.java b/extide/gradle/src/org/netbeans/modules/gradle/api/GradleConfiguration.java
index fe6b233..4e3b137 100644
--- a/extide/gradle/src/org/netbeans/modules/gradle/api/GradleConfiguration.java
+++ b/extide/gradle/src/org/netbeans/modules/gradle/api/GradleConfiguration.java
@@ -23,6 +23,7 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
+import org.netbeans.modules.gradle.GradleModuleFileCache21;
 
 /**
  * This object represents a configuration in a Gradle project.
@@ -86,10 +87,7 @@
 
     @Override
     public Set<GradleDependency.ModuleDependency> findModules(String gav) {
-        String parts[] = GradleDependency.gavSplit(gav);
-        if (parts.length != 3) {
-            throw new IllegalArgumentException("Invalid gav filter: "  + gav);
-        }
+        String parts[] = GradleModuleFileCache21.gavSplit(gav);
         String group = parts[0].isEmpty() ? null : parts[0];
         String artifact = parts[1].isEmpty() ? null : parts[1];
         String version = parts[2].isEmpty() ? null : parts[2];
diff --git a/extide/gradle/src/org/netbeans/modules/gradle/api/GradleDependency.java b/extide/gradle/src/org/netbeans/modules/gradle/api/GradleDependency.java
index ab2b588..8bd32a2 100644
--- a/extide/gradle/src/org/netbeans/modules/gradle/api/GradleDependency.java
+++ b/extide/gradle/src/org/netbeans/modules/gradle/api/GradleDependency.java
@@ -24,6 +24,7 @@
 import java.util.Collections;
 import java.util.Objects;
 import java.util.Set;
+import org.netbeans.modules.gradle.GradleModuleFileCache21;
 
 /**
  * This object represents a Gradle dependency element in a {@link GradleConfiguration}.
@@ -63,19 +64,6 @@
 
     public abstract Type getType();
 
-    static final String[] gavSplit(String gav) {
-        int firstColon = gav.indexOf(':');
-        int lastColon = gav.lastIndexOf(':');
-        if (firstColon == -1 || firstColon == lastColon) {
-            throw new IllegalArgumentException("Invalig GAV format: " + gav);
-        }
-        return new String[] {
-            gav.substring(0, firstColon),
-            gav.substring(firstColon + 1, lastColon),
-            gav.substring(lastColon + 1)
-        };
-    }
-
     /**
      * Dependency for modules usually downloaded from a remote repository.
      * @since 1.0
@@ -92,7 +80,7 @@
         ModuleDependency(String id, Set<File> artifacts) {
             super(id);
             this.artifacts = artifacts;
-            String[] parts = gavSplit(id);
+            String[] parts = GradleModuleFileCache21.gavSplit(id);
             group = parts[0];
             name = parts[1];
             version = parts[2];
diff --git a/extide/gradle/src/org/netbeans/modules/gradle/execute/navigator/TasksPanel.java b/extide/gradle/src/org/netbeans/modules/gradle/execute/navigator/TasksPanel.java
index 39bb2ad..b2fbe31 100644
--- a/extide/gradle/src/org/netbeans/modules/gradle/execute/navigator/TasksPanel.java
+++ b/extide/gradle/src/org/netbeans/modules/gradle/execute/navigator/TasksPanel.java
@@ -260,6 +260,7 @@
         private final ChangeListener listener;
 
         public FavoritesChildren() {
+            assert currentP != null;
             FavoriteTaskManager fvm = getFavoriteTaskManager();
             listener = (e) -> {
                 Set<GradleTask> favs = fvm.getFavoriteTasks();
@@ -271,7 +272,11 @@
 
         @Override
         protected Node[] createNodes(GradleTask key) {
-            return new Node[] {new TaskNode(currentP, key)};
+            // NETBEANS-5340 It might happen that the currentP is null, but the listener
+            // still active on the previous project.
+            return currentP != null ? 
+                    new Node[] {new TaskNode(currentP, key)} :
+                    new Node[0];
         }
 
     }
diff --git a/extide/gradle/src/org/netbeans/modules/gradle/newproject/multi-root.gradle.template b/extide/gradle/src/org/netbeans/modules/gradle/newproject/multi-root.gradle.template
index e834be6..ec5a458 100644
--- a/extide/gradle/src/org/netbeans/modules/gradle/newproject/multi-root.gradle.template
+++ b/extide/gradle/src/org/netbeans/modules/gradle/newproject/multi-root.gradle.template
@@ -9,7 +9,7 @@
 
 </#if>
     repositories {
-        jcenter()
+        mavenCentral()
     }
 }
 
diff --git a/extide/gradle/src/org/netbeans/modules/gradle/newproject/single-build.gradle.template b/extide/gradle/src/org/netbeans/modules/gradle/newproject/single-build.gradle.template
index e9139ab..bfefcff 100644
--- a/extide/gradle/src/org/netbeans/modules/gradle/newproject/single-build.gradle.template
+++ b/extide/gradle/src/org/netbeans/modules/gradle/newproject/single-build.gradle.template
@@ -22,7 +22,7 @@
 targetCompatibility = ${javaVersion}
 </#if>
 repositories {
-    jcenter()
+    mavenCentral()
 }
 
 <#if dependencies??>
diff --git a/ide/api.debugger/src/org/netbeans/api/debugger/Breakpoint.java b/ide/api.debugger/src/org/netbeans/api/debugger/Breakpoint.java
index f35418a..3602993 100644
--- a/ide/api.debugger/src/org/netbeans/api/debugger/Breakpoint.java
+++ b/ide/api.debugger/src/org/netbeans/api/debugger/Breakpoint.java
@@ -195,7 +195,7 @@
 
     /**
      * Get group properties of the breakpoint.
-     * These are implementation-defined group properties as oposed to {@link #getGroupName()},
+     * These are implementation-defined group properties as opposed to {@link #getGroupName()},
      * which returns user-defined group name.
      * <p>
      * These properties are used by the Breakpoint Window to show a tree
diff --git a/java/java.lsp.server/build.xml b/java/java.lsp.server/build.xml
index add7018..543b199 100644
--- a/java/java.lsp.server/build.xml
+++ b/java/java.lsp.server/build.xml
@@ -139,7 +139,11 @@
 
         <zip destfile="${build.dir}/apache-netbeans-java-${vsix.version}.vsix" basedir="${build.dir}/vscode-mandatory/" update="true" />
     </target>
-    <target name="test-vscode-ext" description="Tests the Visual Studio Code extension built by 'build-vscode-ext' target.">
+    <target name="test-lsp-server" description="Tests the LSP server behavior">
+        <ant dir="nbcode" target="test" inheritall="false" inheritrefs="false" />
+    </target>
+
+    <target name="test-vscode-ext" depends="test-lsp-server" description="Tests the Visual Studio Code extension built by 'build-vscode-ext' target.">
         <exec executable="npm" failonerror="true" dir="vscode">
             <arg value="--allow-same-version"/>
             <arg value="run" />
diff --git a/java/java.lsp.server/nbcode/branding/modules/org-openide-loaders.jar/org/netbeans/modules/openide/loaders/Bundle.properties b/java/java.lsp.server/nbcode/branding/modules/org-openide-loaders.jar/org/netbeans/modules/openide/loaders/Bundle.properties
index 5a168f8..caf4c2c 100644
--- a/java/java.lsp.server/nbcode/branding/modules/org-openide-loaders.jar/org/netbeans/modules/openide/loaders/Bundle.properties
+++ b/java/java.lsp.server/nbcode/branding/modules/org-openide-loaders.jar/org/netbeans/modules/openide/loaders/Bundle.properties
@@ -16,6 +16,6 @@
 # under the License.
 
 # yes/no/ask
-ASK_OnSaving=no
+ASK_OnSaving=yes
 # yes/no/ask
 ASK_OnClosing=no
diff --git a/java/java.lsp.server/nbcode/integration/manifest.mf b/java/java.lsp.server/nbcode/integration/manifest.mf
index 2037069..3bffb1b 100644
--- a/java/java.lsp.server/nbcode/integration/manifest.mf
+++ b/java/java.lsp.server/nbcode/integration/manifest.mf
@@ -1,6 +1,7 @@
 Manifest-Version: 1.0
 AutoUpdate-Show-In-Client: false
 OpenIDE-Module: org.netbeans.modules.nbcode.integration
+OpenIDE-Module-Layer: org/netbeans/modules/nbcode/integration/layer.xml
 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/nbcode/integration/Bundle.properties
 OpenIDE-Module-Specification-Version: 1.0
 OpenIDE-Module-Recommends: cnb.org.netbeans.modules.gradle.java
diff --git a/java/java.lsp.server/nbcode/integration/nbproject/project.xml b/java/java.lsp.server/nbcode/integration/nbproject/project.xml
index e87eb05..5139b55 100644
--- a/java/java.lsp.server/nbcode/integration/nbproject/project.xml
+++ b/java/java.lsp.server/nbcode/integration/nbproject/project.xml
@@ -99,7 +99,24 @@
                         <specification-version>8.44</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.updatecenters</code-name-base>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.51</specification-version>
+                    </run-dependency>
+                </dependency>
             </module-dependencies>
+            <test-dependencies>
+                <test-type>
+                    <name>unit</name>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
+                        <compile-dependency/>
+                        <recursive/>
+                    </test-dependency>
+                </test-type>
+            </test-dependencies>
             <public-packages/>
         </data>
     </configuration>
diff --git a/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/layer.xml b/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/layer.xml
new file mode 100644
index 0000000..a1a03ee
--- /dev/null
+++ b/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/layer.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
+<filesystem>
+    <folder name="Services">
+        <folder name="AutoupdateType">
+            <file name="82pluginportal-update-provider.instance_hidden"/>
+            <file name="distribution-update-provider.instance_hidden"/>
+            <file name="pluginportal-update-provider.instance_hidden"/>
+        </folder>
+    </folder>
+</filesystem>
diff --git a/java/java.lsp.server/nbcode/integration/test/unit/src/org/netbeans/modules/nbcode/integration/VerifyJustOneUpdateCenterTest.java b/java/java.lsp.server/nbcode/integration/test/unit/src/org/netbeans/modules/nbcode/integration/VerifyJustOneUpdateCenterTest.java
new file mode 100644
index 0000000..d176098
--- /dev/null
+++ b/java/java.lsp.server/nbcode/integration/test/unit/src/org/netbeans/modules/nbcode/integration/VerifyJustOneUpdateCenterTest.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.nbcode.integration;
+
+import java.util.Arrays;
+import org.netbeans.junit.NbModuleSuite;
+import org.netbeans.junit.NbTestCase;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+
+public class VerifyJustOneUpdateCenterTest extends NbTestCase {
+
+    public VerifyJustOneUpdateCenterTest(String name) {
+        super(name);
+    }
+
+    public static junit.framework.Test suite() {
+        return NbModuleSuite.createConfiguration(VerifyJustOneUpdateCenterTest.class).
+            gui(true).
+            suite();
+    }
+
+    public void testUpdateCenters() {
+        FileObject services = FileUtil.getConfigRoot().getFileObject("Services");
+        assertNotNull("Services found", services);
+        FileObject au = services.getFileObject("AutoupdateType");
+        assertNotNull("AutoUpdate folder found", au);
+        FileObject[] arr = au.getChildren();
+        assertEquals("Just one AutoUpdate center registration: " + Arrays.toString(arr), 1, arr.length);
+        assertEquals("3rdparty.instance", arr[0].getNameExt());
+    }
+}
diff --git a/java/java.lsp.server/nbcode/nbproject/platform.properties b/java/java.lsp.server/nbcode/nbproject/platform.properties
index d7be701..3b34848 100644
--- a/java/java.lsp.server/nbcode/nbproject/platform.properties
+++ b/java/java.lsp.server/nbcode/nbproject/platform.properties
@@ -22,6 +22,7 @@
     ${nbplatform.active.dir}/java:\
     ${nbplatform.active.dir}/nb:\
     ${nbplatform.active.dir}/platform:\
+    ${nbplatform.active.dir}/harness:\
     ${nbplatform.active.dir}/webcommon
 disabled.modules=\
     bcpg,\
@@ -82,6 +83,8 @@
     org.netbeans.libs.jsr223,\
     org.netbeans.libs.jstestdriver,\
     org.netbeans.libs.jvyamlb,\
+    org.netbeans.libs.nbi.ant,\
+    org.netbeans.libs.nbi.engine,\
     org.netbeans.libs.plist,\
     org.netbeans.libs.smack,\
     org.netbeans.libs.springframework,\
@@ -94,6 +97,7 @@
     org.netbeans.modules.ant.grammar,\
     org.netbeans.modules.ant.hints,\
     org.netbeans.modules.ant.kit,\
+    org.netbeans.modules.apisupport.harness,\
     org.netbeans.modules.applemenu,\
     org.netbeans.modules.autoupdate.pluginimporter,\
     org.netbeans.modules.beans,\
@@ -233,6 +237,8 @@
     org.netbeans.modules.javawebstart,\
     org.netbeans.modules.jellytools.ide,\
     org.netbeans.modules.jellytools.java,\
+    org.netbeans.modules.jellytools.platform,\
+    org.netbeans.modules.jemmy,\
     org.netbeans.modules.jshell.support,\
     org.netbeans.modules.junit.ant,\
     org.netbeans.modules.junit.ant.ui,\
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/NbSourceProvider.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/NbSourceProvider.java
index 6303248..9e598bd 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/NbSourceProvider.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/NbSourceProvider.java
@@ -118,11 +118,14 @@
         String uri = sourceProvider.getSourceFileURI(fullyQualifiedName, relativeSourcePath);
 
         if (uri == null || uri.isEmpty()) {
-            for (String path : context.getSourcePaths()) {
-                Path fullpath = Paths.get(path, relativeSourcePath);
-                if (Files.isRegularFile(fullpath)) {
-                    uri = fullpath.toString();
-                    break;
+            String[] sourcePaths = context.getSourcePaths();
+            if (sourcePaths != null) {
+                for (String path : sourcePaths) {
+                    Path fullpath = Paths.get(path, relativeSourcePath);
+                    if (Files.isRegularFile(fullpath)) {
+                        uri = fullpath.toString();
+                        break;
+                    }
                 }
             }
         }
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/NbThreads.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/NbThreads.java
index 81137d9..4e7e439 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/NbThreads.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/NbThreads.java
@@ -27,7 +27,6 @@
 import java.util.function.Supplier;
 import org.eclipse.lsp4j.debug.StoppedEventArguments;
 
-import org.eclipse.lsp4j.debug.TerminatedEventArguments;
 import org.eclipse.lsp4j.debug.ThreadEventArguments;
 import org.netbeans.api.debugger.DebuggerEngine;
 import org.netbeans.api.debugger.DebuggerManager;
@@ -63,15 +62,6 @@
     }
 
     private void initThreads(DebugAdapterContext context, JPDADebugger debugger) {
-        debugger.addPropertyChangeListener(JPDADebugger.PROP_STATE, evt -> {
-            int newState = (int) evt.getNewValue();
-            switch (newState) {
-                case JPDADebugger.STATE_DISCONNECTED:
-                    //debugger.removePropertyChangeListener(this);
-                    context.getClient().terminated(new TerminatedEventArguments());
-                    break;
-            }
-        });
         DebuggerEngine engine = debugger.getSession().getCurrentEngine();
         if (engine == null) {
             debugger.getSession().addPropertyChangeListener(Session.PROP_CURRENT_LANGUAGE, new PropertyChangeListener() {
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchRequestHandler.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchRequestHandler.java
index 1f66724..66ab8d9 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchRequestHandler.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchRequestHandler.java
@@ -27,9 +27,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 import java.util.function.Consumer;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -39,6 +36,7 @@
 import org.eclipse.lsp4j.debug.Source;
 import org.eclipse.lsp4j.debug.TerminatedEventArguments;
 import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode;
+import org.netbeans.api.java.classpath.ClassPath;
 import org.netbeans.modules.java.lsp.server.debugging.DebugAdapterContext;
 import org.netbeans.modules.java.lsp.server.debugging.NbSourceProvider;
 import org.netbeans.modules.java.lsp.server.debugging.utils.ErrorUtilities;
@@ -53,13 +51,13 @@
 public final class NbLaunchRequestHandler {
 
     private NbLaunchDelegate activeLaunchHandler;
-    private final CompletableFuture<Boolean> waitForDebuggeeConsole = new CompletableFuture<>();
 
     public CompletableFuture<Void> launch(Map<String, Object> launchArguments, DebugAdapterContext context) {
         CompletableFuture<Void> resultFuture = new CompletableFuture<>();
         boolean noDebug = (Boolean) launchArguments.getOrDefault("noDebug", Boolean.FALSE);
-        activeLaunchHandler = noDebug ? new NbLaunchWithoutDebuggingDelegate((daContext) -> handleTerminatedEvent(daContext))
-                : new NbLaunchWithDebuggingDelegate();
+        Consumer<DebugAdapterContext> terminateHandle = (daContext) -> handleTerminatedEvent(daContext);
+        activeLaunchHandler = noDebug ? new NbLaunchWithoutDebuggingDelegate(terminateHandle)
+                : new NbLaunchWithDebuggingDelegate(terminateHandle);
         // validation
         List<String> modulePaths = (List<String>) launchArguments.getOrDefault("modulePaths", Collections.emptyList());
         List<String> classPaths = (List<String>) launchArguments.getOrDefault("classPaths", Collections.emptyList());
@@ -112,6 +110,19 @@
                     ResponseErrorCode.serverErrorStart);
             return resultFuture;
         }
+        if (!launchArguments.containsKey("sourcePaths")) {
+            ClassPath sourceCP = ClassPath.getClassPath(file, ClassPath.SOURCE);
+            if (sourceCP != null) {
+                FileObject[] roots = sourceCP.getRoots();
+                String[] sourcePaths = new String[roots.length];
+                for (int i = 0; i < roots.length; i++) {
+                    sourcePaths[i] = roots[i].getPath();
+                }
+                context.setSourcePaths(sourcePaths);
+            }
+        } else {
+            context.setSourcePaths((String[]) launchArguments.get("sourcePaths"));
+        }
         String singleMethod = (String)launchArguments.get("singleMethod");
         activeLaunchHandler.nbLaunch(file, singleMethod, context, !noDebug, new OutputListener(context)).thenRun(() -> {
             activeLaunchHandler.postLaunch(launchArguments, context);
@@ -159,14 +170,9 @@
     }
 
     protected void handleTerminatedEvent(DebugAdapterContext context) {
-        CompletableFuture.runAsync(() -> {
-            try {
-                waitForDebuggeeConsole.get(5, TimeUnit.SECONDS);
-            } catch (InterruptedException | ExecutionException | TimeoutException e) {
-                // do nothing.
-            }
-            context.getClient().terminated(new TerminatedEventArguments());
-        });
+        // Project Action has already closed the I/O streams, and even in NetBeans IDE, the output area
+        // is already inactive at this point.
+        context.getClient().terminated(new TerminatedEventArguments());
     }
 
     private final class OutputListener implements Consumer<NbProcessConsole.ConsoleMessage> {
@@ -179,10 +185,7 @@
 
         @Override
         public void accept(NbProcessConsole.ConsoleMessage message) {
-            if (message == null) {
-                // EOF
-                waitForDebuggeeConsole.complete(true);
-            } else {
+            if (message != null) {
                 OutputEventArguments outputEvent = convertToOutputEventArguments(message.output, message.category, context);
                 context.getClient().output(outputEvent);
             }
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchWithDebuggingDelegate.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchWithDebuggingDelegate.java
index ce14bc7..2ec0b81 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchWithDebuggingDelegate.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/debugging/launch/NbLaunchWithDebuggingDelegate.java
@@ -19,6 +19,7 @@
 package org.netbeans.modules.java.lsp.server.debugging.launch;
 
 import java.util.Map;
+import java.util.function.Consumer;
 import org.netbeans.modules.java.lsp.server.debugging.DebugAdapterContext;
 
 
@@ -28,6 +29,18 @@
  */
 public final class NbLaunchWithDebuggingDelegate extends NbLaunchDelegate {
 
+    private final Consumer<DebugAdapterContext> onFinishCallback;
+
+    NbLaunchWithDebuggingDelegate(Consumer<DebugAdapterContext> onFinishCallback) {
+        this.onFinishCallback = onFinishCallback;
+    }
+
+    @Override
+    protected void notifyFinished(DebugAdapterContext ctx, boolean success) {
+        super.notifyFinished(ctx, success);
+        onFinishCallback.accept(ctx);
+    }
+
     @Override
     public void postLaunch(Map<String, Object> launchArguments, DebugAdapterContext context) {
         context.getClient().initialized();
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java
index 2a9b5b1..a4a5b1d 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java
@@ -322,8 +322,7 @@
                 capabilities.setDocumentHighlightProvider(true);
                 capabilities.setReferencesProvider(true);
                 List<String> commands = new ArrayList<>(Arrays.asList(
-                        JAVA_BUILD_WORKSPACE, GRAALVM_PAUSE_SCRIPT,
-                        JAVA_TEST_SINGLE_METHOD, JAVA_RUN_MAIN_METHOD));
+                        JAVA_BUILD_WORKSPACE, GRAALVM_PAUSE_SCRIPT));
                 for (CodeGenerator codeGenerator : Lookup.getDefault().lookupAll(CodeGenerator.class)) {
                     commands.addAll(codeGenerator.getCommands());
                 }
@@ -419,8 +418,6 @@
     }
     
     public static final String JAVA_BUILD_WORKSPACE =  "java.build.workspace";
-    public static final String JAVA_TEST_SINGLE_METHOD =  "java.test.single.method";
-    public static final String JAVA_RUN_MAIN_METHOD =  "java.run.main.method";
     public static final String GRAALVM_PAUSE_SCRIPT =  "graalvm.pause.script";
     static final String INDEXING_COMPLETED = "Indexing completed.";
     static final String NO_JAVA_SUPPORT = "Cannot initialize Java support on JDK ";
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java
index d7ef2eb..4567b04 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/TextDocumentServiceImpl.java
@@ -24,7 +24,6 @@
 import com.sun.source.tree.CompilationUnitTree;
 import com.sun.source.tree.LineMap;
 import com.sun.source.tree.MethodTree;
-import com.sun.source.tree.PrimitiveTypeTree;
 import com.sun.source.tree.Scope;
 import com.sun.source.tree.Tree;
 import com.sun.source.tree.Tree.Kind;
@@ -61,14 +60,12 @@
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ElementKind;
 import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Modifier;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.TypeParameterElement;
 import javax.lang.model.element.VariableElement;
 import javax.lang.model.type.ArrayType;
 import javax.lang.model.type.DeclaredType;
 import javax.lang.model.type.ExecutableType;
-import javax.lang.model.type.TypeKind;
 import javax.lang.model.type.TypeMirror;
 import javax.lang.model.util.Elements;
 import javax.swing.text.BadLocationException;
@@ -339,6 +336,7 @@
 
     private static class ItemFactoryImpl implements JavaCompletionTask.ItemFactory<CompletionItem> {
 
+        private static final int DEPRECATED = 10;
         private final LanguageClient client;
         private final String uri;
         private final int offset;
@@ -561,12 +559,26 @@
 
         @Override
         public CompletionItem createAttributeItem(CompilationInfo info, ExecutableElement elem, ExecutableType type, int substitutionOffset, boolean isDeprecated) {
-            return null; //TODO: fill
+            CompletionItem item = new CompletionItem(elem.getSimpleName().toString());
+            item.setKind(CompletionItemKind.Property);
+            StringBuilder insertText = new StringBuilder();
+            insertText.append(elem.getSimpleName());
+            insertText.append("=");
+            item.setInsertText(insertText.toString());
+            item.setInsertTextFormat(InsertTextFormat.PlainText);
+            int priority = isDeprecated ? 100 + DEPRECATED : 100;
+            item.setSortText(String.format("%4d%s", priority, elem.getSimpleName().toString()));
+            setCompletionData(item, elem);
+            return item;
         }
 
         @Override
         public CompletionItem createAttributeValueItem(CompilationInfo info, String value, String documentation, TypeElement element, int substitutionOffset, ReferencesCount referencesCount) {
-            return null; //TODO: fill
+            CompletionItem item = new CompletionItem(value);
+            item.setKind(CompletionItemKind.Text);
+            item.setSortText(value);
+            item.setDocumentation(documentation);
+            return item;
         }
 
         private static final Object KEY_IMPORT_TEXT_EDITS = new Object();
@@ -1375,7 +1387,7 @@
                                                     Utils.createPosition(cc.getCompilationUnit(), method.end().getOffset()));
                             List<Object> arguments = Arrays.asList(new Object[]{method.method().getFile().toURI(), method.method().getMethodName()});
                             lens.add(new CodeLens(range,
-                                                  new Command("Run test", Server.JAVA_TEST_SINGLE_METHOD, arguments),
+                                                  new Command("Run test", "java.run.codelens", arguments),
                                                   null));
                             lens.add(new CodeLens(range,
                                                   new Command("Debug test", "java.debug.codelens", arguments),
@@ -1391,7 +1403,7 @@
                             Range range = Utils.treeRange(cc, tree);
                             List<Object> arguments = Collections.singletonList(params.getTextDocument().getUri());
                             lens.add(new CodeLens(range,
-                                                  new Command("Run main", Server.JAVA_RUN_MAIN_METHOD, arguments),
+                                                  new Command("Run main", "java.run.codelens", arguments),
                                                   null));
                             lens.add(new CodeLens(range,
                                                   new Command("Debug main", "java.debug.codelens", arguments),
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/WorkspaceServiceImpl.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/WorkspaceServiceImpl.java
index 4e65d51..a7de5eb 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/WorkspaceServiceImpl.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/WorkspaceServiceImpl.java
@@ -112,33 +112,6 @@
                 progressOfCompilation.checkStatus();
                 return progressOfCompilation.getFinishFuture();
             }
-            case Server.JAVA_TEST_SINGLE_METHOD:
-                CommandProgress progressOfCommand = new CommandProgress();
-                String uriStr = ((JsonPrimitive) params.getArguments().get(0)).getAsString();
-                FileObject file;
-                try {
-                    file = URLMapper.findFileObject(new URL(uriStr));
-                } catch (MalformedURLException ex) {
-                    Exceptions.printStackTrace(ex);
-                    return CompletableFuture.completedFuture(true);
-                }
-                String methodName = ((JsonPrimitive) params.getArguments().get(1)).getAsString();
-                SingleMethod method = new SingleMethod(file, methodName);
-                runSingleMethodCommand(method, SingleMethod.COMMAND_RUN_SINGLE_METHOD, progressOfCommand);
-                progressOfCommand.checkStatus();
-                return progressOfCommand.getFinishFuture();
-            case Server.JAVA_RUN_MAIN_METHOD:
-                progressOfCommand = new CommandProgress();
-                uriStr = ((JsonPrimitive) params.getArguments().get(0)).getAsString();
-                try {
-                    file = URLMapper.findFileObject(new URL(uriStr));
-                } catch (MalformedURLException ex) {
-                    Exceptions.printStackTrace(ex);
-                    return CompletableFuture.completedFuture(true);
-                }
-                runSingleFile(file, ActionProvider.COMMAND_RUN_SINGLE, progressOfCommand);
-                progressOfCommand.checkStatus();
-                return progressOfCommand.getFinishFuture();
             default:
                 for (CodeGenerator codeGenerator : Lookup.getDefault().lookupAll(CodeGenerator.class)) {
                     if (codeGenerator.getCommands().contains(command)) {
@@ -149,46 +122,6 @@
         throw new UnsupportedOperationException("Command not supported: " + params.getCommand());
     }
 
-    @NbBundle.Messages("No_Method_Found=No method found")
-    private void runSingleMethodCommand(SingleMethod singleMethod, String command, CommandProgress progressOfCommand) {
-        if (singleMethod == null) {
-            StatusDisplayer.getDefault().setStatusText(Bundle.No_Method_Found());
-            progressOfCommand.getFinishFuture().complete(true);
-        } else {
-            Mutex.EVENT.readAccess(new Runnable() {
-                @Override
-                public void run() {
-                    Project owner = FileOwnerQuery.getOwner(singleMethod.getFile());
-                    if (owner != null) {
-                        ActionProvider ap = owner.getLookup().lookup(ActionProvider.class);
-                        if (ap != null) {
-                            if (Arrays.asList(ap.getSupportedActions()).contains(command) && ap.isActionEnabled(command, Lookups.singleton(singleMethod))) {
-                                ap.invokeAction(command, Lookups.fixed(singleMethod, progressOfCommand));
-                            }
-                        }
-                    }
-                }
-            });
-        }
-    }
-
-    private void runSingleFile(FileObject file, String command, CommandProgress progressOfCommand) {
-        Mutex.EVENT.readAccess(new Runnable() {
-            @Override
-            public void run() {
-                Project owner = FileOwnerQuery.getOwner(file);
-                if (owner != null) {
-                    ActionProvider ap = owner.getLookup().lookup(ActionProvider.class);
-                    if (ap != null) {
-                        if (Arrays.asList(ap.getSupportedActions()).contains(command) && ap.isActionEnabled(command, Lookups.singleton(file))) {
-                            ap.invokeAction(command, Lookups.fixed(file, progressOfCommand));
-                        }
-                    }
-                }
-            }
-        });
-    }
-
     @Override
     public CompletableFuture<List<? extends SymbolInformation>> symbol(WorkspaceSymbolParams params) {
         String query = params.getQuery();
diff --git a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java
index 14f51d7..5acde78 100644
--- a/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java
+++ b/java/java.lsp.server/test/unit/src/org/netbeans/modules/java/lsp/server/protocol/ServerTest.java
@@ -35,6 +35,7 @@
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -48,6 +49,7 @@
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
+import javax.swing.event.ChangeListener;
 import javax.swing.text.Document;
 import javax.swing.text.StyledDocument;
 import org.eclipse.lsp4j.ApplyWorkspaceEditParams;
@@ -112,6 +114,8 @@
 import org.eclipse.lsp4j.services.LanguageServer;
 import org.netbeans.api.java.classpath.ClassPath;
 import org.netbeans.api.java.classpath.GlobalPathRegistry;
+import org.netbeans.api.java.queries.AnnotationProcessingQuery.Result;
+import org.netbeans.api.java.queries.AnnotationProcessingQuery.Trigger;
 import org.netbeans.api.java.source.JavaSource;
 import org.netbeans.api.project.Project;
 import org.netbeans.api.project.ui.OpenProjects;
@@ -121,6 +125,7 @@
 import org.netbeans.modules.parsing.impl.indexing.implspi.CacheFolderProvider;
 import org.netbeans.spi.java.classpath.ClassPathProvider;
 import org.netbeans.spi.java.classpath.support.ClassPathSupport;
+import org.netbeans.spi.java.queries.AnnotationProcessingQueryImplementation;
 import org.netbeans.spi.project.ProjectFactory;
 import org.netbeans.spi.project.ProjectState;
 import org.netbeans.spi.project.ui.ProjectOpenedHook;
@@ -3234,7 +3239,7 @@
         assertTrue(result.getCapabilities().getFoldingRangeProvider().isRight());
         server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(toURI(src), "java", 0, code)));
         List<FoldingRange> folds = server.getTextDocumentService().foldingRange(new FoldingRangeRequestParams(new TextDocumentIdentifier(toURI(src)))).get();
-        System.err.println("folds=" + folds);
+
         assertEquals(5, folds.size());
 
         assertEquals(0, folds.get(0).getStartLine());
@@ -3268,6 +3273,34 @@
         assertEquals("region", folds.get(4).getKind());
     }
 
+    public void testAnnotationCompletion() throws Exception {
+        File src = new File(getWorkDir(), "Test.java");
+        src.getParentFile().mkdirs();
+        String code = "@java.lang.Supp public class Test { }";
+        try (Writer w = new FileWriter(src)) {
+            w.write(code);
+        }
+        Launcher<LanguageServer> serverLauncher = LSPLauncher.createClientLauncher(new LspClient(), client.getInputStream(), client.getOutputStream());
+        serverLauncher.startListening();
+        LanguageServer server = serverLauncher.getRemoteProxy();
+        InitializeResult result = server.initialize(new InitializeParams()).get();
+        server.getTextDocumentService().didOpen(new DidOpenTextDocumentParams(new TextDocumentItem(toURI(src), "java", 0, code)));
+        Either<List<CompletionItem>, CompletionList> completion = server.getTextDocumentService().completion(new CompletionParams(new TextDocumentIdentifier(toURI(src)), new Position(0, 15))).get();
+        assertTrue(completion.isRight());
+        List<String> actualItems = completion.getRight().getItems().stream().map(ci -> ci.getKind() + ":" + ci.getLabel()).collect(Collectors.toList());
+        assertEquals(Arrays.asList("Interface:SuppressWarnings"), actualItems);
+        VersionedTextDocumentIdentifier id = new VersionedTextDocumentIdentifier(1);
+        id.setUri(toURI(src));
+        server.getTextDocumentService().didChange(new DidChangeTextDocumentParams(id, Arrays.asList(new TextDocumentContentChangeEvent(new Range(new Position(0, 1), new Position(0, 15)), 14, "SuppressWarnings(v"))));
+        completion = server.getTextDocumentService().completion(new CompletionParams(new TextDocumentIdentifier(toURI(src)), new Position(0, 19))).get();
+        actualItems = completion.getRight().getItems().stream().map(ci -> ci.getKind() + ":" + ci.getLabel()).collect(Collectors.toList());
+        assertTrue(actualItems.contains("Property:value"));
+        server.getTextDocumentService().didChange(new DidChangeTextDocumentParams(id, Arrays.asList(new TextDocumentContentChangeEvent(new Range(new Position(0, 19), new Position(0, 19)), 0, "alue=\"\""))));
+        completion = server.getTextDocumentService().completion(new CompletionParams(new TextDocumentIdentifier(toURI(src)), new Position(0, 25))).get();
+        actualItems = completion.getRight().getItems().stream().map(ci -> ci.getKind() + ":" + ci.getLabel()).collect(Collectors.toList());
+        assertTrue(actualItems.contains("Text:\"empty-statement\""));
+    }
+
     interface Validator<T> {
         public void validate(T t) throws Exception;
     }
@@ -3353,6 +3386,42 @@
 
     }
 
+    @ServiceProvider(service=AnnotationProcessingQueryImplementation.class, position=100)
+    public static final class AnnotationProcessingQueryImpl implements AnnotationProcessingQueryImplementation {
+
+        private final Result result = new Result() {
+            @Override
+            public Set<? extends Trigger> annotationProcessingEnabled() {
+                return EnumSet.allOf(Trigger.class);
+            }
+
+            @Override
+            public Iterable<? extends String> annotationProcessorsToRun() {
+                return Collections.emptyList();
+            }
+            @Override
+            public URL sourceOutputDirectory() {
+                return null;
+            }
+            @Override
+            public Map<? extends String, ? extends String> processorOptions() {
+                return Collections.emptyMap();
+            }
+            @Override
+            public void addChangeListener(ChangeListener l) {
+            }
+            @Override
+            public void removeChangeListener(ChangeListener l) {
+            }
+        };
+
+        @Override
+        public Result getAnnotationProcessingOptions(FileObject file) {
+            return result;
+        }
+
+    }
+
     //tests may run as a project, so that indexing works properly:
     @ServiceProvider(service=ProjectFactory.class)
     public static class TestProjectFactory implements ProjectFactory {
diff --git a/java/java.lsp.server/vscode/CHANGELOG.md b/java/java.lsp.server/vscode/CHANGELOG.md
index 401e676..5ef9b72 100644
--- a/java/java.lsp.server/vscode/CHANGELOG.md
+++ b/java/java.lsp.server/vscode/CHANGELOG.md
@@ -20,7 +20,17 @@
     under the License.
 
 -->
+## Version 12.3
 
+* LSP codelens for Run and Debug of main and test methods
+* NETBEANS-5319 - Always do save modified files when used through LSP.
+* Project problems and improvements in headless environment for VSNetBeans.
+  * Showing completions returned by annotation Processors in VS Code.
+  * Project problems are resolved in headless environment.
+  * Restart NBLS when an extension providing some NB cluster is installed/uninstalled.
+  * Enable full VSNetBeans Maven build test.
+  * Don't show reload/save dialogs in VSNetBeans
+  * Properly stop Maven execution from LSP/DAP 
 ## Version 12.2.1
 
 * Numerous refactorings for Java source code editing added
diff --git a/java/java.lsp.server/vscode/package-lock.json b/java/java.lsp.server/vscode/package-lock.json
index 79055ae..23864b2 100644
--- a/java/java.lsp.server/vscode/package-lock.json
+++ b/java/java.lsp.server/vscode/package-lock.json
@@ -38,9 +38,9 @@
 			"integrity": "sha512-HI5l+f38o93x81mbOWZ1IEzj87rGCHfN4A4QyCU1MuViT5Slvlo5F+YVvmBFHfZsEGi0Lo8TghWU2Ew6vBILNA=="
 		},
 		"@types/vscode": {
-			"version": "1.47.0",
-			"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.47.0.tgz",
-			"integrity": "sha512-nJA37ykkz9FYA0ZOQUSc3OZnhuzEW2vUhUEo4MiduUo82jGwwcLfyvmgd/Q7b0WrZAAceojGhZybg319L24bTA==",
+			"version": "1.49.0",
+			"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.49.0.tgz",
+			"integrity": "sha512-wfNQmLmm1VdMBr6iuNdprWmC1YdrgZ9dQzadv+l2eSjJlElOdJw8OTm4RU4oGTBcfvG6RZI2jOcppkdSS18mZw==",
 			"dev": true
 		},
 		"agent-base": {
diff --git a/java/java.lsp.server/vscode/package.json b/java/java.lsp.server/vscode/package.json
index eaac062..863381b 100644
--- a/java/java.lsp.server/vscode/package.json
+++ b/java/java.lsp.server/vscode/package.json
@@ -21,7 +21,7 @@
 		"multi-root ready"
 	],
 	"engines": {
-		"vscode": "^1.47.0"
+		"vscode": "^1.49.0"
 	},
 	"activationEvents": [
 		"onLanguage:java",
@@ -175,7 +175,7 @@
 		"nbjavac": "node ./out/nbcode.js -J-Dnetbeans.close=true --modules --install .*nbjavac.*"
 	},
 	"devDependencies": {
-		"@types/vscode": "^1.47.0",
+		"@types/vscode": "^1.49.0",
 		"@types/glob": "^7.1.1",
 		"@types/mocha": "^7.0.2",
 		"@types/node": "^13.11.0",
diff --git a/java/java.lsp.server/vscode/src/extension.ts b/java/java.lsp.server/vscode/src/extension.ts
index 9d697c1..df15972 100644
--- a/java/java.lsp.server/vscode/src/extension.ts
+++ b/java/java.lsp.server/vscode/src/extension.ts
@@ -211,20 +211,29 @@
             ]);
         }
     }));
-    context.subscriptions.push(commands.registerCommand('java.debug.codelens', async (uri, methodName) => {
+    const runCodelens = async (uri : any, methodName : string, noDebug : boolean) => {
         const editor = window.activeTextEditor;
         if (editor) {
             const docUri = editor.document.uri;
             const workspaceFolder = vscode.workspace.getWorkspaceFolder(docUri);
-            const debugConfig = {
+            const debugConfig : vscode.DebugConfiguration = {
                 type: "java8+",
                 name: "CodeLens Debug",
                 request: "launch",
                 mainClass: uri,
                 singleMethod: methodName,
             };
-            await vscode.debug.startDebugging(workspaceFolder, debugConfig).then();
+            const debugOptions : vscode.DebugSessionOptions = {
+                noDebug: noDebug,
+            }
+            await vscode.debug.startDebugging(workspaceFolder, debugConfig, debugOptions).then();
         }
+    };
+    context.subscriptions.push(commands.registerCommand('java.run.codelens', async (uri, methodName) => {
+        await runCodelens(uri, methodName, true);
+    }));
+    context.subscriptions.push(commands.registerCommand('java.debug.codelens', async (uri, methodName) => {
+        await runCodelens(uri, methodName, false);
     }));
     return Object.freeze({
         version : API_VERSION
@@ -334,7 +343,7 @@
             if (isOut) {
                 stdOut += text;
             }
-            if (stdOut.match(/org.netbeans.modules.java.lsp.server.*Enabled/)) {
+            if (stdOut.match(/org.netbeans.modules.java.lsp.server/)) {
                 resolve(text);
                 stdOut = null;
             }
diff --git a/java/java.lsp.server/vscode/src/test/suite/extension.test.ts b/java/java.lsp.server/vscode/src/test/suite/extension.test.ts
index a6f4143..2d8053a 100644
--- a/java/java.lsp.server/vscode/src/test/suite/extension.test.ts
+++ b/java/java.lsp.server/vscode/src/test/suite/extension.test.ts
@@ -42,8 +42,28 @@
         let clusters = myExtension.findClusters('non-existent').
             // ignore 'extra' cluster in the extension path, since nbjavac is there during development:
             filter(s => !s.startsWith(extraCluster));
-        assert.strictEqual(clusters.length, 6, 'six required clusters found: ' + clusters);
-        for (let c of clusters) {
+
+
+        let found : string[] = [];
+        function assertCluster(name : string) {
+            for (let c of clusters) {
+                if (c.endsWith('/' + name)) {
+                    found.push(c);
+                    return;
+                }
+            }
+            assert.fail(`Cannot find ${name} among ${clusters}`);
+        }
+
+        assertCluster('extide');
+        assertCluster('ide');
+        assertCluster('java');
+        assertCluster('nbcode');
+        assertCluster('platform');
+        assertCluster('webcommon');
+        assertCluster('harness');
+
+        for (let c of found) {
             assert.ok(c.startsWith(nbcode.extensionPath), `All extensions are below ${nbcode.extensionPath}, but: ${c}`);
         }
     });
diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java b/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java
index edbce4c..657cb7f 100644
--- a/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java
+++ b/java/java.source.base/src/org/netbeans/modules/java/source/save/CasualDiff.java
@@ -1422,7 +1422,7 @@
         // check that it is not enum constant. If so, match it in special way
         if ((oldT.mods.flags & Flags.ENUM) != 0) {
             JCModifiers mods = oldT.getModifiers();
-            int startPos = mods.pos != Position.NOPOS ? getOldPos(mods) : getOldPos(parent);
+            int startPos = mods.pos != Position.NOPOS ? getOldPos(mods) : getOldPos(oldT);
 
             localPointer = diffAnnotationsLists(mods.getAnnotations(), newT.getModifiers().getAnnotations(), startPos, localPointer);
 
diff --git a/java/libs.javacapi/external/binaries-list b/java/libs.javacapi/external/binaries-list
index 3070bde..fcdfdd6 100644
--- a/java/libs.javacapi/external/binaries-list
+++ b/java/libs.javacapi/external/binaries-list
@@ -14,4 +14,4 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-267AFC87A08301145B10D86DA674724B884F010C nb-javac-15-api.jar
\ No newline at end of file
+E83D8755DF07D560A633A45A2340419CD1313E8D com.dukescript.nbjavac:nb-javac:15.0.0.2:api
\ No newline at end of file
diff --git a/java/libs.javacapi/external/nb-javac-15-api-license.txt b/java/libs.javacapi/external/nb-javac-15.0.0.2-api-license.txt
similarity index 99%
rename from java/libs.javacapi/external/nb-javac-15-api-license.txt
rename to java/libs.javacapi/external/nb-javac-15.0.0.2-api-license.txt
index e7f2cfa..f15ab01 100644
--- a/java/libs.javacapi/external/nb-javac-15-api-license.txt
+++ b/java/libs.javacapi/external/nb-javac-15.0.0.2-api-license.txt
@@ -1,6 +1,6 @@
 Name: Javac Compiler API
 Description: Javac Compiler API
-Version: 15
+Version: 15.0.0.2
 License: GPL-2-CP
 Origin: OpenJDK (http://hg.openjdk.java.net/)
 Source: http://hg.netbeans.org/main/nb-java-x/
diff --git a/java/libs.javacapi/nbproject/project.xml b/java/libs.javacapi/nbproject/project.xml
index d4d16d2..6d4c69c 100644
--- a/java/libs.javacapi/nbproject/project.xml
+++ b/java/libs.javacapi/nbproject/project.xml
@@ -40,7 +40,7 @@
             </public-packages>
             <class-path-extension>
                 <runtime-relative-path />
-                <binary-origin>external/nb-javac-15-api.jar</binary-origin>
+                <binary-origin>external/nb-javac-15.0.0.2-api.jar</binary-origin>
             </class-path-extension>
         </data>
     </configuration>
diff --git a/java/libs.javacimpl/external/binaries-list b/java/libs.javacimpl/external/binaries-list
index 025eabf..115ef66 100644
--- a/java/libs.javacimpl/external/binaries-list
+++ b/java/libs.javacimpl/external/binaries-list
@@ -14,4 +14,4 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-E03FFC36A80D76A138C5CC8096DFDD7E7BACEE7E nb-javac-15-impl.jar
\ No newline at end of file
+9A4B6A8063E2EE78FF2F12542AC2C06C11B07F61 com.dukescript.nbjavac:nb-javac:15.0.0.2
\ No newline at end of file
diff --git a/java/libs.javacimpl/external/nb-javac-15-impl-license.txt b/java/libs.javacimpl/external/nb-javac-15.0.0.2-license.txt
similarity index 99%
rename from java/libs.javacimpl/external/nb-javac-15-impl-license.txt
rename to java/libs.javacimpl/external/nb-javac-15.0.0.2-license.txt
index b860944..df8f7fe 100644
--- a/java/libs.javacimpl/external/nb-javac-15-impl-license.txt
+++ b/java/libs.javacimpl/external/nb-javac-15.0.0.2-license.txt
@@ -1,6 +1,6 @@
 Name: Javac Compiler Implementation
 Description: Javac Compiler Implementation
-Version: 15
+Version: 15.0.0.2
 License: GPL-2-CP
 Origin: OpenJDK (http://hg.openjdk.java.net/)
 Source: http://hg.netbeans.org/main/nb-java-x/
diff --git a/java/libs.javacimpl/nbproject/project.xml b/java/libs.javacimpl/nbproject/project.xml
index 54b76d5..90d4da4 100644
--- a/java/libs.javacimpl/nbproject/project.xml
+++ b/java/libs.javacimpl/nbproject/project.xml
@@ -37,7 +37,7 @@
             <public-packages/>
             <class-path-extension>
                 <runtime-relative-path />
-                <binary-origin>external/nb-javac-15-impl.jar</binary-origin>
+                <binary-origin>external/nb-javac-15.0.0.2.jar</binary-origin>
             </class-path-extension>
         </data>
     </configuration>
diff --git a/nb/ide.branding/o.n.core/src/org/netbeans/core/Bundle_nb.properties b/nb/ide.branding/o.n.core/src/org/netbeans/core/Bundle_nb.properties
index e2e2b1c..bccab0c 100644
--- a/nb/ide.branding/o.n.core/src/org/netbeans/core/Bundle_nb.properties
+++ b/nb/ide.branding/o.n.core/src/org/netbeans/core/Bundle_nb.properties
@@ -19,7 +19,7 @@
 # {1} - path to system folder
 NTF_ExceptionalException=\
         A {0} exception has occurred.\n\
-	Please report this at https://issues.apache.org/jira/projects/NETBEANS/issues,\n\
+	Please report this at https://netbeans.apache.org/nb/report-issue,\n\
 	including a copy of your messages.log file as an attachment.\n\
 	The messages.log file is located in your {1} folder.
 
diff --git a/nb/ide.launcher/netbeans.conf b/nb/ide.launcher/netbeans.conf
index e9e30e3..413b064 100644
--- a/nb/ide.launcher/netbeans.conf
+++ b/nb/ide.launcher/netbeans.conf
@@ -62,7 +62,8 @@
 # default command line arguments.
 # (see: https://issues.apache.org/jira/browse/NETBEANS-1344)
 #
-netbeans_default_options="-J-XX:+UseStringDeduplication -J-Xss2m @@metabuild.logcli@@ -J-Djdk.gtk.version=2.2 -J-Dapple.laf.useScreenMenuBar=true -J-Dapple.awt.graphics.UseQuartz=true -J-Dsun.java2d.noddraw=true -J-Dsun.java2d.dpiaware=true -J-Dsun.zip.disableMemoryMapping=true -J-Dplugin.manager.check.updates=false -J-Dnetbeans.extbrowser.manual_chrome_plugin_install=yes -J--add-opens=java.base/java.net=ALL-UNNAMED -J--add-opens=java.base/java.lang.ref=ALL-UNNAMED -J--add-opens=java.base/java.lang=ALL-UNNAMED -J--add-opens=java.base/java.security=ALL-UNNAMED -J--add-opens=java.base/java.util=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing.plaf.basic=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing.text=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing=ALL-UNNAMED -J--add-opens=java.desktop/java.awt=ALL-UNNAMED -J--add-opens=java.desktop/java.awt.event=ALL-UNNAMED -J--add-opens=java.prefs/java.util.prefs=ALL-UNNAMED -J--add-opens=jdk.jshell/jdk.jshell=ALL-UNNAMED -J--add-modules=jdk.jshell -J--add-exports=java.desktop/sun.awt=ALL-UNNAMED -J--add-exports=java.desktop/java.awt.peer=ALL-UNNAMED -J--add-exports=java.desktop/com.sun.beans.editors=ALL-UNNAMED -J--add-exports=java.desktop/sun.swing=ALL-UNNAMED -J--add-exports=java.desktop/sun.awt.im=ALL-UNNAMED -J--add-exports=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED -J--add-exports=java.management/sun.management=ALL-UNNAMED -J--add-exports=java.base/sun.reflect.annotation=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED  -J--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED -J-XX:+IgnoreUnrecognizedVMOptions"
+
+netbeans_default_options="-J-XX:+UseStringDeduplication -J-Xss2m @@metabuild.logcli@@ -J-Djdk.gtk.version=2.2 -J-Dapple.laf.useScreenMenuBar=true -J-Dapple.awt.graphics.UseQuartz=true -J-Dsun.java2d.noddraw=true -J-Dsun.java2d.dpiaware=true -J-Dsun.zip.disableMemoryMapping=true -J-Dplugin.manager.check.updates=false -J-Dnetbeans.extbrowser.manual_chrome_plugin_install=yes -J--add-opens=java.base/java.net=ALL-UNNAMED -J--add-opens=java.base/java.lang.ref=ALL-UNNAMED -J--add-opens=java.base/java.lang=ALL-UNNAMED -J--add-opens=java.base/java.security=ALL-UNNAMED -J--add-opens=java.base/java.util=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing.plaf.basic=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing.text=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing=ALL-UNNAMED -J--add-opens=java.desktop/java.awt=ALL-UNNAMED -J--add-opens=java.desktop/java.awt.event=ALL-UNNAMED -J--add-opens=java.prefs/java.util.prefs=ALL-UNNAMED -J--add-opens=jdk.jshell/jdk.jshell=ALL-UNNAMED -J--add-modules=jdk.jshell -J--add-exports=java.desktop/sun.awt=ALL-UNNAMED -J--add-exports=java.desktop/java.awt.peer=ALL-UNNAMED -J--add-exports=java.desktop/com.sun.beans.editors=ALL-UNNAMED -J--add-exports=java.desktop/sun.swing=ALL-UNNAMED -J--add-exports=java.desktop/sun.awt.im=ALL-UNNAMED -J--add-exports=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED -J--add-exports=java.management/sun.management=ALL-UNNAMED -J--add-exports=java.base/sun.reflect.annotation=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED  -J--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED -J--add-exports=jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED -J--add-exports=jdk.jdeps/com.sun.tools.javap=ALL-UNNAMED -J-XX:+IgnoreUnrecognizedVMOptions"
 
 # Default location of JDK:
 # (set by installer or commented out if launcher should decide)
diff --git a/nb/updatecenters/extras/nbjavac.api/manifest.mf b/nb/updatecenters/extras/nbjavac.api/manifest.mf
index fafb1a0..a159562 100644
--- a/nb/updatecenters/extras/nbjavac.api/manifest.mf
+++ b/nb/updatecenters/extras/nbjavac.api/manifest.mf
@@ -2,6 +2,6 @@
 AutoUpdate-Show-In-Client: false
 OpenIDE-Module: org.netbeans.modules.nbjavac.api
 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/nbjavac/api/Bundle.properties
-OpenIDE-Module-Specification-Version: 2.3
+OpenIDE-Module-Specification-Version: 2.4
 OpenIDE-Module-Hide-Classpath-Packages: com.sun.javadoc.**, com.sun.source.**, javax.annotation.processing.**, javax.lang.model.**, javax.tools.**, com.sun.tools.javac.**
 OpenIDE-Module-Fragment-Host: org.netbeans.libs.javacapi
diff --git a/nb/updatecenters/extras/nbjavac.api/nbproject/project.xml b/nb/updatecenters/extras/nbjavac.api/nbproject/project.xml
index a1dc9a8..ecac547 100644
--- a/nb/updatecenters/extras/nbjavac.api/nbproject/project.xml
+++ b/nb/updatecenters/extras/nbjavac.api/nbproject/project.xml
@@ -28,8 +28,8 @@
             <module-dependencies/>
             <public-packages/>
             <class-path-extension>
-                <runtime-relative-path>ext/nb-javac-15-api.jar</runtime-relative-path>
-                <binary-origin>release/modules/ext/nb-javac-15-api.jar</binary-origin>
+                <runtime-relative-path>ext/nb-javac-15.0.0.2-api.jar</runtime-relative-path>
+                <binary-origin>release/modules/ext/nb-javac-15.0.0.2-api.jar</binary-origin>
             </class-path-extension>
         </data>
     </configuration>
diff --git a/nb/updatecenters/extras/nbjavac.api/release/modules/ext/nb-javac-15-api.jar.external b/nb/updatecenters/extras/nbjavac.api/release/modules/ext/nb-javac-15-api.jar.external
deleted file mode 100644
index 2f2ff3b..0000000
--- a/nb/updatecenters/extras/nbjavac.api/release/modules/ext/nb-javac-15-api.jar.external
+++ /dev/null
@@ -1,6 +0,0 @@
-CRC:2157920864
-SIZE:252431
-URL:https://netbeans.osuosl.org/binaries/267AFC87A08301145B10D86DA674724B884F010C-nb-javac-15-api.jar
-URL:https://hg.netbeans.org/binaries/267AFC87A08301145B10D86DA674724B884F010C-nb-javac-15-api.jar
-MessageDigest: SHA-256 0a5e9b6afbdb86deb3286f37e1dee230c91f39438e55dc77910c9a48f38a2ffb
-MessageDigest: SHA-512 5b16a0c6466dc14cf2d428d4a84398f9de2d1782acf445c8da5ca874f807ac550db8b551ec41495963a29c2f400ca24ee8a70b1d589d0cdf2f05af5cb0f4ff56
\ No newline at end of file
diff --git a/nb/updatecenters/extras/nbjavac.api/release/modules/ext/nb-javac-15.0.0.2-api.jar.external b/nb/updatecenters/extras/nbjavac.api/release/modules/ext/nb-javac-15.0.0.2-api.jar.external
new file mode 100644
index 0000000..0abbc18
--- /dev/null
+++ b/nb/updatecenters/extras/nbjavac.api/release/modules/ext/nb-javac-15.0.0.2-api.jar.external
@@ -0,0 +1,5 @@
+CRC:3736270701
+SIZE:210532
+URL:m2:/com.dukescript.nbjavac:nb-javac:15.0.0.2:jar:api
+MessageDigest: SHA-256 20dae9df239aa1d346c56b744aee741f753611e7470640ff1ff7b1731283ed1b
+MessageDigest: SHA-512 e12e603815159cbb348d8d3e73588d8ad549b41cac21831fa1228c0ab9bf23ce18d162b6fe7679de9d249fc2cb3a627edd35ebf2f3851dfd6d2513e1da741447
\ No newline at end of file
diff --git a/nb/updatecenters/extras/nbjavac.impl/manifest.mf b/nb/updatecenters/extras/nbjavac.impl/manifest.mf
index 0a37a20..494638e 100644
--- a/nb/updatecenters/extras/nbjavac.impl/manifest.mf
+++ b/nb/updatecenters/extras/nbjavac.impl/manifest.mf
@@ -2,7 +2,7 @@
 AutoUpdate-Show-In-Client: false
 OpenIDE-Module: org.netbeans.modules.nbjavac.impl
 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/nbjavac/impl/Bundle.properties
-OpenIDE-Module-Specification-Version: 2.3
+OpenIDE-Module-Specification-Version: 2.4
 OpenIDE-Module-Hide-Classpath-Packages: com.sun.tools.javac.**, com.sun.tools.javadoc.**, com.sun.tools.javap.**, com.sun.tools.classfile.**, com.sun.tools.doclint.**
 OpenIDE-Module-Fragment-Host: org.netbeans.libs.javacimpl
 OpenIDE-Module-Provides: org.netbeans.modules.nbjavac
diff --git a/nb/updatecenters/extras/nbjavac.impl/nbproject/project.xml b/nb/updatecenters/extras/nbjavac.impl/nbproject/project.xml
index 5784e85..d933acf 100644
--- a/nb/updatecenters/extras/nbjavac.impl/nbproject/project.xml
+++ b/nb/updatecenters/extras/nbjavac.impl/nbproject/project.xml
@@ -35,8 +35,8 @@
             </module-dependencies>
             <public-packages/>
             <class-path-extension>
-                <runtime-relative-path>ext/nb-javac-15-impl.jar</runtime-relative-path>
-                <binary-origin>release/modules/ext/nb-javac-15-impl.jar</binary-origin>
+                <runtime-relative-path>ext/nb-javac-15.0.0.2-impl.jar</runtime-relative-path>
+                <binary-origin>release/modules/ext/nb-javac-15.0.0.2-impl.jar</binary-origin>
             </class-path-extension>
         </data>
     </configuration>
diff --git a/nb/updatecenters/extras/nbjavac.impl/release/modules/ext/nb-javac-15-impl.jar.external b/nb/updatecenters/extras/nbjavac.impl/release/modules/ext/nb-javac-15-impl.jar.external
deleted file mode 100644
index fdfef79..0000000
--- a/nb/updatecenters/extras/nbjavac.impl/release/modules/ext/nb-javac-15-impl.jar.external
+++ /dev/null
@@ -1,6 +0,0 @@
-CRC:2366439669
-SIZE:3743735
-URL:https://netbeans.osuosl.org/binaries/E03FFC36A80D76A138C5CC8096DFDD7E7BACEE7E-nb-javac-15-impl.jar
-URL:https://hg.netbeans.org/binaries/E03FFC36A80D76A138C5CC8096DFDD7E7BACEE7E-nb-javac-15-impl.jar
-MessageDigest: SHA-256 c9caa104c663166fd8c1b127861b4f196674044b27494d86674b9cf399040c38
-MessageDigest: SHA-512 83b219a3c1c02adc25cdc146a33ef3c431bd5b5e3816f1dc9367f8997eba90509c87c560dda0276f78363ba81f1a8f8dcca201c60946288ca8f9d67ad9010724
\ No newline at end of file
diff --git a/nb/updatecenters/extras/nbjavac.impl/release/modules/ext/nb-javac-15.0.0.2-impl.jar.external b/nb/updatecenters/extras/nbjavac.impl/release/modules/ext/nb-javac-15.0.0.2-impl.jar.external
new file mode 100644
index 0000000..4e44592
--- /dev/null
+++ b/nb/updatecenters/extras/nbjavac.impl/release/modules/ext/nb-javac-15.0.0.2-impl.jar.external
@@ -0,0 +1,5 @@
+CRC:1851126890
+SIZE:3511612
+URL: m2:/com.dukescript.nbjavac:nb-javac:15.0.0.2:jar
+MessageDigest: SHA-256 809b68535b8d5e564802deba7489308f01041acaf0731584544ffd96c6d385c1
+MessageDigest: SHA-512 e450cf9da202dee89ef79bff65fab1a287bd97d08ecc2ea19fbeedd8a16ce79371fbc0a72c68d353d8d13cae18e015ad862b28962cd2f6e43874f52767e99de7
\ No newline at end of file
diff --git a/nb/updatecenters/licenseinfo.xml b/nb/updatecenters/licenseinfo.xml
index bf1b93a..12893ee 100644
--- a/nb/updatecenters/licenseinfo.xml
+++ b/nb/updatecenters/licenseinfo.xml
@@ -26,8 +26,8 @@
         <comment type="COMMENT_UNSUPPORTED" />
     </fileset>
     <fileset>
-        <file>extras/nbjavac.api/release/modules/ext/nb-javac-15-api.jar.external</file>
-        <file>extras/nbjavac.impl/release/modules/ext/nb-javac-15-impl.jar.external</file>
+        <file>extras/nbjavac.api/release/modules/ext/nb-javac-15.0.0.2-api.jar.external</file>
+        <file>extras/nbjavac.impl/release/modules/ext/nb-javac-15.0.0.2-impl.jar.external</file>
         <license ref="Apache-2.0-ASF" />
         <comment type="COMMENT_UNSUPPORTED" />
     </fileset>
diff --git a/nbbuild/notice-stub.txt b/nbbuild/notice-stub.txt
index e6c1723..e0ce5df 100644
--- a/nbbuild/notice-stub.txt
+++ b/nbbuild/notice-stub.txt
@@ -1,5 +1,5 @@
 Apache NetBeans
-Copyright 2017-2020 The Apache Software Foundation
+Copyright 2017-2021 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/nbbuild/templates/projectized.xml b/nbbuild/templates/projectized.xml
index 867d9ca..7e30eb8 100644
--- a/nbbuild/templates/projectized.xml
+++ b/nbbuild/templates/projectized.xml
@@ -177,7 +177,7 @@
         <property name="locmakenbm.brands" value="${brandings}"/>
         <!-- When requires.nb.javac property is true, prepend javac-api and javac-impl on bootclasspath to allow override the default annotation
              processing API located in rt.jar. -->
-        <property name="bootclasspath.prepend.nb" value="${nb_all}/java/libs.javacapi/external/nb-javac-15-api.jar${path.separator}${nb_all}/java/libs.javacimpl/external/nb-javac-15-impl.jar" />
+        <property name="bootclasspath.prepend.nb" value="${nb_all}/java/libs.javacapi/external/nb-javac-15.0.0.2-api.jar${path.separator}${nb_all}/java/libs.javacimpl/external/nb-javac-15.0.0.2.jar" />
         <property name="bootclasspath.prepend.vanilla" value="${nb_all}/nbbuild/external/vanilla-javac-api.jar${path.separator}${nb_all}/nbbuild/external/vanilla-javac-impl.jar" />
         <condition property="bootclasspath.prepend" value="${bootclasspath.prepend.nb}">
             <istrue value="${requires.nb.javac.impl}"/>
diff --git a/platform/libs.flatlaf/external/binaries-list b/platform/libs.flatlaf/external/binaries-list
index cf45445..cb336c4 100644
--- a/platform/libs.flatlaf/external/binaries-list
+++ b/platform/libs.flatlaf/external/binaries-list
@@ -15,4 +15,4 @@
 # specific language governing permissions and limitations
 # under the License.
 
-5507827B39B40EED2942652D4792A51A5C49D67C com.formdev:flatlaf:1.0-rc2
+A807C984F00B683C65503803720821F12E136E93 com.formdev:flatlaf:1.0
diff --git a/platform/libs.flatlaf/external/flatlaf-1.0-rc2-license.txt b/platform/libs.flatlaf/external/flatlaf-1.0-license.txt
similarity index 99%
rename from platform/libs.flatlaf/external/flatlaf-1.0-rc2-license.txt
rename to platform/libs.flatlaf/external/flatlaf-1.0-license.txt
index 1e438d5..c2b9305 100644
--- a/platform/libs.flatlaf/external/flatlaf-1.0-rc2-license.txt
+++ b/platform/libs.flatlaf/external/flatlaf-1.0-license.txt
@@ -1,7 +1,7 @@
 Name: FlatLaf Look and Feel
 Description: FlatLaf Look and Feel
-Version: 1.0-rc2
-Files: flatlaf-1.0-rc2.jar
+Version: 1.0
+Files: flatlaf-1.0.jar
 License: Apache-2.0
 Origin: FormDev Software GmbH.
 URL: https://www.formdev.com/flatlaf/
diff --git a/platform/libs.flatlaf/nbproject/org-netbeans-libs-flatlaf.sig b/platform/libs.flatlaf/nbproject/org-netbeans-libs-flatlaf.sig
index e766572..eb1cf4e 100644
--- a/platform/libs.flatlaf/nbproject/org-netbeans-libs-flatlaf.sig
+++ b/platform/libs.flatlaf/nbproject/org-netbeans-libs-flatlaf.sig
@@ -312,6 +312,7 @@
 cons public init(float)
 fld public final float amount
 intf com.formdev.flatlaf.util.ColorFunctions$ColorFunction
+meth public java.lang.String toString()
 meth public void apply(float[])
 supr java.lang.Object
 
@@ -325,6 +326,7 @@
 fld public final int hslIndex
 intf com.formdev.flatlaf.util.ColorFunctions$ColorFunction
 meth protected boolean shouldInverse(float[])
+meth public java.lang.String toString()
 meth public void apply(float[])
 supr java.lang.Object
 
@@ -344,6 +346,7 @@
 cons public !varargs init(java.awt.Color,com.formdev.flatlaf.util.ColorFunctions$ColorFunction[])
 meth public com.formdev.flatlaf.util.ColorFunctions$ColorFunction[] getFunctions()
 meth public java.awt.Color derive(java.awt.Color)
+meth public java.lang.String toString()
 supr javax.swing.plaf.ColorUIResource
 hfds baseOfDefaultColorRGB,functions,hasBaseOfDefaultColor
 
diff --git a/platform/libs.flatlaf/nbproject/project.properties b/platform/libs.flatlaf/nbproject/project.properties
index 7f6ea54..f0135fe 100644
--- a/platform/libs.flatlaf/nbproject/project.properties
+++ b/platform/libs.flatlaf/nbproject/project.properties
@@ -20,4 +20,4 @@
 javac.source=1.8
 nbm.target.cluster=platform
 
-release.external/flatlaf-1.0-rc2.jar=modules/ext/flatlaf-1.0-rc2.jar
+release.external/flatlaf-1.0.jar=modules/ext/flatlaf-1.0.jar
diff --git a/platform/libs.flatlaf/nbproject/project.xml b/platform/libs.flatlaf/nbproject/project.xml
index 6270740..88ba2c3 100644
--- a/platform/libs.flatlaf/nbproject/project.xml
+++ b/platform/libs.flatlaf/nbproject/project.xml
@@ -30,8 +30,8 @@
                 <package>com.formdev.flatlaf.util</package>
             </public-packages>
             <class-path-extension>
-                <runtime-relative-path>ext/flatlaf-1.0-rc2.jar</runtime-relative-path>
-                <binary-origin>external/flatlaf-1.0-rc2.jar</binary-origin>
+                <runtime-relative-path>ext/flatlaf-1.0.jar</runtime-relative-path>
+                <binary-origin>external/flatlaf-1.0.jar</binary-origin>
             </class-path-extension>
         </data>
     </configuration>
diff --git a/platform/o.n.core/src/org/netbeans/core/ui/Bundle.properties b/platform/o.n.core/src/org/netbeans/core/ui/Bundle.properties
index 3fc1a97..b26a302 100644
--- a/platform/o.n.core/src/org/netbeans/core/ui/Bundle.properties
+++ b/platform/o.n.core/src/org/netbeans/core/ui/Bundle.properties
@@ -18,7 +18,7 @@
 # Product Information panel
 LBL_Copyright=<div style="font-size: {0}pt; font-family: Verdana, 'Verdana CE',  Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif;">\
     NetBeans IDE and NetBeans Platform are based on Apache NetBeans from the Apache Software Foundation \
-    and is licensed under <a href="https://www.apache.org/licenses/LICENSE-2.0">\
+    and are licensed under <a href="https://www.apache.org/licenses/LICENSE-2.0">\
     Apache License Version 2.0</a>. For more information, please visit \
     <a href="https://netbeans.apache.org/">netbeans.apache.org</a>.</div>
 LBL_AddOnCopyright=<div style="font-size: {1}pt; font-family: Verdana, 'Verdana CE',  Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif;">\