diff --git a/java/libphonenumber/src/com/google/i18n/phonenumbers/metadata/DefaultMetadataDependenciesProvider.java b/java/libphonenumber/src/com/google/i18n/phonenumbers/metadata/DefaultMetadataDependenciesProvider.java index 06fd6ad62..ab818acdc 100644 --- a/java/libphonenumber/src/com/google/i18n/phonenumbers/metadata/DefaultMetadataDependenciesProvider.java +++ b/java/libphonenumber/src/com/google/i18n/phonenumbers/metadata/DefaultMetadataDependenciesProvider.java @@ -29,7 +29,7 @@ import com.google.i18n.phonenumbers.metadata.source.RegionMetadataSource; import com.google.i18n.phonenumbers.metadata.source.RegionMetadataSourceImpl; /** - * Provides metadata init & source dependencies when metadata is stored in multi-file mode and + * Provides metadata init and source dependencies when metadata is stored in multi-file mode and * loaded as a classpath resource. */ public final class DefaultMetadataDependenciesProvider { diff --git a/tools/java/java-build/src/com/google/i18n/phonenumbers/buildtools/GeneratePhonePrefixDataEntryPoint.java b/tools/java/java-build/src/com/google/i18n/phonenumbers/buildtools/GeneratePhonePrefixDataEntryPoint.java index efabbca35..f4d8a366d 100644 --- a/tools/java/java-build/src/com/google/i18n/phonenumbers/buildtools/GeneratePhonePrefixDataEntryPoint.java +++ b/tools/java/java-build/src/com/google/i18n/phonenumbers/buildtools/GeneratePhonePrefixDataEntryPoint.java @@ -25,11 +25,13 @@ import java.util.logging.Logger; /** * Entry point class used to invoke the generation of the binary phone prefix data files. - * - * @author Philippe Liard */ public class GeneratePhonePrefixDataEntryPoint extends Command { + private static final Logger logger = Logger.getLogger(GeneratePhonePrefixData.class.getName()); + private static final String USAGE_DESCRIPTION = + "usage: GeneratePhonePrefixData /path/to/input/directory /path/to/output/directory" + + " [outputJarName]"; @Override public String getCommandName() { @@ -40,16 +42,20 @@ public class GeneratePhonePrefixDataEntryPoint extends Command { public boolean start() { String[] args = getArgs(); - if (args.length != 3) { - logger.log(Level.SEVERE, - "usage: GeneratePhonePrefixData /path/to/input/directory " - + "/path/to/output/directory"); + if (args.length < 2 || args.length > 3) { + logger.log(Level.SEVERE, USAGE_DESCRIPTION); return false; } try { - GeneratePhonePrefixData generatePhonePrefixData = - new GeneratePhonePrefixData(new File(args[1]), new PhonePrefixDataIOHandler(new File(args[2]))); - generatePhonePrefixData.run(); + File inputPath = new File(args[0]); + File outputPath = new File(args[1]); + AbstractPhonePrefixDataIOHandler ioHandler = + args.length == 2 + ? new PhonePrefixDataIOHandler(outputPath) + : new JarPhonePrefixDataIOHandler( + outputPath, args[2], GeneratePhonePrefixData.class.getPackage()); + GeneratePhonePrefixData dataGenerator = new GeneratePhonePrefixData(inputPath, ioHandler); + dataGenerator.run(); } catch (IOException e) { logger.log(Level.SEVERE, e.getMessage()); return false; diff --git a/tools/java/java-build/src/com/google/i18n/phonenumbers/buildtools/GenerateTimeZonesMapDataEntryPoint.java b/tools/java/java-build/src/com/google/i18n/phonenumbers/buildtools/GenerateTimeZonesMapDataEntryPoint.java index 77a7e5ea6..edc7a5d18 100644 --- a/tools/java/java-build/src/com/google/i18n/phonenumbers/buildtools/GenerateTimeZonesMapDataEntryPoint.java +++ b/tools/java/java-build/src/com/google/i18n/phonenumbers/buildtools/GenerateTimeZonesMapDataEntryPoint.java @@ -31,6 +31,9 @@ import java.util.logging.Logger; */ public class GenerateTimeZonesMapDataEntryPoint extends Command { private static final Logger logger = Logger.getLogger(GenerateTimeZonesMapData.class.getName()); + private static final String USAGE_DESCRIPTION = + "usage: GenerateTimeZonesMapData /path/to/input/directory /path/to/output/directory" + + " [outputJarName]"; @Override public String getCommandName() { @@ -41,15 +44,19 @@ public class GenerateTimeZonesMapDataEntryPoint extends Command { public boolean start() { String[] args = getArgs(); - if (args.length != 3) { - logger.log(Level.SEVERE, - "usage: GenerateTimeZonesMapData /path/to/input/text_file " - + "/path/to/output/directory"); + if (args.length < 2 || args.length > 3) { + logger.log(Level.SEVERE, USAGE_DESCRIPTION); return false; } try { - GenerateTimeZonesMapData generateTimeZonesMapData = new GenerateTimeZonesMapData( - new File(args[1]), new PhonePrefixDataIOHandler(new File(args[2]))); + File inputPath = new File(args[0]); + File outputPath = new File(args[1]); + AbstractPhonePrefixDataIOHandler ioHandler = + args.length == 2 + ? new PhonePrefixDataIOHandler(outputPath) + : new JarPhonePrefixDataIOHandler( + outputPath, args[2], GeneratePhonePrefixData.class.getPackage()); + GenerateTimeZonesMapData generateTimeZonesMapData = new GenerateTimeZonesMapData(inputPath, ioHandler); generateTimeZonesMapData.run(); } catch (IOException e) { logger.log(Level.SEVERE, e.getMessage()); diff --git a/tools/java/java-build/src/com/google/i18n/phonenumbers/buildtools/JarPhonePrefixDataIOHandler.java b/tools/java/java-build/src/com/google/i18n/phonenumbers/buildtools/JarPhonePrefixDataIOHandler.java new file mode 100644 index 000000000..8a87a43c3 --- /dev/null +++ b/tools/java/java-build/src/com/google/i18n/phonenumbers/buildtools/JarPhonePrefixDataIOHandler.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2012 The Libphonenumber 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.i18n.phonenumbers.buildtools; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; + +/** + * Implementation of the AbstractPhonePrefixDataIOHandler required by the GeneratePhonePrefixData + * class used here to create the output files and add them to the resulting JAR. + */ +public class JarPhonePrefixDataIOHandler extends AbstractPhonePrefixDataIOHandler { + + // Base name of the output JAR files. It also forms part of the name of the package + // containing the generated binary data. + private final String jarBase; + // The path to the output directory. + private final File outputPath; + // The JAR output stream used by the JarPhonePrefixDataIOHandler. + private final JarOutputStream jarOutputStream; + // The package that will be used to create the JAR entry file. + private final Package outputPackage; + + public JarPhonePrefixDataIOHandler(File outputPath, String outputName, Package outputPackage) + throws IOException { + if (outputPath.exists()) { + if (!outputPath.isDirectory()) { + throw new IOException("Expected directory: " + outputPath.getAbsolutePath()); + } + } else { + if (!outputPath.mkdirs()) { + throw new IOException("Could not create directory " + outputPath.getAbsolutePath()); + } + } + this.outputPath = outputPath; + this.jarBase = outputName; + this.outputPackage = outputPackage; + jarOutputStream = createJar(); + } + + private JarOutputStream createJar() throws IOException { + Manifest manifest = new java.util.jar.Manifest(); + manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); + return new JarOutputStream(new FileOutputStream(new File(outputPath, jarBase + ".jar"))); + } + + /** + * Adds the provided file to the created JAR. + */ + @Override + public void addFileToOutput(File file) throws IOException { + JarEntry entry = + new JarEntry( + outputPackage.getName().replace('.', '/') + + String.format("/%s/", jarBase) + + file.getPath()); + entry.setTime(file.lastModified()); + jarOutputStream.putNextEntry(entry); + BufferedInputStream bufferedInputStream = null; + + try { + bufferedInputStream = new BufferedInputStream(new FileInputStream(file)); + byte[] buffer = new byte[4096]; + + for (int read; (read = bufferedInputStream.read(buffer)) > 0; ) { + jarOutputStream.write(buffer, 0, read); + } + if (!file.delete()) { + throw new IOException("Could not delete: " + file.getAbsolutePath()); + } + } finally { + jarOutputStream.closeEntry(); + closeFile(bufferedInputStream); + } + } + + @Override + public File createFile(String path) { + return new File(path); + } + + @Override + public void close() { + closeFile(jarOutputStream); + } +} diff --git a/tools/java/java-build/src/com/google/i18n/phonenumbers/buildtools/PhonePrefixDataIOHandler.java b/tools/java/java-build/src/com/google/i18n/phonenumbers/buildtools/PhonePrefixDataIOHandler.java index 72d3a626b..0584a1519 100644 --- a/tools/java/java-build/src/com/google/i18n/phonenumbers/buildtools/PhonePrefixDataIOHandler.java +++ b/tools/java/java-build/src/com/google/i18n/phonenumbers/buildtools/PhonePrefixDataIOHandler.java @@ -20,10 +20,11 @@ import java.io.File; import java.io.IOException; /** - * Implementation of the IOHandler required by the GeneratePhonePrefixData class used here to create - * the output files. + * Implementation of the AbstractPhonePrefixDataIOHandler required by the GeneratePhonePrefixData + * class used here to create the output files. */ class PhonePrefixDataIOHandler extends AbstractPhonePrefixDataIOHandler { + // The path to the output directory. private final File outputPath; @@ -40,11 +41,14 @@ class PhonePrefixDataIOHandler extends AbstractPhonePrefixDataIOHandler { this.outputPath = outputPath; } + /** + * This is a no-op. + * + *

This would be the place dealing with the addition of the provided file to the resulting JAR + * if the global output was a JAR instead of a directory containing the binary files. + */ @Override - public void addFileToOutput(File file) throws IOException { - // Do nothing. This would be the place dealing with the addition of the provided file to the - // resulting JAR if the global output was a JAR instead of a directory containing the binary - // files. + public void addFileToOutput(File file) { } @Override @@ -52,8 +56,10 @@ class PhonePrefixDataIOHandler extends AbstractPhonePrefixDataIOHandler { return new File(outputPath, path); } + /** + * This is a no-op, as no resource needs to be released. + */ @Override public void close() { - // Do nothing as no resource needs to be released. } } diff --git a/tools/java/java-build/test/com/google/i18n/phonenumbers/buildtools/JarPhonePrefixDataIOHandlerTest.java b/tools/java/java-build/test/com/google/i18n/phonenumbers/buildtools/JarPhonePrefixDataIOHandlerTest.java new file mode 100644 index 000000000..bcb8cae1e --- /dev/null +++ b/tools/java/java-build/test/com/google/i18n/phonenumbers/buildtools/JarPhonePrefixDataIOHandlerTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2012 The Libphonenumber 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.i18n.phonenumbers.buildtools; + +import java.io.File; +import java.io.IOException; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.logging.Level; +import java.util.logging.Logger; +import junit.framework.TestCase; + +/** + * Unittests for JarPhonePrefixDataIOHandler.java + */ +public class JarPhonePrefixDataIOHandlerTest extends TestCase { + + private static final String TESTING_JAR_BASE = "testing_data"; + private static final Logger logger = + Logger.getLogger(JarPhonePrefixDataIOHandlerTest.class.getName()); + + public void testAddFileToOutput() { + File outputFile = null; + + try { + // Create the output jar. + File outputPath = new File("/tmp/build"); + Package outputPackage = JarPhonePrefixDataIOHandlerTest.class.getPackage(); + + JarPhonePrefixDataIOHandler ioHandler = + new JarPhonePrefixDataIOHandler(outputPath, TESTING_JAR_BASE, outputPackage); + outputFile = File.createTempFile("outputTestFile", "txt"); + ioHandler.addFileToOutput(outputFile); + ioHandler.close(); + + JarFile outputJar = new JarFile(new File(outputPath, TESTING_JAR_BASE + ".jar")); + // Test if there is exactly one entry in the jar. + Enumeration entries = outputJar.entries(); + int entriesCount = 0; + while (entries.hasMoreElements()) { + entriesCount++; + entries.nextElement(); + } + assertEquals(1, entriesCount); + + // Test if the entry file in the jar has the expected path. + String jarEntryPath = + "com/google/i18n/phonenumbers/buildtools/" + + TESTING_JAR_BASE + + "/" + + outputFile.getPath(); + JarEntry jarEntry = outputJar.getJarEntry(jarEntryPath); + assertNotNull("Output file not found inside the jar.", jarEntry); + } catch (IOException e) { + logger.log(Level.SEVERE, e.getMessage()); + fail(); + } finally { + if (outputFile != null && outputFile.exists()) { + outputFile.delete(); + } + } + } +} \ No newline at end of file