policeman-tools / forbidden-apis

Policeman's Forbidden API Checker
Apache License 2.0
321 stars 34 forks source link

Proposed unsafe signatures for ICU #90

Open hakanai opened 8 years ago

hakanai commented 8 years ago

ICU mirrors a lot of the Java APIs and our own project has been using it a lot. (Initially, it was just because java.text.MessageFormat is inadequate for internationalising plurals in formats, but other usages have crept in over time. e.g., we use it to get at some additional calendars as well.)

I went through a javap dump of every method signature in ICU 55.1 and came up with the following list. Since commons-io is present out of the box, maybe ICU could be as well. :)

@defaultMessage Uses default locale
com.ibm.icu.text.BreakIterator#getWordInstance()
com.ibm.icu.text.BreakIterator#getLineInstance()
com.ibm.icu.text.BreakIterator#getCharacterInstance()
com.ibm.icu.text.BreakIterator#getSentenceInstance()
com.ibm.icu.text.BreakIterator#getTitleInstance()
com.ibm.icu.text.ChineseDateFormatSymbols#<init>()
com.ibm.icu.text.Collator#getInstance()
com.ibm.icu.text.Collator#getDisplayName(java.util.Locale)
com.ibm.icu.text.Collator#getDisplayName(com.ibm.icu.util.ULocale)
com.ibm.icu.text.DateFormat#getInstance()
com.ibm.icu.text.DateFormat#getDateInstance()
com.ibm.icu.text.DateFormat#getDateInstance(int)
com.ibm.icu.text.DateFormat#getDateInstance(com.ibm.icu.util.Calendar, int)
com.ibm.icu.text.DateFormat#getTimeInstance()
com.ibm.icu.text.DateFormat#getTimeInstance(int)
com.ibm.icu.text.DateFormat#getTimeInstance(com.ibm.icu.util.Calendar, int)
com.ibm.icu.text.DateFormat#getDateTimeInstance()
com.ibm.icu.text.DateFormat#getDateTimeInstance(int, int)
com.ibm.icu.text.DateFormat#getDateTimeInstance(com.ibm.icu.util.Calendar, int, int)
com.ibm.icu.text.DateFormat#getInstance(com.ibm.icu.util.Calendar)
com.ibm.icu.text.DateFormat#getInstanceForSkeleton(java.lang.String)
com.ibm.icu.text.DateFormat#getPatternInstance(java.lang.String)
com.ibm.icu.text.DateFormatSymbols#<init>()
com.ibm.icu.text.DateFormatSymbols#getInstance()
com.ibm.icu.text.DateIntervalFormat#getInstance(java.lang.String)
com.ibm.icu.text.DateIntervalFormat#getInstance(java.lang.String, com.ibm.icu.text.DateIntervalInfo)
com.ibm.icu.text.DateIntervalInfo#<init>()
com.ibm.icu.text.DateTimePatternGenerator#getInstance()
com.ibm.icu.text.DecimalFormat#<init>()
com.ibm.icu.text.DecimalFormat#<init>(java.lang.String)
com.ibm.icu.text.DecimalFormatSymbols#<init>()
com.ibm.icu.text.DecimalFormatSymbols#getInstance()
com.ibm.icu.text.FilteredBreakIteratorBuilder#createInstance()
com.ibm.icu.text.ListFormatter#getInstance()
com.ibm.icu.text.MeasureFormat#getCurrencyFormat()
com.ibm.icu.text.MessageFormat#<init>(java.lang.String)
com.ibm.icu.text.MessageFormat#format(java.lang.String, java.util.Map)
com.ibm.icu.text.MessageFormat#format(java.lang.String, java.lang.Object[])
com.ibm.icu.text.NumberFormat#getInstance()
com.ibm.icu.text.NumberFormat#getInstance(int)
com.ibm.icu.text.NumberFormat#getNumberInstance()
com.ibm.icu.text.NumberFormat#getIntegerInstance()
com.ibm.icu.text.NumberFormat#getCurrencyInstance()
com.ibm.icu.text.NumberFormat#getPercentInstance()
com.ibm.icu.text.NumberFormat#getScientificInstance()
com.ibm.icu.text.NumberingSystem#getInstance()
com.ibm.icu.text.PluralFormat#<init>()
com.ibm.icu.text.PluralFormat#<init>(com.ibm.icu.text.PluralRules)
com.ibm.icu.text.PluralFormat#<init>(java.lang.String)
com.ibm.icu.text.PluralFormat#<init>(com.ibm.icu.text.PluralRules, java.lang.String)
com.ibm.icu.text.RelativeDateTimeFormatter#getInstance()
com.ibm.icu.text.RuleBasedNumberFormat#<init>(java.lang.String)
com.ibm.icu.text.RuleBasedNumberFormat#<init>(java.lang.String, java.lang.String[][])
com.ibm.icu.text.RuleBasedNumberFormat#<init>(int)
com.ibm.icu.text.RuleBasedNumberFormat#getRuleSetDisplayNames()
com.ibm.icu.text.RuleBasedNumberFormat#getRuleSetDisplayName(java.lang.String)
com.ibm.icu.text.SimpleDateFormat#<init>()
com.ibm.icu.text.SimpleDateFormat#<init>(java.lang.String)
com.ibm.icu.text.SimpleDateFormat#<init>(java.lang.String, com.ibm.icu.text.DateFormatSymbols)
com.ibm.icu.text.StringSearch#<init>(java.lang.String, java.lang.String)
com.ibm.icu.text.TimeUnitFormat#<init>()
com.ibm.icu.text.Transliterator#getDisplayName(java.lang.String)
com.ibm.icu.util.Currency#getSymbol()
com.ibm.icu.util.Currency#getDisplayName()
com.ibm.icu.util.Holiday#getHolidays()
com.ibm.icu.util.Holiday#getDisplayName()
com.ibm.icu.util.LocaleData#getInstance()
com.ibm.icu.util.TimeZone#getDisplayName()
com.ibm.icu.util.TimeZone#getDisplayName(boolean, int)
com.ibm.icu.util.ULocale#getDisplayLanguage()
com.ibm.icu.util.ULocale#getDisplayLanguageWithDialect()
com.ibm.icu.util.ULocale#getDisplayScript()
com.ibm.icu.util.ULocale#getDisplayScriptInContext()
com.ibm.icu.util.ULocale#getDisplayCountry()
com.ibm.icu.util.ULocale#getDisplayVariant()
com.ibm.icu.util.ULocale#getDisplayKeyword(java.lang.String)
com.ibm.icu.util.ULocale#getDisplayKeywordValue(java.lang.String)
com.ibm.icu.util.ULocale#getDisplayName()
com.ibm.icu.util.ULocale#getDisplayNameWithDialect()
com.ibm.icu.util.UResourceBundle#getBundleInstance(java.lang.String)

