JAVA: Better exception handling during metadata loading.
authordbeaumont@google.com <dbeaumont@google.com@ee073f10-1060-11df-b6a4-87a95322a99c>
Wed, 5 Sep 2012 16:02:01 +0000 (16:02 +0000)
committerdbeaumont@google.com <dbeaumont@google.com@ee073f10-1060-11df-b6a4-87a95322a99c>
Wed, 5 Sep 2012 16:02:01 +0000 (16:02 +0000)
git-svn-id: http://libphonenumber.googlecode.com/svn/trunk@517 ee073f10-1060-11df-b6a4-87a95322a99c

java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java
java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java
java/release_notes.txt

index b332318..7e4e6bb 100644 (file)
@@ -558,25 +558,38 @@ public class PhoneNumberUtil {
     nanpaRegions.addAll(countryCallingCodeToRegionCodeMap.get(NANPA_COUNTRY_CODE));
   }
 
-  private void loadMetadataFromFile(String filePrefix, String regionCode, int countryCallingCode) {
+  // @VisibleForTesting
+  void loadMetadataFromFile(String filePrefix, String regionCode, int countryCallingCode) {
     boolean isNonGeoRegion = REGION_CODE_FOR_NON_GEO_ENTITY.equals(regionCode);
-    InputStream source = isNonGeoRegion
-        ? PhoneNumberUtil.class.getResourceAsStream(filePrefix + "_" + countryCallingCode)
-        : PhoneNumberUtil.class.getResourceAsStream(filePrefix + "_" + regionCode);
+    String fileName = filePrefix + "_" +
+        (isNonGeoRegion ? String.valueOf(countryCallingCode) : regionCode);
+    InputStream source = PhoneNumberUtil.class.getResourceAsStream(fileName);
+    if (source == null) {
+      LOGGER.log(Level.SEVERE, "missing metadata: " + fileName);
+      throw new RuntimeException("missing metadata: " + fileName);
+    }
     ObjectInputStream in = null;
     try {
       in = new ObjectInputStream(source);
       PhoneMetadataCollection metadataCollection = new PhoneMetadataCollection();
       metadataCollection.readExternal(in);
-      for (PhoneMetadata metadata : metadataCollection.getMetadataList()) {
-        if (isNonGeoRegion) {
-          countryCodeToNonGeographicalMetadataMap.put(countryCallingCode, metadata);
-        } else {
-          regionToMetadataMap.put(regionCode, metadata);
-        }
+      List<PhoneMetadata> metadataList = metadataCollection.getMetadataList();
+      if (metadataList.isEmpty()) {
+        LOGGER.log(Level.SEVERE, "empty metadata: " + fileName);
+        throw new RuntimeException("empty metadata: " + fileName);
+      }
+      if (metadataList.size() > 1) {
+        LOGGER.log(Level.WARNING, "invalid metadata (too many entries): " + fileName);
+      }
+      PhoneMetadata metadata = metadataList.get(0);
+      if (isNonGeoRegion) {
+        countryCodeToNonGeographicalMetadataMap.put(countryCallingCode, metadata);
+      } else {
+        regionToMetadataMap.put(regionCode, metadata);
       }
     } catch (IOException e) {
-      LOGGER.log(Level.WARNING, e.toString());
+      LOGGER.log(Level.SEVERE, "cannot load/parse metadata: " + fileName, e);
+      throw new RuntimeException("cannot load/parse metadata: " + fileName, e);
     } finally {
       close(in);
     }
@@ -587,7 +600,7 @@ public class PhoneNumberUtil {
       try {
         in.close();
       } catch (IOException e) {
-        LOGGER.log(Level.WARNING, e.toString());
+        LOGGER.log(Level.WARNING, "error closing input stream (ignored)", e);
       }
     }
   }
index 59f3f70..714429c 100644 (file)
@@ -111,6 +111,30 @@ public class PhoneNumberUtilTest extends TestMetadataTestCase {
     assertTrue(phoneUtil.getSupportedRegions().size() > 0);
   }
 
+  public void testGetInstanceLoadBadMetadata() {
+    assertNull(phoneUtil.getMetadataForRegion("No Such Region"));
+    assertNull(phoneUtil.getMetadataForNonGeographicalRegion(-1));
+  }
+
+  public void testMissingMetadataFileThrowsRuntimeException() {
+    // In normal usage we should never get a state where we are asking to load metadata that doesn't
+    // exist. However if the library is packaged incorrectly in the jar, this could happen and the
+    // best we can do is make sure the exception has the file name in it.
+    try {
+      phoneUtil.loadMetadataFromFile("no/such/file", "XX", -1);
+      fail("expected exception");
+    } catch (RuntimeException e) {
+      assertTrue("Unexpected error: " + e, e.toString().contains("no/such/file_XX"));
+    }
+    try {
+      phoneUtil.loadMetadataFromFile(
+          "no/such/file", PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY, 123);
+      fail("expected exception");
+    } catch (RuntimeException e) {
+      assertTrue("Unexpected error: " + e, e.getMessage().contains("no/such/file_123"));
+    }
+  }
+
   public void testGetInstanceLoadUSMetadata() {
     PhoneMetadata metadata = phoneUtil.getMetadataForRegion(RegionCode.US);
     assertEquals("US", metadata.getId());
index 20f29c7..ab720e8 100644 (file)
@@ -1,3 +1,7 @@
+Sep 5, 2010: libphonenumber-5.1.1
+* Code changes:
+  - Added better logging/exception handling for catching cases where metadata is invalid/missing.
+
 Sep 3, 2012: libphonenumber-5.1
 * Code changes:
  - Inserting a space after the national prefix in the AsYouTypeFormatter when formatting numbers in