Repository navigation
Java callers cannot specifically catch IOException from KmzParser.parse #1834
Description
Summary
KmzParser.parse(InputStream) can throw IOException for stream failures and KMZ safety-limit violations, but its Java signature does not declare it. A Java caller cannot compile a specific catch (IOException) when the try block contains only the parsing call.
Expected behavior
Provide a Java-callable entry point that declares the parser's I/O failures, while preserving the existing parse(InputStream) contract for current callers.
Observed behavior
The example below fails Java compilation:
error: exception IOException is never thrown in body of corresponding try statement
At runtime, the method can still propagate IOException. Catching Exception is a workaround, but requires a broader handler than the I/O failure being handled.
Environment details
- Repository commit:
b7b09e6c36e31a8fb4b309074de0b84f51eee3c9, moduledata. - Gradle 9.8.1, Kotlin 2.4.21, JDK 17.
- Confirmed against the complete production module classes built with the repository's toolchain. No Android device is required for the Java compilation failure.
Steps to reproduce
- Build the
datamodule and include its classes and dependencies on a Java consumer's compile classpath. - Compile the class below. The
catch (IOException)clause is rejected. - Change the catch type to
Exceptionand invoke the method with a stream whoseread()throwsIOException. The parsing call propagates thatIOExceptionto the handler.
Code example
import com.google.maps.android.data.parser.kml.KmzParser;
import java.io.IOException;
import java.io.InputStream;
public final class KmzConsumer {
public static void load(InputStream input) {
try {
new KmzParser().parse(input);
} catch (IOException failure) {
System.err.println("Could not read KMZ: " + failure.getMessage());
}
}
}Suggested approach
Keep parse(InputStream) unchanged and add a separate entry point, for example:
@Throws(IOException::class)
public fun parseChecked(inputStream: InputStream): Kml =
parse(inputStream)Java callers could opt into parseChecked() and catch IOException, without adding a checked exception to the existing method. The original parsing and stream-closing behavior would remain shared.
Alternatively, adding @Throws(IOException::class) directly to parse() would avoid introducing another method, but existing Java callers might need to catch or declare IOException when recompiling. The separate entry point would avoid that source-compatibility change.
Would this additional entry point fit the intended Java API, or would you prefer another way to expose these failures?
Validation
- The original Java compilation failure and actual
IOExceptionpropagation were reproduced against the real module classes. - An equivalent Java adapter declaring
throws IOExceptionwas tested against those same classes. Existing direct callers and new adapter callers compile; stream-read failure handling and KMZ entry-limit rejection both pass. - The unmodified repository baseline passes
:data:testDebugUnitTest :data:lintDebug: 187 tests, zero failures/errors/skips; lint reports eight warnings and no errors. - The proposed Kotlin entry point has not yet been added to the upstream source. The adapter checks and baseline results are not a patched-module test run.
Activity