diff --git a/Java/commons-lang-LocaleUtils_193/Dockerfile b/Java/commons-lang-LocaleUtils_193/Dockerfile new file mode 100644 index 000000000..7b7fbe349 --- /dev/null +++ b/Java/commons-lang-LocaleUtils_193/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-lang + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/commons-lang-LocaleUtils_193/buggy.java b/Java/commons-lang-LocaleUtils_193/buggy.java new file mode 100644 index 000000000..4bf86865d --- /dev/null +++ b/Java/commons-lang-LocaleUtils_193/buggy.java @@ -0,0 +1,348 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.commons.lang3; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + *

Operations to assist when working with a {@link Locale}.

+ * + *

This class tries to handle {@code null} input gracefully. + * An exception will not be thrown for a {@code null} input. + * Each method documents its behaviour in more detail.

+ * + * @since 2.2 + */ +public class LocaleUtils { + + /** Concurrent map of language locales by country. */ + private static final ConcurrentMap> cLanguagesByCountry = + new ConcurrentHashMap>(); + + /** Concurrent map of country locales by language. */ + private static final ConcurrentMap> cCountriesByLanguage = + new ConcurrentHashMap>(); + + /** + *

{@code LocaleUtils} instances should NOT be constructed in standard programming. + * Instead, the class should be used as {@code LocaleUtils.toLocale("en_GB");}.

+ * + *

This constructor is public to permit tools that require a JavaBean instance + * to operate.

+ */ + public LocaleUtils() { + super(); + } + + //----------------------------------------------------------------------- + /** + *

Converts a String to a Locale.

+ * + *

This method takes the string format of a locale and creates the + * locale object from it.

+ * + *
+     *   LocaleUtils.toLocale("")           = new Locale("", "")
+     *   LocaleUtils.toLocale("en")         = new Locale("en", "")
+     *   LocaleUtils.toLocale("en_GB")      = new Locale("en", "GB")
+     *   LocaleUtils.toLocale("en_GB_xxx")  = new Locale("en", "GB", "xxx")   (#)
+     * 
+ * + *

(#) The behaviour of the JDK variant constructor changed between JDK1.3 and JDK1.4. + * In JDK1.3, the constructor upper cases the variant, in JDK1.4, it doesn't. + * Thus, the result from getVariant() may vary depending on your JDK.

+ * + *

This method validates the input strictly. + * The language code must be lowercase. + * The country code must be uppercase. + * The separator must be an underscore. + * The length must be correct. + *

+ * + * @param str the locale String to convert, null returns null + * @return a Locale, null if null input + * @throws IllegalArgumentException if the string is an invalid format + * @see Locale#forLanguageTag(String) + */ + public static Locale toLocale(final String str) { + if (str == null) { + return null; + } + if (str.isEmpty()) { // LANG-941 - JDK 8 introduced an empty locale where all fields are blank + return new Locale(StringUtils.EMPTY, StringUtils.EMPTY); + } + if (str.contains("#")) { // LANG-879 - Cannot handle Java 7 script & extensions + throw new IllegalArgumentException("Invalid locale format: " + str); + } + final int len = str.length(); + if (len < 2) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + final char ch0 = str.charAt(0); + if (ch0 == '_') { + if (len < 3) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + final char ch1 = str.charAt(1); + final char ch2 = str.charAt(2); + if (!Character.isUpperCase(ch1) || !Character.isUpperCase(ch2)) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + if (len == 3) { + return new Locale(StringUtils.EMPTY, str.substring(1, 3)); + } + if (len < 5) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + if (str.charAt(3) != '_') { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + return new Locale(StringUtils.EMPTY, str.substring(1, 3), str.substring(4)); + } + + final String[] split = str.split("_", -1); + final int occurrences = split.length -1; + switch (occurrences) { + case 0: + if (StringUtils.isAllLowerCase(str) && (len == 2 || len == 3)) { + return new Locale(str); + } + throw new IllegalArgumentException("Invalid locale format: " + str); + + case 1: + if (StringUtils.isAllLowerCase(split[0]) && + (split[0].length() == 2 || split[0].length() == 3) && + split[1].length() == 2 && StringUtils.isAllUpperCase(split[1])) { + return new Locale(split[0], split[1]); + } + throw new IllegalArgumentException("Invalid locale format: " + str); + + case 2: + if (StringUtils.isAllLowerCase(split[0]) && + (split[0].length() == 2 || split[0].length() == 3) && + (split[1].length() == 0 || split[1].length() == 2 && StringUtils.isAllUpperCase(split[1])) && + split[2].length() > 0) { + return new Locale(split[0], split[1], split[2]); + } + + //$FALL-THROUGH$ + default: + throw new IllegalArgumentException("Invalid locale format: " + str); + } + } + + //----------------------------------------------------------------------- + /** + *

Obtains the list of locales to search through when performing + * a locale search.

+ * + *
+     * localeLookupList(Locale("fr","CA","xxx"))
+     *   = [Locale("fr","CA","xxx"), Locale("fr","CA"), Locale("fr")]
+     * 
+ * + * @param locale the locale to start from + * @return the unmodifiable list of Locale objects, 0 being locale, not null + */ + public static List localeLookupList(final Locale locale) { + return localeLookupList(locale, locale); + } + + //----------------------------------------------------------------------- + /** + *

Obtains the list of locales to search through when performing + * a locale search.

+ * + *
+     * localeLookupList(Locale("fr", "CA", "xxx"), Locale("en"))
+     *   = [Locale("fr","CA","xxx"), Locale("fr","CA"), Locale("fr"), Locale("en"]
+     * 
+ * + *

The result list begins with the most specific locale, then the + * next more general and so on, finishing with the default locale. + * The list will never contain the same locale twice.

+ * + * @param locale the locale to start from, null returns empty list + * @param defaultLocale the default locale to use if no other is found + * @return the unmodifiable list of Locale objects, 0 being locale, not null + */ +// ----------------------------------------------------------------------- +/** + *

Obtains the list of locales to search through when performing + * a locale search.

+ * + *
+ * localeLookupList(Locale("fr", "CA", "xxx"), Locale("en"))
+ * = [Locale("fr","CA","xxx"), Locale("fr","CA"), Locale("fr"), Locale("en"]
+ * 
+ * + *

The result list begins with the most specific locale, then the + * next more general and so on, finishing with the default locale. + * The list will never contain the same locale twice.

+ * + * @param locale + * the locale to start from, null returns empty list + * @param defaultLocale + * the default locale to use if no other is found + * @return the unmodifiable list of Locale objects, 0 being locale, not null + */ +public static java.util.List localeLookupList(final java.util.Locale locale, final java.util.Locale defaultLocale) { + final java.util.List list = new java.util.ArrayList(4); + { + list.add(/* NPEX_NULL_EXP */ + locale); + if (locale.getVariant().length() > 0) { + list.add(new java.util.Locale(locale.getLanguage(), locale.getCountry())); + } + if (locale.getCountry().length() > 0) { + list.add(new java.util.Locale(locale.getLanguage(), org.apache.commons.lang3.StringUtils.EMPTY)); + } + if (list.contains(defaultLocale) == false) { + list.add(defaultLocale); + } + } + return java.util.Collections.unmodifiableList(list); +} + + //----------------------------------------------------------------------- + /** + *

Obtains an unmodifiable list of installed locales.

+ * + *

This method is a wrapper around {@link Locale#getAvailableLocales()}. + * It is more efficient, as the JDK method must create a new array each + * time it is called.

+ * + * @return the unmodifiable list of available locales + */ + public static List availableLocaleList() { + return SyncAvoid.AVAILABLE_LOCALE_LIST; + } + + //----------------------------------------------------------------------- + /** + *

Obtains an unmodifiable set of installed locales.

+ * + *

This method is a wrapper around {@link Locale#getAvailableLocales()}. + * It is more efficient, as the JDK method must create a new array each + * time it is called.

+ * + * @return the unmodifiable set of available locales + */ + public static Set availableLocaleSet() { + return SyncAvoid.AVAILABLE_LOCALE_SET; + } + + //----------------------------------------------------------------------- + /** + *

Checks if the locale specified is in the list of available locales.

+ * + * @param locale the Locale object to check if it is available + * @return true if the locale is a known locale + */ + public static boolean isAvailableLocale(final Locale locale) { + return availableLocaleList().contains(locale); + } + + //----------------------------------------------------------------------- + /** + *

Obtains the list of languages supported for a given country.

+ * + *

This method takes a country code and searches to find the + * languages available for that country. Variant locales are removed.

+ * + * @param countryCode the 2 letter country code, null returns empty + * @return an unmodifiable List of Locale objects, not null + */ + public static List languagesByCountry(final String countryCode) { + if (countryCode == null) { + return Collections.emptyList(); + } + List langs = cLanguagesByCountry.get(countryCode); + if (langs == null) { + langs = new ArrayList(); + final List locales = availableLocaleList(); + for (int i = 0; i < locales.size(); i++) { + final Locale locale = locales.get(i); + if (countryCode.equals(locale.getCountry()) && + locale.getVariant().isEmpty()) { + langs.add(locale); + } + } + langs = Collections.unmodifiableList(langs); + cLanguagesByCountry.putIfAbsent(countryCode, langs); + langs = cLanguagesByCountry.get(countryCode); + } + return langs; + } + + //----------------------------------------------------------------------- + /** + *

Obtains the list of countries supported for a given language.

+ * + *

This method takes a language code and searches to find the + * countries available for that language. Variant locales are removed.

+ * + * @param languageCode the 2 letter language code, null returns empty + * @return an unmodifiable List of Locale objects, not null + */ + public static List countriesByLanguage(final String languageCode) { + if (languageCode == null) { + return Collections.emptyList(); + } + List countries = cCountriesByLanguage.get(languageCode); + if (countries == null) { + countries = new ArrayList(); + final List locales = availableLocaleList(); + for (int i = 0; i < locales.size(); i++) { + final Locale locale = locales.get(i); + if (languageCode.equals(locale.getLanguage()) && + locale.getCountry().length() != 0 && + locale.getVariant().isEmpty()) { + countries.add(locale); + } + } + countries = Collections.unmodifiableList(countries); + cCountriesByLanguage.putIfAbsent(languageCode, countries); + countries = cCountriesByLanguage.get(languageCode); + } + return countries; + } + + //----------------------------------------------------------------------- + // class to avoid synchronization (Init on demand) + static class SyncAvoid { + /** Unmodifiable list of available locales. */ + private static final List AVAILABLE_LOCALE_LIST; + /** Unmodifiable set of available locales. */ + private static final Set AVAILABLE_LOCALE_SET; + + static { + final List list = new ArrayList(Arrays.asList(Locale.getAvailableLocales())); // extra safe + AVAILABLE_LOCALE_LIST = Collections.unmodifiableList(list); + AVAILABLE_LOCALE_SET = Collections.unmodifiableSet(new HashSet(list)); + } + } + +} diff --git a/Java/commons-lang-LocaleUtils_193/metadata.json b/Java/commons-lang-LocaleUtils_193/metadata.json new file mode 100644 index 000000000..bd86f425c --- /dev/null +++ b/Java/commons-lang-LocaleUtils_193/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-lang-LocaleUtils_193", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "src/main/java/org/apache/commons/lang3/LocaleUtils.java", + "line": 215, + "npe_method": "localeLookupList", + "deref_field": "locale", + "npe_class": "LocaleUtils", + "repo": "commons-lang", + "bug_id": "LocaleUtils_193" + } +} diff --git a/Java/commons-lang-LocaleUtils_193/npe.json b/Java/commons-lang-LocaleUtils_193/npe.json new file mode 100644 index 000000000..0faa32d0c --- /dev/null +++ b/Java/commons-lang-LocaleUtils_193/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/lang3/LocaleUtils.java", + "line": 215, + "npe_method": "localeLookupList", + "deref_field": "locale", + "npe_class": "LocaleUtils" +} \ No newline at end of file diff --git a/Java/commons-lang-LocaleUtils_258/Dockerfile b/Java/commons-lang-LocaleUtils_258/Dockerfile new file mode 100644 index 000000000..7b7fbe349 --- /dev/null +++ b/Java/commons-lang-LocaleUtils_258/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-lang + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/commons-lang-LocaleUtils_258/buggy.java b/Java/commons-lang-LocaleUtils_258/buggy.java new file mode 100644 index 000000000..d55b5fde9 --- /dev/null +++ b/Java/commons-lang-LocaleUtils_258/buggy.java @@ -0,0 +1,337 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.commons.lang3; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + *

Operations to assist when working with a {@link Locale}.

+ * + *

This class tries to handle {@code null} input gracefully. + * An exception will not be thrown for a {@code null} input. + * Each method documents its behaviour in more detail.

+ * + * @since 2.2 + */ +public class LocaleUtils { + + /** Concurrent map of language locales by country. */ + private static final ConcurrentMap> cLanguagesByCountry = + new ConcurrentHashMap>(); + + /** Concurrent map of country locales by language. */ + private static final ConcurrentMap> cCountriesByLanguage = + new ConcurrentHashMap>(); + + /** + *

{@code LocaleUtils} instances should NOT be constructed in standard programming. + * Instead, the class should be used as {@code LocaleUtils.toLocale("en_GB");}.

+ * + *

This constructor is public to permit tools that require a JavaBean instance + * to operate.

+ */ + public LocaleUtils() { + super(); + } + + //----------------------------------------------------------------------- + /** + *

Converts a String to a Locale.

+ * + *

This method takes the string format of a locale and creates the + * locale object from it.

+ * + *
+     *   LocaleUtils.toLocale("")           = new Locale("", "")
+     *   LocaleUtils.toLocale("en")         = new Locale("en", "")
+     *   LocaleUtils.toLocale("en_GB")      = new Locale("en", "GB")
+     *   LocaleUtils.toLocale("en_GB_xxx")  = new Locale("en", "GB", "xxx")   (#)
+     * 
+ * + *

(#) The behaviour of the JDK variant constructor changed between JDK1.3 and JDK1.4. + * In JDK1.3, the constructor upper cases the variant, in JDK1.4, it doesn't. + * Thus, the result from getVariant() may vary depending on your JDK.

+ * + *

This method validates the input strictly. + * The language code must be lowercase. + * The country code must be uppercase. + * The separator must be an underscore. + * The length must be correct. + *

+ * + * @param str the locale String to convert, null returns null + * @return a Locale, null if null input + * @throws IllegalArgumentException if the string is an invalid format + * @see Locale#forLanguageTag(String) + */ + public static Locale toLocale(final String str) { + if (str == null) { + return null; + } + if (str.isEmpty()) { // LANG-941 - JDK 8 introduced an empty locale where all fields are blank + return new Locale(StringUtils.EMPTY, StringUtils.EMPTY); + } + if (str.contains("#")) { // LANG-879 - Cannot handle Java 7 script & extensions + throw new IllegalArgumentException("Invalid locale format: " + str); + } + final int len = str.length(); + if (len < 2) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + final char ch0 = str.charAt(0); + if (ch0 == '_') { + if (len < 3) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + final char ch1 = str.charAt(1); + final char ch2 = str.charAt(2); + if (!Character.isUpperCase(ch1) || !Character.isUpperCase(ch2)) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + if (len == 3) { + return new Locale(StringUtils.EMPTY, str.substring(1, 3)); + } + if (len < 5) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + if (str.charAt(3) != '_') { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + return new Locale(StringUtils.EMPTY, str.substring(1, 3), str.substring(4)); + } + + final String[] split = str.split("_", -1); + final int occurrences = split.length -1; + switch (occurrences) { + case 0: + if (StringUtils.isAllLowerCase(str) && (len == 2 || len == 3)) { + return new Locale(str); + } + throw new IllegalArgumentException("Invalid locale format: " + str); + + case 1: + if (StringUtils.isAllLowerCase(split[0]) && + (split[0].length() == 2 || split[0].length() == 3) && + split[1].length() == 2 && StringUtils.isAllUpperCase(split[1])) { + return new Locale(split[0], split[1]); + } + throw new IllegalArgumentException("Invalid locale format: " + str); + + case 2: + if (StringUtils.isAllLowerCase(split[0]) && + (split[0].length() == 2 || split[0].length() == 3) && + (split[1].length() == 0 || split[1].length() == 2 && StringUtils.isAllUpperCase(split[1])) && + split[2].length() > 0) { + return new Locale(split[0], split[1], split[2]); + } + + //$FALL-THROUGH$ + default: + throw new IllegalArgumentException("Invalid locale format: " + str); + } + } + + //----------------------------------------------------------------------- + /** + *

Obtains the list of locales to search through when performing + * a locale search.

+ * + *
+     * localeLookupList(Locale("fr","CA","xxx"))
+     *   = [Locale("fr","CA","xxx"), Locale("fr","CA"), Locale("fr")]
+     * 
+ * + * @param locale the locale to start from + * @return the unmodifiable list of Locale objects, 0 being locale, not null + */ + public static List localeLookupList(final Locale locale) { + return localeLookupList(locale, locale); + } + + //----------------------------------------------------------------------- + /** + *

Obtains the list of locales to search through when performing + * a locale search.

+ * + *
+     * localeLookupList(Locale("fr", "CA", "xxx"), Locale("en"))
+     *   = [Locale("fr","CA","xxx"), Locale("fr","CA"), Locale("fr"), Locale("en"]
+     * 
+ * + *

The result list begins with the most specific locale, then the + * next more general and so on, finishing with the default locale. + * The list will never contain the same locale twice.

+ * + * @param locale the locale to start from, null returns empty list + * @param defaultLocale the default locale to use if no other is found + * @return the unmodifiable list of Locale objects, 0 being locale, not null + */ + public static List localeLookupList(final Locale locale, final Locale defaultLocale) { + final List list = new ArrayList(4); + if (locale != null) { + list.add(locale); + if (locale.getVariant().length() > 0) { + list.add(new Locale(locale.getLanguage(), locale.getCountry())); + } + if (locale.getCountry().length() > 0) { + list.add(new Locale(locale.getLanguage(), StringUtils.EMPTY)); + } + if (list.contains(defaultLocale) == false) { + list.add(defaultLocale); + } + } + return Collections.unmodifiableList(list); + } + + //----------------------------------------------------------------------- + /** + *

Obtains an unmodifiable list of installed locales.

+ * + *

This method is a wrapper around {@link Locale#getAvailableLocales()}. + * It is more efficient, as the JDK method must create a new array each + * time it is called.

+ * + * @return the unmodifiable list of available locales + */ + public static List availableLocaleList() { + return SyncAvoid.AVAILABLE_LOCALE_LIST; + } + + //----------------------------------------------------------------------- + /** + *

Obtains an unmodifiable set of installed locales.

+ * + *

This method is a wrapper around {@link Locale#getAvailableLocales()}. + * It is more efficient, as the JDK method must create a new array each + * time it is called.

+ * + * @return the unmodifiable set of available locales + */ + public static Set availableLocaleSet() { + return SyncAvoid.AVAILABLE_LOCALE_SET; + } + + //----------------------------------------------------------------------- + /** + *

Checks if the locale specified is in the list of available locales.

+ * + * @param locale the Locale object to check if it is available + * @return true if the locale is a known locale + */ + public static boolean isAvailableLocale(final Locale locale) { + return availableLocaleList().contains(locale); + } + + //----------------------------------------------------------------------- + /** + *

Obtains the list of languages supported for a given country.

+ * + *

This method takes a country code and searches to find the + * languages available for that country. Variant locales are removed.

+ * + * @param countryCode the 2 letter country code, null returns empty + * @return an unmodifiable List of Locale objects, not null + */ +// ----------------------------------------------------------------------- +/** + *

Obtains the list of languages supported for a given country.

+ * + *

This method takes a country code and searches to find the + * languages available for that country. Variant locales are removed.

+ * + * @param countryCode + * the 2 letter country code, null returns empty + * @return an unmodifiable List of Locale objects, not null + */ +public static java.util.List languagesByCountry(final java.lang.String countryCode) { + { + java.util.List langs = org.apache.commons.lang3.LocaleUtils.cLanguagesByCountry.get(/* NPEX_NULL_EXP */ + countryCode); + if (langs == null) { + langs = new java.util.ArrayList(); + final java.util.List locales = org.apache.commons.lang3.LocaleUtils.availableLocaleList(); + for (int i = 0; i < locales.size(); i++) { + final java.util.Locale locale = locales.get(i); + if (countryCode.equals(locale.getCountry()) && locale.getVariant().isEmpty()) { + langs.add(locale); + } + } + langs = java.util.Collections.unmodifiableList(langs); + org.apache.commons.lang3.LocaleUtils.cLanguagesByCountry.putIfAbsent(countryCode, langs); + langs = org.apache.commons.lang3.LocaleUtils.cLanguagesByCountry.get(countryCode); + } + return langs; + } +} + + //----------------------------------------------------------------------- + /** + *

Obtains the list of countries supported for a given language.

+ * + *

This method takes a language code and searches to find the + * countries available for that language. Variant locales are removed.

+ * + * @param languageCode the 2 letter language code, null returns empty + * @return an unmodifiable List of Locale objects, not null + */ + public static List countriesByLanguage(final String languageCode) { + if (languageCode == null) { + return Collections.emptyList(); + } + List countries = cCountriesByLanguage.get(languageCode); + if (countries == null) { + countries = new ArrayList(); + final List locales = availableLocaleList(); + for (int i = 0; i < locales.size(); i++) { + final Locale locale = locales.get(i); + if (languageCode.equals(locale.getLanguage()) && + locale.getCountry().length() != 0 && + locale.getVariant().isEmpty()) { + countries.add(locale); + } + } + countries = Collections.unmodifiableList(countries); + cCountriesByLanguage.putIfAbsent(languageCode, countries); + countries = cCountriesByLanguage.get(languageCode); + } + return countries; + } + + //----------------------------------------------------------------------- + // class to avoid synchronization (Init on demand) + static class SyncAvoid { + /** Unmodifiable list of available locales. */ + private static final List AVAILABLE_LOCALE_LIST; + /** Unmodifiable set of available locales. */ + private static final Set AVAILABLE_LOCALE_SET; + + static { + final List list = new ArrayList(Arrays.asList(Locale.getAvailableLocales())); // extra safe + AVAILABLE_LOCALE_LIST = Collections.unmodifiableList(list); + AVAILABLE_LOCALE_SET = Collections.unmodifiableSet(new HashSet(list)); + } + } + +} diff --git a/Java/commons-lang-LocaleUtils_258/metadata.json b/Java/commons-lang-LocaleUtils_258/metadata.json new file mode 100644 index 000000000..647342979 --- /dev/null +++ b/Java/commons-lang-LocaleUtils_258/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-lang-LocaleUtils_258", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "src/main/java/org/apache/commons/lang3/LocaleUtils.java", + "line": 271, + "npe_method": "languagesByCountry", + "deref_field": "countryCode", + "npe_class": "LocaleUtils", + "repo": "commons-lang", + "bug_id": "LocaleUtils_258" + } +} diff --git a/Java/commons-lang-LocaleUtils_258/npe.json b/Java/commons-lang-LocaleUtils_258/npe.json new file mode 100644 index 000000000..2497445d8 --- /dev/null +++ b/Java/commons-lang-LocaleUtils_258/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/lang3/LocaleUtils.java", + "line": 271, + "npe_method": "languagesByCountry", + "deref_field": "countryCode", + "npe_class": "LocaleUtils" +} \ No newline at end of file diff --git a/Java/commons-lang-LocaleUtils_290/Dockerfile b/Java/commons-lang-LocaleUtils_290/Dockerfile new file mode 100644 index 000000000..7b7fbe349 --- /dev/null +++ b/Java/commons-lang-LocaleUtils_290/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-lang + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/commons-lang-LocaleUtils_290/buggy.java b/Java/commons-lang-LocaleUtils_290/buggy.java new file mode 100644 index 000000000..72c0e86cd --- /dev/null +++ b/Java/commons-lang-LocaleUtils_290/buggy.java @@ -0,0 +1,336 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.commons.lang3; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + *

Operations to assist when working with a {@link Locale}.

+ * + *

This class tries to handle {@code null} input gracefully. + * An exception will not be thrown for a {@code null} input. + * Each method documents its behaviour in more detail.

+ * + * @since 2.2 + */ +public class LocaleUtils { + + /** Concurrent map of language locales by country. */ + private static final ConcurrentMap> cLanguagesByCountry = + new ConcurrentHashMap>(); + + /** Concurrent map of country locales by language. */ + private static final ConcurrentMap> cCountriesByLanguage = + new ConcurrentHashMap>(); + + /** + *

{@code LocaleUtils} instances should NOT be constructed in standard programming. + * Instead, the class should be used as {@code LocaleUtils.toLocale("en_GB");}.

+ * + *

This constructor is public to permit tools that require a JavaBean instance + * to operate.

+ */ + public LocaleUtils() { + super(); + } + + //----------------------------------------------------------------------- + /** + *

Converts a String to a Locale.

+ * + *

This method takes the string format of a locale and creates the + * locale object from it.

+ * + *
+     *   LocaleUtils.toLocale("")           = new Locale("", "")
+     *   LocaleUtils.toLocale("en")         = new Locale("en", "")
+     *   LocaleUtils.toLocale("en_GB")      = new Locale("en", "GB")
+     *   LocaleUtils.toLocale("en_GB_xxx")  = new Locale("en", "GB", "xxx")   (#)
+     * 
+ * + *

(#) The behaviour of the JDK variant constructor changed between JDK1.3 and JDK1.4. + * In JDK1.3, the constructor upper cases the variant, in JDK1.4, it doesn't. + * Thus, the result from getVariant() may vary depending on your JDK.

+ * + *

This method validates the input strictly. + * The language code must be lowercase. + * The country code must be uppercase. + * The separator must be an underscore. + * The length must be correct. + *

+ * + * @param str the locale String to convert, null returns null + * @return a Locale, null if null input + * @throws IllegalArgumentException if the string is an invalid format + * @see Locale#forLanguageTag(String) + */ + public static Locale toLocale(final String str) { + if (str == null) { + return null; + } + if (str.isEmpty()) { // LANG-941 - JDK 8 introduced an empty locale where all fields are blank + return new Locale(StringUtils.EMPTY, StringUtils.EMPTY); + } + if (str.contains("#")) { // LANG-879 - Cannot handle Java 7 script & extensions + throw new IllegalArgumentException("Invalid locale format: " + str); + } + final int len = str.length(); + if (len < 2) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + final char ch0 = str.charAt(0); + if (ch0 == '_') { + if (len < 3) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + final char ch1 = str.charAt(1); + final char ch2 = str.charAt(2); + if (!Character.isUpperCase(ch1) || !Character.isUpperCase(ch2)) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + if (len == 3) { + return new Locale(StringUtils.EMPTY, str.substring(1, 3)); + } + if (len < 5) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + if (str.charAt(3) != '_') { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + return new Locale(StringUtils.EMPTY, str.substring(1, 3), str.substring(4)); + } + + final String[] split = str.split("_", -1); + final int occurrences = split.length -1; + switch (occurrences) { + case 0: + if (StringUtils.isAllLowerCase(str) && (len == 2 || len == 3)) { + return new Locale(str); + } + throw new IllegalArgumentException("Invalid locale format: " + str); + + case 1: + if (StringUtils.isAllLowerCase(split[0]) && + (split[0].length() == 2 || split[0].length() == 3) && + split[1].length() == 2 && StringUtils.isAllUpperCase(split[1])) { + return new Locale(split[0], split[1]); + } + throw new IllegalArgumentException("Invalid locale format: " + str); + + case 2: + if (StringUtils.isAllLowerCase(split[0]) && + (split[0].length() == 2 || split[0].length() == 3) && + (split[1].length() == 0 || split[1].length() == 2 && StringUtils.isAllUpperCase(split[1])) && + split[2].length() > 0) { + return new Locale(split[0], split[1], split[2]); + } + + //$FALL-THROUGH$ + default: + throw new IllegalArgumentException("Invalid locale format: " + str); + } + } + + //----------------------------------------------------------------------- + /** + *

Obtains the list of locales to search through when performing + * a locale search.

+ * + *
+     * localeLookupList(Locale("fr","CA","xxx"))
+     *   = [Locale("fr","CA","xxx"), Locale("fr","CA"), Locale("fr")]
+     * 
+ * + * @param locale the locale to start from + * @return the unmodifiable list of Locale objects, 0 being locale, not null + */ + public static List localeLookupList(final Locale locale) { + return localeLookupList(locale, locale); + } + + //----------------------------------------------------------------------- + /** + *

Obtains the list of locales to search through when performing + * a locale search.

+ * + *
+     * localeLookupList(Locale("fr", "CA", "xxx"), Locale("en"))
+     *   = [Locale("fr","CA","xxx"), Locale("fr","CA"), Locale("fr"), Locale("en"]
+     * 
+ * + *

The result list begins with the most specific locale, then the + * next more general and so on, finishing with the default locale. + * The list will never contain the same locale twice.

+ * + * @param locale the locale to start from, null returns empty list + * @param defaultLocale the default locale to use if no other is found + * @return the unmodifiable list of Locale objects, 0 being locale, not null + */ + public static List localeLookupList(final Locale locale, final Locale defaultLocale) { + final List list = new ArrayList(4); + if (locale != null) { + list.add(locale); + if (locale.getVariant().length() > 0) { + list.add(new Locale(locale.getLanguage(), locale.getCountry())); + } + if (locale.getCountry().length() > 0) { + list.add(new Locale(locale.getLanguage(), StringUtils.EMPTY)); + } + if (list.contains(defaultLocale) == false) { + list.add(defaultLocale); + } + } + return Collections.unmodifiableList(list); + } + + //----------------------------------------------------------------------- + /** + *

Obtains an unmodifiable list of installed locales.

+ * + *

This method is a wrapper around {@link Locale#getAvailableLocales()}. + * It is more efficient, as the JDK method must create a new array each + * time it is called.

+ * + * @return the unmodifiable list of available locales + */ + public static List availableLocaleList() { + return SyncAvoid.AVAILABLE_LOCALE_LIST; + } + + //----------------------------------------------------------------------- + /** + *

Obtains an unmodifiable set of installed locales.

+ * + *

This method is a wrapper around {@link Locale#getAvailableLocales()}. + * It is more efficient, as the JDK method must create a new array each + * time it is called.

+ * + * @return the unmodifiable set of available locales + */ + public static Set availableLocaleSet() { + return SyncAvoid.AVAILABLE_LOCALE_SET; + } + + //----------------------------------------------------------------------- + /** + *

Checks if the locale specified is in the list of available locales.

+ * + * @param locale the Locale object to check if it is available + * @return true if the locale is a known locale + */ + public static boolean isAvailableLocale(final Locale locale) { + return availableLocaleList().contains(locale); + } + + //----------------------------------------------------------------------- + /** + *

Obtains the list of languages supported for a given country.

+ * + *

This method takes a country code and searches to find the + * languages available for that country. Variant locales are removed.

+ * + * @param countryCode the 2 letter country code, null returns empty + * @return an unmodifiable List of Locale objects, not null + */ + public static List languagesByCountry(final String countryCode) { + if (countryCode == null) { + return Collections.emptyList(); + } + List langs = cLanguagesByCountry.get(countryCode); + if (langs == null) { + langs = new ArrayList(); + final List locales = availableLocaleList(); + for (int i = 0; i < locales.size(); i++) { + final Locale locale = locales.get(i); + if (countryCode.equals(locale.getCountry()) && + locale.getVariant().isEmpty()) { + langs.add(locale); + } + } + langs = Collections.unmodifiableList(langs); + cLanguagesByCountry.putIfAbsent(countryCode, langs); + langs = cLanguagesByCountry.get(countryCode); + } + return langs; + } + + //----------------------------------------------------------------------- + /** + *

Obtains the list of countries supported for a given language.

+ * + *

This method takes a language code and searches to find the + * countries available for that language. Variant locales are removed.

+ * + * @param languageCode the 2 letter language code, null returns empty + * @return an unmodifiable List of Locale objects, not null + */ +// ----------------------------------------------------------------------- +/** + *

Obtains the list of countries supported for a given language.

+ * + *

This method takes a language code and searches to find the + * countries available for that language. Variant locales are removed.

+ * + * @param languageCode + * the 2 letter language code, null returns empty + * @return an unmodifiable List of Locale objects, not null + */ +public static java.util.List countriesByLanguage(final java.lang.String languageCode) { + { + java.util.List countries = org.apache.commons.lang3.LocaleUtils.cCountriesByLanguage.get(/* NPEX_NULL_EXP */ + languageCode); + if (countries == null) { + countries = new java.util.ArrayList(); + final java.util.List locales = org.apache.commons.lang3.LocaleUtils.availableLocaleList(); + for (int i = 0; i < locales.size(); i++) { + final java.util.Locale locale = locales.get(i); + if ((languageCode.equals(locale.getLanguage()) && (locale.getCountry().length() != 0)) && locale.getVariant().isEmpty()) { + countries.add(locale); + } + } + countries = java.util.Collections.unmodifiableList(countries); + org.apache.commons.lang3.LocaleUtils.cCountriesByLanguage.putIfAbsent(languageCode, countries); + countries = org.apache.commons.lang3.LocaleUtils.cCountriesByLanguage.get(languageCode); + } + return countries; + } +} + + //----------------------------------------------------------------------- + // class to avoid synchronization (Init on demand) + static class SyncAvoid { + /** Unmodifiable list of available locales. */ + private static final List AVAILABLE_LOCALE_LIST; + /** Unmodifiable set of available locales. */ + private static final Set AVAILABLE_LOCALE_SET; + + static { + final List list = new ArrayList(Arrays.asList(Locale.getAvailableLocales())); // extra safe + AVAILABLE_LOCALE_LIST = Collections.unmodifiableList(list); + AVAILABLE_LOCALE_SET = Collections.unmodifiableSet(new HashSet(list)); + } + } + +} diff --git a/Java/commons-lang-LocaleUtils_290/metadata.json b/Java/commons-lang-LocaleUtils_290/metadata.json new file mode 100644 index 000000000..5f3fb4947 --- /dev/null +++ b/Java/commons-lang-LocaleUtils_290/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-lang-LocaleUtils_290", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "src/main/java/org/apache/commons/lang3/LocaleUtils.java", + "line": 303, + "npe_method": "countriesByLanguage", + "deref_field": "languageCode", + "npe_class": "LocaleUtils", + "repo": "commons-lang", + "bug_id": "LocaleUtils_290" + } +} diff --git a/Java/commons-lang-LocaleUtils_290/npe.json b/Java/commons-lang-LocaleUtils_290/npe.json new file mode 100644 index 000000000..6618e959d --- /dev/null +++ b/Java/commons-lang-LocaleUtils_290/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/lang3/LocaleUtils.java", + "line": 303, + "npe_method": "countriesByLanguage", + "deref_field": "languageCode", + "npe_class": "LocaleUtils" +} \ No newline at end of file diff --git a/Java/commons-lang-LocaleUtils_90/Dockerfile b/Java/commons-lang-LocaleUtils_90/Dockerfile new file mode 100644 index 000000000..7b7fbe349 --- /dev/null +++ b/Java/commons-lang-LocaleUtils_90/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-lang + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/commons-lang-LocaleUtils_90/buggy.java b/Java/commons-lang-LocaleUtils_90/buggy.java new file mode 100644 index 000000000..08ae9d690 --- /dev/null +++ b/Java/commons-lang-LocaleUtils_90/buggy.java @@ -0,0 +1,352 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.commons.lang3; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + *

Operations to assist when working with a {@link Locale}.

+ * + *

This class tries to handle {@code null} input gracefully. + * An exception will not be thrown for a {@code null} input. + * Each method documents its behaviour in more detail.

+ * + * @since 2.2 + */ +public class LocaleUtils { + + /** Concurrent map of language locales by country. */ + private static final ConcurrentMap> cLanguagesByCountry = + new ConcurrentHashMap>(); + + /** Concurrent map of country locales by language. */ + private static final ConcurrentMap> cCountriesByLanguage = + new ConcurrentHashMap>(); + + /** + *

{@code LocaleUtils} instances should NOT be constructed in standard programming. + * Instead, the class should be used as {@code LocaleUtils.toLocale("en_GB");}.

+ * + *

This constructor is public to permit tools that require a JavaBean instance + * to operate.

+ */ + public LocaleUtils() { + super(); + } + + //----------------------------------------------------------------------- + /** + *

Converts a String to a Locale.

+ * + *

This method takes the string format of a locale and creates the + * locale object from it.

+ * + *
+     *   LocaleUtils.toLocale("")           = new Locale("", "")
+     *   LocaleUtils.toLocale("en")         = new Locale("en", "")
+     *   LocaleUtils.toLocale("en_GB")      = new Locale("en", "GB")
+     *   LocaleUtils.toLocale("en_GB_xxx")  = new Locale("en", "GB", "xxx")   (#)
+     * 
+ * + *

(#) The behaviour of the JDK variant constructor changed between JDK1.3 and JDK1.4. + * In JDK1.3, the constructor upper cases the variant, in JDK1.4, it doesn't. + * Thus, the result from getVariant() may vary depending on your JDK.

+ * + *

This method validates the input strictly. + * The language code must be lowercase. + * The country code must be uppercase. + * The separator must be an underscore. + * The length must be correct. + *

+ * + * @param str the locale String to convert, null returns null + * @return a Locale, null if null input + * @throws IllegalArgumentException if the string is an invalid format + * @see Locale#forLanguageTag(String) + */ +// ----------------------------------------------------------------------- +/** + *

Converts a String to a Locale.

+ * + *

This method takes the string format of a locale and creates the + * locale object from it.

+ * + *
+ * LocaleUtils.toLocale("")           = new Locale("", "")
+ * LocaleUtils.toLocale("en")         = new Locale("en", "")
+ * LocaleUtils.toLocale("en_GB")      = new Locale("en", "GB")
+ * LocaleUtils.toLocale("en_GB_xxx")  = new Locale("en", "GB", "xxx")   (#)
+ * 
+ * + *

(#) The behaviour of the JDK variant constructor changed between JDK1.3 and JDK1.4. + * In JDK1.3, the constructor upper cases the variant, in JDK1.4, it doesn't. + * Thus, the result from getVariant() may vary depending on your JDK.

+ * + *

This method validates the input strictly. + * The language code must be lowercase. + * The country code must be uppercase. + * The separator must be an underscore. + * The length must be correct. + *

+ * + * @param str + * the locale String to convert, null returns null + * @return a Locale, null if null input + * @throws IllegalArgumentException + * if the string is an invalid format + * @see Locale#forLanguageTag(String) + */ +public static java.util.Locale toLocale(final java.lang.String str) { + { + if (/* NPEX_NULL_EXP */ + str.isEmpty()) { + // LANG-941 - JDK 8 introduced an empty locale where all fields are blank + return new java.util.Locale(org.apache.commons.lang3.StringUtils.EMPTY, org.apache.commons.lang3.StringUtils.EMPTY); + } + if (str.contains("#")) { + // LANG-879 - Cannot handle Java 7 script & extensions + throw new java.lang.IllegalArgumentException("Invalid locale format: " + str); + } + final int len = str.length(); + if (len < 2) { + throw new java.lang.IllegalArgumentException("Invalid locale format: " + str); + } + final char ch0 = str.charAt(0); + if (ch0 == '_') { + if (len < 3) { + throw new java.lang.IllegalArgumentException("Invalid locale format: " + str); + } + final char ch1 = str.charAt(1); + final char ch2 = str.charAt(2); + if ((!java.lang.Character.isUpperCase(ch1)) || (!java.lang.Character.isUpperCase(ch2))) { + throw new java.lang.IllegalArgumentException("Invalid locale format: " + str); + } + if (len == 3) { + return new java.util.Locale(org.apache.commons.lang3.StringUtils.EMPTY, str.substring(1, 3)); + } + if (len < 5) { + throw new java.lang.IllegalArgumentException("Invalid locale format: " + str); + } + if (str.charAt(3) != '_') { + throw new java.lang.IllegalArgumentException("Invalid locale format: " + str); + } + return new java.util.Locale(org.apache.commons.lang3.StringUtils.EMPTY, str.substring(1, 3), str.substring(4)); + } + final java.lang.String[] split = str.split("_", -1); + final int occurrences = split.length - 1; + switch (occurrences) { + case 0 : + if (org.apache.commons.lang3.StringUtils.isAllLowerCase(str) && ((len == 2) || (len == 3))) { + return new java.util.Locale(str); + } + throw new java.lang.IllegalArgumentException("Invalid locale format: " + str); + case 1 : + if (((org.apache.commons.lang3.StringUtils.isAllLowerCase(split[0]) && ((split[0].length() == 2) || (split[0].length() == 3))) && (split[1].length() == 2)) && org.apache.commons.lang3.StringUtils.isAllUpperCase(split[1])) { + return new java.util.Locale(split[0], split[1]); + } + throw new java.lang.IllegalArgumentException("Invalid locale format: " + str); + case 2 : + if (((org.apache.commons.lang3.StringUtils.isAllLowerCase(split[0]) && ((split[0].length() == 2) || (split[0].length() == 3))) && ((split[1].length() == 0) || ((split[1].length() == 2) && org.apache.commons.lang3.StringUtils.isAllUpperCase(split[1])))) && (split[2].length() > 0)) { + return new java.util.Locale(split[0], split[1], split[2]); + } + // $FALL-THROUGH$ + default : + throw new java.lang.IllegalArgumentException("Invalid locale format: " + str); + } + } +} + + //----------------------------------------------------------------------- + /** + *

Obtains the list of locales to search through when performing + * a locale search.

+ * + *
+     * localeLookupList(Locale("fr","CA","xxx"))
+     *   = [Locale("fr","CA","xxx"), Locale("fr","CA"), Locale("fr")]
+     * 
+ * + * @param locale the locale to start from + * @return the unmodifiable list of Locale objects, 0 being locale, not null + */ + public static List localeLookupList(final Locale locale) { + return localeLookupList(locale, locale); + } + + //----------------------------------------------------------------------- + /** + *

Obtains the list of locales to search through when performing + * a locale search.

+ * + *
+     * localeLookupList(Locale("fr", "CA", "xxx"), Locale("en"))
+     *   = [Locale("fr","CA","xxx"), Locale("fr","CA"), Locale("fr"), Locale("en"]
+     * 
+ * + *

The result list begins with the most specific locale, then the + * next more general and so on, finishing with the default locale. + * The list will never contain the same locale twice.

+ * + * @param locale the locale to start from, null returns empty list + * @param defaultLocale the default locale to use if no other is found + * @return the unmodifiable list of Locale objects, 0 being locale, not null + */ + public static List localeLookupList(final Locale locale, final Locale defaultLocale) { + final List list = new ArrayList(4); + if (locale != null) { + list.add(locale); + if (locale.getVariant().length() > 0) { + list.add(new Locale(locale.getLanguage(), locale.getCountry())); + } + if (locale.getCountry().length() > 0) { + list.add(new Locale(locale.getLanguage(), StringUtils.EMPTY)); + } + if (list.contains(defaultLocale) == false) { + list.add(defaultLocale); + } + } + return Collections.unmodifiableList(list); + } + + //----------------------------------------------------------------------- + /** + *

Obtains an unmodifiable list of installed locales.

+ * + *

This method is a wrapper around {@link Locale#getAvailableLocales()}. + * It is more efficient, as the JDK method must create a new array each + * time it is called.

+ * + * @return the unmodifiable list of available locales + */ + public static List availableLocaleList() { + return SyncAvoid.AVAILABLE_LOCALE_LIST; + } + + //----------------------------------------------------------------------- + /** + *

Obtains an unmodifiable set of installed locales.

+ * + *

This method is a wrapper around {@link Locale#getAvailableLocales()}. + * It is more efficient, as the JDK method must create a new array each + * time it is called.

+ * + * @return the unmodifiable set of available locales + */ + public static Set availableLocaleSet() { + return SyncAvoid.AVAILABLE_LOCALE_SET; + } + + //----------------------------------------------------------------------- + /** + *

Checks if the locale specified is in the list of available locales.

+ * + * @param locale the Locale object to check if it is available + * @return true if the locale is a known locale + */ + public static boolean isAvailableLocale(final Locale locale) { + return availableLocaleList().contains(locale); + } + + //----------------------------------------------------------------------- + /** + *

Obtains the list of languages supported for a given country.

+ * + *

This method takes a country code and searches to find the + * languages available for that country. Variant locales are removed.

+ * + * @param countryCode the 2 letter country code, null returns empty + * @return an unmodifiable List of Locale objects, not null + */ + public static List languagesByCountry(final String countryCode) { + if (countryCode == null) { + return Collections.emptyList(); + } + List langs = cLanguagesByCountry.get(countryCode); + if (langs == null) { + langs = new ArrayList(); + final List locales = availableLocaleList(); + for (int i = 0; i < locales.size(); i++) { + final Locale locale = locales.get(i); + if (countryCode.equals(locale.getCountry()) && + locale.getVariant().isEmpty()) { + langs.add(locale); + } + } + langs = Collections.unmodifiableList(langs); + cLanguagesByCountry.putIfAbsent(countryCode, langs); + langs = cLanguagesByCountry.get(countryCode); + } + return langs; + } + + //----------------------------------------------------------------------- + /** + *

Obtains the list of countries supported for a given language.

+ * + *

This method takes a language code and searches to find the + * countries available for that language. Variant locales are removed.

+ * + * @param languageCode the 2 letter language code, null returns empty + * @return an unmodifiable List of Locale objects, not null + */ + public static List countriesByLanguage(final String languageCode) { + if (languageCode == null) { + return Collections.emptyList(); + } + List countries = cCountriesByLanguage.get(languageCode); + if (countries == null) { + countries = new ArrayList(); + final List locales = availableLocaleList(); + for (int i = 0; i < locales.size(); i++) { + final Locale locale = locales.get(i); + if (languageCode.equals(locale.getLanguage()) && + locale.getCountry().length() != 0 && + locale.getVariant().isEmpty()) { + countries.add(locale); + } + } + countries = Collections.unmodifiableList(countries); + cCountriesByLanguage.putIfAbsent(languageCode, countries); + countries = cCountriesByLanguage.get(languageCode); + } + return countries; + } + + //----------------------------------------------------------------------- + // class to avoid synchronization (Init on demand) + static class SyncAvoid { + /** Unmodifiable list of available locales. */ + private static final List AVAILABLE_LOCALE_LIST; + /** Unmodifiable set of available locales. */ + private static final Set AVAILABLE_LOCALE_SET; + + static { + final List list = new ArrayList(Arrays.asList(Locale.getAvailableLocales())); // extra safe + AVAILABLE_LOCALE_LIST = Collections.unmodifiableList(list); + AVAILABLE_LOCALE_SET = Collections.unmodifiableSet(new HashSet(list)); + } + } + +} diff --git a/Java/commons-lang-LocaleUtils_90/metadata.json b/Java/commons-lang-LocaleUtils_90/metadata.json new file mode 100644 index 000000000..df3513df4 --- /dev/null +++ b/Java/commons-lang-LocaleUtils_90/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-lang-LocaleUtils_90", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "src/main/java/org/apache/commons/lang3/LocaleUtils.java", + "line": 124, + "npe_method": "toLocale", + "deref_field": "str", + "npe_class": "LocaleUtils", + "repo": "commons-lang", + "bug_id": "LocaleUtils_90" + } +} diff --git a/Java/commons-lang-LocaleUtils_90/npe.json b/Java/commons-lang-LocaleUtils_90/npe.json new file mode 100644 index 000000000..e7c84a568 --- /dev/null +++ b/Java/commons-lang-LocaleUtils_90/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/lang3/LocaleUtils.java", + "line": 124, + "npe_method": "toLocale", + "deref_field": "str", + "npe_class": "LocaleUtils" +} \ No newline at end of file diff --git a/Java/commons-lang-LookupTranslator_83/Dockerfile b/Java/commons-lang-LookupTranslator_83/Dockerfile new file mode 100644 index 000000000..7b7fbe349 --- /dev/null +++ b/Java/commons-lang-LookupTranslator_83/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-lang + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/commons-lang-LookupTranslator_83/buggy.java b/Java/commons-lang-LookupTranslator_83/buggy.java new file mode 100644 index 000000000..85005ee98 --- /dev/null +++ b/Java/commons-lang-LookupTranslator_83/buggy.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.commons.lang3.text.translate; + +import java.io.IOException; +import java.io.Writer; +import java.util.HashMap; +import java.util.HashSet; + +/** + * Translates a value using a lookup table. + * + * @since 3.0 + */ +public class LookupTranslator extends CharSequenceTranslator { + + private final HashMap lookupMap; + private final HashSet prefixSet; + private final int shortest; + private final int longest; + + /** + * Define the lookup table to be used in translation + * + * Note that, as of Lang 3.1, the key to the lookup table is converted to a + * java.lang.String. This is because we need the key to support hashCode and + * equals(Object), allowing it to be the key for a HashMap. See LANG-882. + * + * @param lookup CharSequence[][] table of size [*][2] + */ + public LookupTranslator(final CharSequence[]... lookup) { + lookupMap = new HashMap(); + prefixSet = new HashSet(); + int _shortest = Integer.MAX_VALUE; + int _longest = 0; + if (lookup != null) { + for (final CharSequence[] seq : lookup) { + this.lookupMap.put(seq[0].toString(), seq[1].toString()); + this.prefixSet.add(seq[0].charAt(0)); + final int sz = seq[0].length(); + if (sz < _shortest) { + _shortest = sz; + } + if (sz > _longest) { + _longest = sz; + } + } + } + shortest = _shortest; + longest = _longest; + } + + /** + * {@inheritDoc} + */ + @Override +/** + * {@inheritDoc } + */ +public int translate(final java.lang.CharSequence input, final int index, final java.io.Writer out) throws java.io.IOException { + // check if translation exists for the input at position index + if (prefixSet.contains(input.charAt(index))) { + int max = longest; + if ((index + longest) > input.length()) { + max = input.length() - index; + } + // implement greedy algorithm by trying maximum match first + for (int i = max; i >= shortest; i--) { + final java.lang.CharSequence subSeq = input.subSequence(index, index + i); + final java.lang.String result = lookupMap.get(subSeq.toString()); + { + out.write(/* NPEX_NULL_EXP */ + result); + return i; + } + } + } + return 0; +} +} diff --git a/Java/commons-lang-LookupTranslator_83/metadata.json b/Java/commons-lang-LookupTranslator_83/metadata.json new file mode 100644 index 000000000..ed8443e01 --- /dev/null +++ b/Java/commons-lang-LookupTranslator_83/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-lang-LookupTranslator_83", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "src/main/java/org/apache/commons/lang3/text/translate/LookupTranslator.java", + "line": 87, + "npe_method": "translate", + "deref_field": "result", + "npe_class": "LookupTranslator", + "repo": "commons-lang", + "bug_id": "LookupTranslator_83" + } +} diff --git a/Java/commons-lang-LookupTranslator_83/npe.json b/Java/commons-lang-LookupTranslator_83/npe.json new file mode 100644 index 000000000..1a5cae78b --- /dev/null +++ b/Java/commons-lang-LookupTranslator_83/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/lang3/text/translate/LookupTranslator.java", + "line": 87, + "npe_method": "translate", + "deref_field": "result", + "npe_class": "LookupTranslator" +} \ No newline at end of file