Hi Brian,
Thanks for digging deeper and the recap.
I don't see any cases in which it is necessary or valuable to allow
\0 in Strings (key or value). The original bug report did not indicate
whether
it was discovered as a testing exercise or when diagnosing a bug in an
application.
The compatibility risk is unknown at the moment since no cases have been
noted that require \0 in strings.
Long term the code will be easier to maintain if it is less complex and
has fewer
variables that are platform or format specific and developer errors are
detected
as soon as possible.
Of the possible remedies below, #2 seems the most practical. But it will
further
hide the problem from developers since calling flush and sync is never
required
for correct operation:
///"explicit //flush//invocation is //not//required upon termination to
ensure that pending updates are made persistent"/
Flush and sync would be the only opportunity to throw an exception and
explain the cause.
It will be harder to track down since the true cause will be far removed
from
the time/location of the exception.
In the absence of advice to continue to support \0in Preference strings
on Windows
or Mac I'd continue with the recent direction to make \0 in key and
value strings throw IAE.
Roger
On 4/10/2015 6:26 PM, Brian Burkhalter wrote:
On Apr 4, 2015, at 12:53 PM, Alan Bateman <alan.bate...@oracle.com> wrote:
On 24/03/2015 19:20, Brian Burkhalter wrote:
Please review at your convenience.
Issue: https://bugs.openjdk.java.net/browse/JDK-8075156
Patch: http://cr.openjdk.java.net/~bpb/8075156/webrev.00/
This is a sequel to the resolved issue
https://bugs.openjdk.java.net/browse/JDK-8068373, (prefs) FileSystemPreferences
writes \0 to XML storage, causing loss of all preferences, wherein the code
point U+0000, the null control character, was made illegal to use as a key in
the generic Unix file system-based Preferences.
The issue at hand extends disallowing U+0000 as a key in the put() method on
Mac OS X and Windows, and also disallows this use to the remove() methods on
these platforms and in the generic Unix file system-based Preferences.
Use of U+0000 in the corresponding get() method has not been disallowed as this
method returns a default value. If it would be preferable that the behavior of
get() with respect to the key U+0000 were the same as for put() and remove()
then this patch may be updated to that effect.
Minimally then the putXXX methods should make it clear that they throw IAE for
this case. This would be a javadoc only change because the implementation does
this as a consequence of the original patch.
Agreed.
Actually I am not completely satisfied with the fix for
https://bugs.openjdk.java.net/browse/JDK-8068373 so I went back over all the
discussions and notes on the various ways to fix the problem trying to rethink
whether there might be a better solution. The problem is not really with the
Preferences APIs per se, but rather with the ability of the XML-based backing
store to handle all characters which might be present in a String, in this
particular case \u0000, but there are other possible problematic characters as
well.
Ideally, the fix would be to modify the XML backing store to handle all
possible characters. This does not however appear to be possible without
introducing an incompatibility when the XML backing store is shared between the
set of newer versions of Java which would support storing all characters and
the older versions which do not. There are ways to minimize the incompatibility
but not apparently eliminate it and the additional complexity might not merit
the effort.
In the RFC thread on 8068373, it was concluded that it would be better simply
to disallow \u0000 for XML-backed Preferences. This change however introduced
an incompatibility with non-XML backing stores which might or might not be able
to handle \u0000. So to address this incompatibility (and to address the
companion get/remove methods) the present RFR was introduced. The present
change has the potential however to break Preferences implementations which
have a backing store for which \u0000 *is* legal.
Note also that all Preferences implementations should be able to handle all
Strings if there is no interaction with the backing store, even in the case of
the XML backing store. Without a round trip via the XML backing store no error
would be encountered. This suggests an alternative fix of allowing the illegal
character to be used “live” but disallowed from being written to a backing
store which cannot handle it.
I raise these alternatives here because if any were preferable, then there is
no point in going further in the current direction as one changeset reversion
would already be needed.
In the original discussion then it was just a question as to whether get/getXXX
and remove should be consistent. If the get and remove methods will always
behave as if the key doesn't exist (and return the default value in the case of
get) then it shouldn't require a javadoc change.
In the case of get(), for implementations based on AbstractPreferences, any
exception thrown by getSpi() will in any case be caught and the default value
returned.
For remove() there might after all be no point in checking the key if the key
is disallowed from being stored in the first place, so the method call would be
a no-op and neither an implementation nor a javadoc change would be needed.
However I suspect it will require an implementation change as there may be
non-XML backing stores might that allow \0 in the key (hence get and remove
should actually do something).
As noted above, it might not be correct to extend the checked-in fix for
8068373 to the non-XML backing store cases as is being proposed in this RFR and
likewise not to modify remove() symmetrically.
Rethinking this entire topic l am now inclined to suggest retracting the prior
fix of 8068373 and instead take one of the following approaches:
1. Modify the XML backing store to be able to handle at least \0 if not other
characters problematic for XML. As noted above this might be complicated and
introduce inter-version incompatibilities.
2. Allow \0 to be in Strings at the API level but do not write these entries to
an XML backing store. This would allow in-session use of unsupported characters
but these would magically disappear thereafter which could cause confusion.
3. Change the put() specification to allow throwing an IAE if the backing store
cannot handle the supplied Strings. This however runs somewhat counter to the
Preferences class-level specification that "The user of this class needn't be
concerned with details of the backing store.”
On reexamining things I also noticed this paragraph in the AbstractPreferences
class-level specification:
"The remaining SPI methods putSpi(String,String), removeSpi(String) and
childSpi(String) have more complicated exception behavior. They are not specified to
throw BackingStoreException, as they can generally obey their contracts even if the
backing store is unavailable. This is true because they return no information and their
effects are not required to become permanent until a subsequent call to
Preferences.flush() or Preferences.sync(). Generally speaking, these SPI methods should
not throw exceptions. In some implementations, there may be circumstances under which
these calls cannot even enqueue the requested operation for later processing. Even under
these circumstances it is generally better to simply ignore the invocation and return,
rather than throwing an exception. Under these circumstances, however, all subsequent
invocations of flush() and sync should return false, as returning true would imply that
all previous operations had successfully been made permanent."
This suggests that solution #2 above might be the appropriate fix instead of
that of 8068373 plus the patch in the current RFR. There are errors in the
above specification paragraph however which should also be fixed, viz.,
flush{Spi}() and sync{Spi}() are void, not boolean-returning methods.
Thanks,
Brian