All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.oracle.svm.thirdparty.ICU4JFeature Maven / Gradle / Ivy

There is a newer version: 19.2.1
Show newest version
/*
 * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.oracle.svm.thirdparty;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BooleanSupplier;

import org.graalvm.nativeimage.Feature;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.RuntimeReflection;

import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.AutomaticFeature;
import com.oracle.svm.core.annotate.InjectAccessors;
import com.oracle.svm.core.annotate.RecomputeFieldValue;
import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.core.util.VMError;

/**
 * ICU4JFeature enables ICU4J library ({@link "http://site.icu-project.org/"} to be used in SVM.
 * 

* The main obstacle in using the ICU4J library as is was that the library relies on class loader to * fetch localization data from resource files included in the ICU4J jar archive. This feature is * not supported by SVM, so the next option was to read the resource files from the file system. The * following code addresses several issues that occurred when specifying * com.ibm.icu.impl.ICUBinary.dataPath system property in runtime (standard ICU4J * feature). */ @AutomaticFeature public final class ICU4JFeature implements Feature { static final class IsEnabled implements BooleanSupplier { @Override public boolean getAsBoolean() { return ImageSingletons.contains(ICU4JFeature.class); } } @Override public boolean isInConfiguration(IsInConfigurationAccess access) { return access.findClassByName("com.ibm.icu.impl.ClassLoaderUtil") != null; } @Override public void beforeAnalysis(BeforeAnalysisAccess access) { registerShimClass(access, "com.ibm.icu.text.NumberFormatServiceShim"); registerShimClass(access, "com.ibm.icu.text.CollatorServiceShim"); } private static void registerShimClass(BeforeAnalysisAccess access, String shimClassName) { Class shimClass = access.findClassByName(shimClassName); if (shimClass != null) { RuntimeReflection.registerForReflectiveInstantiation(shimClass); } else { throw VMError.shouldNotReachHere(shimClassName + " not found"); } } static class Helper { /** Dummy ClassLoader used only for resource loading. */ // Checkstyle: stop static final ClassLoader DUMMY_LOADER = new ClassLoader(null) { }; // CheckStyle: resume } } @TargetClass(className = "com.ibm.icu.impl.ClassLoaderUtil", onlyWith = ICU4JFeature.IsEnabled.class) final class Target_com_ibm_icu_impl_ClassLoaderUtil { @Substitute // Checkstyle: stop public static ClassLoader getClassLoader() { return ICU4JFeature.Helper.DUMMY_LOADER; } // Checkstyle: resume } @TargetClass(className = "com.ibm.icu.impl.ICUBinary", onlyWith = ICU4JFeature.IsEnabled.class) final class Target_com_ibm_icu_impl_ICUBinary { @Alias static native void addDataFilesFromPath(String dataPath, List files); @Alias @InjectAccessors(IcuDataFilesAccessors.class) static List icuDataFiles; static final class IcuDataFilesAccessors { private static final String ICU4J_DATA_PATH_SYS_PROP = "com.ibm.icu.impl.ICUBinary.dataPath"; private static final String ICU4J_DATA_PATH_ENV_VAR = "ICU4J_DATA_PATH"; private static final String NO_DATA_PATH_ERR_MSG = "No ICU4J data path was set or found. This will likely end up with a MissingResourceException. " + "To take advantage of the ICU4J library, you should either set system property, " + ICU4J_DATA_PATH_SYS_PROP + ", or set environment variable, " + ICU4J_DATA_PATH_ENV_VAR + ", to contain path to your ICU4J icudt directory"; private static volatile List instance; static List get() { if (instance == null) { // Checkstyle: allow synchronization synchronized (IcuDataFilesAccessors.class) { if (instance == null) { instance = new ArrayList<>(); String dataPath = System.getProperty(ICU4J_DATA_PATH_SYS_PROP); if (dataPath == null || dataPath.isEmpty()) { dataPath = System.getenv(ICU4J_DATA_PATH_ENV_VAR); } if (dataPath != null && !dataPath.isEmpty()) { addDataFilesFromPath(dataPath, instance); } else { System.err.println(NO_DATA_PATH_ERR_MSG); } } } // Checkstyle: disallow synchronization } return instance; } } } @TargetClass(className = "com.ibm.icu.impl.ICUResourceBundle", onlyWith = ICU4JFeature.IsEnabled.class) final class Target_com_ibm_icu_impl_ICUResourceBundle { @Alias @RecomputeFieldValue(kind = Kind.FromAlias, isFinal = true) // Checkstyle: stop private static final ClassLoader ICU_DATA_CLASS_LOADER = ICU4JFeature.Helper.DUMMY_LOADER; // Checkstyle: resume @SuppressWarnings("unused") @Substitute // Checkstyle: stop private static void addBundleBaseNamesFromClassLoader(final String bn, final ClassLoader root, final Set names) { } // Checkstyle: resume } @TargetClass(className = "com.ibm.icu.impl.ICUResourceBundle$WholeBundle", onlyWith = ICU4JFeature.IsEnabled.class) final class Target_com_ibm_icu_impl_ICUResourceBundle_WholeBundle { @Alias @RecomputeFieldValue(kind = Kind.Reset) // Checkstyle: stop ClassLoader loader; // Checkstyle: resume } @TargetClass(className = "com.ibm.icu.impl.SoftCache", onlyWith = ICU4JFeature.IsEnabled.class) final class Target_com_ibm_icu_impl_SoftCache { // Checkstyle: stop @Alias @RecomputeFieldValue(kind = Kind.NewInstance, declClass = ConcurrentHashMap.class) private ConcurrentHashMap map; // Checkstyle: resume } @TargetClass(className = "com.ibm.icu.impl.ICUResourceBundle$AvailEntry", onlyWith = ICU4JFeature.IsEnabled.class) final class Target_com_ibm_icu_impl_ICUResourceBundle_AvailEntry { @Alias @RecomputeFieldValue(kind = Kind.Reset) // Checkstyle: stop ClassLoader loader; // Checkstyle: resume } @TargetClass(className = "com.ibm.icu.util.TimeZone", onlyWith = ICU4JFeature.IsEnabled.class) final class Target_com_ibm_icu_util_TimeZone { // clear default time zone to force reinitialization at run time @Alias @RecomputeFieldValue(kind = Kind.Reset) private static Target_com_ibm_icu_util_TimeZone defaultZone; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy