Hi Sherman,
I didn't think "outside the box" on this one, but was a bit
mechanical with the fix.
Your latter two options are appealing: returning Encoder.RFC4648 or
throwing an exception.
In fact your second option of using the Base64.getEncoder(),
ignoring the line separator and returning the RFC4648 encoder, solves
the issue
neatly, and you can leave the spec as is :-)
As such:
public static Encoder getEncoder(int lineLength, byte[] lineSeparator) {
if (lineLength <= 0) {
return Encoder.RFC4648;
}
Objects.requireNonNull(lineSeparator);
int[] base64 = Decoder.fromBase64;
for (byte b : lineSeparator) {
if (base64[b & 0xff] != -1)
throw new IllegalArgumentException(
"Illegal base64 line separator character 0x"
+ Integer.toString(b, 16));
}
return new Encoder(false, lineSeparator, lineLength >> 2 << 2);
}
will do the job nicely.
While throwing an exception will ensure a single point of access to the
RFC4648 Encoder, and mean the
getEncoder(int, byte[]) is providing a genuine alternative Encoder to
the three "build in" Encoders.
Thus, eliminating the lineLength <=0 option makes sense.
The former has least impact as a fix. The latter makes more sense when
you think about it.
Whichever you favour and I'll make the change.
regards
Mark
On 02/04/2013 18:52, Xueming Shen wrote:
Thanks Mark for looking into this issue.
The change itself looks fine. Though I'm a little concerned whether
the performance cost (need to do an additional linemax > 0 check
inside the 'while" loop) is really worth it. Maybe an alternative is
to simply set the linemax to -1 if it's 0? such as
public static Encoder getEncoder(int lineLength, byte[]
lineSeparator) {
Objects.requireNonNull(lineSeparator);
int[] base64 = Decoder.fromBase64;
for (byte b : lineSeparator) {
if (base64[b & 0xff] != -1)
throw new IllegalArgumentException(
"Illegal base64 line separator character 0x" +
Integer.toString(b, 16));
}
if (lineLength == 0)
lineLength = -1;
return new Encoder(false, lineSeparator, lineLength >> 2 << 2);
}
And given it actually become a "normal" RFC4648 if the lineLength <=0,
maybe
we should simply eliminate this "option" by changing the spec to say
"throw
IAE if lineLength <=0", go use BAse64.getEncoder() if lineSeparator is
not needed.
-Sherman
On 03/27/2013 09:01 AM, Mark Sheppard wrote:
Hi,
please oblige and review the webrev below as a fix for the issue
raised in JDK-8007799
http://cr.openjdk.java.net/~msheppar/8007799/webrev.00/
Description:
"Specification for the method
java.util.Base64.getEncoder(int lineLength, byte[] lineSeparator)
says:
Parameters:
lineLength - the length of each output line (rounded down to
nearest multiple of 4). If lineLength <= 0 the output will not be
separated in lines
However if a zero line length is specified encoding methods wrap()
and encode(ByteBuffer src, ByteBuffer dst, int bytesOut) return
encoded string which starts from the given line separator. "
the patch adds a check for linemax > 0 whenever a line separator
might be added, and adds an new test case.
regards
Mark