• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Libphonenumber Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.i18n.phonenumbers.metadata.init;
18 
19 import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
20 import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.ObjectInputStream;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.List;
27 import java.util.logging.Level;
28 import java.util.logging.Logger;
29 
30 /**
31  * Exposes single method for parsing {@link InputStream} content into {@link Collection} of {@link
32  * PhoneMetadata}
33  */
34 public final class MetadataParser {
35 
36   private static final Logger logger = Logger.getLogger(MetadataParser.class.getName());
37 
38   /**
39    * Creates new instance in lenient mode, see {@link MetadataParser#parse(InputStream)} for more
40    * info.
41    */
newLenientParser()42   public static MetadataParser newLenientParser() {
43     return new MetadataParser(false);
44   }
45 
46   /**
47    * Creates new instance in strict mode, see {@link MetadataParser#parse(InputStream)} for more
48    * info
49    */
newStrictParser()50   public static MetadataParser newStrictParser() {
51     return new MetadataParser(true);
52   }
53 
54   private final boolean strictMode;
55 
MetadataParser(boolean strictMode)56   private MetadataParser(boolean strictMode) {
57     this.strictMode = strictMode;
58   }
59 
60   /**
61    * Parses given {@link InputStream} into a {@link Collection} of {@link PhoneMetadata}.
62    *
63    * @throws IllegalArgumentException if {@code source} is {@code null} and strict mode is on
64    * @return parsed {@link PhoneMetadata}, or empty {@link Collection} if {@code source} is {@code
65    *     null} and lenient mode is on
66    */
parse(InputStream source)67   public Collection<PhoneMetadata> parse(InputStream source) {
68     if (source == null) {
69       return handleNullSource();
70     }
71     ObjectInputStream ois = null;
72     try {
73       ois = new ObjectInputStream(source);
74       PhoneMetadataCollection phoneMetadataCollection = new PhoneMetadataCollection();
75       phoneMetadataCollection.readExternal(ois);
76       List<PhoneMetadata> phoneMetadata = phoneMetadataCollection.getMetadataList();
77       // Sanity check; this should not happen if provided InputStream is valid
78       if (phoneMetadata.isEmpty()) {
79         throw new IllegalStateException("Empty metadata");
80       }
81       return phoneMetadataCollection.getMetadataList();
82     } catch (IOException e) {
83       throw new IllegalStateException("Unable to parse metadata file", e);
84     } finally {
85       if (ois != null) {
86         // This will close all underlying streams as well, including source.
87         close(ois);
88       } else {
89         close(source);
90       }
91     }
92   }
93 
handleNullSource()94   private List<PhoneMetadata> handleNullSource() {
95     if (strictMode) {
96       throw new IllegalArgumentException("Source cannot be null");
97     }
98     return Collections.emptyList();
99   }
100 
close(InputStream inputStream)101   private void close(InputStream inputStream) {
102     try {
103       inputStream.close();
104     } catch (IOException e) {
105       logger.log(Level.WARNING, "Error closing input stream (ignored)", e);
106     }
107   }
108 }