@defaultMessage Uses default locale or time zone
com.ibm.icu.util.BuddhistCalendar#<init>()
com.ibm.icu.util.BuddhistCalendar#<init>(com.ibm.icu.util.TimeZone)
com.ibm.icu.util.BuddhistCalendar#<init>(java.util.Locale)
com.ibm.icu.util.BuddhistCalendar#<init>(com.ibm.icu.util.ULocale)
com.ibm.icu.util.BuddhistCalendar#<init>(java.util.Date)
com.ibm.icu.util.BuddhistCalendar#<init>(int, int, int)
com.ibm.icu.util.BuddhistCalendar#<init>(int, int, int, int, int, int)
com.ibm.icu.util.Calendar#<init>()
com.ibm.icu.util.Calendar#getInstance()
com.ibm.icu.util.Calendar#getInstance(com.ibm.icu.util.TimeZone)
com.ibm.icu.util.Calendar#getInstance(java.util.Locale)
com.ibm.icu.util.Calendar#getInstance(com.ibm.icu.util.ULocale)
com.ibm.icu.util.ChineseCalendar#<init>()
com.ibm.icu.util.ChineseCalendar#<init>(java.util.Date)
com.ibm.icu.util.ChineseCalendar#<init>(int, int, int, int)
com.ibm.icu.util.ChineseCalendar#<init>(int, int, int, int, int, int, int)
com.ibm.icu.util.ChineseCalendar#<init>(int, int, int, int, int)
com.ibm.icu.util.ChineseCalendar#<init>(int, int, int, int, int, int, int, int)
com.ibm.icu.util.ChineseCalendar#<init>(java.util.Locale)
com.ibm.icu.util.ChineseCalendar#<init>(com.ibm.icu.util.TimeZone)
com.ibm.icu.util.ChineseCalendar#<init>(com.ibm.icu.util.ULocale)
com.ibm.icu.util.CopticCalendar#<init>()
com.ibm.icu.util.CopticCalendar#<init>(com.ibm.icu.util.TimeZone)
com.ibm.icu.util.CopticCalendar#<init>(java.util.Locale)
com.ibm.icu.util.CopticCalendar#<init>(com.ibm.icu.util.ULocale)
com.ibm.icu.util.CopticCalendar#<init>(int, int, int)
com.ibm.icu.util.CopticCalendar#<init>(java.util.Date)
com.ibm.icu.util.CopticCalendar#<init>(int, int, int, int, int, int)
com.ibm.icu.util.DangiCalendar#<init>()
com.ibm.icu.util.DangiCalendar#<init>(java.util.Date)
com.ibm.icu.util.EthiopicCalendar#<init>()
com.ibm.icu.util.EthiopicCalendar#<init>(com.ibm.icu.util.TimeZone)
com.ibm.icu.util.EthiopicCalendar#<init>(java.util.Locale)
com.ibm.icu.util.EthiopicCalendar#<init>(com.ibm.icu.util.ULocale)
com.ibm.icu.util.EthiopicCalendar#<init>(int, int, int)
com.ibm.icu.util.EthiopicCalendar#<init>(java.util.Date)
com.ibm.icu.util.EthiopicCalendar#<init>(int, int, int, int, int, int)
com.ibm.icu.util.GregorianCalendar#<init>()
com.ibm.icu.util.GregorianCalendar#<init>(com.ibm.icu.util.TimeZone)
com.ibm.icu.util.GregorianCalendar#<init>(java.util.Locale)
com.ibm.icu.util.GregorianCalendar#<init>(com.ibm.icu.util.ULocale)
com.ibm.icu.util.GregorianCalendar#<init>(int, int, int)
com.ibm.icu.util.GregorianCalendar#<init>(int, int, int, int, int)
com.ibm.icu.util.GregorianCalendar#<init>(int, int, int, int, int, int)
com.ibm.icu.util.HebrewCalendar#<init>()
com.ibm.icu.util.HebrewCalendar#<init>(com.ibm.icu.util.TimeZone)
com.ibm.icu.util.HebrewCalendar#<init>(java.util.Locale)
com.ibm.icu.util.HebrewCalendar#<init>(com.ibm.icu.util.ULocale)
com.ibm.icu.util.HebrewCalendar#<init>(int, int, int)
com.ibm.icu.util.HebrewCalendar#<init>(java.util.Date)
com.ibm.icu.util.HebrewCalendar#<init>(int, int, int, int, int, int)
com.ibm.icu.util.IndianCalendar#<init>()
com.ibm.icu.util.IndianCalendar#<init>(com.ibm.icu.util.TimeZone)
com.ibm.icu.util.IndianCalendar#<init>(java.util.Locale)
com.ibm.icu.util.IndianCalendar#<init>(com.ibm.icu.util.ULocale)
com.ibm.icu.util.IndianCalendar#<init>(java.util.Date)
com.ibm.icu.util.IndianCalendar#<init>(int, int, int)
com.ibm.icu.util.IndianCalendar#<init>(int, int, int, int, int, int)
com.ibm.icu.util.IslamicCalendar#<init>()
com.ibm.icu.util.IslamicCalendar#<init>(com.ibm.icu.util.TimeZone)
com.ibm.icu.util.IslamicCalendar#<init>(java.util.Locale)
com.ibm.icu.util.IslamicCalendar#<init>(com.ibm.icu.util.ULocale)
com.ibm.icu.util.IslamicCalendar#<init>(java.util.Date)
com.ibm.icu.util.IslamicCalendar#<init>(int, int, int)
com.ibm.icu.util.IslamicCalendar#<init>(int, int, int, int, int, int)
com.ibm.icu.util.JapaneseCalendar#<init>()
com.ibm.icu.util.JapaneseCalendar#<init>(com.ibm.icu.util.TimeZone)
com.ibm.icu.util.JapaneseCalendar#<init>(java.util.Locale)
com.ibm.icu.util.JapaneseCalendar#<init>(com.ibm.icu.util.ULocale)
com.ibm.icu.util.JapaneseCalendar#<init>(java.util.Date)
com.ibm.icu.util.JapaneseCalendar#<init>(int, int, int, int)
com.ibm.icu.util.JapaneseCalendar#<init>(int, int, int)
com.ibm.icu.util.JapaneseCalendar#<init>(int, int, int, int, int, int)
com.ibm.icu.util.PersianCalendar#<init>()
com.ibm.icu.util.PersianCalendar#<init>(com.ibm.icu.util.TimeZone)
com.ibm.icu.util.PersianCalendar#<init>(java.util.Locale)
com.ibm.icu.util.PersianCalendar#<init>(com.ibm.icu.util.ULocale)
com.ibm.icu.util.PersianCalendar#<init>(java.util.Date)
com.ibm.icu.util.PersianCalendar#<init>(int, int, int)
com.ibm.icu.util.PersianCalendar#<init>(int, int, int, int, int, int)
com.ibm.icu.util.TaiwanCalendar#<init>()
com.ibm.icu.util.TaiwanCalendar#<init>(com.ibm.icu.util.TimeZone)
com.ibm.icu.util.TaiwanCalendar#<init>(java.util.Locale)
com.ibm.icu.util.TaiwanCalendar#<init>(com.ibm.icu.util.ULocale)
com.ibm.icu.util.TaiwanCalendar#<init>(java.util.Date)
com.ibm.icu.util.TaiwanCalendar#<init>(int, int, int)
com.ibm.icu.util.TaiwanCalendar#<init>(int, int, int, int, int, int)

