diff --git a/javase/src/main/java/com/google/zxing/client/j2se/Base64Decoder.java b/javase/src/main/java/com/google/zxing/client/j2se/Base64Decoder.java new file mode 100644 index 000000000..edf48b24d --- /dev/null +++ b/javase/src/main/java/com/google/zxing/client/j2se/Base64Decoder.java @@ -0,0 +1,47 @@ +/* + * Copyright 2016 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.client.j2se; + +/** + * Abstraction over Base 64 decoding implementations that work across Java versions. + */ +abstract class Base64Decoder { + + private static final Base64Decoder INSTANCE; + static { + Base64Decoder instance; + try { + Class.forName("java.util.Base64"); + // If succeeds, then: + instance = new Java8Base64Decoder(); + } catch (ClassNotFoundException cnfe) { + instance = new JAXBBase64Decoder(); + } + INSTANCE = instance; + } + + /** + * @param s Base-64 encoded string + * @return bytes that the string encodes + */ + abstract byte[] decode(String s); + + static Base64Decoder getInstance() { + return INSTANCE; + } + +} diff --git a/javase/src/main/java/com/google/zxing/client/j2se/ImageReader.java b/javase/src/main/java/com/google/zxing/client/j2se/ImageReader.java index 45312baa1..0d7617cea 100644 --- a/javase/src/main/java/com/google/zxing/client/j2se/ImageReader.java +++ b/javase/src/main/java/com/google/zxing/client/j2se/ImageReader.java @@ -17,7 +17,6 @@ package com.google.zxing.client.j2se; import javax.imageio.ImageIO; -import javax.xml.bind.DatatypeConverter; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -63,7 +62,7 @@ public final class ImageReader { } String base64DataEncoded = uriString.substring(base64Start + BASE64TOKEN.length()); String base64Data = URLDecoder.decode(base64DataEncoded, "UTF-8"); - byte[] imageBytes = DatatypeConverter.parseBase64Binary(base64Data); + byte[] imageBytes = Base64Decoder.getInstance().decode(base64Data); return ImageIO.read(new ByteArrayInputStream(imageBytes)); } diff --git a/javase/src/main/java/com/google/zxing/client/j2se/JAXBBase64Decoder.java b/javase/src/main/java/com/google/zxing/client/j2se/JAXBBase64Decoder.java new file mode 100644 index 000000000..f9b8bf24a --- /dev/null +++ b/javase/src/main/java/com/google/zxing/client/j2se/JAXBBase64Decoder.java @@ -0,0 +1,36 @@ +/* + * Copyright 2016 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.client.j2se; + +import java.lang.reflect.InvocationTargetException; + +/** + * Uses {@code javax.xml.bind.DatatypeConverter}, which is not (necessarily) present + * in Java 9. + */ +final class JAXBBase64Decoder extends Base64Decoder { + @Override + byte[] decode(String s) { + try { + return (byte[]) Class.forName("javax.xml.bind.DatatypeConverter") + .getMethod("parseBase64Binary", String.class).invoke(null, s); + } catch (IllegalAccessException | InvocationTargetException | + NoSuchMethodException | ClassNotFoundException e) { + throw new IllegalStateException(e); + } + } +} diff --git a/javase/src/main/java/com/google/zxing/client/j2se/Java8Base64Decoder.java b/javase/src/main/java/com/google/zxing/client/j2se/Java8Base64Decoder.java new file mode 100644 index 000000000..b54692446 --- /dev/null +++ b/javase/src/main/java/com/google/zxing/client/j2se/Java8Base64Decoder.java @@ -0,0 +1,37 @@ +/* + * Copyright 2016 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.client.j2se; + +import java.lang.reflect.InvocationTargetException; + +/** + * Uses {@code java.util.Base64}, available in Java 8 and later + */ +final class Java8Base64Decoder extends Base64Decoder { + @Override + byte[] decode(String s) { + try { + Object decoder = Class.forName("java.util.Base64") + .getMethod("getDecoder").invoke(null); + return (byte[]) Class.forName("java.util.Base64.Decoder") + .getMethod("decode", String.class).invoke(decoder, s); + } catch (IllegalAccessException | InvocationTargetException | + NoSuchMethodException | ClassNotFoundException e) { + throw new IllegalStateException(e); + } + } +}