1 /* 2 * Copyright (C) 2020 The Android Open Source Project 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.android.timezone.location.common; 18 19 import java.io.BufferedReader; 20 import java.io.File; 21 import java.io.FileInputStream; 22 import java.io.FileReader; 23 import java.io.IOException; 24 import java.nio.file.Files; 25 import java.util.Arrays; 26 import java.util.Objects; 27 28 /** Utilities to help with LICENSE files and associated headers. */ 29 public class LicenseSupport { 30 31 /** 32 * The standard header to be put in files generated from OpenStreetMap data obtained from 33 * https://opendatacommons.org/licenses/odbl/ on 2020-08-04. 34 */ 35 private static final String TEXT_PROTO_ODBL_LICENSE_HEADER = "" 36 + "# This time zone geo data is made available under the Open Database License:\n" 37 + "# http://opendatacommons.org/licenses/odbl/1.0/.\n" 38 + "# Any rights in individual contents of the database are licensed under the Database" 39 + " Contents License:\n" 40 + "# http://opendatacommons.org/licenses/dbcl/1.0/\n" 41 + "\n"; 42 private static final String ODBL_LICENSE_SNIPPET = "Open Database License (ODbL) v1.0"; 43 44 public static final String LICENSE_FILE_NAME = "LICENSE"; 45 46 /** Individual licenses. */ 47 public enum License { 48 ODBL(ODBL_LICENSE_SNIPPET, TEXT_PROTO_ODBL_LICENSE_HEADER); 49 50 private final String mTextProtoHeader; 51 52 private final String mLicenseFileSnippet; 53 License(String licenseFileSnippet, String textProtoHeader)54 License(String licenseFileSnippet, String textProtoHeader) { 55 this.mLicenseFileSnippet = Objects.requireNonNull(licenseFileSnippet); 56 this.mTextProtoHeader = Objects.requireNonNull(textProtoHeader); 57 } 58 59 /** Returns the text proto file header for this license type. */ getTextProtoHeader()60 public String getTextProtoHeader() { 61 return mTextProtoHeader; 62 } 63 64 /** 65 * Confirms a LICENSE file is present and contains a snippet of the expected license, or 66 * throws an exception. 67 */ checkLicensePresentInDir(File dir)68 public void checkLicensePresentInDir(File dir) throws IOException { 69 checkIsDir(dir); 70 File licenseFile = new File(dir, LICENSE_FILE_NAME); 71 checkIsFile(licenseFile); 72 checkFileContains(licenseFile, mLicenseFileSnippet); 73 } 74 } 75 LicenseSupport()76 private LicenseSupport() { 77 } 78 79 /** 80 * Copies the LICENSE file from {@code inputDir} to {@code outputDir} as needed. If the file 81 * already exists in the {@code outputDir}, it is checked to see if it is the same. 82 */ copyLicenseFile(File inputDir, File outputDir)83 public static void copyLicenseFile(File inputDir, File outputDir) throws IOException { 84 checkIsDir(inputDir); 85 checkIsDir(outputDir); 86 87 File licenseFileInput = new File(inputDir, LICENSE_FILE_NAME); 88 if (!licenseFileInput.exists()) { 89 throw new IllegalArgumentException(licenseFileInput + " does not exist"); 90 } 91 File licenseOutputFile = new File(outputDir, LICENSE_FILE_NAME); 92 if (licenseOutputFile.exists()) { 93 System.out.println(licenseOutputFile + " already exists: checking content"); 94 // Just do a basic check for equality. 95 checkFilesIdentical(licenseFileInput, licenseOutputFile); 96 } else { 97 System.out.println( 98 "Copying LICENSE from " + licenseFileInput + " to " + licenseOutputFile); 99 Files.copy(licenseFileInput.toPath(), licenseOutputFile.toPath()); 100 } 101 } 102 checkFilesIdentical(File one, File two)103 private static void checkFilesIdentical(File one, File two) throws IOException { 104 try (FileInputStream oneInput = new FileInputStream(one); 105 FileInputStream twoInput = new FileInputStream(two)) { 106 107 byte[] oneBytes = oneInput.readAllBytes(); 108 byte[] twoBytes = twoInput.readAllBytes(); 109 if (!Arrays.equals(oneBytes, twoBytes)) { 110 throw new IllegalArgumentException("File " + one + " is not the same as " + two); 111 } 112 } 113 } 114 checkFileContains(File file, String snippet)115 private static void checkFileContains(File file, String snippet) throws IOException { 116 try (BufferedReader reader = new BufferedReader(new FileReader(file))) { 117 String line; 118 while ((line = reader.readLine()) != null) { 119 if (line.contains(snippet)) { 120 return; 121 } 122 } 123 } 124 throw new IllegalArgumentException(file + " does not contain " + snippet); 125 } 126 checkIsFile(File file)127 private static void checkIsFile(File file) { 128 if (!file.isFile()) { 129 throw new IllegalArgumentException(file + " is not a file."); 130 } 131 } 132 checkIsDir(File dir)133 private static void checkIsDir(File dir) { 134 if (!dir.isDirectory()) { 135 throw new IllegalArgumentException(dir + " is not a directory."); 136 } 137 } 138 } 139