Skip to content

Commit d95ead0

Browse files
committed
add possibility to configure dap in cfconfig
1 parent 21357a2 commit d95ead0

File tree

13 files changed

+105
-74
lines changed

13 files changed

+105
-74
lines changed

core/src/main/java/lucee/runtime/ComponentImpl.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,7 @@ public final class ComponentImpl extends StructSupport implements Externalizable
179179
/**
180180
* Constructor of the Component, USED ONLY FOR DESERIALIZE
181181
*/
182-
public ComponentImpl() {
183-
}
182+
public ComponentImpl() {}
184183

185184
/**
186185
* constructor of the class
@@ -748,7 +747,8 @@ else if (_namedArgs != null) {
748747
return Reflector.componentToClass(pc, this).getClass();
749748
}
750749

751-
// When calling via super, use public access for error message since super calls should access inherited methods
750+
// When calling via super, use public access for error message since super calls should access
751+
// inherited methods
752752
int errorAccess = superAccess ? ACCESS_PUBLIC : access;
753753
if (member == null) throw ComponentUtil.notFunction(this, KeyImpl.init(name), null, errorAccess);
754754
throw ComponentUtil.notFunction(this, KeyImpl.init(name), member.getValue(), errorAccess);
@@ -978,21 +978,21 @@ private Collection.Key[] keysPreservingOrder(int access) {
978978
if (_udfs.isEmpty() && _data.isEmpty()) {
979979
return new Collection.Key[0];
980980
}
981-
981+
982982
List<Key> orderedKeys = new ArrayList<Key>(_udfs.size() + _data.size());
983-
984-
for (Entry<Key, UDF> entry : _udfs.entrySet()) {
983+
984+
for (Entry<Key, UDF> entry: _udfs.entrySet()) {
985985
if (entry.getValue().getAccess() <= access) {
986986
orderedKeys.add(entry.getKey());
987987
}
988988
}
989-
for (Entry<Key, Member> entry : _data.entrySet()) {
989+
for (Entry<Key, Member> entry: _data.entrySet()) {
990990
Member member = entry.getValue();
991991
if (member.getAccess() <= access && !(member instanceof UDF)) {
992992
orderedKeys.add(entry.getKey());
993993
}
994994
}
995-
995+
996996
return orderedKeys.toArray(new Collection.Key[orderedKeys.size()]);
997997
}
998998

@@ -1182,8 +1182,7 @@ public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties
11821182
try {
11831183
return DumpUtil.toDumpData(_call(pageContext, KeyConstants.__toDumpData, udf, null, new Object[0]), pageContext, maxlevel, dp);
11841184
}
1185-
catch (PageException e) {
1186-
}
1185+
catch (PageException e) {}
11871186
}
11881187
}
11891188
}
@@ -1758,7 +1757,7 @@ protected static Struct getMetaData(int access, PageContext pc, ComponentImpl co
17581757

17591758
boolean supressWSBeforeArg = pc.getConfig().getSuppressWSBeforeArg();
17601759

1761-
Class<?> skeleton = comp.getJavaAccessClass(pc, new RefBooleanImpl(false), ((ConfigPro) pc.getConfig()).getExecutionLogEnabled(), false, false, supressWSBeforeArg);
1760+
Class<?> skeleton = comp.getJavaAccessClass(pc, new RefBooleanImpl(false), ((PageContextImpl) pc).getExecutionLogEnabled(), false, false, supressWSBeforeArg);
17621761
if (skeleton != null) sct.set(KeyConstants._skeleton, skeleton);
17631762

17641763
if (comp.properties.subName == null) {

core/src/main/java/lucee/runtime/PageContextImpl.java

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@
9292
import lucee.runtime.component.ComponentLoader;
9393
import lucee.runtime.config.Config;
9494
import lucee.runtime.config.ConfigPro;
95-
import lucee.runtime.config.ConfigServerImpl;
9695
import lucee.runtime.config.ConfigUtil;
9796
import lucee.runtime.config.ConfigWeb;
9897
import lucee.runtime.config.ConfigWebPro;
@@ -359,6 +358,7 @@ public final class PageContextImpl extends PageContext {
359358
private boolean gatewayContext;
360359
private boolean listenerContext;
361360
private Password serverPassword;
361+
private LinkedList<DebuggerFrame> debuggerFrames;
362362

363363
private PageException pe;
364364
// private Throwable requestTimeoutException;
@@ -438,6 +438,12 @@ public void setTimeoutStackTrace() {
438438
this.timeoutStacktrace = thread.getStackTrace();
439439
}
440440

441+
public boolean getExecutionLogEnabled() {
442+
// we use this because we do not wanna change our mind in mid request when the underlaying config
443+
// setting may change.
444+
return debuggerFrames != null;
445+
}
446+
441447
@Override
442448
public void initialize(Servlet servlet, ServletRequest req, ServletResponse rsp, String errorPageURL, boolean needsSession, int bufferSize, boolean autoFlush)
443449
throws IOException, IllegalStateException, IllegalArgumentException {
@@ -463,6 +469,7 @@ public PageContextImpl initialize(HttpServlet servlet, HttpServletRequest req, H
463469
caller = null;
464470
callerTemplate = null;
465471
root = null;
472+
debuggerFrames = config.getExecutionLogEnabled() ? new LinkedList<DebuggerFrame>() : null;
466473

467474
boolean clone = tmplPC != null;
468475
requestId = counter++;
@@ -572,7 +579,7 @@ else if (variables == null) {
572579
_psq = null;
573580
}
574581
fdEnabled = !config.allowRequestTimeout();
575-
if (config.getExecutionLogEnabled()) this.execLog = config.getExecutionLogFactory().getInstance(this);
582+
if (debuggerFrames != null) this.execLog = config.getExecutionLogFactory().getInstance(this);
576583
if (debugger != null) debugger.init(config);
577584
if (clone) {
578585
((UndefinedImpl) undefined).initialize(this, tmplPC.getScopeCascadingType(), tmplPC.hasDebugOptions(ConfigPro.DEBUG_IMPLICIT_ACCESS));
@@ -631,10 +638,12 @@ else if (variables == null) {
631638
@Override
632639
public void release() {
633640
config.releaseCacheHandlers(this);
634-
635-
if (config.getExecutionLogEnabled() && execLog != null) {
636-
execLog.release();
637-
execLog = null;
641+
if (debuggerFrames != null) {
642+
debuggerFrames = null;
643+
if (execLog != null) {
644+
execLog.release();
645+
execLog = null;
646+
}
638647
}
639648

640649
if (PageContextUtil.debug(this)) {
@@ -3427,7 +3436,7 @@ public void _setCatch(PageException pe, String name, boolean caught, boolean sto
34273436
FDSignal.signal(pe, caught);
34283437
}
34293438
// External debugger (luceedebug) - frames are still intact at this point
3430-
if (ConfigServerImpl.DEBUGGER) {
3439+
if (debuggerFrames != null) {
34313440
DebuggerListener listener = DebuggerRegistry.getListener();
34323441
if (listener != null && listener.isClientConnected() && listener.onException(this, pe, caught)) {
34333442
// Get file/line from exception for debugger display
@@ -3553,8 +3562,6 @@ public String getFile() {
35533562
}
35543563
}
35553564

3556-
private final LinkedList<DebuggerFrame> debuggerFrames = ConfigServerImpl.DEBUGGER ? new LinkedList<DebuggerFrame>() : null;
3557-
35583565
/**
35593566
* Push a new debugger frame onto the stack. Called on UDF entry when DEBUGGER is enabled.
35603567
*/
@@ -3623,7 +3630,7 @@ public DebuggerFrame getTopmostDebuggerFrame() {
36233630
* @param label Optional label to identify the breakpoint in debugger UI
36243631
*/
36253632
public void debuggerSuspend(String label) {
3626-
if (!ConfigServerImpl.DEBUGGER) return;
3633+
if (debuggerFrames == null) return;
36273634

36283635
// Get current file/line for listener callback
36293636
DebuggerFrame frame = getTopmostDebuggerFrame();
@@ -3662,7 +3669,7 @@ public void debuggerSuspend(String label) {
36623669
* @param label Optional label to identify the breakpoint in debugger UI
36633670
*/
36643671
public void debuggerSuspend(String file, int line, String label) {
3665-
if (!ConfigServerImpl.DEBUGGER) return;
3672+
if (debuggerFrames == null) return;
36663673
debuggerSuspendImpl(file, line, label);
36673674
}
36683675

core/src/main/java/lucee/runtime/config/ConfigFactoryImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ public static ExecutionLogFactory loadExeLog(ConfigServerImpl config, Struct roo
837837
Map<String, String> args = null;
838838

839839
// If debugger breakpoint support enabled and no explicit class configured, use DebuggerExecutionLog
840-
if (StringUtil.isEmpty(strClass) && ConfigServerImpl.DEBUGGER) {
840+
if (StringUtil.isEmpty(strClass) && config.getExecutionLogEnabled()) {
841841
LogUtil.log(config, Log.LEVEL_INFO, "application", "Debugger breakpoint support enabled");
842842
clazz = DebuggerExecutionLog.class;
843843
args = new HashMap<String, String>();

core/src/main/java/lucee/runtime/config/ConfigPro.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,4 +425,8 @@ public Resource[] getResources(PageContext pc, Mapping[] mappings, String realPa
425425
public Repository[] getMavenRepository();
426426

427427
public Repository[] getMavenSnapshotRepository();
428+
429+
public String getDapSecret();
430+
431+
public boolean getDapBreakpoint();
428432
}

core/src/main/java/lucee/runtime/config/ConfigServerImpl.java

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -245,29 +245,6 @@ public final class ConfigServerImpl implements ConfigServer, ConfigPro {
245245
public static final ClassDefinition<DummyORMEngine> DEFAULT_ORM_ENGINE = new ClassDefinitionImpl<DummyORMEngine>(DummyORMEngine.class);
246246
private static final long FIVE_SECONDS = 5000;
247247

248-
// DAP secret - required to register a debugger listener. If not set, DAP debugger is disabled.
249-
public static final String DEBUGGER_SECRET;
250-
// DAP enabled if secret is set (non-empty) - enables listener registration and console capture
251-
public static final boolean DEBUGGER_ENABLED;
252-
// DAP debugger active - controls bytecode instrumentation for stepping/breakpoints (default true
253-
// when secret set)
254-
public static final boolean DEBUGGER;
255-
static {
256-
String secret = SystemUtil.getSystemPropOrEnvVar("lucee.dap.secret", null);
257-
if (secret != null && !secret.trim().isEmpty()) {
258-
DEBUGGER_SECRET = secret.trim();
259-
DEBUGGER_ENABLED = true;
260-
// Breakpoint support defaults to true, can be disabled for console-only mode
261-
DEBUGGER = Caster.toBooleanValue(SystemUtil.getSystemPropOrEnvVar("lucee.dap.breakpoint", null), true);
262-
263-
}
264-
else {
265-
DEBUGGER_SECRET = null;
266-
DEBUGGER_ENABLED = false;
267-
DEBUGGER = false;
268-
}
269-
}
270-
271248
public static Config instance;
272249

273250
//////////////////////////
@@ -882,8 +859,17 @@ public final class ConfigServerImpl implements ConfigServer, ConfigPro {
882859
.defaultValue(true).description("check the types defined with function arguments and return type");
883860
private Boolean typeChecking;
884861

885-
private static Prop<Boolean> metaExecutionLogEnabled = Prop.bool().keys("enabled").parent("executionLog").defaultValue(false);
886-
private Boolean executionLogEnabled;
862+
private static Prop<String> metaDapSecret = Prop.str().keys("secret").parent("dap").systemPropEnvVar("lucee.dap.secret")
863+
.description("Security token used to authenticate the connection between the IDE and Lucee's Debug Adapter Protocol (DAP) server. "
864+
+ "This ensures that only authorized clients can attach to the process for step debugging,access variable scopes, or trigger programmatic breakpoints.");
865+
private String dapSecret;
866+
private boolean initDapSecret = true;
867+
868+
private static Prop<Boolean> metaDapBreakpoint = Prop.bool().keys("breakpoint").parent("dap").systemPropEnvVar("lucee.dap.breakpoint").defaultValue(false)
869+
.description("Enables zero-overhead instrumentation for step debugging and breakpoints. When enabled, Lucee leverages its internal execution hooks to monitor for "
870+
+ "registered breakpoints and the programmatic breakpoint() BIF. " + "Unlike traditional JDWP debugging, this event-driven approach incurs "
871+
+ "virtually no performance penalty when no breakpoints are hit, " + "eliminating the need for slow bytecode rewriting.");
872+
private Boolean dapBreakpoint;
887873

888874
private static ImportDefintion DEFAULT_IMPORT_DEFINITION = new ImportDefintionImpl(Constants.DEFAULT_PACKAGE, "*");
889875
private static Prop<String> metaComponentDefaultImport = Prop.str().keys("componentAutoImport", "componentDefaultImport").defaultValue(DEFAULT_IMPORT_DEFINITION.toString())
@@ -6438,31 +6424,57 @@ public ConfigServerImpl resetCacheAll() {
64386424
}
64396425

64406426
@Override
6441-
public boolean getExecutionLogEnabled() {
6427+
public String getDapSecret() {
6428+
if (initDapSecret) {
6429+
synchronized (SystemUtil.createToken("config", "dapSecret")) {
6430+
if (initDapSecret) {
6431+
dapSecret = metaDapSecret.get(this, root);
6432+
}
6433+
}
6434+
}
6435+
return dapSecret;
6436+
}
64426437

6443-
if (DEBUGGER) return true;
6438+
public ConfigServerImpl resetDapSecret() {
6439+
if (!initDapSecret) {
6440+
synchronized (SystemUtil.createToken("config", "dapSecret")) {
6441+
if (!initDapSecret) {
6442+
dapSecret = null;
6443+
}
6444+
}
6445+
}
6446+
return this;
6447+
}
64446448

6445-
if (executionLogEnabled == null) {
6446-
synchronized (SystemUtil.createToken("config", "getExecutionLogEnabled")) {
6447-
if (executionLogEnabled == null) {
6448-
executionLogEnabled = metaExecutionLogEnabled.get(this, root);
6449+
@Override
6450+
public boolean getDapBreakpoint() {
6451+
if (dapBreakpoint == null) {
6452+
synchronized (SystemUtil.createToken("config", "dapBreakpoint")) {
6453+
if (dapBreakpoint == null) {
6454+
dapBreakpoint = metaDapBreakpoint.get(this, root);
64496455
}
64506456
}
64516457
}
6452-
return executionLogEnabled;
6458+
return dapBreakpoint;
64536459
}
64546460

6455-
public ConfigServerImpl resetExecutionLogEnabled() {
6456-
if (executionLogEnabled != null) {
6457-
synchronized (SystemUtil.createToken("config", "getExecutionLogEnabled")) {
6458-
if (executionLogEnabled != null) {
6459-
executionLogEnabled = null;
6461+
public ConfigServerImpl resetDapBreakpoint() {
6462+
if (dapBreakpoint != null) {
6463+
synchronized (SystemUtil.createToken("config", "dapBreakpoint")) {
6464+
if (dapBreakpoint != null) {
6465+
dapBreakpoint = null;
64606466
}
64616467
}
64626468
}
64636469
return this;
64646470
}
64656471

6472+
@Override
6473+
@Deprecated
6474+
public boolean getExecutionLogEnabled() {
6475+
return getDapBreakpoint();
6476+
}
6477+
64666478
@Override
64676479
public ExecutionLogFactory getExecutionLogFactory() {
64686480
if (executionLogFactory == null) {
@@ -8518,7 +8530,7 @@ public void resetAll(ResetFilter filter) throws IOException {
85188530

85198531
List<Method> methods = Reflector.getMethods(this.getClass());
85208532
if (filter == null) {
8521-
LogUtil.log(Log.LEVEL_DEBUG, "config", "rest all");
8533+
LogUtil.log(Log.LEVEL_DEBUG, "config", "reset all");
85228534

85238535
for (Method method: methods) {
85248536
if (!method.getName().startsWith("reset") || method.getName().equals("reset") || method.getName().equals("resetAll") || method.getArgumentCount() != 0) continue;
@@ -8527,7 +8539,7 @@ public void resetAll(ResetFilter filter) throws IOException {
85278539
}
85288540
else {
85298541
ExceptionUtil.initCauseEL(null, null);
8530-
LogUtil.log(Log.LEVEL_DEBUG, "config", "rest the following: " + filter);
8542+
LogUtil.log(Log.LEVEL_DEBUG, "config", "reset the following: " + filter);
85318543

85328544
for (Method method: methods) {
85338545
if (method.getArgumentCount() == 0 && filter.allow(method.getName())) {

core/src/main/java/lucee/runtime/config/ConfigWebImpl.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2100,4 +2100,14 @@ public Repository[] getMavenRepository() {
21002100
public Repository[] getMavenSnapshotRepository() {
21012101
return cs.getMavenSnapshotRepository();
21022102
}
2103+
2104+
@Override
2105+
public String getDapSecret() {
2106+
return cs.getDapSecret();
2107+
}
2108+
2109+
@Override
2110+
public boolean getDapBreakpoint() {
2111+
return cs.getDapBreakpoint();
2112+
}
21032113
}

core/src/main/java/lucee/runtime/debug/DebuggerRegistry.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
import lucee.commons.io.log.Log;
44
import lucee.commons.io.log.LogUtil;
5-
import lucee.runtime.config.ConfigServerImpl;
5+
import lucee.runtime.config.ConfigPro;
6+
import lucee.runtime.engine.ThreadLocalPageContext;
67

78
/**
89
* Static registry for the debugger listener. Only one debugger listener is supported at a time.
@@ -37,7 +38,7 @@ public static boolean setListener(DebuggerListener l, String secret) {
3738
return true;
3839
}
3940
// Registration requires valid secret
40-
String expectedSecret = ConfigServerImpl.DEBUGGER_SECRET;
41+
String expectedSecret = ((ConfigPro) ThreadLocalPageContext.getConfig()).getDapSecret();
4142
if (expectedSecret == null || !expectedSecret.equals(secret)) {
4243
return false;
4344
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package lucee.runtime.functions.decision;
22

33
import lucee.runtime.PageContext;
4-
import lucee.runtime.config.ConfigServerImpl;
4+
import lucee.runtime.PageContextImpl;
55
import lucee.runtime.ext.function.Function;
66

77
public final class IsDebuggerEnabled implements Function {
88

99
public static boolean call(PageContext pc) {
10-
return ConfigServerImpl.DEBUGGER;
10+
return ((PageContextImpl) pc).getExecutionLogEnabled();
1111
}
1212
}

core/src/main/java/lucee/runtime/functions/system/Breakpoint.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import lucee.runtime.PageContext;
44
import lucee.runtime.PageContextImpl;
5-
import lucee.runtime.config.ConfigServerImpl;
65
import lucee.runtime.debug.DebuggerRegistry;
76

87
public final class Breakpoint {
@@ -17,7 +16,7 @@ public static boolean call(PageContext pc, String label) {
1716

1817
public static boolean call(PageContext pc, String label, boolean condition) {
1918
// Only suspend if debugger breakpoint support is enabled AND a debugger client is connected
20-
if (condition && ConfigServerImpl.DEBUGGER && DebuggerRegistry.isClientConnected()) {
19+
if (condition && ((PageContextImpl) pc).getExecutionLogEnabled() && DebuggerRegistry.isClientConnected()) {
2120
((PageContextImpl) pc).debuggerSuspend(label);
2221
return true;
2322
}

core/src/main/java/lucee/runtime/tag/Admin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4352,7 +4352,7 @@ private void doUpdateExecutionLog() throws PageException {
43524352
lucee.runtime.db.ClassDefinition cd = ClassDefinitionImpl.toClassDefinitionImpl(attributes, null, true, config.getIdentification());
43534353
admin.updateExecutionLog(cd, getStruct("admin", "updateExecutionLog", "arguments"), getBool("admin", "updateExecutionLog", "enabled"));
43544354
store();
4355-
ConfigUtil.getConfigServerImpl(config).resetExecutionLogEnabled().resetExecutionLogFactory();
4355+
ConfigUtil.getConfigServerImpl(config).resetDapBreakpoint().resetDapSecret().resetExecutionLogFactory();
43564356
adminSync.broadcast(attributes, config);
43574357
}
43584358

0 commit comments

Comments
 (0)