12ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* GENERATED SOURCE. DO NOT MODIFY. */
2f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// © 2016 and later: Unicode, Inc. and others.
3f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
42ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/*
52ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *******************************************************************************
62ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Copyright (C) 2004-2014, International Business Machines Corporation and
72ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * others. All Rights Reserved.
82ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *******************************************************************************
92ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Created on Feb 4, 2004
112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpackage android.icu.impl;
142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.io.IOException;
162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.io.InputStream;
172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.net.URL;
182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.security.AccessController;
192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.security.PrivilegedAction;
202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.MissingResourceException;
212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.logging.Logger;
222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.util.VersionInfo;
242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/**
262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Provides access to ICU data files as InputStreams.  Implements security checking.
27836e6b40a94ec3fb7545a76cb072960442b7eee9Neil Fuller * @hide Only a subset of ICU is exposed in Android
282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpublic final class ICUData {
302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The data path to be used with getBundleInstance API
322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    static final String ICU_DATA_PATH = "android/icu/impl/";
342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The ICU data package name.
362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * This is normally the name of the .dat package, and the prefix (plus '/')
372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * of the package entry names.
382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    static final String PACKAGE_NAME = "icudt" + VersionInfo.ICU_DATA_VERSION_PATH;
402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The data path to be used with Class.getResourceAsStream().
422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final String ICU_BUNDLE = "data/" + PACKAGE_NAME;
442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The base name of ICU data to be used with ClassLoader.getResourceAsStream(),
472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * ICUResourceBundle.getBundleInstance() etc.
482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final String ICU_BASE_NAME = ICU_DATA_PATH + ICU_BUNDLE;
502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The base name of collation data to be used with getBundleInstance API
532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final String ICU_COLLATION_BASE_NAME = ICU_BASE_NAME + "/coll";
552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The base name of rbbi data to be used with getData API
582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final String ICU_BRKITR_NAME = "brkitr";
602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The base name of rbbi data to be used with getBundleInstance API
632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final String ICU_BRKITR_BASE_NAME = ICU_BASE_NAME + '/' + ICU_BRKITR_NAME;
652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The base name of rbnf data to be used with getBundleInstance API
682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final String ICU_RBNF_BASE_NAME = ICU_BASE_NAME + "/rbnf";
702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The base name of transliterator data to be used with getBundleInstance API
732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final String ICU_TRANSLIT_BASE_NAME = ICU_BASE_NAME + "/translit";
752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final String ICU_LANG_BASE_NAME = ICU_BASE_NAME + "/lang";
772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final String ICU_CURR_BASE_NAME = ICU_BASE_NAME + "/curr";
782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final String ICU_REGION_BASE_NAME = ICU_BASE_NAME + "/region";
792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final String ICU_ZONE_BASE_NAME = ICU_BASE_NAME + "/zone";
802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final String ICU_UNIT_BASE_NAME = ICU_BASE_NAME + "/unit";
812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * For testing (otherwise false): When reading an InputStream from a Class or ClassLoader
842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * (that is, not from a file), log when the stream contains ICU binary data.
852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * This cannot be ICUConfig'ured because ICUConfig calls ICUData.getStream()
872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * to read the properties file, so we would get a circular dependency
882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * in the class initialization.
892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final boolean logBinaryDataFromInputStream = false;
912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final Logger logger = logBinaryDataFromInputStream ?
922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            Logger.getLogger(ICUData.class.getName()) : null;
932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static boolean exists(final String resourceName) {
952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        URL i = null;
962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (System.getSecurityManager() != null) {
972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            i = AccessController.doPrivileged(new PrivilegedAction<URL>() {
98f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    @Override
992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    public URL run() {
1002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        return ICUData.class.getResource(resourceName);
1012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
1022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                });
1032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
1042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            i = ICUData.class.getResource(resourceName);
1052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return i != null;
1072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static InputStream getStream(final Class<?> root, final String resourceName, boolean required) {
1102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        InputStream i = null;
1112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (System.getSecurityManager() != null) {
1122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            i = AccessController.doPrivileged(new PrivilegedAction<InputStream>() {
113f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    @Override
1142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    public InputStream run() {
1152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        return root.getResourceAsStream(resourceName);
1162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
1172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                });
1182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
1192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            i = root.getResourceAsStream(resourceName);
1202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (i == null && required) {
1232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new MissingResourceException("could not locate data " +resourceName, root.getPackage().getName(), resourceName);
1242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        checkStreamForBinaryData(i, resourceName);
1262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return i;
1272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Should be called only from ICUBinary.getData() or from convenience overloads here.
1312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    static InputStream getStream(final ClassLoader loader, final String resourceName, boolean required) {
1332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        InputStream i = null;
1342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (System.getSecurityManager() != null) {
1352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            i = AccessController.doPrivileged(new PrivilegedAction<InputStream>() {
136f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    @Override
1372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    public InputStream run() {
1382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        return loader.getResourceAsStream(resourceName);
1392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
1402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                });
1412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
1422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            i = loader.getResourceAsStream(resourceName);
1432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (i == null && required) {
1452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new MissingResourceException("could not locate data", loader.toString(), resourceName);
1462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        checkStreamForBinaryData(i, resourceName);
1482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return i;
1492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @SuppressWarnings("unused")  // used if logBinaryDataFromInputStream == true
1522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static void checkStreamForBinaryData(InputStream is, String resourceName) {
1532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (logBinaryDataFromInputStream && is != null && resourceName.indexOf(PACKAGE_NAME) >= 0) {
1542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            try {
1552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                is.mark(32);
1562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                byte[] b = new byte[32];
1572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int len = is.read(b);
1582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (len == 32 && b[2] == (byte)0xda && b[3] == 0x27) {
1592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    String msg = String.format(
1602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            "ICU binary data file loaded from Class/ClassLoader as InputStream " +
1612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            "from %s: MappedData %02x%02x%02x%02x  dataFormat %02x%02x%02x%02x",
1622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            resourceName,
1632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            b[0], b[1], b[2], b[3],
1642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                            b[12], b[13], b[14], b[15]);
1652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    logger.info(msg);
1662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
1672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                is.reset();
1682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } catch (IOException ignored) {
1692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static InputStream getStream(ClassLoader loader, String resourceName){
1742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return getStream(loader,resourceName, false);
1752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static InputStream getRequiredStream(ClassLoader loader, String resourceName){
1782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return getStream(loader, resourceName, true);
1792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convenience override that calls getStream(ICUData.class, resourceName, false);
1832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns null if the resource could not be found.
1842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static InputStream getStream(String resourceName) {
1862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return getStream(ICUData.class, resourceName, false);
1872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convenience method that calls getStream(ICUData.class, resourceName, true).
1912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @throws MissingResourceException if the resource could not be found
1922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static InputStream getRequiredStream(String resourceName) {
1942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return getStream(ICUData.class, resourceName, true);
1952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convenience override that calls getStream(root, resourceName, false);
1992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns null if the resource could not be found.
2002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static InputStream getStream(Class<?> root, String resourceName) {
2022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return getStream(root, resourceName, false);
2032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convenience method that calls getStream(root, resourceName, true).
2072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @throws MissingResourceException if the resource could not be found
2082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static InputStream getRequiredStream(Class<?> root, String resourceName) {
2102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return getStream(root, resourceName, true);
2112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller}
213