I don't know if there is a better way to find potential methods but what I did was search the list for methods taking TimeZone or Locale and then looked at any overloads or similar-looking methods in the same class. So maybe I have missed some... but at least it's smaller than the JRE, so it's comparatively easier to do this sort of exercise.

uschindler commented 8 years ago

Cool! I let @rmuir look into it :-)

uschindler commented 8 years ago

There is only one issue: For commons-io we have a per-version file. Not sure if we need the same for ICU.

hakanai commented 8 years ago

Yeah... I did this for 55 but even we're going to roll back to 54 at some point so at that point I will have to split it into two files. I'm not sure about breaking it up all the way back to 1 though. ;)

uschindler commented 8 years ago

Maybe its time to have some @since annotation in the files...

rmuir commented 8 years ago

the list looks good, yeah basically grep for Locale/TimeZone/Charset/etc and then reviewing classes using them is the way to find these.

@uschindler I think the version file would be good, the reason is new calendars get added and so on.

hakanai commented 8 years ago

You almost want a 'since' and 'until' annotation because some libraries do eventually remove API (even though the JRE is adverse to removing even the most cancerous growths...)

uschindler commented 8 years ago

even though the JRE is adverse to removing even the most cancerous growths...

Oh with @deprecated we have seen removal already. For the @deprecated ones there is a @suppress annotation used internally to suppress warnings appearing because of removal :-)

uschindler commented 8 years ago

@uschindler I think the version file would be good, the reason is new calendars get added and so on.

I just don't want to have a file for every 55 major version... I will think about a better solution for bundled signatures. Also commons-io is a mess currently. Every newer version is including the previous ones! For 55 this is also leading to slowdown caused by the chain of includes.

uschindler commented 8 years ago

I still have no idea about how to fix versioning. I will open separate issue for that and during that issue "merge" all version specific signatures files into one.

About the additional calendars: Maybe this is another reason for #88 (glob patterns also allowed in combination with methods). You could then add some signature like com.ibm.icu.util.*Calendar#<init>() and similar. As said on #88, unfortunately with glob patterns it is impossible to check the signatures for validity! So I don't like this added...