Skip to content

Commit 927efdb

Browse files
committed
Implement more and louder validation of config properties.
1 parent 872613d commit 927efdb

File tree

7 files changed

+104
-13
lines changed

7 files changed

+104
-13
lines changed

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
-- Implement more and "louder" (log ugly stack traces) validation of
2+
config properties.
13
-- Modify former InUseLock (now InternalUseLock) and NewProxyConnection
24
to use ReentrantLock rather than native monitors, to prevent pinning
35
when clients run on loom virtual threads.

bean/beangen/com/mchange/v2/c3p0/impl/WrapperConnectionPoolDataSourceBase.beangen-xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<imports>
44
<specific>javax.sql.DataSource</specific>
55
<specific>com.mchange.v2.c3p0.cfg.C3P0Config</specific>
6+
<specific>com.mchange.v2.c3p0.cfg.Validators</specific>
67
</imports>
78
<modifiers>
89
<modifier>public</modifier>
@@ -149,7 +150,7 @@
149150
<type>String</type>
150151
<name>contextClassLoaderSource</name>
151152
<constrained/>
152-
<default-value>C3P0Config.initializeStringPropertyVar("contextClassLoaderSource", C3P0Defaults.contextClassLoaderSource())</default-value>
153+
<default-value>C3P0Config.initializeStringPropertyVar("contextClassLoaderSource", C3P0Defaults.contextClassLoaderSource(), Validators.ContextClassLoaderSource)</default-value>
153154
<getter><modifiers><modifier>public</modifier><modifier>synchronized</modifier></modifiers></getter>
154155
<setter><modifiers><modifier>public</modifier><modifier>synchronized</modifier></modifiers></setter>
155156
</property>
@@ -177,7 +178,7 @@
177178
<property>
178179
<type>String</type>
179180
<name>markSessionBoundaries</name>
180-
<default-value>C3P0Config.initializeStringPropertyVar("markSessionBoundaries", C3P0Defaults.markSessionBoundaries())</default-value>
181+
<default-value>C3P0Config.initializeStringPropertyVar("markSessionBoundaries", C3P0Defaults.markSessionBoundaries(), Validators.MarkSessionBoundaries)</default-value>
181182
<constrained/>
182183
<getter><modifiers><modifier>public</modifier><modifier>synchronized</modifier></modifiers></getter>
183184
<setter><modifiers><modifier>public</modifier><modifier>synchronized</modifier></modifiers></setter>

dev-notes.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
# dev-notes
22

33
* It looks like throwing of PropertyVetoException may not be implemented for ostensibly constrained parameters:
4-
- `connectionTesterClassName` (should classname params be constrained?)
4+
- `connectionTesterClassName` (should classname params be constrained? no actual implementation I think)
55
- `contextClassLoaderSource`
66
- `markSessionBoundaries`
7-
- `taskRunnerFactoryClassName` (should classname params be constrained?)
7+
- `taskRunnerFactoryClassName` (should classname params be constrained? no actual implementation I think)
88
- `userOverridesAsString`
99
It might be disruptive to "fix" this now, as installations may have configs that are stable despite
1010
bad (vetoable) settings.
11+
12+
PropertyVetoException appears to be thrown with explicit calls to setters, but not on implementation via config.
13+
Variables are initialized to config values, circumventing validation.
14+
15+
Okay. We've added a way to validate String config properties, and validation for `contextClassLoaderSource` and `markSessionBoundaries`.
1116

1217
If class name properties should be constrained, probably so too ought be
1318
- `connectionCustomizerClassName`
19+
but making it so would be an incompatible API change at this point, callers of the setter would have to prepare
20+
for `ProppertyVetoException`, which now they do not.
1421

