Skip to content

Commit 39e3b21

Browse files
committed
DefaultPrefService: fix bug with keys >80 chars
The Java Preferences API does not allow keys greater than 80 characters long (the Preferences.MAX_KEY_LENGTH constant). As a workaround, we limit the key length internally, using the last 77 characters of the string prepending with "..." to suggest this occurred. This means, of course, that two keys with identical latter 77 characters will now stomp each other. But there is little we can do aside from using hashes or some such, which would mangle the keys too much IMHO (configuration files on disk would be incomprehensible, for example). The fix is also incomplete when it comes to persisting maps: if you have a map with such long keys, they will be mangled when restored. But I do not have enough time and energy to address that right now. Tripped over by Kyle Harrington.
1 parent 5d4b849 commit 39e3b21

File tree

1 file changed

+44
-13
lines changed

1 file changed

+44
-13
lines changed

src/main/java/org/scijava/prefs/DefaultPrefService.java

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ private void findNext() {
507507

508508
/** @see java.util.prefs.Preferences#put */
509509
public void put(final String key, final Object value) {
510-
p.put(key, value == null ? null : value.toString());
510+
p.put(safeKey(key), value == null ? null : value.toString());
511511
}
512512

513513
/** @see java.util.prefs.Preferences#get(String, String) */
@@ -517,7 +517,7 @@ public String get(final String key) {
517517

518518
/** @see java.util.prefs.Preferences#get(String, String) */
519519
public String get(final String key, final String def) {
520-
return p.get(key, def);
520+
return p.get(safeKey(key), def);
521521
}
522522

523523
/** @see java.util.prefs.Preferences#clear() */
@@ -532,58 +532,62 @@ public void clear() {
532532

533533
/** @see java.util.prefs.Preferences#putInt(String, int) */
534534
public void putInt(final String key, final int value) {
535-
p.putInt(key, value);
535+
p.putInt(safeKey(key), value);
536536
}
537537

538538
/** @see java.util.prefs.Preferences#getInt(String, int) */
539539
public int getInt(final String key, final int def) {
540-
return p.getInt(key, def);
540+
return p.getInt(safeKey(key), def);
541541
}
542542

543543
/** @see java.util.prefs.Preferences#putLong(String, long) */
544544
public void putLong(final String key, final long value) {
545-
p.putLong(key, value);
545+
p.putLong(safeKey(key), value);
546546
}
547547

548548
/** @see java.util.prefs.Preferences#getLong(String, long) */
549549
public long getLong(final String key, final long def) {
550-
return p.getLong(key, def);
550+
return p.getLong(safeKey(key), def);
551551
}
552552

553553
/** @see java.util.prefs.Preferences#putBoolean(String, boolean) */
554554
public void putBoolean(final String key, final boolean value) {
555-
p.putBoolean(key, value);
555+
p.putBoolean(safeKey(key), value);
556556
}
557557

558558
/** @see java.util.prefs.Preferences#getFloat(String, float) */
559559
public boolean getBoolean(final String key, final boolean def) {
560-
return p.getBoolean(key, def);
560+
return p.getBoolean(safeKey(key), def);
561561
}
562562

563563
/** @see java.util.prefs.Preferences#putFloat(String, float) */
564564
public void putFloat(final String key, final float value) {
565-
p.putFloat(key, value);
565+
p.putFloat(safeKey(key), value);
566566
}
567567

568568
/** @see java.util.prefs.Preferences#getFloat(String, float) */
569569
public float getFloat(final String key, final float def) {
570-
return p.getFloat(key, def);
570+
return p.getFloat(safeKey(key), def);
571571
}
572572

573573
/** @see java.util.prefs.Preferences#putDouble(String, double) */
574574
public void putDouble(final String key, final double value) {
575-
p.putDouble(key, value);
575+
p.putDouble(safeKey(key), value);
576576
}
577577

578578
/** @see java.util.prefs.Preferences#getDouble(String, double) */
579579
public double getDouble(final String key, final double def) {
580-
return p.getDouble(key, def);
580+
return p.getDouble(safeKey(key), def);
581581
}
582582

583583
/** @see java.util.prefs.Preferences#keys() */
584584
public String[] keys() {
585585
try {
586-
return p.keys();
586+
final String[] keys = p.keys();
587+
for (int i = 0; i < keys.length; i++) {
588+
keys[i] = safeKey(keys[i]);
589+
}
590+
return keys;
587591
}
588592
catch (final java.util.prefs.BackingStoreException exc) {
589593
log.error(exc);
@@ -617,6 +621,33 @@ public void removeNode() {
617621
}
618622
}
619623

624+
// -- Helper methods --
625+
626+
private String safeKey(final String key) {
627+
return makeSafe(key, java.util.prefs.Preferences.MAX_KEY_LENGTH);
628+
}
629+
630+
/**
631+
* This method limits the given string to the specified maximum length using
632+
* its latter characters prepended with "..." as needed.
633+
* <p>
634+
* This is necessary because the Java Preferences API does not allow:
635+
* </p>
636+
* <ul>
637+
* <li>Keys longer than {@link java.util.prefs.Preferences#MAX_KEY_LENGTH}
638+
* </li>
639+
* <li>Values longer than
640+
* {@link java.util.prefs.Preferences#MAX_VALUE_LENGTH}</li>
641+
* <li>Node names longer than
642+
* {@link java.util.prefs.Preferences#MAX_NAME_LENGTH}</li>
643+
* </ul>
644+
*/
645+
private String makeSafe(final String s, final int max) {
646+
final int len = s.length();
647+
if (len < max) return s;
648+
return "..." + s.substring(len - max + 3, len);
649+
}
650+
620651
}
621652

622653
}

0 commit comments

Comments
 (0)