1522
* When testing against intentionally chaotic configs, we occasionally see, at debug level FINE:
1623
```plaintext

src/com/mchange/v2/c3p0/cfg/C3P0Config.java

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -518,13 +518,27 @@ public static String initializeUserOverridesAsString()
518518
public static Map initializeExtensions()
519519
{ return getExtensions( null ); }
520520

521-
public static String initializeStringPropertyVar(String propKey, String dflt)
521+
public static String initializeStringPropertyVar(String propKey, String dflt, Validator<String> validator)
522522
{
523-
String out = getUnspecifiedUserProperty( propKey, null );
524-
if (out == null) out = dflt;
525-
return out;
523+
String out = getUnspecifiedUserProperty( propKey, null );
524+
try
525+
{
526+
if (out == null) out = dflt;
527+
else if (validator != null) out = validator.validate(out);
528+
return out;
529+
}
530+
catch (InvalidConfigException ice)
531+
{
532+
logger.log(MLevel.WARNING, "'" + out + "' is not a legal value for property '" + propKey +
533+
"'. Using default value: " + dflt, ice);
534+
return dflt;
535+
}
526536
}
527537

538+
public static String initializeStringPropertyVar(String propKey, String dflt)
539+
{ return initializeStringPropertyVar(propKey, dflt, null); }
540+
541+
528542
public static int initializeIntPropertyVar(String propKey, int dflt)
529543
{
530544
boolean set = false;
@@ -535,13 +549,13 @@ public static int initializeIntPropertyVar(String propKey, int dflt)
535549
{
536550
try
537551
{
538-
out = Integer.parseInt( outStr.trim() );
552+
out = Integer.parseInt( outStr.trim() );
539553
set = true;
540554
}
541555
catch (NumberFormatException e)
542556
{
543-
logger.info("'" + outStr + "' is not a legal value for property '" + propKey +
544-
"'. Using default value: " + dflt);
557+
logger.log(MLevel.WARNING, "'" + outStr + "' is not a legal value for property '" + propKey +
558+
"'. Using default value: " + dflt, e);
545559
}
546560
}
547561

@@ -567,8 +581,8 @@ public static boolean initializeBooleanPropertyVar(String propKey, boolean dflt)
567581
}
568582
catch (IllegalArgumentException e)
569583
{
570-
logger.info("'" + outStr + "' is not a legal value for property '" + propKey +
571-
"'. Using default value: " + dflt);
584+
logger.log(MLevel.WARNING, "'" + outStr + "' is not a legal value for property '" + propKey +
585+
"'. Using default value: " + dflt, e);
572586
}
573587
}
574588

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.mchange.v2.c3p0.cfg;
2+
3+
public final class InvalidConfigException extends Exception
4+
{
5+
public InvalidConfigException( String message, Throwable cause )
6+
{ super( message, cause ); }
7+
8+
public InvalidConfigException( String message )
9+
{ this( message, null ); }
10+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.mchange.v2.c3p0.cfg;
2+
3+
interface Validator<T>
4+
{
5+
public T validate( T value ) throws InvalidConfigException;
6+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.mchange.v2.c3p0.cfg;
2+
3+
public final class Validators
4+
{
5+
static abstract class AbstractValidator<T> implements Validator<T>
6+
{
7+
String param;
8+
9+
AbstractValidator( String param )
10+
{ this.param = param; }
11+
12+
abstract T _validate( T value ) throws InvalidConfigException;
13+
14+
public T validate( T value ) throws InvalidConfigException
15+
{
16+
try
17+
{ return _validate(value); }
18+
catch (InvalidConfigException ice)
19+
{ throw ice; }
20+
catch (Exception e)
21+
{ throw new InvalidConfigException("While validating '" + param + "', encountered Exception: " + e, e); }
22+
}
23+
}
24+
25+
public static Validator<String> MarkSessionBoundaries = new AbstractValidator<String>("markSessionBoundaries")
26+
{
27+
String _validate( String value ) throws InvalidConfigException
28+
{
29+
String out = value.toLowerCase();
30+
if ("always".equals(out)||"never".equals(out)||"if-no-statement-cache".equals(out))
31+
return out;
32+
else
33+
throw new InvalidConfigException(param + " must be one of 'always', 'never', or 'if-no-statement-cache'. Found '" + value + "'.");
34+
}
35+
};
36+
37+
public static Validator<String> ContextClassLoaderSource = new AbstractValidator<String>("contextClassLoaderSource")
38+
{
39+
String _validate( String value ) throws InvalidConfigException
40+
{
41+
String out = value.toLowerCase();
42+
if ("caller".equals(out)||"library".equals(out)||"none".equals(out))
43+
return out;
44+
else
45+
throw new InvalidConfigException(param + " must be one of 'caller', 'library', or 'none'. Found '" + value + "'.");
46+
}
47+
};
48+
49+
private Validators()
50+
{}
51+
}

0 commit comments

Comments
 (0)