From cff1bdcb40073d84e0cd0acc4cae710b1577c06f Mon Sep 17 00:00:00 2001 From: Henry Lee Date: Thu, 30 Nov 2023 14:00:21 +0900 Subject: [PATCH] refactor(java): refactoring java bugs for 3 projects --- .../Dockerfile | 18 + .../buggy.java | 272 +++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 441 ++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 437 ++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 439 ++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 439 ++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 432 ++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 432 ++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 432 ++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 250 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 288 +++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 287 +++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 288 +++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 288 +++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 516 ++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 2126 +++++++++++++++++ .../metadata.json | 21 + .../npe.json | 7 + Java/commons-validator-Field_346/Dockerfile | 18 + Java/commons-validator-Field_346/buggy.java | 960 ++++++++ .../commons-validator-Field_346/metadata.json | 21 + Java/commons-validator-Field_346/npe.json | 7 + Java/commons-validator-Field_443/Dockerfile | 18 + Java/commons-validator-Field_443/buggy.java | 969 ++++++++ .../commons-validator-Field_443/metadata.json | 21 + Java/commons-validator-Field_443/npe.json | 7 + Java/commons-validator-Field_500/Dockerfile | 18 + Java/commons-validator-Field_500/buggy.java | 964 ++++++++ .../commons-validator-Field_500/metadata.json | 21 + Java/commons-validator-Field_500/npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 153 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 124 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 283 +++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 278 +++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 214 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 216 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 189 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 138 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 238 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 239 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 239 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 240 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 353 +++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 584 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 584 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 560 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 582 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 207 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 103 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 103 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 72 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 72 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 244 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 101 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 102 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 78 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 78 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 101 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 102 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 77 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 78 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 101 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 102 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 73 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 72 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 101 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 102 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 75 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 76 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 101 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 102 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 77 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 78 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 535 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 535 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 535 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 535 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 535 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 535 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 535 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 535 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 535 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 535 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 535 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 557 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 557 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 557 +++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 104 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 104 + .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 154 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 153 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 153 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 154 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 154 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 877 +++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 875 +++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 875 +++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 877 +++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 870 +++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 874 +++++++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 284 +++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 281 +++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 137 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 134 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 134 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 134 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 134 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 137 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 137 ++ .../metadata.json | 21 + .../npe.json | 7 + .../Dockerfile | 18 + .../buggy.java | 136 ++ .../metadata.json | 21 + .../npe.json | 7 + 392 files changed, 37988 insertions(+) create mode 100644 Java/commons-validator-AbstractCalendarValidatorTest_230/Dockerfile create mode 100644 Java/commons-validator-AbstractCalendarValidatorTest_230/buggy.java create mode 100644 Java/commons-validator-AbstractCalendarValidatorTest_230/metadata.json create mode 100644 Java/commons-validator-AbstractCalendarValidatorTest_230/npe.json create mode 100644 Java/commons-validator-AbstractCalendarValidator_141/Dockerfile create mode 100644 Java/commons-validator-AbstractCalendarValidator_141/buggy.java create mode 100644 Java/commons-validator-AbstractCalendarValidator_141/metadata.json create mode 100644 Java/commons-validator-AbstractCalendarValidator_141/npe.json create mode 100644 Java/commons-validator-AbstractCalendarValidator_158/Dockerfile create mode 100644 Java/commons-validator-AbstractCalendarValidator_158/buggy.java create mode 100644 Java/commons-validator-AbstractCalendarValidator_158/metadata.json create mode 100644 Java/commons-validator-AbstractCalendarValidator_158/npe.json create mode 100644 Java/commons-validator-AbstractCalendarValidator_183/Dockerfile create mode 100644 Java/commons-validator-AbstractCalendarValidator_183/buggy.java create mode 100644 Java/commons-validator-AbstractCalendarValidator_183/metadata.json create mode 100644 Java/commons-validator-AbstractCalendarValidator_183/npe.json create mode 100644 Java/commons-validator-AbstractCalendarValidator_217/Dockerfile create mode 100644 Java/commons-validator-AbstractCalendarValidator_217/buggy.java create mode 100644 Java/commons-validator-AbstractCalendarValidator_217/metadata.json create mode 100644 Java/commons-validator-AbstractCalendarValidator_217/npe.json create mode 100644 Java/commons-validator-AbstractCalendarValidator_238/Dockerfile create mode 100644 Java/commons-validator-AbstractCalendarValidator_238/buggy.java create mode 100644 Java/commons-validator-AbstractCalendarValidator_238/metadata.json create mode 100644 Java/commons-validator-AbstractCalendarValidator_238/npe.json create mode 100644 Java/commons-validator-AbstractCalendarValidator_244/Dockerfile create mode 100644 Java/commons-validator-AbstractCalendarValidator_244/buggy.java create mode 100644 Java/commons-validator-AbstractCalendarValidator_244/metadata.json create mode 100644 Java/commons-validator-AbstractCalendarValidator_244/npe.json create mode 100644 Java/commons-validator-AbstractCalendarValidator_251/Dockerfile create mode 100644 Java/commons-validator-AbstractCalendarValidator_251/buggy.java create mode 100644 Java/commons-validator-AbstractCalendarValidator_251/metadata.json create mode 100644 Java/commons-validator-AbstractCalendarValidator_251/npe.json create mode 100644 Java/commons-validator-AbstractNumberValidatorTest_101/Dockerfile create mode 100644 Java/commons-validator-AbstractNumberValidatorTest_101/buggy.java create mode 100644 Java/commons-validator-AbstractNumberValidatorTest_101/metadata.json create mode 100644 Java/commons-validator-AbstractNumberValidatorTest_101/npe.json create mode 100644 Java/commons-validator-AbstractNumberValidator_157/Dockerfile create mode 100644 Java/commons-validator-AbstractNumberValidator_157/buggy.java create mode 100644 Java/commons-validator-AbstractNumberValidator_157/metadata.json create mode 100644 Java/commons-validator-AbstractNumberValidator_157/npe.json create mode 100644 Java/commons-validator-AbstractNumberValidator_194/Dockerfile create mode 100644 Java/commons-validator-AbstractNumberValidator_194/buggy.java create mode 100644 Java/commons-validator-AbstractNumberValidator_194/metadata.json create mode 100644 Java/commons-validator-AbstractNumberValidator_194/npe.json create mode 100644 Java/commons-validator-CodeValidator_251/Dockerfile create mode 100644 Java/commons-validator-CodeValidator_251/buggy.java create mode 100644 Java/commons-validator-CodeValidator_251/metadata.json create mode 100644 Java/commons-validator-CodeValidator_251/npe.json create mode 100644 Java/commons-validator-CodeValidator_261/Dockerfile create mode 100644 Java/commons-validator-CodeValidator_261/buggy.java create mode 100644 Java/commons-validator-CodeValidator_261/metadata.json create mode 100644 Java/commons-validator-CodeValidator_261/npe.json create mode 100644 Java/commons-validator-CreditCardValidator_478/Dockerfile create mode 100644 Java/commons-validator-CreditCardValidator_478/buggy.java create mode 100644 Java/commons-validator-CreditCardValidator_478/metadata.json create mode 100644 Java/commons-validator-CreditCardValidator_478/npe.json create mode 100644 Java/commons-validator-DomainValidator_163/Dockerfile create mode 100644 Java/commons-validator-DomainValidator_163/buggy.java create mode 100644 Java/commons-validator-DomainValidator_163/metadata.json create mode 100644 Java/commons-validator-DomainValidator_163/npe.json create mode 100644 Java/commons-validator-Field_346/Dockerfile create mode 100644 Java/commons-validator-Field_346/buggy.java create mode 100644 Java/commons-validator-Field_346/metadata.json create mode 100644 Java/commons-validator-Field_346/npe.json create mode 100644 Java/commons-validator-Field_443/Dockerfile create mode 100644 Java/commons-validator-Field_443/buggy.java create mode 100644 Java/commons-validator-Field_443/metadata.json create mode 100644 Java/commons-validator-Field_443/npe.json create mode 100644 Java/commons-validator-Field_500/Dockerfile create mode 100644 Java/commons-validator-Field_500/buggy.java create mode 100644 Java/commons-validator-Field_500/metadata.json create mode 100644 Java/commons-validator-Field_500/npe.json create mode 100644 Java/commons-validator-IBANCheckDigit_102/Dockerfile create mode 100644 Java/commons-validator-IBANCheckDigit_102/buggy.java create mode 100644 Java/commons-validator-IBANCheckDigit_102/metadata.json create mode 100644 Java/commons-validator-IBANCheckDigit_102/npe.json create mode 100644 Java/commons-validator-ISBNCheckDigit_95/Dockerfile create mode 100644 Java/commons-validator-ISBNCheckDigit_95/buggy.java create mode 100644 Java/commons-validator-ISBNCheckDigit_95/metadata.json create mode 100644 Java/commons-validator-ISBNCheckDigit_95/npe.json create mode 100644 Java/commons-validator-ISBNValidator_220/Dockerfile create mode 100644 Java/commons-validator-ISBNValidator_220/buggy.java create mode 100644 Java/commons-validator-ISBNValidator_220/metadata.json create mode 100644 Java/commons-validator-ISBNValidator_220/npe.json create mode 100644 Java/commons-validator-ISBNValidator_250/Dockerfile create mode 100644 Java/commons-validator-ISBNValidator_250/buggy.java create mode 100644 Java/commons-validator-ISBNValidator_250/metadata.json create mode 100644 Java/commons-validator-ISBNValidator_250/npe.json create mode 100644 Java/commons-validator-ISSNValidator_149/Dockerfile create mode 100644 Java/commons-validator-ISSNValidator_149/buggy.java create mode 100644 Java/commons-validator-ISSNValidator_149/metadata.json create mode 100644 Java/commons-validator-ISSNValidator_149/npe.json create mode 100644 Java/commons-validator-ISSNValidator_186/Dockerfile create mode 100644 Java/commons-validator-ISSNValidator_186/buggy.java create mode 100644 Java/commons-validator-ISSNValidator_186/metadata.json create mode 100644 Java/commons-validator-ISSNValidator_186/npe.json create mode 100644 Java/commons-validator-InetAddressValidator_90/Dockerfile create mode 100644 Java/commons-validator-InetAddressValidator_90/buggy.java create mode 100644 Java/commons-validator-InetAddressValidator_90/metadata.json create mode 100644 Java/commons-validator-InetAddressValidator_90/npe.json create mode 100644 Java/commons-validator-PercentValidator_120/Dockerfile create mode 100644 Java/commons-validator-PercentValidator_120/buggy.java create mode 100644 Java/commons-validator-PercentValidator_120/metadata.json create mode 100644 Java/commons-validator-PercentValidator_120/npe.json create mode 100644 Java/commons-validator-RegexValidator_142/Dockerfile create mode 100644 Java/commons-validator-RegexValidator_142/buggy.java create mode 100644 Java/commons-validator-RegexValidator_142/metadata.json create mode 100644 Java/commons-validator-RegexValidator_142/npe.json create mode 100644 Java/commons-validator-RegexValidator_162/Dockerfile create mode 100644 Java/commons-validator-RegexValidator_162/buggy.java create mode 100644 Java/commons-validator-RegexValidator_162/metadata.json create mode 100644 Java/commons-validator-RegexValidator_162/npe.json create mode 100644 Java/commons-validator-RegexValidator_189/Dockerfile create mode 100644 Java/commons-validator-RegexValidator_189/buggy.java create mode 100644 Java/commons-validator-RegexValidator_189/metadata.json create mode 100644 Java/commons-validator-RegexValidator_189/npe.json create mode 100644 Java/commons-validator-RegexValidator_202/Dockerfile create mode 100644 Java/commons-validator-RegexValidator_202/buggy.java create mode 100644 Java/commons-validator-RegexValidator_202/metadata.json create mode 100644 Java/commons-validator-RegexValidator_202/npe.json create mode 100644 Java/commons-validator-TimeValidatorTest_315/Dockerfile create mode 100644 Java/commons-validator-TimeValidatorTest_315/buggy.java create mode 100644 Java/commons-validator-TimeValidatorTest_315/metadata.json create mode 100644 Java/commons-validator-TimeValidatorTest_315/npe.json create mode 100644 Java/commons-validator-UrlValidator_351/Dockerfile create mode 100644 Java/commons-validator-UrlValidator_351/buggy.java create mode 100644 Java/commons-validator-UrlValidator_351/metadata.json create mode 100644 Java/commons-validator-UrlValidator_351/npe.json create mode 100644 Java/commons-validator-UrlValidator_378/Dockerfile create mode 100644 Java/commons-validator-UrlValidator_378/buggy.java create mode 100644 Java/commons-validator-UrlValidator_378/metadata.json create mode 100644 Java/commons-validator-UrlValidator_378/npe.json create mode 100644 Java/commons-validator-UrlValidator_396/Dockerfile create mode 100644 Java/commons-validator-UrlValidator_396/buggy.java create mode 100644 Java/commons-validator-UrlValidator_396/metadata.json create mode 100644 Java/commons-validator-UrlValidator_396/npe.json create mode 100644 Java/commons-validator-UrlValidator_475/Dockerfile create mode 100644 Java/commons-validator-UrlValidator_475/buggy.java create mode 100644 Java/commons-validator-UrlValidator_475/metadata.json create mode 100644 Java/commons-validator-UrlValidator_475/npe.json create mode 100644 Java/commons-validator-ValidatorUtils_115/Dockerfile create mode 100644 Java/commons-validator-ValidatorUtils_115/buggy.java create mode 100644 Java/commons-validator-ValidatorUtils_115/metadata.json create mode 100644 Java/commons-validator-ValidatorUtils_115/npe.json create mode 100644 Java/directory-mavibot-BooleanArrayComparator_59/Dockerfile create mode 100644 Java/directory-mavibot-BooleanArrayComparator_59/buggy.java create mode 100644 Java/directory-mavibot-BooleanArrayComparator_59/metadata.json create mode 100644 Java/directory-mavibot-BooleanArrayComparator_59/npe.json create mode 100644 Java/directory-mavibot-BooleanArrayComparator_64/Dockerfile create mode 100644 Java/directory-mavibot-BooleanArrayComparator_64/buggy.java create mode 100644 Java/directory-mavibot-BooleanArrayComparator_64/metadata.json create mode 100644 Java/directory-mavibot-BooleanArrayComparator_64/npe.json create mode 100644 Java/directory-mavibot-BooleanComparator_58/Dockerfile create mode 100644 Java/directory-mavibot-BooleanComparator_58/buggy.java create mode 100644 Java/directory-mavibot-BooleanComparator_58/metadata.json create mode 100644 Java/directory-mavibot-BooleanComparator_58/npe.json create mode 100644 Java/directory-mavibot-BooleanComparator_63/Dockerfile create mode 100644 Java/directory-mavibot-BooleanComparator_63/buggy.java create mode 100644 Java/directory-mavibot-BooleanComparator_63/metadata.json create mode 100644 Java/directory-mavibot-BooleanComparator_63/npe.json create mode 100644 Java/directory-mavibot-BulkDataSorter_184/Dockerfile create mode 100644 Java/directory-mavibot-BulkDataSorter_184/buggy.java create mode 100644 Java/directory-mavibot-BulkDataSorter_184/metadata.json create mode 100644 Java/directory-mavibot-BulkDataSorter_184/npe.json create mode 100644 Java/directory-mavibot-ByteArrayComparator_58/Dockerfile create mode 100644 Java/directory-mavibot-ByteArrayComparator_58/buggy.java create mode 100644 Java/directory-mavibot-ByteArrayComparator_58/metadata.json create mode 100644 Java/directory-mavibot-ByteArrayComparator_58/npe.json create mode 100644 Java/directory-mavibot-ByteArrayComparator_64/Dockerfile create mode 100644 Java/directory-mavibot-ByteArrayComparator_64/buggy.java create mode 100644 Java/directory-mavibot-ByteArrayComparator_64/metadata.json create mode 100644 Java/directory-mavibot-ByteArrayComparator_64/npe.json create mode 100644 Java/directory-mavibot-ByteComparator_58/Dockerfile create mode 100644 Java/directory-mavibot-ByteComparator_58/buggy.java create mode 100644 Java/directory-mavibot-ByteComparator_58/metadata.json create mode 100644 Java/directory-mavibot-ByteComparator_58/npe.json create mode 100644 Java/directory-mavibot-ByteComparator_63/Dockerfile create mode 100644 Java/directory-mavibot-ByteComparator_63/buggy.java create mode 100644 Java/directory-mavibot-ByteComparator_63/metadata.json create mode 100644 Java/directory-mavibot-ByteComparator_63/npe.json create mode 100644 Java/directory-mavibot-CharArrayComparator_58/Dockerfile create mode 100644 Java/directory-mavibot-CharArrayComparator_58/buggy.java create mode 100644 Java/directory-mavibot-CharArrayComparator_58/metadata.json create mode 100644 Java/directory-mavibot-CharArrayComparator_58/npe.json create mode 100644 Java/directory-mavibot-CharArrayComparator_71/Dockerfile create mode 100644 Java/directory-mavibot-CharArrayComparator_71/buggy.java create mode 100644 Java/directory-mavibot-CharArrayComparator_71/metadata.json create mode 100644 Java/directory-mavibot-CharArrayComparator_71/npe.json create mode 100644 Java/directory-mavibot-CharComparator_58/Dockerfile create mode 100644 Java/directory-mavibot-CharComparator_58/buggy.java create mode 100644 Java/directory-mavibot-CharComparator_58/metadata.json create mode 100644 Java/directory-mavibot-CharComparator_58/npe.json create mode 100644 Java/directory-mavibot-CharComparator_71/Dockerfile create mode 100644 Java/directory-mavibot-CharComparator_71/buggy.java create mode 100644 Java/directory-mavibot-CharComparator_71/metadata.json create mode 100644 Java/directory-mavibot-CharComparator_71/npe.json create mode 100644 Java/directory-mavibot-IntArrayComparator_58/Dockerfile create mode 100644 Java/directory-mavibot-IntArrayComparator_58/buggy.java create mode 100644 Java/directory-mavibot-IntArrayComparator_58/metadata.json create mode 100644 Java/directory-mavibot-IntArrayComparator_58/npe.json create mode 100644 Java/directory-mavibot-IntArrayComparator_71/Dockerfile create mode 100644 Java/directory-mavibot-IntArrayComparator_71/buggy.java create mode 100644 Java/directory-mavibot-IntArrayComparator_71/metadata.json create mode 100644 Java/directory-mavibot-IntArrayComparator_71/npe.json create mode 100644 Java/directory-mavibot-IntComparator_58/Dockerfile create mode 100644 Java/directory-mavibot-IntComparator_58/buggy.java create mode 100644 Java/directory-mavibot-IntComparator_58/metadata.json create mode 100644 Java/directory-mavibot-IntComparator_58/npe.json create mode 100644 Java/directory-mavibot-IntComparator_71/Dockerfile create mode 100644 Java/directory-mavibot-IntComparator_71/buggy.java create mode 100644 Java/directory-mavibot-IntComparator_71/metadata.json create mode 100644 Java/directory-mavibot-IntComparator_71/npe.json create mode 100644 Java/directory-mavibot-LongArrayComparator_58/Dockerfile create mode 100644 Java/directory-mavibot-LongArrayComparator_58/buggy.java create mode 100644 Java/directory-mavibot-LongArrayComparator_58/metadata.json create mode 100644 Java/directory-mavibot-LongArrayComparator_58/npe.json create mode 100644 Java/directory-mavibot-LongArrayComparator_71/Dockerfile create mode 100644 Java/directory-mavibot-LongArrayComparator_71/buggy.java create mode 100644 Java/directory-mavibot-LongArrayComparator_71/metadata.json create mode 100644 Java/directory-mavibot-LongArrayComparator_71/npe.json create mode 100644 Java/directory-mavibot-LongComparator_56/Dockerfile create mode 100644 Java/directory-mavibot-LongComparator_56/buggy.java create mode 100644 Java/directory-mavibot-LongComparator_56/metadata.json create mode 100644 Java/directory-mavibot-LongComparator_56/npe.json create mode 100644 Java/directory-mavibot-LongComparator_69/Dockerfile create mode 100644 Java/directory-mavibot-LongComparator_69/buggy.java create mode 100644 Java/directory-mavibot-LongComparator_69/metadata.json create mode 100644 Java/directory-mavibot-LongComparator_69/npe.json create mode 100644 Java/directory-mavibot-ShortArrayComparator_58/Dockerfile create mode 100644 Java/directory-mavibot-ShortArrayComparator_58/buggy.java create mode 100644 Java/directory-mavibot-ShortArrayComparator_58/metadata.json create mode 100644 Java/directory-mavibot-ShortArrayComparator_58/npe.json create mode 100644 Java/directory-mavibot-ShortArrayComparator_71/Dockerfile create mode 100644 Java/directory-mavibot-ShortArrayComparator_71/buggy.java create mode 100644 Java/directory-mavibot-ShortArrayComparator_71/metadata.json create mode 100644 Java/directory-mavibot-ShortArrayComparator_71/npe.json create mode 100644 Java/directory-mavibot-ShortComparator_58/Dockerfile create mode 100644 Java/directory-mavibot-ShortComparator_58/buggy.java create mode 100644 Java/directory-mavibot-ShortComparator_58/metadata.json create mode 100644 Java/directory-mavibot-ShortComparator_58/npe.json create mode 100644 Java/directory-mavibot-ShortComparator_71/Dockerfile create mode 100644 Java/directory-mavibot-ShortComparator_71/buggy.java create mode 100644 Java/directory-mavibot-ShortComparator_71/metadata.json create mode 100644 Java/directory-mavibot-ShortComparator_71/npe.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_126/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_126/buggy.java create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_126/metadata.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_126/npe.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_128/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_128/buggy.java create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_128/metadata.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_128/npe.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_130/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_130/buggy.java create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_130/metadata.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_130/npe.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_134/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_134/buggy.java create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_134/metadata.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_134/npe.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_135/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_135/buggy.java create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_135/metadata.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_135/npe.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_137/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_137/buggy.java create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_137/metadata.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_137/npe.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_141/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_141/buggy.java create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_141/metadata.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_141/npe.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_143/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_143/buggy.java create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_143/metadata.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_143/npe.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_145/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_145/buggy.java create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_145/metadata.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_145/npe.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_149/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_149/buggy.java create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_149/metadata.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_149/npe.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_151/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_151/buggy.java create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_151/metadata.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_151/npe.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_180/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_180/buggy.java create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_180/metadata.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_180/npe.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_251/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_251/buggy.java create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_251/metadata.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_251/npe.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_265/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_265/buggy.java create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_265/metadata.json create mode 100644 Java/geronimo-jcache-simple-CDIJCacheHelper_265/npe.json create mode 100644 Java/geronimo-jcache-simple-CacheResultInterceptor_72/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CacheResultInterceptor_72/buggy.java create mode 100644 Java/geronimo-jcache-simple-CacheResultInterceptor_72/metadata.json create mode 100644 Java/geronimo-jcache-simple-CacheResultInterceptor_72/npe.json create mode 100644 Java/geronimo-jcache-simple-CacheResultInterceptor_83/Dockerfile create mode 100644 Java/geronimo-jcache-simple-CacheResultInterceptor_83/buggy.java create mode 100644 Java/geronimo-jcache-simple-CacheResultInterceptor_83/metadata.json create mode 100644 Java/geronimo-jcache-simple-CacheResultInterceptor_83/npe.json create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/Dockerfile create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/buggy.java create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/metadata.json create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/npe.json create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/Dockerfile create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/buggy.java create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/metadata.json create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/npe.json create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/Dockerfile create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/buggy.java create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/metadata.json create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/npe.json create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/Dockerfile create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/buggy.java create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/metadata.json create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/npe.json create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/Dockerfile create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/buggy.java create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/metadata.json create mode 100644 Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleCache_188/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleCache_188/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleCache_188/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleCache_188/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleCache_216/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleCache_216/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleCache_216/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleCache_216/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleCache_219/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleCache_219/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleCache_219/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleCache_219/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleCache_222/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleCache_222/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleCache_222/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleCache_222/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleCache_251/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleCache_251/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleCache_251/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleCache_251/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleCache_619/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleCache_619/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleCache_619/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleCache_619/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleManager_103/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleManager_103/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleManager_103/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleManager_103/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleManager_248/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleManager_248/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleManager_248/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleManager_248/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_129/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_129/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_129/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_129/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_39/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_39/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_39/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_39/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_40/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_40/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_40/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_40/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_46/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_46/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_46/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_46/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_55/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_55/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_55/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_55/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_82/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_82/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_82/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_82/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_93/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_93/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_93/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_93/npe.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_95/Dockerfile create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_95/buggy.java create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_95/metadata.json create mode 100644 Java/geronimo-jcache-simple-SimpleProvider_95/npe.json diff --git a/Java/commons-validator-AbstractCalendarValidatorTest_230/Dockerfile b/Java/commons-validator-AbstractCalendarValidatorTest_230/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidatorTest_230/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-AbstractCalendarValidatorTest_230/buggy.java b/Java/commons-validator-AbstractCalendarValidatorTest_230/buggy.java new file mode 100644 index 000000000..3447484ed --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidatorTest_230/buggy.java @@ -0,0 +1,272 @@ +/* + * 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.validator.routines; + +import junit.framework.TestCase; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Date; +import java.util.Calendar; +import java.util.Locale; +import java.util.TimeZone; + +/** + * Base Calendar Test Case. + * + * @version $Revision$ + */ +public abstract class AbstractCalendarValidatorTest extends TestCase { + + protected AbstractCalendarValidator validator; + + protected static final TimeZone GMT = TimeZone.getTimeZone("GMT"); // 0 offset + protected static final TimeZone EST = TimeZone.getTimeZone("EST"); // - 5 hours + protected static final TimeZone EET = TimeZone.getTimeZone("EET"); // + 2 hours + protected static final TimeZone UTC = TimeZone.getTimeZone("UTC"); // + 2 hours + + protected String[] patternValid = new String[] { + "2005-01-01" + ,"2005-12-31" + ,"2004-02-29" // valid leap + ,"2005-04-30" + ,"05-12-31" + ,"2005-1-1" + ,"05-1-1"}; + protected String[] localeValid = new String[] { + "01/01/2005" + ,"12/31/2005" + ,"02/29/2004" // valid leap + ,"04/30/2005" + ,"12/31/05" + ,"1/1/2005" + ,"1/1/05"}; + protected Date[] patternExpect = new Date[] { + createDate(null, 20050101, 0) + ,createDate(null, 20051231, 0) + ,createDate(null, 20040229, 0) + ,createDate(null, 20050430, 0) + ,createDate(null, 20051231, 0) + ,createDate(null, 20050101, 0) + ,createDate(null, 20050101, 0)}; + protected String[] patternInvalid = new String[] { + "2005-00-01" // zero month + ,"2005-01-00" // zero day + ,"2005-13-03" // month invalid + ,"2005-04-31" // invalid day + ,"2005-03-32" // invalid day + ,"2005-02-29" // invalid leap + ,"200X-01-01" // invalid char + ,"2005-0X-01" // invalid char + ,"2005-01-0X" // invalid char + ,"01/01/2005" // invalid pattern + ,"2005-01" // invalid pattern + ,"2005--01" // invalid pattern + ,"2005-01-"}; // invalid pattern + protected String[] localeInvalid = new String[] { + "01/00/2005" // zero month + ,"00/01/2005" // zero day + ,"13/01/2005" // month invalid + ,"04/31/2005" // invalid day + ,"03/32/2005" // invalid day + ,"02/29/2005" // invalid leap + ,"01/01/200X" // invalid char + ,"01/0X/2005" // invalid char + ,"0X/01/2005" // invalid char + ,"01-01-2005" // invalid pattern + ,"01/2005" // invalid pattern + // -------- ,"/01/2005" ---- passes on some JDK + ,"01//2005"}; // invalid pattern + + /** + * Constructor + * @param name test name + */ + public AbstractCalendarValidatorTest(String name) { + super(name); + } + + /** + * Set Up. + * @throws Exception + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + /** + * Tear down + * @throws Exception + */ + @Override + protected void tearDown() throws Exception { + super.tearDown(); + validator = null; + } + + /** + * Test Valid Dates with "pattern" validation + */ + public void testPatternValid() { + for (int i = 0; i < patternValid.length; i++) { + String text = i + " value=[" +patternValid[i]+"] failed "; + Object date = validator.parse(patternValid[i], "yy-MM-dd", null, null); + assertNotNull("validateObj() " + text + date, date); + assertTrue("isValid() " + text, validator.isValid(patternValid[i], "yy-MM-dd")); + if (date instanceof Calendar) { + date = ((Calendar)date).getTime(); + } + assertEquals("compare " + text, patternExpect[i], date); + } + } + + /** + * Test Invalid Dates with "pattern" validation + */ + public void testPatternInvalid() { + for (int i = 0; i < patternInvalid.length; i++) { + String text = i + " value=[" +patternInvalid[i]+"] passed "; + Object date = validator.parse(patternInvalid[i], "yy-MM-dd", null, null); + assertNull("validateObj() " + text + date, date); + assertFalse("isValid() " + text, validator.isValid(patternInvalid[i], "yy-MM-dd")); + } + } + + /** + * Test Valid Dates with "locale" validation + */ + public void testLocaleValid() { + for (int i = 0; i < localeValid.length; i++) { + String text = i + " value=[" +localeValid[i]+"] failed "; + Object date = validator.parse(localeValid[i], null, Locale.US, null); + assertNotNull("validateObj() " + text + date, date); + assertTrue("isValid() " + text, validator.isValid(localeValid[i], Locale.US)); + if (date instanceof Calendar) { + date = ((Calendar)date).getTime(); + } + assertEquals("compare " + text, patternExpect[i], date); + } + } + + /** + * Test Invalid Dates with "locale" validation + */ + public void testLocaleInvalid() { + for (int i = 0; i < localeInvalid.length; i++) { + String text = i + " value=[" +localeInvalid[i]+"] passed "; + Object date = validator.parse(localeInvalid[i], null, Locale.US, null); + assertNull("validateObj() " + text + date, date); + assertFalse("isValid() " + text, validator.isValid(localeInvalid[i], Locale.US)); + } + } + + /** + * Test Invalid Dates with "locale" validation + */ + public void testFormat() { + + // Create a Date or Calendar + Object test = validator.parse("2005-11-28", "yyyy-MM-dd", null, null); + assertNotNull("Test Date ", test); + assertEquals("Format pattern", "28.11.05", validator.format(test, "dd.MM.yy")); + assertEquals("Format locale", "11/28/05", validator.format(test, Locale.US)); + } + + /** + * Test validator serialization. + */ + public void testSerialization() { + // Serialize the check digit routine + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(validator); + oos.flush(); + oos.close(); + } catch (Exception e) { + fail(validator.getClass().getName() + " error during serialization: " + e); + } + + // Deserialize the test object + Object result = null; + try { + ByteArrayInputStream bais = + new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bais); + result = ois.readObject(); + bais.close(); + } catch (Exception e) { + fail(validator.getClass().getName() + " error during deserialization: " + e); + } + assertNotNull(result); + } + + /** + * Create a calendar instance for a specified time zone, date and time. + * + * @param zone The time zone + * @param date The date in yyyyMMdd format + * @param time the time in HH:mm:ss format + * @return the new Calendar instance. + */ +/** + * Create a calendar instance for a specified time zone, date and time. + * + * @param zone + * The time zone + * @param date + * The date in yyyyMMdd format + * @param time + * the time in HH:mm:ss format + * @return the new Calendar instance. + */ +protected static java.util.Calendar createCalendar(java.util.TimeZone zone, int date, int time) { + java.util.Calendar calendar = java.util.Calendar.getInstance(/* NPEX_NULL_EXP */ + zone); + int year = (date / 10000) * 10000; + int mth = ((date / 100) * 100) - year; + int day = date - (year + mth); + int hour = (time / 10000) * 10000; + int min = ((time / 100) * 100) - hour; + int sec = time - (hour + min); + calendar.set(java.util.Calendar.YEAR, year / 10000); + calendar.set(java.util.Calendar.MONTH, (mth / 100) - 1); + calendar.set(java.util.Calendar.DATE, day); + calendar.set(java.util.Calendar.HOUR_OF_DAY, hour / 10000); + calendar.set(java.util.Calendar.MINUTE, min / 100); + calendar.set(java.util.Calendar.SECOND, sec); + calendar.set(java.util.Calendar.MILLISECOND, 0); + return calendar; +} + + /** + * Create a date instance for a specified time zone, date and time. + * + * @param zone The time zone + * @param date The date in yyyyMMdd format + * @param time the time in HH:mm:ss format + * @return the new Date instance. + */ + protected static Date createDate(TimeZone zone, int date, int time) { + Calendar calendar = createCalendar(zone, date, time); + return calendar.getTime(); + } + +} diff --git a/Java/commons-validator-AbstractCalendarValidatorTest_230/metadata.json b/Java/commons-validator-AbstractCalendarValidatorTest_230/metadata.json new file mode 100644 index 000000000..8ad6a8136 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidatorTest_230/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-AbstractCalendarValidatorTest_230", + "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/test/java/org/apache/commons/validator/routines/AbstractCalendarValidatorTest.java", + "line": 242, + "npe_method": "createCalendar", + "deref_field": "zone", + "npe_class": "AbstractCalendarValidatorTest", + "repo": "commons-validator", + "bug_id": "AbstractCalendarValidatorTest_230" + } +} diff --git a/Java/commons-validator-AbstractCalendarValidatorTest_230/npe.json b/Java/commons-validator-AbstractCalendarValidatorTest_230/npe.json new file mode 100644 index 000000000..51f8bbc2c --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidatorTest_230/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/test/java/org/apache/commons/validator/routines/AbstractCalendarValidatorTest.java", + "line": 242, + "npe_method": "createCalendar", + "deref_field": "zone", + "npe_class": "AbstractCalendarValidatorTest" +} \ No newline at end of file diff --git a/Java/commons-validator-AbstractCalendarValidator_141/Dockerfile b/Java/commons-validator-AbstractCalendarValidator_141/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_141/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-AbstractCalendarValidator_141/buggy.java b/Java/commons-validator-AbstractCalendarValidator_141/buggy.java new file mode 100644 index 000000000..6ba2334b9 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_141/buggy.java @@ -0,0 +1,441 @@ +/* + * 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.validator.routines; + +import java.text.DateFormatSymbols; +import java.text.Format; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Locale; +import java.util.TimeZone; + +/** + *

Abstract class for Date/Time/Calendar validation.

+ * + *

This is a base class for building Date / Time + * Validators using format parsing.

+ * + * @version $Revision$ + * @since Validator 1.3.0 + */ +public abstract class AbstractCalendarValidator extends AbstractFormatValidator { + + private static final long serialVersionUID = -1410008585975827379L; + + private final int dateStyle; + + private final int timeStyle; + + /** + * Construct an instance with the specified strict, + * time and date style parameters. + * + * @param strict true if strict + * Format parsing should be used. + * @param dateStyle the date style to use for Locale validation. + * @param timeStyle the time style to use for Locale validation. + */ + public AbstractCalendarValidator(boolean strict, int dateStyle, int timeStyle) { + super(strict); + this.dateStyle = dateStyle; + this.timeStyle = timeStyle; + } + + /** + *

Validate using the specified Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format, defaults to the default + * @return true if the value is valid. + */ + @Override + public boolean isValid(String value, String pattern, Locale locale) { + Object parsedValue = parse(value, pattern, locale, (TimeZone)null); + return (parsedValue == null ? false : true); + } + + /** + *

Format an object into a String using + * the default Locale.

+ * + * @param value The value validation is being performed on. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, TimeZone timeZone) { + return format(value, (String)null, (Locale)null, timeZone); + } + + /** + *

Format an object into a String using + * the specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, String pattern, TimeZone timeZone) { + return format(value, pattern, (Locale)null, timeZone); + } + + /** + *

Format an object into a String using + * the specified Locale.

+ * + * @param value The value validation is being performed on. + * @param locale The locale to use for the Format. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, Locale locale, TimeZone timeZone) { + return format(value, (String)null, locale, timeZone); + } + + /** + *

Format an object using the specified pattern and/or + * Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format. + * @return The value formatted as a String. + */ + @Override + public String format(Object value, String pattern, Locale locale) { + return format(value, pattern, locale, (TimeZone)null); + } + + /** + *

Format an object using the specified pattern and/or + * Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ +/** + *

Format an object using the specified pattern and/or + * Locale. + * + * @param value + * The value validation is being performed on. + * @param pattern + * The pattern used to format the value. + * @param locale + * The locale to use for the Format. + * @param timeZone + * The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ +public java.lang.String format(java.lang.Object value, java.lang.String pattern, java.util.Locale locale, java.util.TimeZone timeZone) { + java.text.DateFormat formatter = ((java.text.DateFormat) (getFormat(pattern, locale))); + { + formatter.setTimeZone(/* NPEX_NULL_EXP */ + timeZone); + } + return format(value, formatter); +} + + /** + *

Format a value with the specified DateFormat.

+ * + * @param value The value to be formatted. + * @param formatter The Format to use. + * @return The formatted value. + */ + @Override + protected String format(Object value, Format formatter) { + if (value == null) { + return null; + } else if (value instanceof Calendar) { + value = ((Calendar)value).getTime(); + } + return formatter.format(value); + } + + /** + *

Checks if the value is valid against a specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to validate the value against, or the + * default for the Locale if null. + * @param locale The locale to use for the date format, system default if null. + * @param timeZone The Time Zone used to parse the date, system default if null. + * @return The parsed value if valid or null if invalid. + */ + protected Object parse(String value, String pattern, Locale locale, TimeZone timeZone) { + + value = (value == null ? null : value.trim()); + if (value == null || value.length() == 0) { + return null; + } + DateFormat formatter = (DateFormat)getFormat(pattern, locale); + if (timeZone != null) { + formatter.setTimeZone(timeZone); + } + return parse(value, formatter); + + } + + /** + *

Process the parsed value, performing any further validation + * and type conversion required.

+ * + * @param value The parsed object created. + * @param formatter The Format used to parse the value with. + * @return The parsed value converted to the appropriate type + * if valid or null if invalid. + */ + @Override + protected abstract Object processParsedValue(Object value, Format formatter); + + /** + *

Returns a DateFormat for the specified pattern + * and/or Locale.

+ * + * @param pattern The pattern used to validate the value against or + * null to use the default for the Locale. + * @param locale The locale to use for the currency format, system default if null. + * @return The DateFormat to created. + */ + @Override + protected Format getFormat(String pattern, Locale locale) { + DateFormat formatter = null; + boolean usePattern = (pattern != null && pattern.length() > 0); + if (!usePattern) { + formatter = (DateFormat)getFormat(locale); + } else if (locale == null) { + formatter = new SimpleDateFormat(pattern); + } else { + DateFormatSymbols symbols = new DateFormatSymbols(locale); + formatter = new SimpleDateFormat(pattern, symbols); + } + formatter.setLenient(false); + return formatter; + } + + /** + *

Returns a DateFormat for the specified Locale.

+ * + * @param locale The locale a DateFormat is required for, + * system default if null. + * @return The DateFormat to created. + */ + protected Format getFormat(Locale locale) { + + DateFormat formatter = null; + if (dateStyle >= 0 && timeStyle >= 0) { + if (locale == null) { + formatter = DateFormat.getDateTimeInstance(dateStyle, timeStyle); + } else { + formatter = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale); + } + } else if (timeStyle >= 0) { + if (locale == null) { + formatter = DateFormat.getTimeInstance(timeStyle); + } else { + formatter = DateFormat.getTimeInstance(timeStyle, locale); + } + } else { + int useDateStyle = dateStyle >= 0 ? dateStyle : DateFormat.SHORT; + if (locale == null) { + formatter = DateFormat.getDateInstance(useDateStyle); + } else { + formatter = DateFormat.getDateInstance(useDateStyle, locale); + } + } + formatter.setLenient(false); + return formatter; + + } + + /** + *

Compares a calendar value to another, indicating whether it is + * equal, less then or more than at a specified level.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field level to compare to - e.g. specifying + * Calendar.MONTH will compare the year and month + * portions of the calendar. + * @return Zero if the first value is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compare(Calendar value, Calendar compare, int field) { + + int result = 0; + + // Compare Year + result = calculateCompareResult(value, compare, Calendar.YEAR); + if (result != 0 || field == Calendar.YEAR) { + return result; + } + + // Compare Week of Year + if (field == Calendar.WEEK_OF_YEAR) { + return calculateCompareResult(value, compare, Calendar.WEEK_OF_YEAR); + } + + // Compare Day of the Year + if (field == Calendar.DAY_OF_YEAR) { + return calculateCompareResult(value, compare, Calendar.DAY_OF_YEAR); + } + + // Compare Month + result = calculateCompareResult(value, compare, Calendar.MONTH); + if (result != 0 || field == Calendar.MONTH) { + return result; + } + + // Compare Week of Month + if (field == Calendar.WEEK_OF_MONTH) { + return calculateCompareResult(value, compare, Calendar.WEEK_OF_MONTH); + } + + // Compare Date + result = calculateCompareResult(value, compare, Calendar.DATE); + if (result != 0 || (field == Calendar.DATE || + field == Calendar.DAY_OF_WEEK || + field == Calendar.DAY_OF_WEEK_IN_MONTH)) { + return result; + } + + // Compare Time fields + return compareTime(value, compare, field); + + } + + /** + *

Compares a calendar time value to another, indicating whether it is + * equal, less then or more than at a specified level.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field level to compare to - e.g. specifying + * Calendar.MINUTE will compare the hours and minutes + * portions of the calendar. + * @return Zero if the first value is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compareTime(Calendar value, Calendar compare, int field) { + + int result = 0; + + // Compare Hour + result = calculateCompareResult(value, compare, Calendar.HOUR_OF_DAY); + if (result != 0 || (field == Calendar.HOUR || field == Calendar.HOUR_OF_DAY)) { + return result; + } + + // Compare Minute + result = calculateCompareResult(value, compare, Calendar.MINUTE); + if (result != 0 || field == Calendar.MINUTE) { + return result; + } + + // Compare Second + result = calculateCompareResult(value, compare, Calendar.SECOND); + if (result != 0 || field == Calendar.SECOND) { + return result; + } + + // Compare Milliseconds + if (field == Calendar.MILLISECOND) { + return calculateCompareResult(value, compare, Calendar.MILLISECOND); + } + + throw new IllegalArgumentException("Invalid field: " + field); + + } + + /** + *

Compares a calendar's quarter value to another, indicating whether it is + * equal, less then or more than the specified quarter.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param monthOfFirstQuarter The month that the first quarter starts. + * @return Zero if the first quarter is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compareQuarters(Calendar value, Calendar compare, int monthOfFirstQuarter) { + int valueQuarter = calculateQuarter(value, monthOfFirstQuarter); + int compareQuarter = calculateQuarter(compare, monthOfFirstQuarter); + if (valueQuarter < compareQuarter) { + return -1; + } else if (valueQuarter > compareQuarter) { + return 1; + } else { + return 0; + } + } + + /** + *

Calculate the quarter for the specified Calendar.

+ * + * @param calendar The Calendar value. + * @param monthOfFirstQuarter The month that the first quarter starts. + * @return The calculated quarter. + */ + private int calculateQuarter(Calendar calendar, int monthOfFirstQuarter) { + // Add Year + int year = calendar.get(Calendar.YEAR); + + int month = (calendar.get(Calendar.MONTH) + 1); + int relativeMonth = (month >= monthOfFirstQuarter) + ? (month - monthOfFirstQuarter) + : (month + (12 - monthOfFirstQuarter)); // CHECKSTYLE IGNORE MagicNumber + int quarter = ((relativeMonth / 3) + 1); // CHECKSTYLE IGNORE MagicNumber + // adjust the year if the quarter doesn't start in January + if (month < monthOfFirstQuarter) { + --year; + } + return (year * 10) + quarter; // CHECKSTYLE IGNORE MagicNumber + } + + /** + *

Compares the field from two calendars indicating whether the field for the + * first calendar is equal to, less than or greater than the field from the + * second calendar. + * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field to compare for the calendars. + * @return Zero if the first calendar's field is equal to the seconds, -1 + * if it is less than the seconds or +1 if it is greater than the seconds. + */ + private int calculateCompareResult(Calendar value, Calendar compare, int field) { + int difference = value.get(field) - compare.get(field); + if (difference < 0) { + return -1; + } else if (difference > 0) { + return 1; + } else { + return 0; + } + } +} diff --git a/Java/commons-validator-AbstractCalendarValidator_141/metadata.json b/Java/commons-validator-AbstractCalendarValidator_141/metadata.json new file mode 100644 index 000000000..bbe6c3ad2 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_141/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-AbstractCalendarValidator_141", + "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/validator/routines/AbstractCalendarValidator.java", + "line": 158, + "npe_method": "format", + "deref_field": "timeZone", + "npe_class": "AbstractCalendarValidator", + "repo": "commons-validator", + "bug_id": "AbstractCalendarValidator_141" + } +} diff --git a/Java/commons-validator-AbstractCalendarValidator_141/npe.json b/Java/commons-validator-AbstractCalendarValidator_141/npe.json new file mode 100644 index 000000000..b0ab5dadc --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_141/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/AbstractCalendarValidator.java", + "line": 158, + "npe_method": "format", + "deref_field": "timeZone", + "npe_class": "AbstractCalendarValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-AbstractCalendarValidator_158/Dockerfile b/Java/commons-validator-AbstractCalendarValidator_158/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_158/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-AbstractCalendarValidator_158/buggy.java b/Java/commons-validator-AbstractCalendarValidator_158/buggy.java new file mode 100644 index 000000000..3aced00b9 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_158/buggy.java @@ -0,0 +1,437 @@ +/* + * 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.validator.routines; + +import java.text.DateFormatSymbols; +import java.text.Format; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Locale; +import java.util.TimeZone; + +/** + *

Abstract class for Date/Time/Calendar validation.

+ * + *

This is a base class for building Date / Time + * Validators using format parsing.

+ * + * @version $Revision$ + * @since Validator 1.3.0 + */ +public abstract class AbstractCalendarValidator extends AbstractFormatValidator { + + private static final long serialVersionUID = -1410008585975827379L; + + private final int dateStyle; + + private final int timeStyle; + + /** + * Construct an instance with the specified strict, + * time and date style parameters. + * + * @param strict true if strict + * Format parsing should be used. + * @param dateStyle the date style to use for Locale validation. + * @param timeStyle the time style to use for Locale validation. + */ + public AbstractCalendarValidator(boolean strict, int dateStyle, int timeStyle) { + super(strict); + this.dateStyle = dateStyle; + this.timeStyle = timeStyle; + } + + /** + *

Validate using the specified Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format, defaults to the default + * @return true if the value is valid. + */ + @Override + public boolean isValid(String value, String pattern, Locale locale) { + Object parsedValue = parse(value, pattern, locale, (TimeZone)null); + return (parsedValue == null ? false : true); + } + + /** + *

Format an object into a String using + * the default Locale.

+ * + * @param value The value validation is being performed on. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, TimeZone timeZone) { + return format(value, (String)null, (Locale)null, timeZone); + } + + /** + *

Format an object into a String using + * the specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, String pattern, TimeZone timeZone) { + return format(value, pattern, (Locale)null, timeZone); + } + + /** + *

Format an object into a String using + * the specified Locale.

+ * + * @param value The value validation is being performed on. + * @param locale The locale to use for the Format. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, Locale locale, TimeZone timeZone) { + return format(value, (String)null, locale, timeZone); + } + + /** + *

Format an object using the specified pattern and/or + * Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format. + * @return The value formatted as a String. + */ + @Override + public String format(Object value, String pattern, Locale locale) { + return format(value, pattern, locale, (TimeZone)null); + } + + /** + *

Format an object using the specified pattern and/or + * Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, String pattern, Locale locale, TimeZone timeZone) { + DateFormat formatter = (DateFormat)getFormat(pattern, locale); + if (timeZone != null) { + formatter.setTimeZone(timeZone); + } else if (value instanceof Calendar) { + formatter.setTimeZone(((Calendar)value).getTimeZone()); + } + return format(value, formatter); + } + + /** + *

Format a value with the specified DateFormat.

+ * + * @param value The value to be formatted. + * @param formatter The Format to use. + * @return The formatted value. + */ + @Override +/** + *

Format a value with the specified DateFormat.

+ * + * @param value + * The value to be formatted. + * @param formatter + * The Format to use. + * @return The formatted value. + */ +protected java.lang.String format(java.lang.Object value, java.text.Format formatter) { + { + if (/* NPEX_NULL_EXP */ + value instanceof java.util.Calendar) { + value = ((java.util.Calendar) (value)).getTime(); + } + } + return formatter.format(value); +} + + /** + *

Checks if the value is valid against a specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to validate the value against, or the + * default for the Locale if null. + * @param locale The locale to use for the date format, system default if null. + * @param timeZone The Time Zone used to parse the date, system default if null. + * @return The parsed value if valid or null if invalid. + */ + protected Object parse(String value, String pattern, Locale locale, TimeZone timeZone) { + + value = (value == null ? null : value.trim()); + if (value == null || value.length() == 0) { + return null; + } + DateFormat formatter = (DateFormat)getFormat(pattern, locale); + if (timeZone != null) { + formatter.setTimeZone(timeZone); + } + return parse(value, formatter); + + } + + /** + *

Process the parsed value, performing any further validation + * and type conversion required.

+ * + * @param value The parsed object created. + * @param formatter The Format used to parse the value with. + * @return The parsed value converted to the appropriate type + * if valid or null if invalid. + */ + @Override + protected abstract Object processParsedValue(Object value, Format formatter); + + /** + *

Returns a DateFormat for the specified pattern + * and/or Locale.

+ * + * @param pattern The pattern used to validate the value against or + * null to use the default for the Locale. + * @param locale The locale to use for the currency format, system default if null. + * @return The DateFormat to created. + */ + @Override + protected Format getFormat(String pattern, Locale locale) { + DateFormat formatter = null; + boolean usePattern = (pattern != null && pattern.length() > 0); + if (!usePattern) { + formatter = (DateFormat)getFormat(locale); + } else if (locale == null) { + formatter = new SimpleDateFormat(pattern); + } else { + DateFormatSymbols symbols = new DateFormatSymbols(locale); + formatter = new SimpleDateFormat(pattern, symbols); + } + formatter.setLenient(false); + return formatter; + } + + /** + *

Returns a DateFormat for the specified Locale.

+ * + * @param locale The locale a DateFormat is required for, + * system default if null. + * @return The DateFormat to created. + */ + protected Format getFormat(Locale locale) { + + DateFormat formatter = null; + if (dateStyle >= 0 && timeStyle >= 0) { + if (locale == null) { + formatter = DateFormat.getDateTimeInstance(dateStyle, timeStyle); + } else { + formatter = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale); + } + } else if (timeStyle >= 0) { + if (locale == null) { + formatter = DateFormat.getTimeInstance(timeStyle); + } else { + formatter = DateFormat.getTimeInstance(timeStyle, locale); + } + } else { + int useDateStyle = dateStyle >= 0 ? dateStyle : DateFormat.SHORT; + if (locale == null) { + formatter = DateFormat.getDateInstance(useDateStyle); + } else { + formatter = DateFormat.getDateInstance(useDateStyle, locale); + } + } + formatter.setLenient(false); + return formatter; + + } + + /** + *

Compares a calendar value to another, indicating whether it is + * equal, less then or more than at a specified level.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field level to compare to - e.g. specifying + * Calendar.MONTH will compare the year and month + * portions of the calendar. + * @return Zero if the first value is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compare(Calendar value, Calendar compare, int field) { + + int result = 0; + + // Compare Year + result = calculateCompareResult(value, compare, Calendar.YEAR); + if (result != 0 || field == Calendar.YEAR) { + return result; + } + + // Compare Week of Year + if (field == Calendar.WEEK_OF_YEAR) { + return calculateCompareResult(value, compare, Calendar.WEEK_OF_YEAR); + } + + // Compare Day of the Year + if (field == Calendar.DAY_OF_YEAR) { + return calculateCompareResult(value, compare, Calendar.DAY_OF_YEAR); + } + + // Compare Month + result = calculateCompareResult(value, compare, Calendar.MONTH); + if (result != 0 || field == Calendar.MONTH) { + return result; + } + + // Compare Week of Month + if (field == Calendar.WEEK_OF_MONTH) { + return calculateCompareResult(value, compare, Calendar.WEEK_OF_MONTH); + } + + // Compare Date + result = calculateCompareResult(value, compare, Calendar.DATE); + if (result != 0 || (field == Calendar.DATE || + field == Calendar.DAY_OF_WEEK || + field == Calendar.DAY_OF_WEEK_IN_MONTH)) { + return result; + } + + // Compare Time fields + return compareTime(value, compare, field); + + } + + /** + *

Compares a calendar time value to another, indicating whether it is + * equal, less then or more than at a specified level.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field level to compare to - e.g. specifying + * Calendar.MINUTE will compare the hours and minutes + * portions of the calendar. + * @return Zero if the first value is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compareTime(Calendar value, Calendar compare, int field) { + + int result = 0; + + // Compare Hour + result = calculateCompareResult(value, compare, Calendar.HOUR_OF_DAY); + if (result != 0 || (field == Calendar.HOUR || field == Calendar.HOUR_OF_DAY)) { + return result; + } + + // Compare Minute + result = calculateCompareResult(value, compare, Calendar.MINUTE); + if (result != 0 || field == Calendar.MINUTE) { + return result; + } + + // Compare Second + result = calculateCompareResult(value, compare, Calendar.SECOND); + if (result != 0 || field == Calendar.SECOND) { + return result; + } + + // Compare Milliseconds + if (field == Calendar.MILLISECOND) { + return calculateCompareResult(value, compare, Calendar.MILLISECOND); + } + + throw new IllegalArgumentException("Invalid field: " + field); + + } + + /** + *

Compares a calendar's quarter value to another, indicating whether it is + * equal, less then or more than the specified quarter.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param monthOfFirstQuarter The month that the first quarter starts. + * @return Zero if the first quarter is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compareQuarters(Calendar value, Calendar compare, int monthOfFirstQuarter) { + int valueQuarter = calculateQuarter(value, monthOfFirstQuarter); + int compareQuarter = calculateQuarter(compare, monthOfFirstQuarter); + if (valueQuarter < compareQuarter) { + return -1; + } else if (valueQuarter > compareQuarter) { + return 1; + } else { + return 0; + } + } + + /** + *

Calculate the quarter for the specified Calendar.

+ * + * @param calendar The Calendar value. + * @param monthOfFirstQuarter The month that the first quarter starts. + * @return The calculated quarter. + */ + private int calculateQuarter(Calendar calendar, int monthOfFirstQuarter) { + // Add Year + int year = calendar.get(Calendar.YEAR); + + int month = (calendar.get(Calendar.MONTH) + 1); + int relativeMonth = (month >= monthOfFirstQuarter) + ? (month - monthOfFirstQuarter) + : (month + (12 - monthOfFirstQuarter)); // CHECKSTYLE IGNORE MagicNumber + int quarter = ((relativeMonth / 3) + 1); // CHECKSTYLE IGNORE MagicNumber + // adjust the year if the quarter doesn't start in January + if (month < monthOfFirstQuarter) { + --year; + } + return (year * 10) + quarter; // CHECKSTYLE IGNORE MagicNumber + } + + /** + *

Compares the field from two calendars indicating whether the field for the + * first calendar is equal to, less than or greater than the field from the + * second calendar. + * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field to compare for the calendars. + * @return Zero if the first calendar's field is equal to the seconds, -1 + * if it is less than the seconds or +1 if it is greater than the seconds. + */ + private int calculateCompareResult(Calendar value, Calendar compare, int field) { + int difference = value.get(field) - compare.get(field); + if (difference < 0) { + return -1; + } else if (difference > 0) { + return 1; + } else { + return 0; + } + } +} diff --git a/Java/commons-validator-AbstractCalendarValidator_158/metadata.json b/Java/commons-validator-AbstractCalendarValidator_158/metadata.json new file mode 100644 index 000000000..dc682a990 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_158/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-AbstractCalendarValidator_158", + "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/validator/routines/AbstractCalendarValidator.java", + "line": 169, + "npe_method": "format", + "deref_field": "value", + "npe_class": "AbstractCalendarValidator", + "repo": "commons-validator", + "bug_id": "AbstractCalendarValidator_158" + } +} diff --git a/Java/commons-validator-AbstractCalendarValidator_158/npe.json b/Java/commons-validator-AbstractCalendarValidator_158/npe.json new file mode 100644 index 000000000..207e91420 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_158/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/AbstractCalendarValidator.java", + "line": 169, + "npe_method": "format", + "deref_field": "value", + "npe_class": "AbstractCalendarValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-AbstractCalendarValidator_183/Dockerfile b/Java/commons-validator-AbstractCalendarValidator_183/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_183/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-AbstractCalendarValidator_183/buggy.java b/Java/commons-validator-AbstractCalendarValidator_183/buggy.java new file mode 100644 index 000000000..0d92c8fcb --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_183/buggy.java @@ -0,0 +1,439 @@ +/* + * 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.validator.routines; + +import java.text.DateFormatSymbols; +import java.text.Format; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Locale; +import java.util.TimeZone; + +/** + *

Abstract class for Date/Time/Calendar validation.

+ * + *

This is a base class for building Date / Time + * Validators using format parsing.

+ * + * @version $Revision$ + * @since Validator 1.3.0 + */ +public abstract class AbstractCalendarValidator extends AbstractFormatValidator { + + private static final long serialVersionUID = -1410008585975827379L; + + private final int dateStyle; + + private final int timeStyle; + + /** + * Construct an instance with the specified strict, + * time and date style parameters. + * + * @param strict true if strict + * Format parsing should be used. + * @param dateStyle the date style to use for Locale validation. + * @param timeStyle the time style to use for Locale validation. + */ + public AbstractCalendarValidator(boolean strict, int dateStyle, int timeStyle) { + super(strict); + this.dateStyle = dateStyle; + this.timeStyle = timeStyle; + } + + /** + *

Validate using the specified Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format, defaults to the default + * @return true if the value is valid. + */ + @Override + public boolean isValid(String value, String pattern, Locale locale) { + Object parsedValue = parse(value, pattern, locale, (TimeZone)null); + return (parsedValue == null ? false : true); + } + + /** + *

Format an object into a String using + * the default Locale.

+ * + * @param value The value validation is being performed on. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, TimeZone timeZone) { + return format(value, (String)null, (Locale)null, timeZone); + } + + /** + *

Format an object into a String using + * the specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, String pattern, TimeZone timeZone) { + return format(value, pattern, (Locale)null, timeZone); + } + + /** + *

Format an object into a String using + * the specified Locale.

+ * + * @param value The value validation is being performed on. + * @param locale The locale to use for the Format. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, Locale locale, TimeZone timeZone) { + return format(value, (String)null, locale, timeZone); + } + + /** + *

Format an object using the specified pattern and/or + * Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format. + * @return The value formatted as a String. + */ + @Override + public String format(Object value, String pattern, Locale locale) { + return format(value, pattern, locale, (TimeZone)null); + } + + /** + *

Format an object using the specified pattern and/or + * Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, String pattern, Locale locale, TimeZone timeZone) { + DateFormat formatter = (DateFormat)getFormat(pattern, locale); + if (timeZone != null) { + formatter.setTimeZone(timeZone); + } else if (value instanceof Calendar) { + formatter.setTimeZone(((Calendar)value).getTimeZone()); + } + return format(value, formatter); + } + + /** + *

Format a value with the specified DateFormat.

+ * + * @param value The value to be formatted. + * @param formatter The Format to use. + * @return The formatted value. + */ + @Override + protected String format(Object value, Format formatter) { + if (value == null) { + return null; + } else if (value instanceof Calendar) { + value = ((Calendar)value).getTime(); + } + return formatter.format(value); + } + + /** + *

Checks if the value is valid against a specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to validate the value against, or the + * default for the Locale if null. + * @param locale The locale to use for the date format, system default if null. + * @param timeZone The Time Zone used to parse the date, system default if null. + * @return The parsed value if valid or null if invalid. + */ +/** + *

Checks if the value is valid against a specified pattern.

+ * + * @param value + * The value validation is being performed on. + * @param pattern + * The pattern used to validate the value against, or the + * default for the Locale if null. + * @param locale + * The locale to use for the date format, system default if null. + * @param timeZone + * The Time Zone used to parse the date, system default if null. + * @return The parsed value if valid or null if invalid. + */ +protected java.lang.Object parse(java.lang.String value, java.lang.String pattern, java.util.Locale locale, java.util.TimeZone timeZone) { + value = (value == null) ? null : value.trim(); + if ((value == null) || (value.length() == 0)) { + return null; + } + java.text.DateFormat formatter = ((java.text.DateFormat) (getFormat(pattern, locale))); + { + formatter.setTimeZone(timeZone); + } + return parse(value, formatter); +} + + /** + *

Process the parsed value, performing any further validation + * and type conversion required.

+ * + * @param value The parsed object created. + * @param formatter The Format used to parse the value with. + * @return The parsed value converted to the appropriate type + * if valid or null if invalid. + */ + @Override + protected abstract Object processParsedValue(Object value, Format formatter); + + /** + *

Returns a DateFormat for the specified pattern + * and/or Locale.

+ * + * @param pattern The pattern used to validate the value against or + * null to use the default for the Locale. + * @param locale The locale to use for the currency format, system default if null. + * @return The DateFormat to created. + */ + @Override + protected Format getFormat(String pattern, Locale locale) { + DateFormat formatter = null; + boolean usePattern = (pattern != null && pattern.length() > 0); + if (!usePattern) { + formatter = (DateFormat)getFormat(locale); + } else if (locale == null) { + formatter = new SimpleDateFormat(pattern); + } else { + DateFormatSymbols symbols = new DateFormatSymbols(locale); + formatter = new SimpleDateFormat(pattern, symbols); + } + formatter.setLenient(false); + return formatter; + } + + /** + *

Returns a DateFormat for the specified Locale.

+ * + * @param locale The locale a DateFormat is required for, + * system default if null. + * @return The DateFormat to created. + */ + protected Format getFormat(Locale locale) { + + DateFormat formatter = null; + if (dateStyle >= 0 && timeStyle >= 0) { + if (locale == null) { + formatter = DateFormat.getDateTimeInstance(dateStyle, timeStyle); + } else { + formatter = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale); + } + } else if (timeStyle >= 0) { + if (locale == null) { + formatter = DateFormat.getTimeInstance(timeStyle); + } else { + formatter = DateFormat.getTimeInstance(timeStyle, locale); + } + } else { + int useDateStyle = dateStyle >= 0 ? dateStyle : DateFormat.SHORT; + if (locale == null) { + formatter = DateFormat.getDateInstance(useDateStyle); + } else { + formatter = DateFormat.getDateInstance(useDateStyle, locale); + } + } + formatter.setLenient(false); + return formatter; + + } + + /** + *

Compares a calendar value to another, indicating whether it is + * equal, less then or more than at a specified level.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field level to compare to - e.g. specifying + * Calendar.MONTH will compare the year and month + * portions of the calendar. + * @return Zero if the first value is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compare(Calendar value, Calendar compare, int field) { + + int result = 0; + + // Compare Year + result = calculateCompareResult(value, compare, Calendar.YEAR); + if (result != 0 || field == Calendar.YEAR) { + return result; + } + + // Compare Week of Year + if (field == Calendar.WEEK_OF_YEAR) { + return calculateCompareResult(value, compare, Calendar.WEEK_OF_YEAR); + } + + // Compare Day of the Year + if (field == Calendar.DAY_OF_YEAR) { + return calculateCompareResult(value, compare, Calendar.DAY_OF_YEAR); + } + + // Compare Month + result = calculateCompareResult(value, compare, Calendar.MONTH); + if (result != 0 || field == Calendar.MONTH) { + return result; + } + + // Compare Week of Month + if (field == Calendar.WEEK_OF_MONTH) { + return calculateCompareResult(value, compare, Calendar.WEEK_OF_MONTH); + } + + // Compare Date + result = calculateCompareResult(value, compare, Calendar.DATE); + if (result != 0 || (field == Calendar.DATE || + field == Calendar.DAY_OF_WEEK || + field == Calendar.DAY_OF_WEEK_IN_MONTH)) { + return result; + } + + // Compare Time fields + return compareTime(value, compare, field); + + } + + /** + *

Compares a calendar time value to another, indicating whether it is + * equal, less then or more than at a specified level.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field level to compare to - e.g. specifying + * Calendar.MINUTE will compare the hours and minutes + * portions of the calendar. + * @return Zero if the first value is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compareTime(Calendar value, Calendar compare, int field) { + + int result = 0; + + // Compare Hour + result = calculateCompareResult(value, compare, Calendar.HOUR_OF_DAY); + if (result != 0 || (field == Calendar.HOUR || field == Calendar.HOUR_OF_DAY)) { + return result; + } + + // Compare Minute + result = calculateCompareResult(value, compare, Calendar.MINUTE); + if (result != 0 || field == Calendar.MINUTE) { + return result; + } + + // Compare Second + result = calculateCompareResult(value, compare, Calendar.SECOND); + if (result != 0 || field == Calendar.SECOND) { + return result; + } + + // Compare Milliseconds + if (field == Calendar.MILLISECOND) { + return calculateCompareResult(value, compare, Calendar.MILLISECOND); + } + + throw new IllegalArgumentException("Invalid field: " + field); + + } + + /** + *

Compares a calendar's quarter value to another, indicating whether it is + * equal, less then or more than the specified quarter.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param monthOfFirstQuarter The month that the first quarter starts. + * @return Zero if the first quarter is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compareQuarters(Calendar value, Calendar compare, int monthOfFirstQuarter) { + int valueQuarter = calculateQuarter(value, monthOfFirstQuarter); + int compareQuarter = calculateQuarter(compare, monthOfFirstQuarter); + if (valueQuarter < compareQuarter) { + return -1; + } else if (valueQuarter > compareQuarter) { + return 1; + } else { + return 0; + } + } + + /** + *

Calculate the quarter for the specified Calendar.

+ * + * @param calendar The Calendar value. + * @param monthOfFirstQuarter The month that the first quarter starts. + * @return The calculated quarter. + */ + private int calculateQuarter(Calendar calendar, int monthOfFirstQuarter) { + // Add Year + int year = calendar.get(Calendar.YEAR); + + int month = (calendar.get(Calendar.MONTH) + 1); + int relativeMonth = (month >= monthOfFirstQuarter) + ? (month - monthOfFirstQuarter) + : (month + (12 - monthOfFirstQuarter)); // CHECKSTYLE IGNORE MagicNumber + int quarter = ((relativeMonth / 3) + 1); // CHECKSTYLE IGNORE MagicNumber + // adjust the year if the quarter doesn't start in January + if (month < monthOfFirstQuarter) { + --year; + } + return (year * 10) + quarter; // CHECKSTYLE IGNORE MagicNumber + } + + /** + *

Compares the field from two calendars indicating whether the field for the + * first calendar is equal to, less than or greater than the field from the + * second calendar. + * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field to compare for the calendars. + * @return Zero if the first calendar's field is equal to the seconds, -1 + * if it is less than the seconds or +1 if it is greater than the seconds. + */ + private int calculateCompareResult(Calendar value, Calendar compare, int field) { + int difference = value.get(field) - compare.get(field); + if (difference < 0) { + return -1; + } else if (difference > 0) { + return 1; + } else { + return 0; + } + } +} diff --git a/Java/commons-validator-AbstractCalendarValidator_183/metadata.json b/Java/commons-validator-AbstractCalendarValidator_183/metadata.json new file mode 100644 index 000000000..1dcdff2e9 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_183/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-AbstractCalendarValidator_183", + "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/validator/routines/AbstractCalendarValidator.java", + "line": 142, + "npe_method": "parse", + "deref_field": "timeZone", + "npe_class": "AbstractCalendarValidator", + "repo": "commons-validator", + "bug_id": "AbstractCalendarValidator_183" + } +} diff --git a/Java/commons-validator-AbstractCalendarValidator_183/npe.json b/Java/commons-validator-AbstractCalendarValidator_183/npe.json new file mode 100644 index 000000000..848a9439b --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_183/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/AbstractCalendarValidator.java", + "line": 142, + "npe_method": "parse", + "deref_field": "timeZone", + "npe_class": "AbstractCalendarValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-AbstractCalendarValidator_217/Dockerfile b/Java/commons-validator-AbstractCalendarValidator_217/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_217/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-AbstractCalendarValidator_217/buggy.java b/Java/commons-validator-AbstractCalendarValidator_217/buggy.java new file mode 100644 index 000000000..a0c35c937 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_217/buggy.java @@ -0,0 +1,439 @@ +/* + * 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.validator.routines; + +import java.text.DateFormatSymbols; +import java.text.Format; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Locale; +import java.util.TimeZone; + +/** + *

Abstract class for Date/Time/Calendar validation.

+ * + *

This is a base class for building Date / Time + * Validators using format parsing.

+ * + * @version $Revision$ + * @since Validator 1.3.0 + */ +public abstract class AbstractCalendarValidator extends AbstractFormatValidator { + + private static final long serialVersionUID = -1410008585975827379L; + + private final int dateStyle; + + private final int timeStyle; + + /** + * Construct an instance with the specified strict, + * time and date style parameters. + * + * @param strict true if strict + * Format parsing should be used. + * @param dateStyle the date style to use for Locale validation. + * @param timeStyle the time style to use for Locale validation. + */ + public AbstractCalendarValidator(boolean strict, int dateStyle, int timeStyle) { + super(strict); + this.dateStyle = dateStyle; + this.timeStyle = timeStyle; + } + + /** + *

Validate using the specified Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format, defaults to the default + * @return true if the value is valid. + */ + @Override + public boolean isValid(String value, String pattern, Locale locale) { + Object parsedValue = parse(value, pattern, locale, (TimeZone)null); + return (parsedValue == null ? false : true); + } + + /** + *

Format an object into a String using + * the default Locale.

+ * + * @param value The value validation is being performed on. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, TimeZone timeZone) { + return format(value, (String)null, (Locale)null, timeZone); + } + + /** + *

Format an object into a String using + * the specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, String pattern, TimeZone timeZone) { + return format(value, pattern, (Locale)null, timeZone); + } + + /** + *

Format an object into a String using + * the specified Locale.

+ * + * @param value The value validation is being performed on. + * @param locale The locale to use for the Format. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, Locale locale, TimeZone timeZone) { + return format(value, (String)null, locale, timeZone); + } + + /** + *

Format an object using the specified pattern and/or + * Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format. + * @return The value formatted as a String. + */ + @Override + public String format(Object value, String pattern, Locale locale) { + return format(value, pattern, locale, (TimeZone)null); + } + + /** + *

Format an object using the specified pattern and/or + * Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, String pattern, Locale locale, TimeZone timeZone) { + DateFormat formatter = (DateFormat)getFormat(pattern, locale); + if (timeZone != null) { + formatter.setTimeZone(timeZone); + } else if (value instanceof Calendar) { + formatter.setTimeZone(((Calendar)value).getTimeZone()); + } + return format(value, formatter); + } + + /** + *

Format a value with the specified DateFormat.

+ * + * @param value The value to be formatted. + * @param formatter The Format to use. + * @return The formatted value. + */ + @Override + protected String format(Object value, Format formatter) { + if (value == null) { + return null; + } else if (value instanceof Calendar) { + value = ((Calendar)value).getTime(); + } + return formatter.format(value); + } + + /** + *

Checks if the value is valid against a specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to validate the value against, or the + * default for the Locale if null. + * @param locale The locale to use for the date format, system default if null. + * @param timeZone The Time Zone used to parse the date, system default if null. + * @return The parsed value if valid or null if invalid. + */ + protected Object parse(String value, String pattern, Locale locale, TimeZone timeZone) { + + value = (value == null ? null : value.trim()); + if (value == null || value.length() == 0) { + return null; + } + DateFormat formatter = (DateFormat)getFormat(pattern, locale); + if (timeZone != null) { + formatter.setTimeZone(timeZone); + } + return parse(value, formatter); + + } + + /** + *

Process the parsed value, performing any further validation + * and type conversion required.

+ * + * @param value The parsed object created. + * @param formatter The Format used to parse the value with. + * @return The parsed value converted to the appropriate type + * if valid or null if invalid. + */ + @Override + protected abstract Object processParsedValue(Object value, Format formatter); + + /** + *

Returns a DateFormat for the specified pattern + * and/or Locale.

+ * + * @param pattern The pattern used to validate the value against or + * null to use the default for the Locale. + * @param locale The locale to use for the currency format, system default if null. + * @return The DateFormat to created. + */ + @Override +/** + *

Returns a DateFormat for the specified pattern + * and/or Locale.

+ * + * @param pattern + * The pattern used to validate the value against or + * null to use the default for the Locale. + * @param locale + * The locale to use for the currency format, system default if null. + * @return The DateFormat to created. + */ +protected java.text.Format getFormat(java.lang.String pattern, java.util.Locale locale) { + java.text.DateFormat formatter = null; + boolean usePattern = (pattern != null) && (pattern.length() > 0); + if (!usePattern) { + formatter = ((java.text.DateFormat) (getFormat(locale))); + } else { + { + java.text.DateFormatSymbols symbols = new java.text.DateFormatSymbols(/* NPEX_NULL_EXP */ + locale); + formatter = new java.text.SimpleDateFormat(pattern, symbols); + } + } + formatter.setLenient(false); + return formatter; +} + + /** + *

Returns a DateFormat for the specified Locale.

+ * + * @param locale The locale a DateFormat is required for, + * system default if null. + * @return The DateFormat to created. + */ + protected Format getFormat(Locale locale) { + + DateFormat formatter = null; + if (dateStyle >= 0 && timeStyle >= 0) { + if (locale == null) { + formatter = DateFormat.getDateTimeInstance(dateStyle, timeStyle); + } else { + formatter = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale); + } + } else if (timeStyle >= 0) { + if (locale == null) { + formatter = DateFormat.getTimeInstance(timeStyle); + } else { + formatter = DateFormat.getTimeInstance(timeStyle, locale); + } + } else { + int useDateStyle = dateStyle >= 0 ? dateStyle : DateFormat.SHORT; + if (locale == null) { + formatter = DateFormat.getDateInstance(useDateStyle); + } else { + formatter = DateFormat.getDateInstance(useDateStyle, locale); + } + } + formatter.setLenient(false); + return formatter; + + } + + /** + *

Compares a calendar value to another, indicating whether it is + * equal, less then or more than at a specified level.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field level to compare to - e.g. specifying + * Calendar.MONTH will compare the year and month + * portions of the calendar. + * @return Zero if the first value is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compare(Calendar value, Calendar compare, int field) { + + int result = 0; + + // Compare Year + result = calculateCompareResult(value, compare, Calendar.YEAR); + if (result != 0 || field == Calendar.YEAR) { + return result; + } + + // Compare Week of Year + if (field == Calendar.WEEK_OF_YEAR) { + return calculateCompareResult(value, compare, Calendar.WEEK_OF_YEAR); + } + + // Compare Day of the Year + if (field == Calendar.DAY_OF_YEAR) { + return calculateCompareResult(value, compare, Calendar.DAY_OF_YEAR); + } + + // Compare Month + result = calculateCompareResult(value, compare, Calendar.MONTH); + if (result != 0 || field == Calendar.MONTH) { + return result; + } + + // Compare Week of Month + if (field == Calendar.WEEK_OF_MONTH) { + return calculateCompareResult(value, compare, Calendar.WEEK_OF_MONTH); + } + + // Compare Date + result = calculateCompareResult(value, compare, Calendar.DATE); + if (result != 0 || (field == Calendar.DATE || + field == Calendar.DAY_OF_WEEK || + field == Calendar.DAY_OF_WEEK_IN_MONTH)) { + return result; + } + + // Compare Time fields + return compareTime(value, compare, field); + + } + + /** + *

Compares a calendar time value to another, indicating whether it is + * equal, less then or more than at a specified level.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field level to compare to - e.g. specifying + * Calendar.MINUTE will compare the hours and minutes + * portions of the calendar. + * @return Zero if the first value is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compareTime(Calendar value, Calendar compare, int field) { + + int result = 0; + + // Compare Hour + result = calculateCompareResult(value, compare, Calendar.HOUR_OF_DAY); + if (result != 0 || (field == Calendar.HOUR || field == Calendar.HOUR_OF_DAY)) { + return result; + } + + // Compare Minute + result = calculateCompareResult(value, compare, Calendar.MINUTE); + if (result != 0 || field == Calendar.MINUTE) { + return result; + } + + // Compare Second + result = calculateCompareResult(value, compare, Calendar.SECOND); + if (result != 0 || field == Calendar.SECOND) { + return result; + } + + // Compare Milliseconds + if (field == Calendar.MILLISECOND) { + return calculateCompareResult(value, compare, Calendar.MILLISECOND); + } + + throw new IllegalArgumentException("Invalid field: " + field); + + } + + /** + *

Compares a calendar's quarter value to another, indicating whether it is + * equal, less then or more than the specified quarter.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param monthOfFirstQuarter The month that the first quarter starts. + * @return Zero if the first quarter is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compareQuarters(Calendar value, Calendar compare, int monthOfFirstQuarter) { + int valueQuarter = calculateQuarter(value, monthOfFirstQuarter); + int compareQuarter = calculateQuarter(compare, monthOfFirstQuarter); + if (valueQuarter < compareQuarter) { + return -1; + } else if (valueQuarter > compareQuarter) { + return 1; + } else { + return 0; + } + } + + /** + *

Calculate the quarter for the specified Calendar.

+ * + * @param calendar The Calendar value. + * @param monthOfFirstQuarter The month that the first quarter starts. + * @return The calculated quarter. + */ + private int calculateQuarter(Calendar calendar, int monthOfFirstQuarter) { + // Add Year + int year = calendar.get(Calendar.YEAR); + + int month = (calendar.get(Calendar.MONTH) + 1); + int relativeMonth = (month >= monthOfFirstQuarter) + ? (month - monthOfFirstQuarter) + : (month + (12 - monthOfFirstQuarter)); // CHECKSTYLE IGNORE MagicNumber + int quarter = ((relativeMonth / 3) + 1); // CHECKSTYLE IGNORE MagicNumber + // adjust the year if the quarter doesn't start in January + if (month < monthOfFirstQuarter) { + --year; + } + return (year * 10) + quarter; // CHECKSTYLE IGNORE MagicNumber + } + + /** + *

Compares the field from two calendars indicating whether the field for the + * first calendar is equal to, less than or greater than the field from the + * second calendar. + * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field to compare for the calendars. + * @return Zero if the first calendar's field is equal to the seconds, -1 + * if it is less than the seconds or +1 if it is greater than the seconds. + */ + private int calculateCompareResult(Calendar value, Calendar compare, int field) { + int difference = value.get(field) - compare.get(field); + if (difference < 0) { + return -1; + } else if (difference > 0) { + return 1; + } else { + return 0; + } + } +} diff --git a/Java/commons-validator-AbstractCalendarValidator_217/metadata.json b/Java/commons-validator-AbstractCalendarValidator_217/metadata.json new file mode 100644 index 000000000..68edcb67c --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_217/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-AbstractCalendarValidator_217", + "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/validator/routines/AbstractCalendarValidator.java", + "line": 231, + "npe_method": "getFormat", + "deref_field": "locale", + "npe_class": "AbstractCalendarValidator", + "repo": "commons-validator", + "bug_id": "AbstractCalendarValidator_217" + } +} diff --git a/Java/commons-validator-AbstractCalendarValidator_217/npe.json b/Java/commons-validator-AbstractCalendarValidator_217/npe.json new file mode 100644 index 000000000..7059a92aa --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_217/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/AbstractCalendarValidator.java", + "line": 231, + "npe_method": "getFormat", + "deref_field": "locale", + "npe_class": "AbstractCalendarValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-AbstractCalendarValidator_238/Dockerfile b/Java/commons-validator-AbstractCalendarValidator_238/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_238/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-AbstractCalendarValidator_238/buggy.java b/Java/commons-validator-AbstractCalendarValidator_238/buggy.java new file mode 100644 index 000000000..099c74470 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_238/buggy.java @@ -0,0 +1,432 @@ +/* + * 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.validator.routines; + +import java.text.DateFormatSymbols; +import java.text.Format; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Locale; +import java.util.TimeZone; + +/** + *

Abstract class for Date/Time/Calendar validation.

+ * + *

This is a base class for building Date / Time + * Validators using format parsing.

+ * + * @version $Revision$ + * @since Validator 1.3.0 + */ +public abstract class AbstractCalendarValidator extends AbstractFormatValidator { + + private static final long serialVersionUID = -1410008585975827379L; + + private final int dateStyle; + + private final int timeStyle; + + /** + * Construct an instance with the specified strict, + * time and date style parameters. + * + * @param strict true if strict + * Format parsing should be used. + * @param dateStyle the date style to use for Locale validation. + * @param timeStyle the time style to use for Locale validation. + */ + public AbstractCalendarValidator(boolean strict, int dateStyle, int timeStyle) { + super(strict); + this.dateStyle = dateStyle; + this.timeStyle = timeStyle; + } + + /** + *

Validate using the specified Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format, defaults to the default + * @return true if the value is valid. + */ + @Override + public boolean isValid(String value, String pattern, Locale locale) { + Object parsedValue = parse(value, pattern, locale, (TimeZone)null); + return (parsedValue == null ? false : true); + } + + /** + *

Format an object into a String using + * the default Locale.

+ * + * @param value The value validation is being performed on. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, TimeZone timeZone) { + return format(value, (String)null, (Locale)null, timeZone); + } + + /** + *

Format an object into a String using + * the specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, String pattern, TimeZone timeZone) { + return format(value, pattern, (Locale)null, timeZone); + } + + /** + *

Format an object into a String using + * the specified Locale.

+ * + * @param value The value validation is being performed on. + * @param locale The locale to use for the Format. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, Locale locale, TimeZone timeZone) { + return format(value, (String)null, locale, timeZone); + } + + /** + *

Format an object using the specified pattern and/or + * Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format. + * @return The value formatted as a String. + */ + @Override + public String format(Object value, String pattern, Locale locale) { + return format(value, pattern, locale, (TimeZone)null); + } + + /** + *

Format an object using the specified pattern and/or + * Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, String pattern, Locale locale, TimeZone timeZone) { + DateFormat formatter = (DateFormat)getFormat(pattern, locale); + if (timeZone != null) { + formatter.setTimeZone(timeZone); + } else if (value instanceof Calendar) { + formatter.setTimeZone(((Calendar)value).getTimeZone()); + } + return format(value, formatter); + } + + /** + *

Format a value with the specified DateFormat.

+ * + * @param value The value to be formatted. + * @param formatter The Format to use. + * @return The formatted value. + */ + @Override + protected String format(Object value, Format formatter) { + if (value == null) { + return null; + } else if (value instanceof Calendar) { + value = ((Calendar)value).getTime(); + } + return formatter.format(value); + } + + /** + *

Checks if the value is valid against a specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to validate the value against, or the + * default for the Locale if null. + * @param locale The locale to use for the date format, system default if null. + * @param timeZone The Time Zone used to parse the date, system default if null. + * @return The parsed value if valid or null if invalid. + */ + protected Object parse(String value, String pattern, Locale locale, TimeZone timeZone) { + + value = (value == null ? null : value.trim()); + if (value == null || value.length() == 0) { + return null; + } + DateFormat formatter = (DateFormat)getFormat(pattern, locale); + if (timeZone != null) { + formatter.setTimeZone(timeZone); + } + return parse(value, formatter); + + } + + /** + *

Process the parsed value, performing any further validation + * and type conversion required.

+ * + * @param value The parsed object created. + * @param formatter The Format used to parse the value with. + * @return The parsed value converted to the appropriate type + * if valid or null if invalid. + */ + @Override + protected abstract Object processParsedValue(Object value, Format formatter); + + /** + *

Returns a DateFormat for the specified pattern + * and/or Locale.

+ * + * @param pattern The pattern used to validate the value against or + * null to use the default for the Locale. + * @param locale The locale to use for the currency format, system default if null. + * @return The DateFormat to created. + */ + @Override + protected Format getFormat(String pattern, Locale locale) { + DateFormat formatter = null; + boolean usePattern = (pattern != null && pattern.length() > 0); + if (!usePattern) { + formatter = (DateFormat)getFormat(locale); + } else if (locale == null) { + formatter = new SimpleDateFormat(pattern); + } else { + DateFormatSymbols symbols = new DateFormatSymbols(locale); + formatter = new SimpleDateFormat(pattern, symbols); + } + formatter.setLenient(false); + return formatter; + } + + /** + *

Returns a DateFormat for the specified Locale.

+ * + * @param locale The locale a DateFormat is required for, + * system default if null. + * @return The DateFormat to created. + */ +/** + *

Returns a DateFormat for the specified Locale.

+ * + * @param locale + * The locale a DateFormat is required for, + * system default if null. + * @return The DateFormat to created. + */ +protected java.text.Format getFormat(java.util.Locale locale) { + java.text.DateFormat formatter = null; + if ((dateStyle >= 0) && (timeStyle >= 0)) { + { + formatter = java.text.DateFormat.getDateTimeInstance(dateStyle, timeStyle, /* NPEX_NULL_EXP */ + locale); + } + } else if (timeStyle >= 0) { + if (locale == null) { + formatter = java.text.DateFormat.getTimeInstance(timeStyle); + } else { + formatter = java.text.DateFormat.getTimeInstance(timeStyle, locale); + } + } else { + int useDateStyle = (dateStyle >= 0) ? dateStyle : java.text.DateFormat.SHORT; + if (locale == null) { + formatter = java.text.DateFormat.getDateInstance(useDateStyle); + } else { + formatter = java.text.DateFormat.getDateInstance(useDateStyle, locale); + } + } + formatter.setLenient(false); + return formatter; +} + + /** + *

Compares a calendar value to another, indicating whether it is + * equal, less then or more than at a specified level.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field level to compare to - e.g. specifying + * Calendar.MONTH will compare the year and month + * portions of the calendar. + * @return Zero if the first value is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compare(Calendar value, Calendar compare, int field) { + + int result = 0; + + // Compare Year + result = calculateCompareResult(value, compare, Calendar.YEAR); + if (result != 0 || field == Calendar.YEAR) { + return result; + } + + // Compare Week of Year + if (field == Calendar.WEEK_OF_YEAR) { + return calculateCompareResult(value, compare, Calendar.WEEK_OF_YEAR); + } + + // Compare Day of the Year + if (field == Calendar.DAY_OF_YEAR) { + return calculateCompareResult(value, compare, Calendar.DAY_OF_YEAR); + } + + // Compare Month + result = calculateCompareResult(value, compare, Calendar.MONTH); + if (result != 0 || field == Calendar.MONTH) { + return result; + } + + // Compare Week of Month + if (field == Calendar.WEEK_OF_MONTH) { + return calculateCompareResult(value, compare, Calendar.WEEK_OF_MONTH); + } + + // Compare Date + result = calculateCompareResult(value, compare, Calendar.DATE); + if (result != 0 || (field == Calendar.DATE || + field == Calendar.DAY_OF_WEEK || + field == Calendar.DAY_OF_WEEK_IN_MONTH)) { + return result; + } + + // Compare Time fields + return compareTime(value, compare, field); + + } + + /** + *

Compares a calendar time value to another, indicating whether it is + * equal, less then or more than at a specified level.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field level to compare to - e.g. specifying + * Calendar.MINUTE will compare the hours and minutes + * portions of the calendar. + * @return Zero if the first value is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compareTime(Calendar value, Calendar compare, int field) { + + int result = 0; + + // Compare Hour + result = calculateCompareResult(value, compare, Calendar.HOUR_OF_DAY); + if (result != 0 || (field == Calendar.HOUR || field == Calendar.HOUR_OF_DAY)) { + return result; + } + + // Compare Minute + result = calculateCompareResult(value, compare, Calendar.MINUTE); + if (result != 0 || field == Calendar.MINUTE) { + return result; + } + + // Compare Second + result = calculateCompareResult(value, compare, Calendar.SECOND); + if (result != 0 || field == Calendar.SECOND) { + return result; + } + + // Compare Milliseconds + if (field == Calendar.MILLISECOND) { + return calculateCompareResult(value, compare, Calendar.MILLISECOND); + } + + throw new IllegalArgumentException("Invalid field: " + field); + + } + + /** + *

Compares a calendar's quarter value to another, indicating whether it is + * equal, less then or more than the specified quarter.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param monthOfFirstQuarter The month that the first quarter starts. + * @return Zero if the first quarter is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compareQuarters(Calendar value, Calendar compare, int monthOfFirstQuarter) { + int valueQuarter = calculateQuarter(value, monthOfFirstQuarter); + int compareQuarter = calculateQuarter(compare, monthOfFirstQuarter); + if (valueQuarter < compareQuarter) { + return -1; + } else if (valueQuarter > compareQuarter) { + return 1; + } else { + return 0; + } + } + + /** + *

Calculate the quarter for the specified Calendar.

+ * + * @param calendar The Calendar value. + * @param monthOfFirstQuarter The month that the first quarter starts. + * @return The calculated quarter. + */ + private int calculateQuarter(Calendar calendar, int monthOfFirstQuarter) { + // Add Year + int year = calendar.get(Calendar.YEAR); + + int month = (calendar.get(Calendar.MONTH) + 1); + int relativeMonth = (month >= monthOfFirstQuarter) + ? (month - monthOfFirstQuarter) + : (month + (12 - monthOfFirstQuarter)); // CHECKSTYLE IGNORE MagicNumber + int quarter = ((relativeMonth / 3) + 1); // CHECKSTYLE IGNORE MagicNumber + // adjust the year if the quarter doesn't start in January + if (month < monthOfFirstQuarter) { + --year; + } + return (year * 10) + quarter; // CHECKSTYLE IGNORE MagicNumber + } + + /** + *

Compares the field from two calendars indicating whether the field for the + * first calendar is equal to, less than or greater than the field from the + * second calendar. + * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field to compare for the calendars. + * @return Zero if the first calendar's field is equal to the seconds, -1 + * if it is less than the seconds or +1 if it is greater than the seconds. + */ + private int calculateCompareResult(Calendar value, Calendar compare, int field) { + int difference = value.get(field) - compare.get(field); + if (difference < 0) { + return -1; + } else if (difference > 0) { + return 1; + } else { + return 0; + } + } +} diff --git a/Java/commons-validator-AbstractCalendarValidator_238/metadata.json b/Java/commons-validator-AbstractCalendarValidator_238/metadata.json new file mode 100644 index 000000000..2e61a39c3 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_238/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-AbstractCalendarValidator_238", + "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/validator/routines/AbstractCalendarValidator.java", + "line": 247, + "npe_method": "getFormat", + "deref_field": "locale", + "npe_class": "AbstractCalendarValidator", + "repo": "commons-validator", + "bug_id": "AbstractCalendarValidator_238" + } +} diff --git a/Java/commons-validator-AbstractCalendarValidator_238/npe.json b/Java/commons-validator-AbstractCalendarValidator_238/npe.json new file mode 100644 index 000000000..76f1be4b7 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_238/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/AbstractCalendarValidator.java", + "line": 247, + "npe_method": "getFormat", + "deref_field": "locale", + "npe_class": "AbstractCalendarValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-AbstractCalendarValidator_244/Dockerfile b/Java/commons-validator-AbstractCalendarValidator_244/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_244/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-AbstractCalendarValidator_244/buggy.java b/Java/commons-validator-AbstractCalendarValidator_244/buggy.java new file mode 100644 index 000000000..3ecb54e67 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_244/buggy.java @@ -0,0 +1,432 @@ +/* + * 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.validator.routines; + +import java.text.DateFormatSymbols; +import java.text.Format; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Locale; +import java.util.TimeZone; + +/** + *

Abstract class for Date/Time/Calendar validation.

+ * + *

This is a base class for building Date / Time + * Validators using format parsing.

+ * + * @version $Revision$ + * @since Validator 1.3.0 + */ +public abstract class AbstractCalendarValidator extends AbstractFormatValidator { + + private static final long serialVersionUID = -1410008585975827379L; + + private final int dateStyle; + + private final int timeStyle; + + /** + * Construct an instance with the specified strict, + * time and date style parameters. + * + * @param strict true if strict + * Format parsing should be used. + * @param dateStyle the date style to use for Locale validation. + * @param timeStyle the time style to use for Locale validation. + */ + public AbstractCalendarValidator(boolean strict, int dateStyle, int timeStyle) { + super(strict); + this.dateStyle = dateStyle; + this.timeStyle = timeStyle; + } + + /** + *

Validate using the specified Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format, defaults to the default + * @return true if the value is valid. + */ + @Override + public boolean isValid(String value, String pattern, Locale locale) { + Object parsedValue = parse(value, pattern, locale, (TimeZone)null); + return (parsedValue == null ? false : true); + } + + /** + *

Format an object into a String using + * the default Locale.

+ * + * @param value The value validation is being performed on. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, TimeZone timeZone) { + return format(value, (String)null, (Locale)null, timeZone); + } + + /** + *

Format an object into a String using + * the specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, String pattern, TimeZone timeZone) { + return format(value, pattern, (Locale)null, timeZone); + } + + /** + *

Format an object into a String using + * the specified Locale.

+ * + * @param value The value validation is being performed on. + * @param locale The locale to use for the Format. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, Locale locale, TimeZone timeZone) { + return format(value, (String)null, locale, timeZone); + } + + /** + *

Format an object using the specified pattern and/or + * Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format. + * @return The value formatted as a String. + */ + @Override + public String format(Object value, String pattern, Locale locale) { + return format(value, pattern, locale, (TimeZone)null); + } + + /** + *

Format an object using the specified pattern and/or + * Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, String pattern, Locale locale, TimeZone timeZone) { + DateFormat formatter = (DateFormat)getFormat(pattern, locale); + if (timeZone != null) { + formatter.setTimeZone(timeZone); + } else if (value instanceof Calendar) { + formatter.setTimeZone(((Calendar)value).getTimeZone()); + } + return format(value, formatter); + } + + /** + *

Format a value with the specified DateFormat.

+ * + * @param value The value to be formatted. + * @param formatter The Format to use. + * @return The formatted value. + */ + @Override + protected String format(Object value, Format formatter) { + if (value == null) { + return null; + } else if (value instanceof Calendar) { + value = ((Calendar)value).getTime(); + } + return formatter.format(value); + } + + /** + *

Checks if the value is valid against a specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to validate the value against, or the + * default for the Locale if null. + * @param locale The locale to use for the date format, system default if null. + * @param timeZone The Time Zone used to parse the date, system default if null. + * @return The parsed value if valid or null if invalid. + */ + protected Object parse(String value, String pattern, Locale locale, TimeZone timeZone) { + + value = (value == null ? null : value.trim()); + if (value == null || value.length() == 0) { + return null; + } + DateFormat formatter = (DateFormat)getFormat(pattern, locale); + if (timeZone != null) { + formatter.setTimeZone(timeZone); + } + return parse(value, formatter); + + } + + /** + *

Process the parsed value, performing any further validation + * and type conversion required.

+ * + * @param value The parsed object created. + * @param formatter The Format used to parse the value with. + * @return The parsed value converted to the appropriate type + * if valid or null if invalid. + */ + @Override + protected abstract Object processParsedValue(Object value, Format formatter); + + /** + *

Returns a DateFormat for the specified pattern + * and/or Locale.

+ * + * @param pattern The pattern used to validate the value against or + * null to use the default for the Locale. + * @param locale The locale to use for the currency format, system default if null. + * @return The DateFormat to created. + */ + @Override + protected Format getFormat(String pattern, Locale locale) { + DateFormat formatter = null; + boolean usePattern = (pattern != null && pattern.length() > 0); + if (!usePattern) { + formatter = (DateFormat)getFormat(locale); + } else if (locale == null) { + formatter = new SimpleDateFormat(pattern); + } else { + DateFormatSymbols symbols = new DateFormatSymbols(locale); + formatter = new SimpleDateFormat(pattern, symbols); + } + formatter.setLenient(false); + return formatter; + } + + /** + *

Returns a DateFormat for the specified Locale.

+ * + * @param locale The locale a DateFormat is required for, + * system default if null. + * @return The DateFormat to created. + */ +/** + *

Returns a DateFormat for the specified Locale.

+ * + * @param locale + * The locale a DateFormat is required for, + * system default if null. + * @return The DateFormat to created. + */ +protected java.text.Format getFormat(java.util.Locale locale) { + java.text.DateFormat formatter = null; + if ((dateStyle >= 0) && (timeStyle >= 0)) { + if (locale == null) { + formatter = java.text.DateFormat.getDateTimeInstance(dateStyle, timeStyle); + } else { + formatter = java.text.DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale); + } + } else if (timeStyle >= 0) { + { + formatter = java.text.DateFormat.getTimeInstance(timeStyle, /* NPEX_NULL_EXP */ + locale); + } + } else { + int useDateStyle = (dateStyle >= 0) ? dateStyle : java.text.DateFormat.SHORT; + if (locale == null) { + formatter = java.text.DateFormat.getDateInstance(useDateStyle); + } else { + formatter = java.text.DateFormat.getDateInstance(useDateStyle, locale); + } + } + formatter.setLenient(false); + return formatter; +} + + /** + *

Compares a calendar value to another, indicating whether it is + * equal, less then or more than at a specified level.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field level to compare to - e.g. specifying + * Calendar.MONTH will compare the year and month + * portions of the calendar. + * @return Zero if the first value is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compare(Calendar value, Calendar compare, int field) { + + int result = 0; + + // Compare Year + result = calculateCompareResult(value, compare, Calendar.YEAR); + if (result != 0 || field == Calendar.YEAR) { + return result; + } + + // Compare Week of Year + if (field == Calendar.WEEK_OF_YEAR) { + return calculateCompareResult(value, compare, Calendar.WEEK_OF_YEAR); + } + + // Compare Day of the Year + if (field == Calendar.DAY_OF_YEAR) { + return calculateCompareResult(value, compare, Calendar.DAY_OF_YEAR); + } + + // Compare Month + result = calculateCompareResult(value, compare, Calendar.MONTH); + if (result != 0 || field == Calendar.MONTH) { + return result; + } + + // Compare Week of Month + if (field == Calendar.WEEK_OF_MONTH) { + return calculateCompareResult(value, compare, Calendar.WEEK_OF_MONTH); + } + + // Compare Date + result = calculateCompareResult(value, compare, Calendar.DATE); + if (result != 0 || (field == Calendar.DATE || + field == Calendar.DAY_OF_WEEK || + field == Calendar.DAY_OF_WEEK_IN_MONTH)) { + return result; + } + + // Compare Time fields + return compareTime(value, compare, field); + + } + + /** + *

Compares a calendar time value to another, indicating whether it is + * equal, less then or more than at a specified level.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field level to compare to - e.g. specifying + * Calendar.MINUTE will compare the hours and minutes + * portions of the calendar. + * @return Zero if the first value is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compareTime(Calendar value, Calendar compare, int field) { + + int result = 0; + + // Compare Hour + result = calculateCompareResult(value, compare, Calendar.HOUR_OF_DAY); + if (result != 0 || (field == Calendar.HOUR || field == Calendar.HOUR_OF_DAY)) { + return result; + } + + // Compare Minute + result = calculateCompareResult(value, compare, Calendar.MINUTE); + if (result != 0 || field == Calendar.MINUTE) { + return result; + } + + // Compare Second + result = calculateCompareResult(value, compare, Calendar.SECOND); + if (result != 0 || field == Calendar.SECOND) { + return result; + } + + // Compare Milliseconds + if (field == Calendar.MILLISECOND) { + return calculateCompareResult(value, compare, Calendar.MILLISECOND); + } + + throw new IllegalArgumentException("Invalid field: " + field); + + } + + /** + *

Compares a calendar's quarter value to another, indicating whether it is + * equal, less then or more than the specified quarter.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param monthOfFirstQuarter The month that the first quarter starts. + * @return Zero if the first quarter is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compareQuarters(Calendar value, Calendar compare, int monthOfFirstQuarter) { + int valueQuarter = calculateQuarter(value, monthOfFirstQuarter); + int compareQuarter = calculateQuarter(compare, monthOfFirstQuarter); + if (valueQuarter < compareQuarter) { + return -1; + } else if (valueQuarter > compareQuarter) { + return 1; + } else { + return 0; + } + } + + /** + *

Calculate the quarter for the specified Calendar.

+ * + * @param calendar The Calendar value. + * @param monthOfFirstQuarter The month that the first quarter starts. + * @return The calculated quarter. + */ + private int calculateQuarter(Calendar calendar, int monthOfFirstQuarter) { + // Add Year + int year = calendar.get(Calendar.YEAR); + + int month = (calendar.get(Calendar.MONTH) + 1); + int relativeMonth = (month >= monthOfFirstQuarter) + ? (month - monthOfFirstQuarter) + : (month + (12 - monthOfFirstQuarter)); // CHECKSTYLE IGNORE MagicNumber + int quarter = ((relativeMonth / 3) + 1); // CHECKSTYLE IGNORE MagicNumber + // adjust the year if the quarter doesn't start in January + if (month < monthOfFirstQuarter) { + --year; + } + return (year * 10) + quarter; // CHECKSTYLE IGNORE MagicNumber + } + + /** + *

Compares the field from two calendars indicating whether the field for the + * first calendar is equal to, less than or greater than the field from the + * second calendar. + * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field to compare for the calendars. + * @return Zero if the first calendar's field is equal to the seconds, -1 + * if it is less than the seconds or +1 if it is greater than the seconds. + */ + private int calculateCompareResult(Calendar value, Calendar compare, int field) { + int difference = value.get(field) - compare.get(field); + if (difference < 0) { + return -1; + } else if (difference > 0) { + return 1; + } else { + return 0; + } + } +} diff --git a/Java/commons-validator-AbstractCalendarValidator_244/metadata.json b/Java/commons-validator-AbstractCalendarValidator_244/metadata.json new file mode 100644 index 000000000..83e301a52 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_244/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-AbstractCalendarValidator_244", + "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/validator/routines/AbstractCalendarValidator.java", + "line": 253, + "npe_method": "getFormat", + "deref_field": "locale", + "npe_class": "AbstractCalendarValidator", + "repo": "commons-validator", + "bug_id": "AbstractCalendarValidator_244" + } +} diff --git a/Java/commons-validator-AbstractCalendarValidator_244/npe.json b/Java/commons-validator-AbstractCalendarValidator_244/npe.json new file mode 100644 index 000000000..08e42425a --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_244/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/AbstractCalendarValidator.java", + "line": 253, + "npe_method": "getFormat", + "deref_field": "locale", + "npe_class": "AbstractCalendarValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-AbstractCalendarValidator_251/Dockerfile b/Java/commons-validator-AbstractCalendarValidator_251/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_251/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-AbstractCalendarValidator_251/buggy.java b/Java/commons-validator-AbstractCalendarValidator_251/buggy.java new file mode 100644 index 000000000..84fccc691 --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_251/buggy.java @@ -0,0 +1,432 @@ +/* + * 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.validator.routines; + +import java.text.DateFormatSymbols; +import java.text.Format; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Locale; +import java.util.TimeZone; + +/** + *

Abstract class for Date/Time/Calendar validation.

+ * + *

This is a base class for building Date / Time + * Validators using format parsing.

+ * + * @version $Revision$ + * @since Validator 1.3.0 + */ +public abstract class AbstractCalendarValidator extends AbstractFormatValidator { + + private static final long serialVersionUID = -1410008585975827379L; + + private final int dateStyle; + + private final int timeStyle; + + /** + * Construct an instance with the specified strict, + * time and date style parameters. + * + * @param strict true if strict + * Format parsing should be used. + * @param dateStyle the date style to use for Locale validation. + * @param timeStyle the time style to use for Locale validation. + */ + public AbstractCalendarValidator(boolean strict, int dateStyle, int timeStyle) { + super(strict); + this.dateStyle = dateStyle; + this.timeStyle = timeStyle; + } + + /** + *

Validate using the specified Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format, defaults to the default + * @return true if the value is valid. + */ + @Override + public boolean isValid(String value, String pattern, Locale locale) { + Object parsedValue = parse(value, pattern, locale, (TimeZone)null); + return (parsedValue == null ? false : true); + } + + /** + *

Format an object into a String using + * the default Locale.

+ * + * @param value The value validation is being performed on. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, TimeZone timeZone) { + return format(value, (String)null, (Locale)null, timeZone); + } + + /** + *

Format an object into a String using + * the specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, String pattern, TimeZone timeZone) { + return format(value, pattern, (Locale)null, timeZone); + } + + /** + *

Format an object into a String using + * the specified Locale.

+ * + * @param value The value validation is being performed on. + * @param locale The locale to use for the Format. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, Locale locale, TimeZone timeZone) { + return format(value, (String)null, locale, timeZone); + } + + /** + *

Format an object using the specified pattern and/or + * Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format. + * @return The value formatted as a String. + */ + @Override + public String format(Object value, String pattern, Locale locale) { + return format(value, pattern, locale, (TimeZone)null); + } + + /** + *

Format an object using the specified pattern and/or + * Locale. + * + * @param value The value validation is being performed on. + * @param pattern The pattern used to format the value. + * @param locale The locale to use for the Format. + * @param timeZone The Time Zone used to format the date, + * system default if null (unless value is a Calendar. + * @return The value formatted as a String. + */ + public String format(Object value, String pattern, Locale locale, TimeZone timeZone) { + DateFormat formatter = (DateFormat)getFormat(pattern, locale); + if (timeZone != null) { + formatter.setTimeZone(timeZone); + } else if (value instanceof Calendar) { + formatter.setTimeZone(((Calendar)value).getTimeZone()); + } + return format(value, formatter); + } + + /** + *

Format a value with the specified DateFormat.

+ * + * @param value The value to be formatted. + * @param formatter The Format to use. + * @return The formatted value. + */ + @Override + protected String format(Object value, Format formatter) { + if (value == null) { + return null; + } else if (value instanceof Calendar) { + value = ((Calendar)value).getTime(); + } + return formatter.format(value); + } + + /** + *

Checks if the value is valid against a specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to validate the value against, or the + * default for the Locale if null. + * @param locale The locale to use for the date format, system default if null. + * @param timeZone The Time Zone used to parse the date, system default if null. + * @return The parsed value if valid or null if invalid. + */ + protected Object parse(String value, String pattern, Locale locale, TimeZone timeZone) { + + value = (value == null ? null : value.trim()); + if (value == null || value.length() == 0) { + return null; + } + DateFormat formatter = (DateFormat)getFormat(pattern, locale); + if (timeZone != null) { + formatter.setTimeZone(timeZone); + } + return parse(value, formatter); + + } + + /** + *

Process the parsed value, performing any further validation + * and type conversion required.

+ * + * @param value The parsed object created. + * @param formatter The Format used to parse the value with. + * @return The parsed value converted to the appropriate type + * if valid or null if invalid. + */ + @Override + protected abstract Object processParsedValue(Object value, Format formatter); + + /** + *

Returns a DateFormat for the specified pattern + * and/or Locale.

+ * + * @param pattern The pattern used to validate the value against or + * null to use the default for the Locale. + * @param locale The locale to use for the currency format, system default if null. + * @return The DateFormat to created. + */ + @Override + protected Format getFormat(String pattern, Locale locale) { + DateFormat formatter = null; + boolean usePattern = (pattern != null && pattern.length() > 0); + if (!usePattern) { + formatter = (DateFormat)getFormat(locale); + } else if (locale == null) { + formatter = new SimpleDateFormat(pattern); + } else { + DateFormatSymbols symbols = new DateFormatSymbols(locale); + formatter = new SimpleDateFormat(pattern, symbols); + } + formatter.setLenient(false); + return formatter; + } + + /** + *

Returns a DateFormat for the specified Locale.

+ * + * @param locale The locale a DateFormat is required for, + * system default if null. + * @return The DateFormat to created. + */ +/** + *

Returns a DateFormat for the specified Locale.

+ * + * @param locale + * The locale a DateFormat is required for, + * system default if null. + * @return The DateFormat to created. + */ +protected java.text.Format getFormat(java.util.Locale locale) { + java.text.DateFormat formatter = null; + if ((dateStyle >= 0) && (timeStyle >= 0)) { + if (locale == null) { + formatter = java.text.DateFormat.getDateTimeInstance(dateStyle, timeStyle); + } else { + formatter = java.text.DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale); + } + } else if (timeStyle >= 0) { + if (locale == null) { + formatter = java.text.DateFormat.getTimeInstance(timeStyle); + } else { + formatter = java.text.DateFormat.getTimeInstance(timeStyle, locale); + } + } else { + int useDateStyle = (dateStyle >= 0) ? dateStyle : java.text.DateFormat.SHORT; + { + formatter = java.text.DateFormat.getDateInstance(useDateStyle, /* NPEX_NULL_EXP */ + locale); + } + } + formatter.setLenient(false); + return formatter; +} + + /** + *

Compares a calendar value to another, indicating whether it is + * equal, less then or more than at a specified level.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field level to compare to - e.g. specifying + * Calendar.MONTH will compare the year and month + * portions of the calendar. + * @return Zero if the first value is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compare(Calendar value, Calendar compare, int field) { + + int result = 0; + + // Compare Year + result = calculateCompareResult(value, compare, Calendar.YEAR); + if (result != 0 || field == Calendar.YEAR) { + return result; + } + + // Compare Week of Year + if (field == Calendar.WEEK_OF_YEAR) { + return calculateCompareResult(value, compare, Calendar.WEEK_OF_YEAR); + } + + // Compare Day of the Year + if (field == Calendar.DAY_OF_YEAR) { + return calculateCompareResult(value, compare, Calendar.DAY_OF_YEAR); + } + + // Compare Month + result = calculateCompareResult(value, compare, Calendar.MONTH); + if (result != 0 || field == Calendar.MONTH) { + return result; + } + + // Compare Week of Month + if (field == Calendar.WEEK_OF_MONTH) { + return calculateCompareResult(value, compare, Calendar.WEEK_OF_MONTH); + } + + // Compare Date + result = calculateCompareResult(value, compare, Calendar.DATE); + if (result != 0 || (field == Calendar.DATE || + field == Calendar.DAY_OF_WEEK || + field == Calendar.DAY_OF_WEEK_IN_MONTH)) { + return result; + } + + // Compare Time fields + return compareTime(value, compare, field); + + } + + /** + *

Compares a calendar time value to another, indicating whether it is + * equal, less then or more than at a specified level.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field level to compare to - e.g. specifying + * Calendar.MINUTE will compare the hours and minutes + * portions of the calendar. + * @return Zero if the first value is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compareTime(Calendar value, Calendar compare, int field) { + + int result = 0; + + // Compare Hour + result = calculateCompareResult(value, compare, Calendar.HOUR_OF_DAY); + if (result != 0 || (field == Calendar.HOUR || field == Calendar.HOUR_OF_DAY)) { + return result; + } + + // Compare Minute + result = calculateCompareResult(value, compare, Calendar.MINUTE); + if (result != 0 || field == Calendar.MINUTE) { + return result; + } + + // Compare Second + result = calculateCompareResult(value, compare, Calendar.SECOND); + if (result != 0 || field == Calendar.SECOND) { + return result; + } + + // Compare Milliseconds + if (field == Calendar.MILLISECOND) { + return calculateCompareResult(value, compare, Calendar.MILLISECOND); + } + + throw new IllegalArgumentException("Invalid field: " + field); + + } + + /** + *

Compares a calendar's quarter value to another, indicating whether it is + * equal, less then or more than the specified quarter.

+ * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param monthOfFirstQuarter The month that the first quarter starts. + * @return Zero if the first quarter is equal to the second, -1 + * if it is less than the second or +1 if it is greater than the second. + */ + protected int compareQuarters(Calendar value, Calendar compare, int monthOfFirstQuarter) { + int valueQuarter = calculateQuarter(value, monthOfFirstQuarter); + int compareQuarter = calculateQuarter(compare, monthOfFirstQuarter); + if (valueQuarter < compareQuarter) { + return -1; + } else if (valueQuarter > compareQuarter) { + return 1; + } else { + return 0; + } + } + + /** + *

Calculate the quarter for the specified Calendar.

+ * + * @param calendar The Calendar value. + * @param monthOfFirstQuarter The month that the first quarter starts. + * @return The calculated quarter. + */ + private int calculateQuarter(Calendar calendar, int monthOfFirstQuarter) { + // Add Year + int year = calendar.get(Calendar.YEAR); + + int month = (calendar.get(Calendar.MONTH) + 1); + int relativeMonth = (month >= monthOfFirstQuarter) + ? (month - monthOfFirstQuarter) + : (month + (12 - monthOfFirstQuarter)); // CHECKSTYLE IGNORE MagicNumber + int quarter = ((relativeMonth / 3) + 1); // CHECKSTYLE IGNORE MagicNumber + // adjust the year if the quarter doesn't start in January + if (month < monthOfFirstQuarter) { + --year; + } + return (year * 10) + quarter; // CHECKSTYLE IGNORE MagicNumber + } + + /** + *

Compares the field from two calendars indicating whether the field for the + * first calendar is equal to, less than or greater than the field from the + * second calendar. + * + * @param value The Calendar value. + * @param compare The Calendar to check the value against. + * @param field The field to compare for the calendars. + * @return Zero if the first calendar's field is equal to the seconds, -1 + * if it is less than the seconds or +1 if it is greater than the seconds. + */ + private int calculateCompareResult(Calendar value, Calendar compare, int field) { + int difference = value.get(field) - compare.get(field); + if (difference < 0) { + return -1; + } else if (difference > 0) { + return 1; + } else { + return 0; + } + } +} diff --git a/Java/commons-validator-AbstractCalendarValidator_251/metadata.json b/Java/commons-validator-AbstractCalendarValidator_251/metadata.json new file mode 100644 index 000000000..dea8234bd --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_251/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-AbstractCalendarValidator_251", + "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/validator/routines/AbstractCalendarValidator.java", + "line": 260, + "npe_method": "getFormat", + "deref_field": "locale", + "npe_class": "AbstractCalendarValidator", + "repo": "commons-validator", + "bug_id": "AbstractCalendarValidator_251" + } +} diff --git a/Java/commons-validator-AbstractCalendarValidator_251/npe.json b/Java/commons-validator-AbstractCalendarValidator_251/npe.json new file mode 100644 index 000000000..9736fe2ad --- /dev/null +++ b/Java/commons-validator-AbstractCalendarValidator_251/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/AbstractCalendarValidator.java", + "line": 260, + "npe_method": "getFormat", + "deref_field": "locale", + "npe_class": "AbstractCalendarValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-AbstractNumberValidatorTest_101/Dockerfile b/Java/commons-validator-AbstractNumberValidatorTest_101/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-AbstractNumberValidatorTest_101/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-AbstractNumberValidatorTest_101/buggy.java b/Java/commons-validator-AbstractNumberValidatorTest_101/buggy.java new file mode 100644 index 000000000..b0195ca75 --- /dev/null +++ b/Java/commons-validator-AbstractNumberValidatorTest_101/buggy.java @@ -0,0 +1,250 @@ +/* + * 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.validator.routines; + +import junit.framework.TestCase; + +import java.util.Locale; +import java.text.DecimalFormat; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.math.BigDecimal; +/** + * Base Number Test Case. + * + * @version $Revision$ + */ +public abstract class AbstractNumberValidatorTest extends TestCase { + + protected AbstractNumberValidator validator; + protected AbstractNumberValidator strictValidator; + + protected Number max; + protected Number maxPlusOne; + protected Number min; + protected Number minMinusOne; + protected String[] invalid; + protected String[] valid; + protected Number[] validCompare; + + protected String[] invalidStrict; + protected String[] validStrict; + protected Number[] validStrictCompare; + + protected String testPattern; + protected Number testNumber; + protected Number testZero; + protected String testStringUS; + protected String testStringDE; + + protected String localeValue; + protected String localePattern; + protected Locale testLocale; + protected Number localeExpected; + + /** + * Constructor + * @param name test name + */ + public AbstractNumberValidatorTest(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + Locale.setDefault(Locale.US); + + } + + /** + * Tear down + * @throws Exception + */ + @Override + protected void tearDown() throws Exception { + super.tearDown(); + validator = null; + strictValidator = null; + } + + /** + * Test Format Type + */ + public void testFormatType() { + assertEquals("Format Type A", 0, validator.getFormatType()); + assertEquals("Format Type B", AbstractNumberValidator.STANDARD_FORMAT, validator.getFormatType()); + } + + /** + * Test Min/Max values allowed + */ +/** + * Test Min/Max values allowed + */ +public void testValidateMinMax() { + java.text.DecimalFormat fmt = new java.text.DecimalFormat("#"); + { + junit.framework.TestCase.assertEquals("Test Max", /* NPEX_NULL_EXP */ + max, validator.parse(fmt.format(max), "#", null)); + junit.framework.TestCase.assertNull("Test Max + 1", validator.parse(fmt.format(maxPlusOne), "#", null)); + junit.framework.TestCase.assertEquals("Test Min", min, validator.parse(fmt.format(min), "#", null)); + junit.framework.TestCase.assertNull("Test min - 1", validator.parse(fmt.format(minMinusOne), "#", null)); + } +} + + /** + * Test Invalid, strict=true + */ + public void testInvalidStrict() { + for (int i = 0; i < invalidStrict.length; i++) { + String text = "idx=["+i+"] value=[" + invalidStrict[i] + "]"; + assertNull("(A) " + text, strictValidator.parse(invalidStrict[i], null, Locale.US)); + assertFalse("(B) " + text, strictValidator.isValid(invalidStrict[i], null, Locale.US)); + assertNull("(C) " + text, strictValidator.parse(invalidStrict[i], testPattern, null)); + assertFalse("(D) " + text, strictValidator.isValid(invalidStrict[i], testPattern, null)); + } + } + + /** + * Test Invalid, strict=false + */ + public void testInvalidNotStrict() { + for (int i = 0; i < invalid.length; i++) { + String text = "idx=["+i+"] value=[" + invalid[i] + "]"; + assertNull("(A) " + text, validator.parse(invalid[i], null, Locale.US)); + assertFalse("(B) " + text, validator.isValid(invalid[i], null, Locale.US)); + assertNull("(C) " + text, validator.parse(invalid[i], testPattern, null)); + assertFalse("(D) " + text, validator.isValid(invalid[i], testPattern, null)); + } + } + + /** + * Test Valid, strict=true + */ + public void testValidStrict() { + for (int i = 0; i < validStrict.length; i++) { + String text = "idx=["+i+"] value=[" + validStrictCompare[i] + "]"; + assertEquals("(A) " + text, validStrictCompare[i], strictValidator.parse(validStrict[i], null, Locale.US)); + assertTrue("(B) " + text, strictValidator.isValid(validStrict[i], null, Locale.US)); + assertEquals("(C) " + text, validStrictCompare[i], strictValidator.parse(validStrict[i], testPattern, null)); + assertTrue("(D) " + text, strictValidator.isValid(validStrict[i], testPattern, null)); + } + } + + /** + * Test Valid, strict=false + */ + public void testValidNotStrict() { + for (int i = 0; i < valid.length; i++) { + String text = "idx=["+i+"] value=[" + validCompare[i] + "]"; + assertEquals("(A) " + text, validCompare[i], validator.parse(valid[i], null, Locale.US)); + assertTrue("(B) " + text, validator.isValid(valid[i], null, Locale.US)); + assertEquals("(C) " + text, validCompare[i], validator.parse(valid[i], testPattern, null)); + assertTrue("(D) " + text, validator.isValid(valid[i], testPattern, null)); + } + } + + /** + * Test different Locale + */ + public void testValidateLocale() { + + assertEquals("US Locale, US Format", testNumber, strictValidator.parse(testStringUS, null, Locale.US)); + assertNull("US Locale, DE Format", strictValidator.parse(testStringDE, null, Locale.US)); + + // Default German Locale + assertEquals("DE Locale, DE Format", testNumber, strictValidator.parse(testStringDE, null, Locale.GERMAN)); + assertNull("DE Locale, US Format", strictValidator.parse(testStringUS, null, Locale.GERMAN)); + + // Default Locale has been set to Locale.US in setup() + assertEquals("Default Locale, US Format", testNumber, strictValidator.parse(testStringUS, null, null)); + assertNull("Default Locale, DE Format", strictValidator.parse(testStringDE, null, null)); + } + + /** + * Test format() methods + */ + public void testFormat() { + Number number = new BigDecimal("1234.5"); + assertEquals("US Locale, US Format", "1,234.5", strictValidator.format(number, Locale.US)); + assertEquals("DE Locale, DE Format", "1.234,5", strictValidator.format(number, Locale.GERMAN)); + assertEquals("Pattern #,#0.00", "12,34.50", strictValidator.format(number, "#,#0.00")); + } + + /** + * Test Range/Min/Max + */ + public void testRangeMinMax() { + Number number9 = Integer.valueOf(9); + Number number10 = Integer.valueOf(10); + Number number11 = Integer.valueOf(11); + Number number19 = Integer.valueOf(19); + Number number20 = Integer.valueOf(20); + Number number21 = Integer.valueOf(21); + + // Test isInRange() + assertFalse("isInRange() < min", strictValidator.isInRange(number9 , number10, number20)); + assertTrue("isInRange() = min", strictValidator.isInRange(number10 , number10, number20)); + assertTrue("isInRange() in range", strictValidator.isInRange(number11 , number10, number20)); + assertTrue("isInRange() = max", strictValidator.isInRange(number20 , number10, number20)); + assertFalse("isInRange() > max", strictValidator.isInRange(number21 , number10, number20)); + + // Test minValue() + assertFalse("minValue() < min", strictValidator.minValue(number9 , number10)); + assertTrue("minValue() = min", strictValidator.minValue(number10 , number10)); + assertTrue("minValue() > min", strictValidator.minValue(number11 , number10)); + + // Test minValue() + assertTrue("maxValue() < max", strictValidator.maxValue(number19 , number20)); + assertTrue("maxValue() = max", strictValidator.maxValue(number20 , number20)); + assertFalse("maxValue() > max", strictValidator.maxValue(number21 , number20)); + } + + /** + * Test validator serialization. + */ + public void testSerialization() { + // Serialize the check digit routine + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(validator); + oos.flush(); + oos.close(); + } catch (Exception e) { + fail(validator.getClass().getName() + " error during serialization: " + e); + } + + // Deserialize the test object + Object result = null; + try { + ByteArrayInputStream bais = + new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bais); + result = ois.readObject(); + bais.close(); + } catch (Exception e) { + fail(validator.getClass().getName() + " error during deserialization: " + e); + } + assertNotNull(result); + } + +} diff --git a/Java/commons-validator-AbstractNumberValidatorTest_101/metadata.json b/Java/commons-validator-AbstractNumberValidatorTest_101/metadata.json new file mode 100644 index 000000000..688a5859b --- /dev/null +++ b/Java/commons-validator-AbstractNumberValidatorTest_101/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-AbstractNumberValidatorTest_101", + "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/test/java/org/apache/commons/validator/routines/AbstractNumberValidatorTest.java", + "line": 106, + "npe_method": "testValidateMinMax", + "deref_field": "max", + "npe_class": "AbstractNumberValidatorTest", + "repo": "commons-validator", + "bug_id": "AbstractNumberValidatorTest_101" + } +} diff --git a/Java/commons-validator-AbstractNumberValidatorTest_101/npe.json b/Java/commons-validator-AbstractNumberValidatorTest_101/npe.json new file mode 100644 index 000000000..cfd935df4 --- /dev/null +++ b/Java/commons-validator-AbstractNumberValidatorTest_101/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/test/java/org/apache/commons/validator/routines/AbstractNumberValidatorTest.java", + "line": 106, + "npe_method": "testValidateMinMax", + "deref_field": "max", + "npe_class": "AbstractNumberValidatorTest" +} \ No newline at end of file diff --git a/Java/commons-validator-AbstractNumberValidator_157/Dockerfile b/Java/commons-validator-AbstractNumberValidator_157/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-AbstractNumberValidator_157/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-AbstractNumberValidator_157/buggy.java b/Java/commons-validator-AbstractNumberValidator_157/buggy.java new file mode 100644 index 000000000..047bb82fd --- /dev/null +++ b/Java/commons-validator-AbstractNumberValidator_157/buggy.java @@ -0,0 +1,288 @@ +/* + * 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.validator.routines; + +import java.text.DecimalFormatSymbols; +import java.text.Format; +import java.text.NumberFormat; +import java.text.DecimalFormat; +import java.util.Locale; + +/** + *

Abstract class for Number Validation.

+ * + *

This is a base class for building Number + * Validators using format parsing.

+ * + * @version $Revision$ + * @since Validator 1.3.0 + */ +public abstract class AbstractNumberValidator extends AbstractFormatValidator { + + private static final long serialVersionUID = -3088817875906765463L; + + /** Standard NumberFormat type */ + public static final int STANDARD_FORMAT = 0; + + /** Currency NumberFormat type */ + public static final int CURRENCY_FORMAT = 1; + + /** Percent NumberFormat type */ + public static final int PERCENT_FORMAT = 2; + + private final boolean allowFractions; + private final int formatType; + + /** + * Construct an instance with specified strict + * and decimal parameters. + * + * @param strict true if strict + * Format parsing should be used. + * @param formatType The NumberFormat type to + * create for validation, default is STANDARD_FORMAT. + * @param allowFractions true if fractions are + * allowed or false if integers only. + */ + public AbstractNumberValidator(boolean strict, int formatType, boolean allowFractions) { + super(strict); + this.allowFractions = allowFractions; + this.formatType = formatType; + } + + /** + *

Indicates whether the number being validated is + * a decimal or integer.

+ * + * @return true if decimals are allowed + * or false if the number is an integer. + */ + public boolean isAllowFractions() { + return allowFractions; + } + + /** + *

Indicates the type of NumberFormat created + * by this validator instance.

+ * + * @return the format type created. + */ + public int getFormatType() { + return formatType; + } + + /** + *

Validate using the specified Locale.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to validate the value against, or the + * default for the Locale if null. + * @param locale The locale to use for the date format, system default if null. + * @return true if the value is valid. + */ + @Override + public boolean isValid(String value, String pattern, Locale locale) { + Object parsedValue = parse(value, pattern, locale); + return (parsedValue == null ? false : true); + } + + /** + * Check if the value is within a specified range. + * + * @param value The value validation is being performed on. + * @param min The minimum value of the range. + * @param max The maximum value of the range. + * @return true if the value is within the + * specified range. + */ + public boolean isInRange(Number value, Number min, Number max) { + return (minValue(value, min) && maxValue(value, max)); + } + + /** + * Check if the value is greater than or equal to a minimum. + * + * @param value The value validation is being performed on. + * @param min The minimum value. + * @return true if the value is greater than + * or equal to the minimum. + */ + public boolean minValue(Number value, Number min) { + if (isAllowFractions()) { + return (value.doubleValue() >= min.doubleValue()); + } + return (value.longValue() >= min.longValue()); + } + + /** + * Check if the value is less than or equal to a maximum. + * + * @param value The value validation is being performed on. + * @param max The maximum value. + * @return true if the value is less than + * or equal to the maximum. + */ + public boolean maxValue(Number value, Number max) { + if (isAllowFractions()) { + return (value.doubleValue() <= max.doubleValue()); + } + return (value.longValue() <= max.longValue()); + } + + /** + *

Parse the value using the specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to validate the value against, or the + * default for the Locale if null. + * @param locale The locale to use for the date format, system default if null. + * @return The parsed value if valid or null if invalid. + */ +/** + *

Parse the value using the specified pattern.

+ * + * @param value + * The value validation is being performed on. + * @param pattern + * The pattern used to validate the value against, or the + * default for the Locale if null. + * @param locale + * The locale to use for the date format, system default if null. + * @return The parsed value if valid or null if invalid. + */ +protected java.lang.Object parse(java.lang.String value, java.lang.String pattern, java.util.Locale locale) { + value = /* NPEX_NULL_EXP */ + value.trim(); + if ((value == null) || (value.length() == 0)) { + return null; + } + java.text.Format formatter = getFormat(pattern, locale); + return parse(value, formatter); +} + + /** + *

Process the parsed value, performing any further validation + * and type conversion required.

+ * + * @param value The parsed object created. + * @param formatter The Format used to parse the value with. + * @return The parsed value converted to the appropriate type + * if valid or null if invalid. + */ + @Override + protected abstract Object processParsedValue(Object value, Format formatter); + + /** + *

Returns a NumberFormat for the specified pattern + * and/or Locale.

+ * + * @param pattern The pattern used to validate the value against or + * null to use the default for the Locale. + * @param locale The locale to use for the currency format, system default if null. + * @return The NumberFormat to created. + */ + @Override + protected Format getFormat(String pattern, Locale locale) { + + NumberFormat formatter = null; + boolean usePattern = (pattern != null && pattern.length() > 0); + if (!usePattern) { + formatter = (NumberFormat)getFormat(locale); + } else if (locale == null) { + formatter = new DecimalFormat(pattern); + } else { + DecimalFormatSymbols symbols = new DecimalFormatSymbols(locale); + formatter = new DecimalFormat(pattern, symbols); + } + + if (!isAllowFractions()) { + formatter.setParseIntegerOnly(true); + } + return formatter; + } + + /** + *

Returns the multiplier of the NumberFormat.

+ * + * @param format The NumberFormat to determine the + * multiplier of. + * @return The multiplying factor for the format.. + */ + protected int determineScale(NumberFormat format) { + if (!isStrict()) { + return -1; + } + if (!isAllowFractions() || format.isParseIntegerOnly()) { + return 0; + } + int minimumFraction = format.getMinimumFractionDigits(); + int maximumFraction = format.getMaximumFractionDigits(); + if (minimumFraction != maximumFraction) { + return -1; + } + int scale = minimumFraction; + if (format instanceof DecimalFormat) { + int multiplier = ((DecimalFormat)format).getMultiplier(); + if (multiplier == 100) { // CHECKSTYLE IGNORE MagicNumber + scale += 2; // CHECKSTYLE IGNORE MagicNumber + } else if (multiplier == 1000) { // CHECKSTYLE IGNORE MagicNumber + scale += 3; // CHECKSTYLE IGNORE MagicNumber + } + } else if (formatType == PERCENT_FORMAT) { + scale += 2; // CHECKSTYLE IGNORE MagicNumber + } + return scale; + } + + /** + *

Returns a NumberFormat for the specified Locale.

+ * + * @param locale The locale a NumberFormat is required for, + * system default if null. + * @return The NumberFormat to created. + */ + protected Format getFormat(Locale locale) { + NumberFormat formatter = null; + switch (formatType) { + case CURRENCY_FORMAT: + if (locale == null) { + formatter = NumberFormat.getCurrencyInstance(); + } else { + formatter = NumberFormat.getCurrencyInstance(locale); + } + break; + case PERCENT_FORMAT: + if (locale == null) { + formatter = NumberFormat.getPercentInstance(); + } else { + formatter = NumberFormat.getPercentInstance(locale); + } + break; + default: + if (locale == null) { + formatter = NumberFormat.getInstance(); + } else { + formatter = NumberFormat.getInstance(locale); + } + if (!isAllowFractions()) { + formatter.setParseIntegerOnly(true); + } + break; + } + return formatter; + } +} diff --git a/Java/commons-validator-AbstractNumberValidator_157/metadata.json b/Java/commons-validator-AbstractNumberValidator_157/metadata.json new file mode 100644 index 000000000..ce1ec9766 --- /dev/null +++ b/Java/commons-validator-AbstractNumberValidator_157/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-AbstractNumberValidator_157", + "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/validator/routines/AbstractNumberValidator.java", + "line": 169, + "npe_method": "parse", + "deref_field": "value", + "npe_class": "AbstractNumberValidator", + "repo": "commons-validator", + "bug_id": "AbstractNumberValidator_157" + } +} diff --git a/Java/commons-validator-AbstractNumberValidator_157/npe.json b/Java/commons-validator-AbstractNumberValidator_157/npe.json new file mode 100644 index 000000000..be17bae2f --- /dev/null +++ b/Java/commons-validator-AbstractNumberValidator_157/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/AbstractNumberValidator.java", + "line": 169, + "npe_method": "parse", + "deref_field": "value", + "npe_class": "AbstractNumberValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-AbstractNumberValidator_194/Dockerfile b/Java/commons-validator-AbstractNumberValidator_194/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-AbstractNumberValidator_194/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-AbstractNumberValidator_194/buggy.java b/Java/commons-validator-AbstractNumberValidator_194/buggy.java new file mode 100644 index 000000000..0cf372a83 --- /dev/null +++ b/Java/commons-validator-AbstractNumberValidator_194/buggy.java @@ -0,0 +1,287 @@ +/* + * 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.validator.routines; + +import java.text.DecimalFormatSymbols; +import java.text.Format; +import java.text.NumberFormat; +import java.text.DecimalFormat; +import java.util.Locale; + +/** + *

Abstract class for Number Validation.

+ * + *

This is a base class for building Number + * Validators using format parsing.

+ * + * @version $Revision$ + * @since Validator 1.3.0 + */ +public abstract class AbstractNumberValidator extends AbstractFormatValidator { + + private static final long serialVersionUID = -3088817875906765463L; + + /** Standard NumberFormat type */ + public static final int STANDARD_FORMAT = 0; + + /** Currency NumberFormat type */ + public static final int CURRENCY_FORMAT = 1; + + /** Percent NumberFormat type */ + public static final int PERCENT_FORMAT = 2; + + private final boolean allowFractions; + private final int formatType; + + /** + * Construct an instance with specified strict + * and decimal parameters. + * + * @param strict true if strict + * Format parsing should be used. + * @param formatType The NumberFormat type to + * create for validation, default is STANDARD_FORMAT. + * @param allowFractions true if fractions are + * allowed or false if integers only. + */ + public AbstractNumberValidator(boolean strict, int formatType, boolean allowFractions) { + super(strict); + this.allowFractions = allowFractions; + this.formatType = formatType; + } + + /** + *

Indicates whether the number being validated is + * a decimal or integer.

+ * + * @return true if decimals are allowed + * or false if the number is an integer. + */ + public boolean isAllowFractions() { + return allowFractions; + } + + /** + *

Indicates the type of NumberFormat created + * by this validator instance.

+ * + * @return the format type created. + */ + public int getFormatType() { + return formatType; + } + + /** + *

Validate using the specified Locale.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to validate the value against, or the + * default for the Locale if null. + * @param locale The locale to use for the date format, system default if null. + * @return true if the value is valid. + */ + @Override + public boolean isValid(String value, String pattern, Locale locale) { + Object parsedValue = parse(value, pattern, locale); + return (parsedValue == null ? false : true); + } + + /** + * Check if the value is within a specified range. + * + * @param value The value validation is being performed on. + * @param min The minimum value of the range. + * @param max The maximum value of the range. + * @return true if the value is within the + * specified range. + */ + public boolean isInRange(Number value, Number min, Number max) { + return (minValue(value, min) && maxValue(value, max)); + } + + /** + * Check if the value is greater than or equal to a minimum. + * + * @param value The value validation is being performed on. + * @param min The minimum value. + * @return true if the value is greater than + * or equal to the minimum. + */ + public boolean minValue(Number value, Number min) { + if (isAllowFractions()) { + return (value.doubleValue() >= min.doubleValue()); + } + return (value.longValue() >= min.longValue()); + } + + /** + * Check if the value is less than or equal to a maximum. + * + * @param value The value validation is being performed on. + * @param max The maximum value. + * @return true if the value is less than + * or equal to the maximum. + */ + public boolean maxValue(Number value, Number max) { + if (isAllowFractions()) { + return (value.doubleValue() <= max.doubleValue()); + } + return (value.longValue() <= max.longValue()); + } + + /** + *

Parse the value using the specified pattern.

+ * + * @param value The value validation is being performed on. + * @param pattern The pattern used to validate the value against, or the + * default for the Locale if null. + * @param locale The locale to use for the date format, system default if null. + * @return The parsed value if valid or null if invalid. + */ + protected Object parse(String value, String pattern, Locale locale) { + + value = (value == null ? null : value.trim()); + if (value == null || value.length() == 0) { + return null; + } + Format formatter = getFormat(pattern, locale); + return parse(value, formatter); + + } + + /** + *

Process the parsed value, performing any further validation + * and type conversion required.

+ * + * @param value The parsed object created. + * @param formatter The Format used to parse the value with. + * @return The parsed value converted to the appropriate type + * if valid or null if invalid. + */ + @Override + protected abstract Object processParsedValue(Object value, Format formatter); + + /** + *

Returns a NumberFormat for the specified pattern + * and/or Locale.

+ * + * @param pattern The pattern used to validate the value against or + * null to use the default for the Locale. + * @param locale The locale to use for the currency format, system default if null. + * @return The NumberFormat to created. + */ + @Override +/** + *

Returns a NumberFormat for the specified pattern + * and/or Locale.

+ * + * @param pattern + * The pattern used to validate the value against or + * null to use the default for the Locale. + * @param locale + * The locale to use for the currency format, system default if null. + * @return The NumberFormat to created. + */ +protected java.text.Format getFormat(java.lang.String pattern, java.util.Locale locale) { + java.text.NumberFormat formatter = null; + boolean usePattern = (pattern != null) && (pattern.length() > 0); + if (!usePattern) { + formatter = ((java.text.NumberFormat) (getFormat(locale))); + } else { + { + java.text.DecimalFormatSymbols symbols = new java.text.DecimalFormatSymbols(/* NPEX_NULL_EXP */ + locale); + formatter = new java.text.DecimalFormat(pattern, symbols); + } + } + if (!isAllowFractions()) { + formatter.setParseIntegerOnly(true); + } + return formatter; +} + + /** + *

Returns the multiplier of the NumberFormat.

+ * + * @param format The NumberFormat to determine the + * multiplier of. + * @return The multiplying factor for the format.. + */ + protected int determineScale(NumberFormat format) { + if (!isStrict()) { + return -1; + } + if (!isAllowFractions() || format.isParseIntegerOnly()) { + return 0; + } + int minimumFraction = format.getMinimumFractionDigits(); + int maximumFraction = format.getMaximumFractionDigits(); + if (minimumFraction != maximumFraction) { + return -1; + } + int scale = minimumFraction; + if (format instanceof DecimalFormat) { + int multiplier = ((DecimalFormat)format).getMultiplier(); + if (multiplier == 100) { // CHECKSTYLE IGNORE MagicNumber + scale += 2; // CHECKSTYLE IGNORE MagicNumber + } else if (multiplier == 1000) { // CHECKSTYLE IGNORE MagicNumber + scale += 3; // CHECKSTYLE IGNORE MagicNumber + } + } else if (formatType == PERCENT_FORMAT) { + scale += 2; // CHECKSTYLE IGNORE MagicNumber + } + return scale; + } + + /** + *

Returns a NumberFormat for the specified Locale.

+ * + * @param locale The locale a NumberFormat is required for, + * system default if null. + * @return The NumberFormat to created. + */ + protected Format getFormat(Locale locale) { + NumberFormat formatter = null; + switch (formatType) { + case CURRENCY_FORMAT: + if (locale == null) { + formatter = NumberFormat.getCurrencyInstance(); + } else { + formatter = NumberFormat.getCurrencyInstance(locale); + } + break; + case PERCENT_FORMAT: + if (locale == null) { + formatter = NumberFormat.getPercentInstance(); + } else { + formatter = NumberFormat.getPercentInstance(locale); + } + break; + default: + if (locale == null) { + formatter = NumberFormat.getInstance(); + } else { + formatter = NumberFormat.getInstance(locale); + } + if (!isAllowFractions()) { + formatter.setParseIntegerOnly(true); + } + break; + } + return formatter; + } +} diff --git a/Java/commons-validator-AbstractNumberValidator_194/metadata.json b/Java/commons-validator-AbstractNumberValidator_194/metadata.json new file mode 100644 index 000000000..b47e8bee3 --- /dev/null +++ b/Java/commons-validator-AbstractNumberValidator_194/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-AbstractNumberValidator_194", + "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/validator/routines/AbstractNumberValidator.java", + "line": 207, + "npe_method": "getFormat", + "deref_field": "locale", + "npe_class": "AbstractNumberValidator", + "repo": "commons-validator", + "bug_id": "AbstractNumberValidator_194" + } +} diff --git a/Java/commons-validator-AbstractNumberValidator_194/npe.json b/Java/commons-validator-AbstractNumberValidator_194/npe.json new file mode 100644 index 000000000..56af2f22c --- /dev/null +++ b/Java/commons-validator-AbstractNumberValidator_194/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/AbstractNumberValidator.java", + "line": 207, + "npe_method": "getFormat", + "deref_field": "locale", + "npe_class": "AbstractNumberValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-CodeValidator_251/Dockerfile b/Java/commons-validator-CodeValidator_251/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-CodeValidator_251/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-CodeValidator_251/buggy.java b/Java/commons-validator-CodeValidator_251/buggy.java new file mode 100644 index 000000000..abbb9d7fc --- /dev/null +++ b/Java/commons-validator-CodeValidator_251/buggy.java @@ -0,0 +1,288 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; + +import org.apache.commons.validator.routines.checkdigit.CheckDigit; + +/** + * Generic Code Validation providing format, minimum/maximum + * length and {@link CheckDigit} validations. + *

+ * Performs the following validations on a code: + *

+ *

+ * Note + * The {@link #isValid(String)} method will return true if the input passes validation. + * Since this includes trimming as well as potentially dropping parts of the input, + * it is possible for a String to pass validation + * but fail the checkdigit test if passed directly to it (the check digit routines generally don't trim input + * nor do they generally check the format/length). + * To be sure that you are passing valid input to a method use {@link #validate(String)} as follows: + *

+ * Object valid = validator.validate(input); 
+ * if (valid != null) {
+ *    some_method(valid.toString());
+ * }
+ * 
+ *

+ * Configure the validator with the appropriate regular expression, minimum/maximum length + * and {@link CheckDigit} validator and then call one of the two validation + * methods provided:

+ * + *

+ * Codes often include format characters - such as hyphens - to make them + * more easily human readable. These can be removed prior to length and check digit + * validation by specifying them as a non-capturing group in the regular + * expression (i.e. use the (?: ) notation). + *
+ * Or just avoid using parentheses except for the parts you want to capture + * + * @version $Revision$ + * @since Validator 1.4 + */ +public final class CodeValidator implements Serializable { + + private static final long serialVersionUID = 446960910870938233L; + + private final RegexValidator regexValidator; + private final int minLength; + private final int maxLength; + private final CheckDigit checkdigit; + + /** + * Construct a code validator with a specified regular + * expression and {@link CheckDigit}. + * The RegexValidator validator is created to be case-sensitive + * + * @param regex The format regular expression + * @param checkdigit The check digit validation routine + */ + public CodeValidator(String regex, CheckDigit checkdigit) { + this(regex, -1, -1, checkdigit); + } + + /** + * Construct a code validator with a specified regular + * expression, length and {@link CheckDigit}. + * The RegexValidator validator is created to be case-sensitive + * + * @param regex The format regular expression. + * @param length The length of the code + * (sets the mimimum/maximum to the same) + * @param checkdigit The check digit validation routine + */ + public CodeValidator(String regex, int length, CheckDigit checkdigit) { + this(regex, length, length, checkdigit); + } + + /** + * Construct a code validator with a specified regular + * expression, minimum/maximum length and {@link CheckDigit} validation. + * The RegexValidator validator is created to be case-sensitive + * + * @param regex The regular expression + * @param minLength The minimum length of the code + * @param maxLength The maximum length of the code + * @param checkdigit The check digit validation routine + */ + public CodeValidator(String regex, int minLength, int maxLength, + CheckDigit checkdigit) { + if (regex != null && regex.length() > 0) { + this.regexValidator = new RegexValidator(regex); + } else { + this.regexValidator = null; + } + this.minLength = minLength; + this.maxLength = maxLength; + this.checkdigit = checkdigit; + } + + /** + * Construct a code validator with a specified regular expression, + * validator and {@link CheckDigit} validation. + * + * @param regexValidator The format regular expression validator + * @param checkdigit The check digit validation routine. + */ + public CodeValidator(RegexValidator regexValidator, CheckDigit checkdigit) { + this(regexValidator, -1, -1, checkdigit); + } + + /** + * Construct a code validator with a specified regular expression, + * validator, length and {@link CheckDigit} validation. + * + * @param regexValidator The format regular expression validator + * @param length The length of the code + * (sets the mimimum/maximum to the same value) + * @param checkdigit The check digit validation routine + */ + public CodeValidator(RegexValidator regexValidator, int length, CheckDigit checkdigit) { + this(regexValidator, length, length, checkdigit); + } + + /** + * Construct a code validator with a specified regular expression + * validator, minimum/maximum length and {@link CheckDigit} validation. + * + * @param regexValidator The format regular expression validator + * @param minLength The minimum length of the code + * @param maxLength The maximum length of the code + * @param checkdigit The check digit validation routine + */ + public CodeValidator(RegexValidator regexValidator, int minLength, int maxLength, + CheckDigit checkdigit) { + this.regexValidator = regexValidator; + this.minLength = minLength; + this.maxLength = maxLength; + this.checkdigit = checkdigit; + } + + /** + * Return the check digit validation routine. + *

+ * N.B. Optional, if not set no Check Digit + * validation will be performed on the code. + * + * @return The check digit validation routine + */ + public CheckDigit getCheckDigit() { + return checkdigit; + } + + /** + * Return the minimum length of the code. + *

+ * N.B. Optional, if less than zero the + * minimum length will not be checked. + * + * @return The minimum length of the code or + * -1 if the code has no minimum length + */ + public int getMinLength() { + return minLength; + } + + /** + * Return the maximum length of the code. + *

+ * N.B. Optional, if less than zero the + * maximum length will not be checked. + * + * @return The maximum length of the code or + * -1 if the code has no maximum length + */ + public int getMaxLength() { + return maxLength; + } + + /** + * Return the regular expression validator. + *

+ * N.B. Optional, if not set no regular + * expression validation will be performed on the code. + * + * @return The regular expression validator + */ + public RegexValidator getRegexValidator() { + return regexValidator; + } + + /** + * Validate the code returning either true + * or false. + *

+ * This calls {@link #validate(String)} and returns false + * if the return value is null, true otherwise. + *

+ * Note that {@link #validate(String)} trims the input + * and if there is a {@link RegexValidator} it may also + * change the input as part of the validation. + * + * @param input The code to validate + * @return true if valid, otherwise + * false + */ + public boolean isValid(String input) { + return (validate(input) != null); + } + + /** + * Validate the code returning either the valid code or + * null if invalid. + *

+ * Note that this method trims the input + * and if there is a {@link RegexValidator} it may also + * change the input as part of the validation. + * + * @param input The code to validate + * @return The code if valid, otherwise null + * if invalid + */ +/** + * Validate the code returning either the valid code or + * null if invalid. + *

+ * Note that this method trims the input + * and if there is a {@link RegexValidator} it may also + * change the input as part of the validation. + * + * @param input + * The code to validate + * @return The code if valid, otherwise null +if invalid + */ +public java.lang.Object validate(java.lang.String input) { + { + java.lang.String code = /* NPEX_NULL_EXP */ + input.trim(); + if (code.length() == 0) { + return null; + } + // validate/reformat using regular expression + if (regexValidator != null) { + code = regexValidator.validate(code); + if (code == null) { + return null; + } + } + // check the length (must be done after validate as that can change the code) + if (((minLength >= 0) && (code.length() < minLength)) || ((maxLength >= 0) && (code.length() > maxLength))) { + return null; + } + // validate the check digit + if ((checkdigit != null) && (!checkdigit.isValid(code))) { + return null; + } + return code; + } +} + +} diff --git a/Java/commons-validator-CodeValidator_251/metadata.json b/Java/commons-validator-CodeValidator_251/metadata.json new file mode 100644 index 000000000..3da0ec6ae --- /dev/null +++ b/Java/commons-validator-CodeValidator_251/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-CodeValidator_251", + "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/validator/routines/CodeValidator.java", + "line": 265, + "npe_method": "validate", + "deref_field": "input", + "npe_class": "CodeValidator", + "repo": "commons-validator", + "bug_id": "CodeValidator_251" + } +} diff --git a/Java/commons-validator-CodeValidator_251/npe.json b/Java/commons-validator-CodeValidator_251/npe.json new file mode 100644 index 000000000..82b4518ba --- /dev/null +++ b/Java/commons-validator-CodeValidator_251/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/CodeValidator.java", + "line": 265, + "npe_method": "validate", + "deref_field": "input", + "npe_class": "CodeValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-CodeValidator_261/Dockerfile b/Java/commons-validator-CodeValidator_261/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-CodeValidator_261/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-CodeValidator_261/buggy.java b/Java/commons-validator-CodeValidator_261/buggy.java new file mode 100644 index 000000000..ef575b163 --- /dev/null +++ b/Java/commons-validator-CodeValidator_261/buggy.java @@ -0,0 +1,288 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; + +import org.apache.commons.validator.routines.checkdigit.CheckDigit; + +/** + * Generic Code Validation providing format, minimum/maximum + * length and {@link CheckDigit} validations. + *

+ * Performs the following validations on a code: + *

+ *

+ * Note + * The {@link #isValid(String)} method will return true if the input passes validation. + * Since this includes trimming as well as potentially dropping parts of the input, + * it is possible for a String to pass validation + * but fail the checkdigit test if passed directly to it (the check digit routines generally don't trim input + * nor do they generally check the format/length). + * To be sure that you are passing valid input to a method use {@link #validate(String)} as follows: + *

+ * Object valid = validator.validate(input); 
+ * if (valid != null) {
+ *    some_method(valid.toString());
+ * }
+ * 
+ *

+ * Configure the validator with the appropriate regular expression, minimum/maximum length + * and {@link CheckDigit} validator and then call one of the two validation + * methods provided:

+ * + *

+ * Codes often include format characters - such as hyphens - to make them + * more easily human readable. These can be removed prior to length and check digit + * validation by specifying them as a non-capturing group in the regular + * expression (i.e. use the (?: ) notation). + *
+ * Or just avoid using parentheses except for the parts you want to capture + * + * @version $Revision$ + * @since Validator 1.4 + */ +public final class CodeValidator implements Serializable { + + private static final long serialVersionUID = 446960910870938233L; + + private final RegexValidator regexValidator; + private final int minLength; + private final int maxLength; + private final CheckDigit checkdigit; + + /** + * Construct a code validator with a specified regular + * expression and {@link CheckDigit}. + * The RegexValidator validator is created to be case-sensitive + * + * @param regex The format regular expression + * @param checkdigit The check digit validation routine + */ + public CodeValidator(String regex, CheckDigit checkdigit) { + this(regex, -1, -1, checkdigit); + } + + /** + * Construct a code validator with a specified regular + * expression, length and {@link CheckDigit}. + * The RegexValidator validator is created to be case-sensitive + * + * @param regex The format regular expression. + * @param length The length of the code + * (sets the mimimum/maximum to the same) + * @param checkdigit The check digit validation routine + */ + public CodeValidator(String regex, int length, CheckDigit checkdigit) { + this(regex, length, length, checkdigit); + } + + /** + * Construct a code validator with a specified regular + * expression, minimum/maximum length and {@link CheckDigit} validation. + * The RegexValidator validator is created to be case-sensitive + * + * @param regex The regular expression + * @param minLength The minimum length of the code + * @param maxLength The maximum length of the code + * @param checkdigit The check digit validation routine + */ + public CodeValidator(String regex, int minLength, int maxLength, + CheckDigit checkdigit) { + if (regex != null && regex.length() > 0) { + this.regexValidator = new RegexValidator(regex); + } else { + this.regexValidator = null; + } + this.minLength = minLength; + this.maxLength = maxLength; + this.checkdigit = checkdigit; + } + + /** + * Construct a code validator with a specified regular expression, + * validator and {@link CheckDigit} validation. + * + * @param regexValidator The format regular expression validator + * @param checkdigit The check digit validation routine. + */ + public CodeValidator(RegexValidator regexValidator, CheckDigit checkdigit) { + this(regexValidator, -1, -1, checkdigit); + } + + /** + * Construct a code validator with a specified regular expression, + * validator, length and {@link CheckDigit} validation. + * + * @param regexValidator The format regular expression validator + * @param length The length of the code + * (sets the mimimum/maximum to the same value) + * @param checkdigit The check digit validation routine + */ + public CodeValidator(RegexValidator regexValidator, int length, CheckDigit checkdigit) { + this(regexValidator, length, length, checkdigit); + } + + /** + * Construct a code validator with a specified regular expression + * validator, minimum/maximum length and {@link CheckDigit} validation. + * + * @param regexValidator The format regular expression validator + * @param minLength The minimum length of the code + * @param maxLength The maximum length of the code + * @param checkdigit The check digit validation routine + */ + public CodeValidator(RegexValidator regexValidator, int minLength, int maxLength, + CheckDigit checkdigit) { + this.regexValidator = regexValidator; + this.minLength = minLength; + this.maxLength = maxLength; + this.checkdigit = checkdigit; + } + + /** + * Return the check digit validation routine. + *

+ * N.B. Optional, if not set no Check Digit + * validation will be performed on the code. + * + * @return The check digit validation routine + */ + public CheckDigit getCheckDigit() { + return checkdigit; + } + + /** + * Return the minimum length of the code. + *

+ * N.B. Optional, if less than zero the + * minimum length will not be checked. + * + * @return The minimum length of the code or + * -1 if the code has no minimum length + */ + public int getMinLength() { + return minLength; + } + + /** + * Return the maximum length of the code. + *

+ * N.B. Optional, if less than zero the + * maximum length will not be checked. + * + * @return The maximum length of the code or + * -1 if the code has no maximum length + */ + public int getMaxLength() { + return maxLength; + } + + /** + * Return the regular expression validator. + *

+ * N.B. Optional, if not set no regular + * expression validation will be performed on the code. + * + * @return The regular expression validator + */ + public RegexValidator getRegexValidator() { + return regexValidator; + } + + /** + * Validate the code returning either true + * or false. + *

+ * This calls {@link #validate(String)} and returns false + * if the return value is null, true otherwise. + *

+ * Note that {@link #validate(String)} trims the input + * and if there is a {@link RegexValidator} it may also + * change the input as part of the validation. + * + * @param input The code to validate + * @return true if valid, otherwise + * false + */ + public boolean isValid(String input) { + return (validate(input) != null); + } + + /** + * Validate the code returning either the valid code or + * null if invalid. + *

+ * Note that this method trims the input + * and if there is a {@link RegexValidator} it may also + * change the input as part of the validation. + * + * @param input The code to validate + * @return The code if valid, otherwise null + * if invalid + */ +/** + * Validate the code returning either the valid code or + * null if invalid. + *

+ * Note that this method trims the input + * and if there is a {@link RegexValidator} it may also + * change the input as part of the validation. + * + * @param input + * The code to validate + * @return The code if valid, otherwise null +if invalid + */ +public java.lang.Object validate(java.lang.String input) { + if (input == null) { + return null; + } + java.lang.String code = input.trim(); + if (code.length() == 0) { + return null; + } + { + code = /* NPEX_NULL_EXP */ + regexValidator.validate(code); + if (code == null) { + return null; + } + } + // check the length (must be done after validate as that can change the code) + if (((minLength >= 0) && (code.length() < minLength)) || ((maxLength >= 0) && (code.length() > maxLength))) { + return null; + } + // validate the check digit + if ((checkdigit != null) && (!checkdigit.isValid(code))) { + return null; + } + return code; +} + +} diff --git a/Java/commons-validator-CodeValidator_261/metadata.json b/Java/commons-validator-CodeValidator_261/metadata.json new file mode 100644 index 000000000..4107b2b87 --- /dev/null +++ b/Java/commons-validator-CodeValidator_261/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-CodeValidator_261", + "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/validator/routines/CodeValidator.java", + "line": 272, + "npe_method": "validate", + "deref_field": "regexValidator", + "npe_class": "CodeValidator", + "repo": "commons-validator", + "bug_id": "CodeValidator_261" + } +} diff --git a/Java/commons-validator-CodeValidator_261/npe.json b/Java/commons-validator-CodeValidator_261/npe.json new file mode 100644 index 000000000..0f3a7ed55 --- /dev/null +++ b/Java/commons-validator-CodeValidator_261/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/CodeValidator.java", + "line": 272, + "npe_method": "validate", + "deref_field": "regexValidator", + "npe_class": "CodeValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-CreditCardValidator_478/Dockerfile b/Java/commons-validator-CreditCardValidator_478/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-CreditCardValidator_478/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-CreditCardValidator_478/buggy.java b/Java/commons-validator-CreditCardValidator_478/buggy.java new file mode 100644 index 000000000..a0b732b7b --- /dev/null +++ b/Java/commons-validator-CreditCardValidator_478/buggy.java @@ -0,0 +1,516 @@ +/* + * 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.validator.routines; + +import org.apache.commons.validator.routines.checkdigit.CheckDigit; +import org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit; +import java.io.Serializable; +import java.util.Collections; +import java.util.List; +import java.util.ArrayList; + +/** + * Perform credit card validations. + * + *

+ * By default, AMEX + VISA + MASTERCARD + DISCOVER card types are allowed. You can specify which + * cards should pass validation by configuring the validation options. For + * example, + *

+ * + *
+ * CreditCardValidator ccv = new CreditCardValidator(CreditCardValidator.AMEX + CreditCardValidator.VISA);
+ * 
+ * + *

+ * configures the validator to only pass American Express and Visa cards. + * If a card type is not directly supported by this class, you can create an + * instance of the {@link CodeValidator} class and pass it to a {@link CreditCardValidator} + * constructor along with any existing validators. For example: + *

+ * + *
+ * CreditCardValidator ccv = new CreditCardValidator(
+ *     new CodeValidator[] {
+ *         CreditCardValidator.AMEX_VALIDATOR,
+ *         CreditCardValidator.VISA_VALIDATOR,
+ *         new CodeValidator("^(4)(\\d{12,18})$", LUHN_VALIDATOR) // add VPAY
+ * };
+ * 
+ * + *

+ * Alternatively you can define a validator using the {@link CreditCardRange} class. + * For example: + *

+ * + *
+ * CreditCardValidator ccv = new CreditCardValidator(
+ *    new CreditCardRange[]{
+ *        new CreditCardRange("300", "305", 14, 14), // Diners
+ *        new CreditCardRange("3095", null, 14, 14), // Diners
+ *        new CreditCardRange("36",   null, 14, 14), // Diners
+ *        new CreditCardRange("38",   "39", 14, 14), // Diners
+ *        new CreditCardRange("4",    null, new int[] {13, 16}), // VISA
+ *    }
+ * );
+ * 
+ * 
+ *

+ * This can be combined with a list of {@code CodeValidator}s + *

+ *

+ * More information can be found in Michael Gilleland's essay + * Anatomy of Credit Card Numbers. + *

+ * + * @version $Revision$ + * @since Validator 1.4 + */ +public class CreditCardValidator implements Serializable { + + private static final long serialVersionUID = 5955978921148959496L; + + private static final int MIN_CC_LENGTH = 12; // minimum allowed length + + private static final int MAX_CC_LENGTH = 19; // maximum allowed length + + /** + * Class that represents a credit card range. + * @since 1.6 + */ + public static class CreditCardRange { + final String low; // e.g. 34 or 644 + final String high; // e.g. 34 or 65 + final int minLen; // e.g. 16 or -1 + final int maxLen; // e.g. 19 or -1 + final int lengths[]; // e.g. 16,18,19 + + /** + * Create a credit card range specifier for use in validation + * of the number syntax including the IIN range. + *

+ * The low and high parameters may be shorter than the length + * of an IIN (currently 6 digits) in which case subsequent digits + * are ignored and may range from 0-9. + *
+ * The low and high parameters may be different lengths. + * e.g. Discover "644" and "65". + *

+ * @param low the low digits of the IIN range + * @param high the high digits of the IIN range + * @param minLen the minimum length of the entire number + * @param maxLen the maximum length of the entire number + */ + public CreditCardRange(String low, String high, int minLen, int maxLen) { + this.low = low; + this.high = high; + this.minLen = minLen; + this.maxLen = maxLen; + this.lengths = null; + } + + /** + * Create a credit card range specifier for use in validation + * of the number syntax including the IIN range. + *

+ * The low and high parameters may be shorter than the length + * of an IIN (currently 6 digits) in which case subsequent digits + * are ignored and may range from 0-9. + *
+ * The low and high parameters may be different lengths. + * e.g. Discover "644" and "65". + *

+ * @param low the low digits of the IIN range + * @param high the high digits of the IIN range + * @param lengths array of valid lengths + */ + public CreditCardRange(String low, String high, int [] lengths) { + this.low = low; + this.high = high; + this.minLen = -1; + this.maxLen = -1; + this.lengths = lengths.clone(); + } + } + + /** + * Option specifying that no cards are allowed. This is useful if + * you want only custom card types to validate so you turn off the + * default cards with this option. + * + *
+     * 
+     * CreditCardValidator v = new CreditCardValidator(CreditCardValidator.NONE);
+     * v.addAllowedCardType(customType);
+     * v.isValid(aCardNumber);
+     * 
+     * 
+ */ + public static final long NONE = 0; + + /** + * Option specifying that American Express cards are allowed. + */ + public static final long AMEX = 1 << 0; + + /** + * Option specifying that Visa cards are allowed. + */ + public static final long VISA = 1 << 1; + + /** + * Option specifying that Mastercard cards are allowed. + */ + public static final long MASTERCARD = 1 << 2; + + /** + * Option specifying that Discover cards are allowed. + */ + public static final long DISCOVER = 1 << 3; // CHECKSTYLE IGNORE MagicNumber + + /** + * Option specifying that Diners cards are allowed. + */ + public static final long DINERS = 1 << 4; // CHECKSTYLE IGNORE MagicNumber + + /** + * Option specifying that VPay (Visa) cards are allowed. + * @since 1.5.0 + */ + public static final long VPAY = 1 << 5; // CHECKSTYLE IGNORE MagicNumber + + /** + * Option specifying that Mastercard cards (pre Oct 2016 only) are allowed. + * @deprecated for use until Oct 2016 only + */ + @Deprecated + public static final long MASTERCARD_PRE_OCT2016 = 1 << 6; // CHECKSTYLE IGNORE MagicNumber + + + /** + * The CreditCardTypes that are allowed to pass validation. + */ + private final List cardTypes = new ArrayList(); + + /** + * Luhn checkdigit validator for the card numbers. + */ + private static final CheckDigit LUHN_VALIDATOR = LuhnCheckDigit.LUHN_CHECK_DIGIT; + + /** + * American Express (Amex) Card Validator + *

+ * 34xxxx (15)
+ * 37xxxx (15)
+ */ + public static final CodeValidator AMEX_VALIDATOR = new CodeValidator("^(3[47]\\d{13})$", LUHN_VALIDATOR); + + /** + * Diners Card Validator + *

+ * 300xxx - 305xxx (14)
+ * 3095xx (14)
+ * 36xxxx (14)
+ * 38xxxx (14)
+ * 39xxxx (14)
+ */ + public static final CodeValidator DINERS_VALIDATOR = new CodeValidator("^(30[0-5]\\d{11}|3095\\d{10}|36\\d{12}|3[8-9]\\d{12})$", LUHN_VALIDATOR); + + /** + * Discover Card regular expressions + *

+ * 6011xx (16)
+ * 644xxx - 65xxxx (16)
+ */ + private static final RegexValidator DISCOVER_REGEX = new RegexValidator(new String[] {"^(6011\\d{12})$", "^(64[4-9]\\d{13})$", "^(65\\d{14})$"}); + + /** Discover Card Validator */ + public static final CodeValidator DISCOVER_VALIDATOR = new CodeValidator(DISCOVER_REGEX, LUHN_VALIDATOR); + + /** + * Mastercard regular expressions + *

+ * 2221xx - 2720xx (16)
+ * 51xxx - 55xxx (16)
+ */ + private static final RegexValidator MASTERCARD_REGEX = new RegexValidator( + new String[] { + "^(5[1-5]\\d{14})$", // 51 - 55 (pre Oct 2016) + // valid from October 2016 + "^(2221\\d{12})$", // 222100 - 222199 + "^(222[2-9]\\d{12})$",// 222200 - 222999 + "^(22[3-9]\\d{13})$", // 223000 - 229999 + "^(2[3-6]\\d{14})$", // 230000 - 269999 + "^(27[01]\\d{13})$", // 270000 - 271999 + "^(2720\\d{12})$", // 272000 - 272099 + }); + + /** Mastercard Card Validator */ + public static final CodeValidator MASTERCARD_VALIDATOR = new CodeValidator(MASTERCARD_REGEX, LUHN_VALIDATOR); + + /** + * Mastercard Card Validator (pre Oct 2016) + * @deprecated for use until Oct 2016 only + */ + @Deprecated + public static final CodeValidator MASTERCARD_VALIDATOR_PRE_OCT2016 = new CodeValidator("^(5[1-5]\\d{14})$", LUHN_VALIDATOR); + + /** + * Visa Card Validator + *

+ * 4xxxxx (13 or 16) + */ + public static final CodeValidator VISA_VALIDATOR = new CodeValidator("^(4)(\\d{12}|\\d{15})$", LUHN_VALIDATOR); + + /** VPay (Visa) Card Validator + *

+ * 4xxxxx (13-19) + * @since 1.5.0 + */ + public static final CodeValidator VPAY_VALIDATOR = new CodeValidator("^(4)(\\d{12,18})$", LUHN_VALIDATOR); + + /** + * Create a new CreditCardValidator with default options. + * The default options are: + * AMEX, VISA, MASTERCARD and DISCOVER + */ + public CreditCardValidator() { + this(AMEX + VISA + MASTERCARD + DISCOVER); + } + + /** + * Create a new CreditCardValidator with the specified options. + * @param options Pass in + * CreditCardValidator.VISA + CreditCardValidator.AMEX to specify that + * those are the only valid card types. + */ + public CreditCardValidator(long options) { + super(); + + if (isOn(options, VISA)) { + this.cardTypes.add(VISA_VALIDATOR); + } + + if (isOn(options, VPAY)) { + this.cardTypes.add(VPAY_VALIDATOR); + } + + if (isOn(options, AMEX)) { + this.cardTypes.add(AMEX_VALIDATOR); + } + + if (isOn(options, MASTERCARD)) { + this.cardTypes.add(MASTERCARD_VALIDATOR); + } + + if (isOn(options, MASTERCARD_PRE_OCT2016)) { + this.cardTypes.add(MASTERCARD_VALIDATOR_PRE_OCT2016); + } + + if (isOn(options, DISCOVER)) { + this.cardTypes.add(DISCOVER_VALIDATOR); + } + + if (isOn(options, DINERS)) { + this.cardTypes.add(DINERS_VALIDATOR); + } + } + + /** + * Create a new CreditCardValidator with the specified {@link CodeValidator}s. + * @param creditCardValidators Set of valid code validators + */ + public CreditCardValidator(CodeValidator[] creditCardValidators) { + if (creditCardValidators == null) { + throw new IllegalArgumentException("Card validators are missing"); + } + Collections.addAll(cardTypes, creditCardValidators); + } + + /** + * Create a new CreditCardValidator with the specified {@link CreditCardRange}s. + * @param creditCardRanges Set of valid code validators + * @since 1.6 + */ + public CreditCardValidator(CreditCardRange[] creditCardRanges) { + if (creditCardRanges == null) { + throw new IllegalArgumentException("Card ranges are missing"); + } + Collections.addAll(cardTypes, createRangeValidator(creditCardRanges, LUHN_VALIDATOR)); + } + + /** + * Create a new CreditCardValidator with the specified {@link CodeValidator}s + * and {@link CreditCardRange}s. + *

+ * This can be used to combine predefined validators such as {@link #MASTERCARD_VALIDATOR} + * with additional validators using the simpler {@link CreditCardRange}s. + * @param creditCardValidators Set of valid code validators + * @param creditCardRanges Set of valid code validators + * @since 1.6 + */ + public CreditCardValidator(CodeValidator[] creditCardValidators, CreditCardRange[] creditCardRanges) { + if (creditCardValidators == null) { + throw new IllegalArgumentException("Card validators are missing"); + } + if (creditCardRanges == null) { + throw new IllegalArgumentException("Card ranges are missing"); + } + Collections.addAll(cardTypes, creditCardValidators); + Collections.addAll(cardTypes, createRangeValidator(creditCardRanges, LUHN_VALIDATOR)); + } + + /** + * Create a new generic CreditCardValidator which validates the syntax and check digit only. + * Does not check the Issuer Identification Number (IIN) + * + * @param minLen minimum allowed length + * @param maxLen maximum allowed length + * @return the validator + * @since 1.6 + */ + public static CreditCardValidator genericCreditCardValidator(int minLen, int maxLen) { + return new CreditCardValidator(new CodeValidator[] {new CodeValidator("(\\d+)", minLen, maxLen, LUHN_VALIDATOR)}); + } + + /** + * Create a new generic CreditCardValidator which validates the syntax and check digit only. + * Does not check the Issuer Identification Number (IIN) + * + * @param length exact length + * @return the validator + * @since 1.6 + */ + public static CreditCardValidator genericCreditCardValidator(int length) { + return genericCreditCardValidator(length, length); + } + + /** + * Create a new generic CreditCardValidator which validates the syntax and check digit only. + * Does not check the Issuer Identification Number (IIN) + * + * @return the validator + * @since 1.6 + */ + public static CreditCardValidator genericCreditCardValidator() { + return genericCreditCardValidator(MIN_CC_LENGTH, MAX_CC_LENGTH); + } + + /** + * Checks if the field is a valid credit card number. + * @param card The card number to validate. + * @return Whether the card number is valid. + */ + public boolean isValid(String card) { + if (card == null || card.length() == 0) { + return false; + } + for (CodeValidator cardType : cardTypes) { + if (cardType.isValid(card)) { + return true; + } + } + return false; + } + + /** + * Checks if the field is a valid credit card number. + * @param card The card number to validate. + * @return The card number if valid or null + * if invalid. + */ + public Object validate(String card) { + if (card == null || card.length() == 0) { + return null; + } + Object result = null; + for (CodeValidator cardType : cardTypes) { + result = cardType.validate(card); + if (result != null) { + return result; + } + } + return null; + + } + + // package protected for unit test access + static boolean validLength(int valueLength, CreditCardRange range) { + if (range.lengths != null) { + for(int length : range.lengths) { + if (valueLength == length) { + return true; + } + } + return false; + } + return valueLength >= range.minLen && valueLength <= range.maxLen; + } + + // package protected for unit test access + static CodeValidator createRangeValidator(final CreditCardRange[] creditCardRanges, final CheckDigit digitCheck ) { + return new CodeValidator( + // must be numeric (rest of validation is done later) + new RegexValidator("(\\d+)") { + private static final long serialVersionUID = 1L; + private CreditCardRange[] ccr = creditCardRanges.clone(); + @Override + // must return full string +// must return full string +public java.lang.String validate(java.lang.String value) { + { + int length = value.length(); + for (org.apache.commons.validator.routines.CreditCardValidator.CreditCardRange range : ccr) { + if (org.apache.commons.validator.routines.CreditCardValidator.validLength(length, range)) { + { + if ((range.low.compareTo(value) <= 0)// no need to trim value here + && // here we have to ignore digits beyond the prefix + (/* NPEX_NULL_EXP */ + range.high.compareTo(value.substring(0, range.high.length())) >= 0)) { + return value; + } + } + } + } + } + return null; +} + @Override + public boolean isValid(String value) { + return validate(value) != null; + } + @Override + public String[] match(String value) { + return new String[]{validate(value)}; + } + }, digitCheck); + } + + /** + * Tests whether the given flag is on. If the flag is not a power of 2 + * (ie. 3) this tests whether the combination of flags is on. + * + * @param options The options specified. + * @param flag Flag value to check. + * + * @return whether the specified flag value is on. + */ + private boolean isOn(long options, long flag) { + return (options & flag) > 0; + } + +} diff --git a/Java/commons-validator-CreditCardValidator_478/metadata.json b/Java/commons-validator-CreditCardValidator_478/metadata.json new file mode 100644 index 000000000..77c722a67 --- /dev/null +++ b/Java/commons-validator-CreditCardValidator_478/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-CreditCardValidator_478", + "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/validator/routines/CreditCardValidator.java", + "line": 483, + "npe_method": "validate", + "deref_field": "range.high", + "npe_class": "1", + "repo": "commons-validator", + "bug_id": "CreditCardValidator_478" + } +} diff --git a/Java/commons-validator-CreditCardValidator_478/npe.json b/Java/commons-validator-CreditCardValidator_478/npe.json new file mode 100644 index 000000000..135da25c7 --- /dev/null +++ b/Java/commons-validator-CreditCardValidator_478/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/CreditCardValidator.java", + "line": 483, + "npe_method": "validate", + "deref_field": "range.high", + "npe_class": "1" +} \ No newline at end of file diff --git a/Java/commons-validator-DomainValidator_163/Dockerfile b/Java/commons-validator-DomainValidator_163/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-DomainValidator_163/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-DomainValidator_163/buggy.java b/Java/commons-validator-DomainValidator_163/buggy.java new file mode 100644 index 000000000..a234cbd91 --- /dev/null +++ b/Java/commons-validator-DomainValidator_163/buggy.java @@ -0,0 +1,2126 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; +import java.net.IDN; +import java.util.Arrays; +import java.util.Locale; + +/** + *

Domain name validation routines.

+ * + *

+ * This validator provides methods for validating Internet domain names + * and top-level domains. + *

+ * + *

Domain names are evaluated according + * to the standards RFC1034, + * section 3, and RFC1123, + * section 2.1. No accommodation is provided for the specialized needs of + * other applications; if the domain name has been URL-encoded, for example, + * validation will fail even though the equivalent plaintext version of the + * same name would have passed. + *

+ * + *

+ * Validation is also provided for top-level domains (TLDs) as defined and + * maintained by the Internet Assigned Numbers Authority (IANA): + *

+ * + *
    + *
  • {@link #isValidInfrastructureTld} - validates infrastructure TLDs + * (.arpa, etc.)
  • + *
  • {@link #isValidGenericTld} - validates generic TLDs + * (.com, .org, etc.)
  • + *
  • {@link #isValidCountryCodeTld} - validates country code TLDs + * (.us, .uk, .cn, etc.)
  • + *
+ * + *

+ * (NOTE: This class does not provide IP address lookup for domain names or + * methods to ensure that a given domain name matches a specific IP; see + * {@link java.net.InetAddress} for that functionality.) + *

+ * + * @version $Revision$ + * @since Validator 1.4 + */ +public class DomainValidator implements Serializable { + + /** Maximum allowable length ({@value}) of a domain name */ + private static final int MAX_DOMAIN_LENGTH = 253; + + private static final String[] EMPTY_STRING_ARRAY = new String[0]; + + private static final long serialVersionUID = -4407125112880174009L; + + // Regular expression strings for hostnames (derived from RFC2396 and RFC 1123) + + // RFC2396: domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum + // Max 63 characters + private static final String DOMAIN_LABEL_REGEX = "\\p{Alnum}(?>[\\p{Alnum}-]{0,61}\\p{Alnum})?"; + + // RFC2396 toplabel = alpha | alpha *( alphanum | "-" ) alphanum + // Max 63 characters + private static final String TOP_LABEL_REGEX = "\\p{Alpha}(?>[\\p{Alnum}-]{0,61}\\p{Alnum})?"; + + // RFC2396 hostname = *( domainlabel "." ) toplabel [ "." ] + // Note that the regex currently requires both a domain label and a top level label, whereas + // the RFC does not. This is because the regex is used to detect if a TLD is present. + // If the match fails, input is checked against DOMAIN_LABEL_REGEX (hostnameRegex) + // RFC1123 sec 2.1 allows hostnames to start with a digit + private static final String DOMAIN_NAME_REGEX = + "^(?:" + DOMAIN_LABEL_REGEX + "\\.)+" + "(" + TOP_LABEL_REGEX + ")\\.?$"; + + private final boolean allowLocal; + + /** + * Singleton instance of this validator, which + * doesn't consider local addresses as valid. + */ + private static final DomainValidator DOMAIN_VALIDATOR = new DomainValidator(false); + + /** + * Singleton instance of this validator, which does + * consider local addresses valid. + */ + private static final DomainValidator DOMAIN_VALIDATOR_WITH_LOCAL = new DomainValidator(true); + + /** + * The above instances must only be returned via the getInstance() methods. + * This is to ensure that the override data arrays are properly protected. + */ + + /** + * RegexValidator for matching domains. + */ + private final RegexValidator domainRegex = + new RegexValidator(DOMAIN_NAME_REGEX); + /** + * RegexValidator for matching a local hostname + */ + // RFC1123 sec 2.1 allows hostnames to start with a digit + private final RegexValidator hostnameRegex = + new RegexValidator(DOMAIN_LABEL_REGEX); + + /** + * Returns the singleton instance of this validator. It + * will not consider local addresses as valid. + * @return the singleton instance of this validator + */ + public static synchronized DomainValidator getInstance() { + inUse = true; + return DOMAIN_VALIDATOR; + } + + /** + * Returns the singleton instance of this validator, + * with local validation as required. + * @param allowLocal Should local addresses be considered valid? + * @return the singleton instance of this validator + */ + public static synchronized DomainValidator getInstance(boolean allowLocal) { + inUse = true; + if(allowLocal) { + return DOMAIN_VALIDATOR_WITH_LOCAL; + } + return DOMAIN_VALIDATOR; + } + + /** + * Private constructor. + * This does not set the inUse flag - that is done by getInstance. + * This is to allow the static shared instances to be created. + */ + private DomainValidator(boolean allowLocal) { + this.allowLocal = allowLocal; + } + + /** + * Returns true if the specified String parses + * as a valid domain name with a recognized top-level domain. + * The parsing is case-insensitive. + * @param domain the parameter to check for domain name syntax + * @return true if the parameter is a valid domain name + */ +/** + * Returns true if the specified String parses + * as a valid domain name with a recognized top-level domain. + * The parsing is case-insensitive. + * + * @param domain + * the parameter to check for domain name syntax + * @return true if the parameter is a valid domain name + */ +public boolean isValid(java.lang.String domain) { + { + domain = org.apache.commons.validator.routines.DomainValidator.unicodeToASCII(/* NPEX_NULL_EXP */ + domain); + // hosts must be equally reachable via punycode and Unicode + // Unicode is never shorter than punycode, so check punycode + // if domain did not convert, then it will be caught by ASCII + // checks in the regexes below + if (domain.length() > org.apache.commons.validator.routines.DomainValidator.MAX_DOMAIN_LENGTH) { + return false; + } + java.lang.String[] groups = domainRegex.match(domain); + if ((groups != null) && (groups.length > 0)) { + return isValidTld(groups[0]); + } + return allowLocal && hostnameRegex.isValid(domain); + } +} + + // package protected for unit test access + // must agree with isValid() above + final boolean isValidDomainSyntax(String domain) { + if (domain == null) { + return false; + } + domain = unicodeToASCII(domain); + // hosts must be equally reachable via punycode and Unicode + // Unicode is never shorter than punycode, so check punycode + // if domain did not convert, then it will be caught by ASCII + // checks in the regexes below + if (domain.length() > MAX_DOMAIN_LENGTH) { + return false; + } + String[] groups = domainRegex.match(domain); + return (groups != null && groups.length > 0) + || hostnameRegex.isValid(domain); + } + + /** + * Returns true if the specified String matches any + * IANA-defined top-level domain. Leading dots are ignored if present. + * The search is case-insensitive. + *

+ * If allowLocal is true, the TLD is checked using {@link #isValidLocalTld(String)}. + * The TLD is then checked against {@link #isValidInfrastructureTld(String)}, + * {@link #isValidGenericTld(String)} and {@link #isValidCountryCodeTld(String)} + * @param tld the parameter to check for TLD status, not null + * @return true if the parameter is a TLD + */ + public boolean isValidTld(String tld) { + if(allowLocal && isValidLocalTld(tld)) { + return true; + } + return isValidInfrastructureTld(tld) + || isValidGenericTld(tld) + || isValidCountryCodeTld(tld); + } + + /** + * Returns true if the specified String matches any + * IANA-defined infrastructure top-level domain. Leading dots are + * ignored if present. The search is case-insensitive. + * @param iTld the parameter to check for infrastructure TLD status, not null + * @return true if the parameter is an infrastructure TLD + */ + public boolean isValidInfrastructureTld(String iTld) { + final String key = chompLeadingDot(unicodeToASCII(iTld).toLowerCase(Locale.ENGLISH)); + return arrayContains(INFRASTRUCTURE_TLDS, key); + } + + /** + * Returns true if the specified String matches any + * IANA-defined generic top-level domain. Leading dots are ignored + * if present. The search is case-insensitive. + * @param gTld the parameter to check for generic TLD status, not null + * @return true if the parameter is a generic TLD + */ + public boolean isValidGenericTld(String gTld) { + final String key = chompLeadingDot(unicodeToASCII(gTld).toLowerCase(Locale.ENGLISH)); + return (arrayContains(GENERIC_TLDS, key) || arrayContains(genericTLDsPlus, key)) + && !arrayContains(genericTLDsMinus, key); + } + + /** + * Returns true if the specified String matches any + * IANA-defined country code top-level domain. Leading dots are + * ignored if present. The search is case-insensitive. + * @param ccTld the parameter to check for country code TLD status, not null + * @return true if the parameter is a country code TLD + */ + public boolean isValidCountryCodeTld(String ccTld) { + final String key = chompLeadingDot(unicodeToASCII(ccTld).toLowerCase(Locale.ENGLISH)); + return (arrayContains(COUNTRY_CODE_TLDS, key) || arrayContains(countryCodeTLDsPlus, key)) + && !arrayContains(countryCodeTLDsMinus, key); + } + + /** + * Returns true if the specified String matches any + * widely used "local" domains (localhost or localdomain). Leading dots are + * ignored if present. The search is case-insensitive. + * @param lTld the parameter to check for local TLD status, not null + * @return true if the parameter is an local TLD + */ + public boolean isValidLocalTld(String lTld) { + final String key = chompLeadingDot(unicodeToASCII(lTld).toLowerCase(Locale.ENGLISH)); + return arrayContains(LOCAL_TLDS, key); + } + + private String chompLeadingDot(String str) { + if (str.startsWith(".")) { + return str.substring(1); + } + return str; + } + + // --------------------------------------------- + // ----- TLDs defined by IANA + // ----- Authoritative and comprehensive list at: + // ----- http://data.iana.org/TLD/tlds-alpha-by-domain.txt + + // Note that the above list is in UPPER case. + // The code currently converts strings to lower case (as per the tables below) + + // IANA also provide an HTML list at http://www.iana.org/domains/root/db + // Note that this contains several country code entries which are NOT in + // the text file. These all have the "Not assigned" in the "Sponsoring Organisation" column + // For example (as of 2015-01-02): + // .bl country-code Not assigned + // .um country-code Not assigned + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static final String[] INFRASTRUCTURE_TLDS = new String[] { + "arpa", // internet infrastructure + }; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static final String[] GENERIC_TLDS = new String[] { + // Taken from Version 2020062100, Last Updated Sun Jun 21 07:07:01 2020 UTC + "aaa", // aaa American Automobile Association, Inc. + "aarp", // aarp AARP + "abarth", // abarth Fiat Chrysler Automobiles N.V. + "abb", // abb ABB Ltd + "abbott", // abbott Abbott Laboratories, Inc. + "abbvie", // abbvie AbbVie Inc. + "abc", // abc Disney Enterprises, Inc. + "able", // able Able Inc. + "abogado", // abogado Top Level Domain Holdings Limited + "abudhabi", // abudhabi Abu Dhabi Systems and Information Centre + "academy", // academy Half Oaks, LLC + "accenture", // accenture Accenture plc + "accountant", // accountant dot Accountant Limited + "accountants", // accountants Knob Town, LLC + "aco", // aco ACO Severin Ahlmann GmbH & Co. KG +// "active", // active The Active Network, Inc + "actor", // actor United TLD Holdco Ltd. + "adac", // adac Allgemeiner Deutscher Automobil-Club e.V. (ADAC) + "ads", // ads Charleston Road Registry Inc. + "adult", // adult ICM Registry AD LLC + "aeg", // aeg Aktiebolaget Electrolux + "aero", // aero Societe Internationale de Telecommunications Aeronautique (SITA INC USA) + "aetna", // aetna Aetna Life Insurance Company + "afamilycompany", // afamilycompany Johnson Shareholdings, Inc. + "afl", // afl Australian Football League + "africa", // africa ZA Central Registry NPC trading as Registry.Africa + "agakhan", // agakhan Fondation Aga Khan (Aga Khan Foundation) + "agency", // agency Steel Falls, LLC + "aig", // aig American International Group, Inc. + "aigo", // aigo aigo Digital Technology Co,Ltd. + "airbus", // airbus Airbus S.A.S. + "airforce", // airforce United TLD Holdco Ltd. + "airtel", // airtel Bharti Airtel Limited + "akdn", // akdn Fondation Aga Khan (Aga Khan Foundation) + "alfaromeo", // alfaromeo Fiat Chrysler Automobiles N.V. + "alibaba", // alibaba Alibaba Group Holding Limited + "alipay", // alipay Alibaba Group Holding Limited + "allfinanz", // allfinanz Allfinanz Deutsche Vermögensberatung Aktiengesellschaft + "allstate", // allstate Allstate Fire and Casualty Insurance Company + "ally", // ally Ally Financial Inc. + "alsace", // alsace REGION D ALSACE + "alstom", // alstom ALSTOM + "amazon", // amazon Amazon Registry Services, Inc. + "americanexpress", // americanexpress American Express Travel Related Services Company, Inc. + "americanfamily", // americanfamily AmFam, Inc. + "amex", // amex American Express Travel Related Services Company, Inc. + "amfam", // amfam AmFam, Inc. + "amica", // amica Amica Mutual Insurance Company + "amsterdam", // amsterdam Gemeente Amsterdam + "analytics", // analytics Campus IP LLC + "android", // android Charleston Road Registry Inc. + "anquan", // anquan QIHOO 360 TECHNOLOGY CO. LTD. + "anz", // anz Australia and New Zealand Banking Group Limited + "aol", // aol AOL Inc. + "apartments", // apartments June Maple, LLC + "app", // app Charleston Road Registry Inc. + "apple", // apple Apple Inc. + "aquarelle", // aquarelle Aquarelle.com + "arab", // arab League of Arab States + "aramco", // aramco Aramco Services Company + "archi", // archi STARTING DOT LIMITED + "army", // army United TLD Holdco Ltd. + "art", // art UK Creative Ideas Limited + "arte", // arte Association Relative à la Télévision Européenne G.E.I.E. + "asda", // asda Wal-Mart Stores, Inc. + "asia", // asia DotAsia Organisation Ltd. + "associates", // associates Baxter Hill, LLC + "athleta", // athleta The Gap, Inc. + "attorney", // attorney United TLD Holdco, Ltd + "auction", // auction United TLD HoldCo, Ltd. + "audi", // audi AUDI Aktiengesellschaft + "audible", // audible Amazon Registry Services, Inc. + "audio", // audio Uniregistry, Corp. + "auspost", // auspost Australian Postal Corporation + "author", // author Amazon Registry Services, Inc. + "auto", // auto Uniregistry, Corp. + "autos", // autos DERAutos, LLC + "avianca", // avianca Aerovias del Continente Americano S.A. Avianca + "aws", // aws Amazon Registry Services, Inc. + "axa", // axa AXA SA + "azure", // azure Microsoft Corporation + "baby", // baby Johnson & Johnson Services, Inc. + "baidu", // baidu Baidu, Inc. + "banamex", // banamex Citigroup Inc. + "bananarepublic", // bananarepublic The Gap, Inc. + "band", // band United TLD Holdco, Ltd + "bank", // bank fTLD Registry Services, LLC + "bar", // bar Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable + "barcelona", // barcelona Municipi de Barcelona + "barclaycard", // barclaycard Barclays Bank PLC + "barclays", // barclays Barclays Bank PLC + "barefoot", // barefoot Gallo Vineyards, Inc. + "bargains", // bargains Half Hallow, LLC + "baseball", // baseball MLB Advanced Media DH, LLC + "basketball", // basketball Fédération Internationale de Basketball (FIBA) + "bauhaus", // bauhaus Werkhaus GmbH + "bayern", // bayern Bayern Connect GmbH + "bbc", // bbc British Broadcasting Corporation + "bbt", // bbt BB&T Corporation + "bbva", // bbva BANCO BILBAO VIZCAYA ARGENTARIA, S.A. + "bcg", // bcg The Boston Consulting Group, Inc. + "bcn", // bcn Municipi de Barcelona + "beats", // beats Beats Electronics, LLC + "beauty", // beauty L'Oréal + "beer", // beer Top Level Domain Holdings Limited + "bentley", // bentley Bentley Motors Limited + "berlin", // berlin dotBERLIN GmbH & Co. KG + "best", // best BestTLD Pty Ltd + "bestbuy", // bestbuy BBY Solutions, Inc. + "bet", // bet Afilias plc + "bharti", // bharti Bharti Enterprises (Holding) Private Limited + "bible", // bible American Bible Society + "bid", // bid dot Bid Limited + "bike", // bike Grand Hollow, LLC + "bing", // bing Microsoft Corporation + "bingo", // bingo Sand Cedar, LLC + "bio", // bio STARTING DOT LIMITED + "biz", // biz Neustar, Inc. + "black", // black Afilias Limited + "blackfriday", // blackfriday Uniregistry, Corp. +// "blanco", // blanco BLANCO GmbH + Co KG + "blockbuster", // blockbuster Dish DBS Corporation + "blog", // blog Knock Knock WHOIS There, LLC + "bloomberg", // bloomberg Bloomberg IP Holdings LLC + "blue", // blue Afilias Limited + "bms", // bms Bristol-Myers Squibb Company + "bmw", // bmw Bayerische Motoren Werke Aktiengesellschaft +// "bnl", // bnl Banca Nazionale del Lavoro + "bnpparibas", // bnpparibas BNP Paribas + "boats", // boats DERBoats, LLC + "boehringer", // boehringer Boehringer Ingelheim International GmbH + "bofa", // bofa NMS Services, Inc. + "bom", // bom Núcleo de Informação e Coordenação do Ponto BR - NIC.br + "bond", // bond Bond University Limited + "boo", // boo Charleston Road Registry Inc. + "book", // book Amazon Registry Services, Inc. + "booking", // booking Booking.com B.V. +// "boots", // boots THE BOOTS COMPANY PLC + "bosch", // bosch Robert Bosch GMBH + "bostik", // bostik Bostik SA + "boston", // boston Boston TLD Management, LLC + "bot", // bot Amazon Registry Services, Inc. + "boutique", // boutique Over Galley, LLC + "box", // box NS1 Limited + "bradesco", // bradesco Banco Bradesco S.A. + "bridgestone", // bridgestone Bridgestone Corporation + "broadway", // broadway Celebrate Broadway, Inc. + "broker", // broker DOTBROKER REGISTRY LTD + "brother", // brother Brother Industries, Ltd. + "brussels", // brussels DNS.be vzw + "budapest", // budapest Top Level Domain Holdings Limited + "bugatti", // bugatti Bugatti International SA + "build", // build Plan Bee LLC + "builders", // builders Atomic Madison, LLC + "business", // business Spring Cross, LLC + "buy", // buy Amazon Registry Services, INC + "buzz", // buzz DOTSTRATEGY CO. + "bzh", // bzh Association www.bzh + "cab", // cab Half Sunset, LLC + "cafe", // cafe Pioneer Canyon, LLC + "cal", // cal Charleston Road Registry Inc. + "call", // call Amazon Registry Services, Inc. + "calvinklein", // calvinklein PVH gTLD Holdings LLC + "cam", // cam AC Webconnecting Holding B.V. + "camera", // camera Atomic Maple, LLC + "camp", // camp Delta Dynamite, LLC + "cancerresearch", // cancerresearch Australian Cancer Research Foundation + "canon", // canon Canon Inc. + "capetown", // capetown ZA Central Registry NPC trading as ZA Central Registry + "capital", // capital Delta Mill, LLC + "capitalone", // capitalone Capital One Financial Corporation + "car", // car Cars Registry Limited + "caravan", // caravan Caravan International, Inc. + "cards", // cards Foggy Hollow, LLC + "care", // care Goose Cross, LLC + "career", // career dotCareer LLC + "careers", // careers Wild Corner, LLC + "cars", // cars Uniregistry, Corp. +// "cartier", // cartier Richemont DNS Inc. + "casa", // casa Top Level Domain Holdings Limited + "case", // case CNH Industrial N.V. + "caseih", // caseih CNH Industrial N.V. + "cash", // cash Delta Lake, LLC + "casino", // casino Binky Sky, LLC + "cat", // cat Fundacio puntCAT + "catering", // catering New Falls. LLC + "catholic", // catholic Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) + "cba", // cba COMMONWEALTH BANK OF AUSTRALIA + "cbn", // cbn The Christian Broadcasting Network, Inc. + "cbre", // cbre CBRE, Inc. + "cbs", // cbs CBS Domains Inc. + "ceb", // ceb The Corporate Executive Board Company + "center", // center Tin Mill, LLC + "ceo", // ceo CEOTLD Pty Ltd + "cern", // cern European Organization for Nuclear Research ("CERN") + "cfa", // cfa CFA Institute + "cfd", // cfd DOTCFD REGISTRY LTD + "chanel", // chanel Chanel International B.V. + "channel", // channel Charleston Road Registry Inc. + "charity", // charity Corn Lake, LLC + "chase", // chase JPMorgan Chase & Co. + "chat", // chat Sand Fields, LLC + "cheap", // cheap Sand Cover, LLC + "chintai", // chintai CHINTAI Corporation +// "chloe", // chloe Richemont DNS Inc. (Not assigned) + "christmas", // christmas Uniregistry, Corp. + "chrome", // chrome Charleston Road Registry Inc. +// "chrysler", // chrysler FCA US LLC. + "church", // church Holly Fileds, LLC + "cipriani", // cipriani Hotel Cipriani Srl + "circle", // circle Amazon Registry Services, Inc. + "cisco", // cisco Cisco Technology, Inc. + "citadel", // citadel Citadel Domain LLC + "citi", // citi Citigroup Inc. + "citic", // citic CITIC Group Corporation + "city", // city Snow Sky, LLC + "cityeats", // cityeats Lifestyle Domain Holdings, Inc. + "claims", // claims Black Corner, LLC + "cleaning", // cleaning Fox Shadow, LLC + "click", // click Uniregistry, Corp. + "clinic", // clinic Goose Park, LLC + "clinique", // clinique The Estée Lauder Companies Inc. + "clothing", // clothing Steel Lake, LLC + "cloud", // cloud ARUBA S.p.A. + "club", // club .CLUB DOMAINS, LLC + "clubmed", // clubmed Club Méditerranée S.A. + "coach", // coach Koko Island, LLC + "codes", // codes Puff Willow, LLC + "coffee", // coffee Trixy Cover, LLC + "college", // college XYZ.COM LLC + "cologne", // cologne NetCologne Gesellschaft für Telekommunikation mbH + "com", // com VeriSign Global Registry Services + "comcast", // comcast Comcast IP Holdings I, LLC + "commbank", // commbank COMMONWEALTH BANK OF AUSTRALIA + "community", // community Fox Orchard, LLC + "company", // company Silver Avenue, LLC + "compare", // compare iSelect Ltd + "computer", // computer Pine Mill, LLC + "comsec", // comsec VeriSign, Inc. + "condos", // condos Pine House, LLC + "construction", // construction Fox Dynamite, LLC + "consulting", // consulting United TLD Holdco, LTD. + "contact", // contact Top Level Spectrum, Inc. + "contractors", // contractors Magic Woods, LLC + "cooking", // cooking Top Level Domain Holdings Limited + "cookingchannel", // cookingchannel Lifestyle Domain Holdings, Inc. + "cool", // cool Koko Lake, LLC + "coop", // coop DotCooperation LLC + "corsica", // corsica Collectivité Territoriale de Corse + "country", // country Top Level Domain Holdings Limited + "coupon", // coupon Amazon Registry Services, Inc. + "coupons", // coupons Black Island, LLC + "courses", // courses OPEN UNIVERSITIES AUSTRALIA PTY LTD + "cpa", // cpa American Institute of Certified Public Accountants + "credit", // credit Snow Shadow, LLC + "creditcard", // creditcard Binky Frostbite, LLC + "creditunion", // creditunion CUNA Performance Resources, LLC + "cricket", // cricket dot Cricket Limited + "crown", // crown Crown Equipment Corporation + "crs", // crs Federated Co-operatives Limited + "cruise", // cruise Viking River Cruises (Bermuda) Ltd. + "cruises", // cruises Spring Way, LLC + "csc", // csc Alliance-One Services, Inc. + "cuisinella", // cuisinella SALM S.A.S. + "cymru", // cymru Nominet UK + "cyou", // cyou Beijing Gamease Age Digital Technology Co., Ltd. + "dabur", // dabur Dabur India Limited + "dad", // dad Charleston Road Registry Inc. + "dance", // dance United TLD Holdco Ltd. + "data", // data Dish DBS Corporation + "date", // date dot Date Limited + "dating", // dating Pine Fest, LLC + "datsun", // datsun NISSAN MOTOR CO., LTD. + "day", // day Charleston Road Registry Inc. + "dclk", // dclk Charleston Road Registry Inc. + "dds", // dds Minds + Machines Group Limited + "deal", // deal Amazon Registry Services, Inc. + "dealer", // dealer Dealer Dot Com, Inc. + "deals", // deals Sand Sunset, LLC + "degree", // degree United TLD Holdco, Ltd + "delivery", // delivery Steel Station, LLC + "dell", // dell Dell Inc. + "deloitte", // deloitte Deloitte Touche Tohmatsu + "delta", // delta Delta Air Lines, Inc. + "democrat", // democrat United TLD Holdco Ltd. + "dental", // dental Tin Birch, LLC + "dentist", // dentist United TLD Holdco, Ltd + "desi", // desi Desi Networks LLC + "design", // design Top Level Design, LLC + "dev", // dev Charleston Road Registry Inc. + "dhl", // dhl Deutsche Post AG + "diamonds", // diamonds John Edge, LLC + "diet", // diet Uniregistry, Corp. + "digital", // digital Dash Park, LLC + "direct", // direct Half Trail, LLC + "directory", // directory Extra Madison, LLC + "discount", // discount Holly Hill, LLC + "discover", // discover Discover Financial Services + "dish", // dish Dish DBS Corporation + "diy", // diy Lifestyle Domain Holdings, Inc. + "dnp", // dnp Dai Nippon Printing Co., Ltd. + "docs", // docs Charleston Road Registry Inc. + "doctor", // doctor Brice Trail, LLC +// "dodge", // dodge FCA US LLC. + "dog", // dog Koko Mill, LLC +// "doha", // doha Communications Regulatory Authority (CRA) + "domains", // domains Sugar Cross, LLC +// "doosan", // doosan Doosan Corporation (retired) + "dot", // dot Dish DBS Corporation + "download", // download dot Support Limited + "drive", // drive Charleston Road Registry Inc. + "dtv", // dtv Dish DBS Corporation + "dubai", // dubai Dubai Smart Government Department + "duck", // duck Johnson Shareholdings, Inc. + "dunlop", // dunlop The Goodyear Tire & Rubber Company +// "duns", // duns The Dun & Bradstreet Corporation + "dupont", // dupont E. I. du Pont de Nemours and Company + "durban", // durban ZA Central Registry NPC trading as ZA Central Registry + "dvag", // dvag Deutsche Vermögensberatung Aktiengesellschaft DVAG + "dvr", // dvr Hughes Satellite Systems Corporation + "earth", // earth Interlink Co., Ltd. + "eat", // eat Charleston Road Registry Inc. + "eco", // eco Big Room Inc. + "edeka", // edeka EDEKA Verband kaufmännischer Genossenschaften e.V. + "edu", // edu EDUCAUSE + "education", // education Brice Way, LLC + "email", // email Spring Madison, LLC + "emerck", // emerck Merck KGaA + "energy", // energy Binky Birch, LLC + "engineer", // engineer United TLD Holdco Ltd. + "engineering", // engineering Romeo Canyon + "enterprises", // enterprises Snow Oaks, LLC +// "epost", // epost Deutsche Post AG + "epson", // epson Seiko Epson Corporation + "equipment", // equipment Corn Station, LLC + "ericsson", // ericsson Telefonaktiebolaget L M Ericsson + "erni", // erni ERNI Group Holding AG + "esq", // esq Charleston Road Registry Inc. + "estate", // estate Trixy Park, LLC + // "esurance", // esurance Esurance Insurance Company (not assigned as at Version 2020062100) + "etisalat", // etisalat Emirates Telecommunic + "eurovision", // eurovision European Broadcasting Union (EBU) + "eus", // eus Puntueus Fundazioa + "events", // events Pioneer Maple, LLC +// "everbank", // everbank EverBank + "exchange", // exchange Spring Falls, LLC + "expert", // expert Magic Pass, LLC + "exposed", // exposed Victor Beach, LLC + "express", // express Sea Sunset, LLC + "extraspace", // extraspace Extra Space Storage LLC + "fage", // fage Fage International S.A. + "fail", // fail Atomic Pipe, LLC + "fairwinds", // fairwinds FairWinds Partners, LLC + "faith", // faith dot Faith Limited + "family", // family United TLD Holdco Ltd. + "fan", // fan Asiamix Digital Ltd + "fans", // fans Asiamix Digital Limited + "farm", // farm Just Maple, LLC + "farmers", // farmers Farmers Insurance Exchange + "fashion", // fashion Top Level Domain Holdings Limited + "fast", // fast Amazon Registry Services, Inc. + "fedex", // fedex Federal Express Corporation + "feedback", // feedback Top Level Spectrum, Inc. + "ferrari", // ferrari Fiat Chrysler Automobiles N.V. + "ferrero", // ferrero Ferrero Trading Lux S.A. + "fiat", // fiat Fiat Chrysler Automobiles N.V. + "fidelity", // fidelity Fidelity Brokerage Services LLC + "fido", // fido Rogers Communications Canada Inc. + "film", // film Motion Picture Domain Registry Pty Ltd + "final", // final Núcleo de Informação e Coordenação do Ponto BR - NIC.br + "finance", // finance Cotton Cypress, LLC + "financial", // financial Just Cover, LLC + "fire", // fire Amazon Registry Services, Inc. + "firestone", // firestone Bridgestone Corporation + "firmdale", // firmdale Firmdale Holdings Limited + "fish", // fish Fox Woods, LLC + "fishing", // fishing Top Level Domain Holdings Limited + "fit", // fit Minds + Machines Group Limited + "fitness", // fitness Brice Orchard, LLC + "flickr", // flickr Yahoo! Domain Services Inc. + "flights", // flights Fox Station, LLC + "flir", // flir FLIR Systems, Inc. + "florist", // florist Half Cypress, LLC + "flowers", // flowers Uniregistry, Corp. +// "flsmidth", // flsmidth FLSmidth A/S retired 2016-07-22 + "fly", // fly Charleston Road Registry Inc. + "foo", // foo Charleston Road Registry Inc. + "food", // food Lifestyle Domain Holdings, Inc. + "foodnetwork", // foodnetwork Lifestyle Domain Holdings, Inc. + "football", // football Foggy Farms, LLC + "ford", // ford Ford Motor Company + "forex", // forex DOTFOREX REGISTRY LTD + "forsale", // forsale United TLD Holdco, LLC + "forum", // forum Fegistry, LLC + "foundation", // foundation John Dale, LLC + "fox", // fox FOX Registry, LLC + "free", // free Amazon Registry Services, Inc. + "fresenius", // fresenius Fresenius Immobilien-Verwaltungs-GmbH + "frl", // frl FRLregistry B.V. + "frogans", // frogans OP3FT + "frontdoor", // frontdoor Lifestyle Domain Holdings, Inc. + "frontier", // frontier Frontier Communications Corporation + "ftr", // ftr Frontier Communications Corporation + "fujitsu", // fujitsu Fujitsu Limited + "fujixerox", // fujixerox Xerox DNHC LLC + "fun", // fun DotSpace, Inc. + "fund", // fund John Castle, LLC + "furniture", // furniture Lone Fields, LLC + "futbol", // futbol United TLD Holdco, Ltd. + "fyi", // fyi Silver Tigers, LLC + "gal", // gal Asociación puntoGAL + "gallery", // gallery Sugar House, LLC + "gallo", // gallo Gallo Vineyards, Inc. + "gallup", // gallup Gallup, Inc. + "game", // game Uniregistry, Corp. + "games", // games United TLD Holdco Ltd. + "gap", // gap The Gap, Inc. + "garden", // garden Top Level Domain Holdings Limited + "gay", // gay Top Level Design, LLC + "gbiz", // gbiz Charleston Road Registry Inc. + "gdn", // gdn Joint Stock Company "Navigation-information systems" + "gea", // gea GEA Group Aktiengesellschaft + "gent", // gent COMBELL GROUP NV/SA + "genting", // genting Resorts World Inc. Pte. Ltd. + "george", // george Wal-Mart Stores, Inc. + "ggee", // ggee GMO Internet, Inc. + "gift", // gift Uniregistry, Corp. + "gifts", // gifts Goose Sky, LLC + "gives", // gives United TLD Holdco Ltd. + "giving", // giving Giving Limited + "glade", // glade Johnson Shareholdings, Inc. + "glass", // glass Black Cover, LLC + "gle", // gle Charleston Road Registry Inc. + "global", // global Dot Global Domain Registry Limited + "globo", // globo Globo Comunicação e Participações S.A + "gmail", // gmail Charleston Road Registry Inc. + "gmbh", // gmbh Extra Dynamite, LLC + "gmo", // gmo GMO Internet, Inc. + "gmx", // gmx 1&1 Mail & Media GmbH + "godaddy", // godaddy Go Daddy East, LLC + "gold", // gold June Edge, LLC + "goldpoint", // goldpoint YODOBASHI CAMERA CO.,LTD. + "golf", // golf Lone Falls, LLC + "goo", // goo NTT Resonant Inc. +// "goodhands", // goodhands Allstate Fire and Casualty Insurance Company + "goodyear", // goodyear The Goodyear Tire & Rubber Company + "goog", // goog Charleston Road Registry Inc. + "google", // google Charleston Road Registry Inc. + "gop", // gop Republican State Leadership Committee, Inc. + "got", // got Amazon Registry Services, Inc. + "gov", // gov General Services Administration Attn: QTDC, 2E08 (.gov Domain Registration) + "grainger", // grainger Grainger Registry Services, LLC + "graphics", // graphics Over Madison, LLC + "gratis", // gratis Pioneer Tigers, LLC + "green", // green Afilias Limited + "gripe", // gripe Corn Sunset, LLC + "grocery", // grocery Wal-Mart Stores, Inc. + "group", // group Romeo Town, LLC + "guardian", // guardian The Guardian Life Insurance Company of America + "gucci", // gucci Guccio Gucci S.p.a. + "guge", // guge Charleston Road Registry Inc. + "guide", // guide Snow Moon, LLC + "guitars", // guitars Uniregistry, Corp. + "guru", // guru Pioneer Cypress, LLC + "hair", // hair L'Oreal + "hamburg", // hamburg Hamburg Top-Level-Domain GmbH + "hangout", // hangout Charleston Road Registry Inc. + "haus", // haus United TLD Holdco, LTD. + "hbo", // hbo HBO Registry Services, Inc. + "hdfc", // hdfc HOUSING DEVELOPMENT FINANCE CORPORATION LIMITED + "hdfcbank", // hdfcbank HDFC Bank Limited + "health", // health DotHealth, LLC + "healthcare", // healthcare Silver Glen, LLC + "help", // help Uniregistry, Corp. + "helsinki", // helsinki City of Helsinki + "here", // here Charleston Road Registry Inc. + "hermes", // hermes Hermes International + "hgtv", // hgtv Lifestyle Domain Holdings, Inc. + "hiphop", // hiphop Uniregistry, Corp. + "hisamitsu", // hisamitsu Hisamitsu Pharmaceutical Co.,Inc. + "hitachi", // hitachi Hitachi, Ltd. + "hiv", // hiv dotHIV gemeinnuetziger e.V. + "hkt", // hkt PCCW-HKT DataCom Services Limited + "hockey", // hockey Half Willow, LLC + "holdings", // holdings John Madison, LLC + "holiday", // holiday Goose Woods, LLC + "homedepot", // homedepot Homer TLC, Inc. + "homegoods", // homegoods The TJX Companies, Inc. + "homes", // homes DERHomes, LLC + "homesense", // homesense The TJX Companies, Inc. + "honda", // honda Honda Motor Co., Ltd. +// "honeywell", // honeywell Honeywell GTLD LLC + "horse", // horse Top Level Domain Holdings Limited + "hospital", // hospital Ruby Pike, LLC + "host", // host DotHost Inc. + "hosting", // hosting Uniregistry, Corp. + "hot", // hot Amazon Registry Services, Inc. + "hoteles", // hoteles Travel Reservations SRL + "hotels", // hotels Booking.com B.V. + "hotmail", // hotmail Microsoft Corporation + "house", // house Sugar Park, LLC + "how", // how Charleston Road Registry Inc. + "hsbc", // hsbc HSBC Holdings PLC +// "htc", // htc HTC corporation (Not assigned) + "hughes", // hughes Hughes Satellite Systems Corporation + "hyatt", // hyatt Hyatt GTLD, L.L.C. + "hyundai", // hyundai Hyundai Motor Company + "ibm", // ibm International Business Machines Corporation + "icbc", // icbc Industrial and Commercial Bank of China Limited + "ice", // ice IntercontinentalExchange, Inc. + "icu", // icu One.com A/S + "ieee", // ieee IEEE Global LLC + "ifm", // ifm ifm electronic gmbh +// "iinet", // iinet Connect West Pty. Ltd. (Retired) + "ikano", // ikano Ikano S.A. + "imamat", // imamat Fondation Aga Khan (Aga Khan Foundation) + "imdb", // imdb Amazon Registry Services, Inc. + "immo", // immo Auburn Bloom, LLC + "immobilien", // immobilien United TLD Holdco Ltd. + "inc", // inc Intercap Holdings Inc. + "industries", // industries Outer House, LLC + "infiniti", // infiniti NISSAN MOTOR CO., LTD. + "info", // info Afilias Limited + "ing", // ing Charleston Road Registry Inc. + "ink", // ink Top Level Design, LLC + "institute", // institute Outer Maple, LLC + "insurance", // insurance fTLD Registry Services LLC + "insure", // insure Pioneer Willow, LLC + "int", // int Internet Assigned Numbers Authority + "intel", // intel Intel Corporation + "international", // international Wild Way, LLC + "intuit", // intuit Intuit Administrative Services, Inc. + "investments", // investments Holly Glen, LLC + "ipiranga", // ipiranga Ipiranga Produtos de Petroleo S.A. + "irish", // irish Dot-Irish LLC +// "iselect", // iselect iSelect Ltd + "ismaili", // ismaili Fondation Aga Khan (Aga Khan Foundation) + "ist", // ist Istanbul Metropolitan Municipality + "istanbul", // istanbul Istanbul Metropolitan Municipality / Medya A.S. + "itau", // itau Itau Unibanco Holding S.A. + "itv", // itv ITV Services Limited + "iveco", // iveco CNH Industrial N.V. +// "iwc", // iwc Richemont DNS Inc. + "jaguar", // jaguar Jaguar Land Rover Ltd + "java", // java Oracle Corporation + "jcb", // jcb JCB Co., Ltd. + "jcp", // jcp JCP Media, Inc. + "jeep", // jeep FCA US LLC. + "jetzt", // jetzt New TLD Company AB + "jewelry", // jewelry Wild Bloom, LLC + "jio", // jio Affinity Names, Inc. +// "jlc", // jlc Richemont DNS Inc. + "jll", // jll Jones Lang LaSalle Incorporated + "jmp", // jmp Matrix IP LLC + "jnj", // jnj Johnson & Johnson Services, Inc. + "jobs", // jobs Employ Media LLC + "joburg", // joburg ZA Central Registry NPC trading as ZA Central Registry + "jot", // jot Amazon Registry Services, Inc. + "joy", // joy Amazon Registry Services, Inc. + "jpmorgan", // jpmorgan JPMorgan Chase & Co. + "jprs", // jprs Japan Registry Services Co., Ltd. + "juegos", // juegos Uniregistry, Corp. + "juniper", // juniper JUNIPER NETWORKS, INC. + "kaufen", // kaufen United TLD Holdco Ltd. + "kddi", // kddi KDDI CORPORATION + "kerryhotels", // kerryhotels Kerry Trading Co. Limited + "kerrylogistics", // kerrylogistics Kerry Trading Co. Limited + "kerryproperties", // kerryproperties Kerry Trading Co. Limited + "kfh", // kfh Kuwait Finance House + "kia", // kia KIA MOTORS CORPORATION + "kim", // kim Afilias Limited + "kinder", // kinder Ferrero Trading Lux S.A. + "kindle", // kindle Amazon Registry Services, Inc. + "kitchen", // kitchen Just Goodbye, LLC + "kiwi", // kiwi DOT KIWI LIMITED + "koeln", // koeln NetCologne Gesellschaft für Telekommunikation mbH + "komatsu", // komatsu Komatsu Ltd. + "kosher", // kosher Kosher Marketing Assets LLC + "kpmg", // kpmg KPMG International Cooperative (KPMG International Genossenschaft) + "kpn", // kpn Koninklijke KPN N.V. + "krd", // krd KRG Department of Information Technology + "kred", // kred KredTLD Pty Ltd + "kuokgroup", // kuokgroup Kerry Trading Co. Limited + "kyoto", // kyoto Academic Institution: Kyoto Jyoho Gakuen + "lacaixa", // lacaixa CAIXA D'ESTALVIS I PENSIONS DE BARCELONA +// "ladbrokes", // ladbrokes LADBROKES INTERNATIONAL PLC + "lamborghini", // lamborghini Automobili Lamborghini S.p.A. + "lamer", // lamer The Estée Lauder Companies Inc. + "lancaster", // lancaster LANCASTER + "lancia", // lancia Fiat Chrysler Automobiles N.V. +// "lancome", // lancome L'Oréal + "land", // land Pine Moon, LLC + "landrover", // landrover Jaguar Land Rover Ltd + "lanxess", // lanxess LANXESS Corporation + "lasalle", // lasalle Jones Lang LaSalle Incorporated + "lat", // lat ECOM-LAC Federación de Latinoamérica y el Caribe para Internet y el Comercio Electrónico + "latino", // latino Dish DBS Corporation + "latrobe", // latrobe La Trobe University + "law", // law Minds + Machines Group Limited + "lawyer", // lawyer United TLD Holdco, Ltd + "lds", // lds IRI Domain Management, LLC + "lease", // lease Victor Trail, LLC + "leclerc", // leclerc A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc + "lefrak", // lefrak LeFrak Organization, Inc. + "legal", // legal Blue Falls, LLC + "lego", // lego LEGO Juris A/S + "lexus", // lexus TOYOTA MOTOR CORPORATION + "lgbt", // lgbt Afilias Limited +// "liaison", // liaison Liaison Technologies, Incorporated + "lidl", // lidl Schwarz Domains und Services GmbH & Co. KG + "life", // life Trixy Oaks, LLC + "lifeinsurance", // lifeinsurance American Council of Life Insurers + "lifestyle", // lifestyle Lifestyle Domain Holdings, Inc. + "lighting", // lighting John McCook, LLC + "like", // like Amazon Registry Services, Inc. + "lilly", // lilly Eli Lilly and Company + "limited", // limited Big Fest, LLC + "limo", // limo Hidden Frostbite, LLC + "lincoln", // lincoln Ford Motor Company + "linde", // linde Linde Aktiengesellschaft + "link", // link Uniregistry, Corp. + "lipsy", // lipsy Lipsy Ltd + "live", // live United TLD Holdco Ltd. + "living", // living Lifestyle Domain Holdings, Inc. + "lixil", // lixil LIXIL Group Corporation + "llc", // llc Afilias plc + "llp", // llp Dot Registry LLC + "loan", // loan dot Loan Limited + "loans", // loans June Woods, LLC + "locker", // locker Dish DBS Corporation + "locus", // locus Locus Analytics LLC + "loft", // loft Annco, Inc. + "lol", // lol Uniregistry, Corp. + "london", // london Dot London Domains Limited + "lotte", // lotte Lotte Holdings Co., Ltd. + "lotto", // lotto Afilias Limited + "love", // love Merchant Law Group LLP + "lpl", // lpl LPL Holdings, Inc. + "lplfinancial", // lplfinancial LPL Holdings, Inc. + "ltd", // ltd Over Corner, LLC + "ltda", // ltda InterNetX Corp. + "lundbeck", // lundbeck H. Lundbeck A/S + "lupin", // lupin LUPIN LIMITED + "luxe", // luxe Top Level Domain Holdings Limited + "luxury", // luxury Luxury Partners LLC + "macys", // macys Macys, Inc. + "madrid", // madrid Comunidad de Madrid + "maif", // maif Mutuelle Assurance Instituteur France (MAIF) + "maison", // maison Victor Frostbite, LLC + "makeup", // makeup L'Oréal + "man", // man MAN SE + "management", // management John Goodbye, LLC + "mango", // mango PUNTO FA S.L. + "map", // map Charleston Road Registry Inc. + "market", // market Unitied TLD Holdco, Ltd + "marketing", // marketing Fern Pass, LLC + "markets", // markets DOTMARKETS REGISTRY LTD + "marriott", // marriott Marriott Worldwide Corporation + "marshalls", // marshalls The TJX Companies, Inc. + "maserati", // maserati Fiat Chrysler Automobiles N.V. + "mattel", // mattel Mattel Sites, Inc. + "mba", // mba Lone Hollow, LLC +// "mcd", // mcd McDonald’s Corporation (Not assigned) +// "mcdonalds", // mcdonalds McDonald’s Corporation (Not assigned) + "mckinsey", // mckinsey McKinsey Holdings, Inc. + "med", // med Medistry LLC + "media", // media Grand Glen, LLC + "meet", // meet Afilias Limited + "melbourne", // melbourne The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation + "meme", // meme Charleston Road Registry Inc. + "memorial", // memorial Dog Beach, LLC + "men", // men Exclusive Registry Limited + "menu", // menu Wedding TLD2, LLC +// "meo", // meo PT Comunicacoes S.A. + "merckmsd", // merckmsd MSD Registry Holdings, Inc. + "metlife", // metlife MetLife Services and Solutions, LLC + "miami", // miami Top Level Domain Holdings Limited + "microsoft", // microsoft Microsoft Corporation + "mil", // mil DoD Network Information Center + "mini", // mini Bayerische Motoren Werke Aktiengesellschaft + "mint", // mint Intuit Administrative Services, Inc. + "mit", // mit Massachusetts Institute of Technology + "mitsubishi", // mitsubishi Mitsubishi Corporation + "mlb", // mlb MLB Advanced Media DH, LLC + "mls", // mls The Canadian Real Estate Association + "mma", // mma MMA IARD + "mobi", // mobi Afilias Technologies Limited dba dotMobi + "mobile", // mobile Dish DBS Corporation +// "mobily", // mobily GreenTech Consultancy Company W.L.L. + "moda", // moda United TLD Holdco Ltd. + "moe", // moe Interlink Co., Ltd. + "moi", // moi Amazon Registry Services, Inc. + "mom", // mom Uniregistry, Corp. + "monash", // monash Monash University + "money", // money Outer McCook, LLC + "monster", // monster Monster Worldwide, Inc. +// "montblanc", // montblanc Richemont DNS Inc. (Not assigned) +// "mopar", // mopar FCA US LLC. + "mormon", // mormon IRI Domain Management, LLC ("Applicant") + "mortgage", // mortgage United TLD Holdco, Ltd + "moscow", // moscow Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) + "moto", // moto Motorola Trademark Holdings, LLC + "motorcycles", // motorcycles DERMotorcycles, LLC + "mov", // mov Charleston Road Registry Inc. + "movie", // movie New Frostbite, LLC +// "movistar", // movistar Telefónica S.A. + "msd", // msd MSD Registry Holdings, Inc. + "mtn", // mtn MTN Dubai Limited +// "mtpc", // mtpc Mitsubishi Tanabe Pharma Corporation (Retired) + "mtr", // mtr MTR Corporation Limited + "museum", // museum Museum Domain Management Association + "mutual", // mutual Northwestern Mutual MU TLD Registry, LLC +// "mutuelle", // mutuelle Fédération Nationale de la Mutualité Française (Retired) + "nab", // nab National Australia Bank Limited +// "nadex", // nadex Nadex Domains, Inc + "nagoya", // nagoya GMO Registry, Inc. + "name", // name VeriSign Information Services, Inc. + "nationwide", // nationwide Nationwide Mutual Insurance Company + "natura", // natura NATURA COSMÉTICOS S.A. + "navy", // navy United TLD Holdco Ltd. + "nba", // nba NBA REGISTRY, LLC + "nec", // nec NEC Corporation + "net", // net VeriSign Global Registry Services + "netbank", // netbank COMMONWEALTH BANK OF AUSTRALIA + "netflix", // netflix Netflix, Inc. + "network", // network Trixy Manor, LLC + "neustar", // neustar NeuStar, Inc. + "new", // new Charleston Road Registry Inc. + "newholland", // newholland CNH Industrial N.V. + "news", // news United TLD Holdco Ltd. + "next", // next Next plc + "nextdirect", // nextdirect Next plc + "nexus", // nexus Charleston Road Registry Inc. + "nfl", // nfl NFL Reg Ops LLC + "ngo", // ngo Public Interest Registry + "nhk", // nhk Japan Broadcasting Corporation (NHK) + "nico", // nico DWANGO Co., Ltd. + "nike", // nike NIKE, Inc. + "nikon", // nikon NIKON CORPORATION + "ninja", // ninja United TLD Holdco Ltd. + "nissan", // nissan NISSAN MOTOR CO., LTD. + "nissay", // nissay Nippon Life Insurance Company + "nokia", // nokia Nokia Corporation + "northwesternmutual", // northwesternmutual Northwestern Mutual Registry, LLC + "norton", // norton Symantec Corporation + "now", // now Amazon Registry Services, Inc. + "nowruz", // nowruz Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. + "nowtv", // nowtv Starbucks (HK) Limited + "nra", // nra NRA Holdings Company, INC. + "nrw", // nrw Minds + Machines GmbH + "ntt", // ntt NIPPON TELEGRAPH AND TELEPHONE CORPORATION + "nyc", // nyc The City of New York by and through the New York City Department of Information Technology & Telecommunications + "obi", // obi OBI Group Holding SE & Co. KGaA + "observer", // observer Top Level Spectrum, Inc. + "off", // off Johnson Shareholdings, Inc. + "office", // office Microsoft Corporation + "okinawa", // okinawa BusinessRalliart inc. + "olayan", // olayan Crescent Holding GmbH + "olayangroup", // olayangroup Crescent Holding GmbH + "oldnavy", // oldnavy The Gap, Inc. + "ollo", // ollo Dish DBS Corporation + "omega", // omega The Swatch Group Ltd + "one", // one One.com A/S + "ong", // ong Public Interest Registry + "onl", // onl I-REGISTRY Ltd., Niederlassung Deutschland + "online", // online DotOnline Inc. + "onyourside", // onyourside Nationwide Mutual Insurance Company + "ooo", // ooo INFIBEAM INCORPORATION LIMITED + "open", // open American Express Travel Related Services Company, Inc. + "oracle", // oracle Oracle Corporation + "orange", // orange Orange Brand Services Limited + "org", // org Public Interest Registry (PIR) + "organic", // organic Afilias Limited +// "orientexpress", // orientexpress Orient Express (retired 2017-04-11) + "origins", // origins The Estée Lauder Companies Inc. + "osaka", // osaka Interlink Co., Ltd. + "otsuka", // otsuka Otsuka Holdings Co., Ltd. + "ott", // ott Dish DBS Corporation + "ovh", // ovh OVH SAS + "page", // page Charleston Road Registry Inc. +// "pamperedchef", // pamperedchef The Pampered Chef, Ltd. (Not assigned) + "panasonic", // panasonic Panasonic Corporation +// "panerai", // panerai Richemont DNS Inc. + "paris", // paris City of Paris + "pars", // pars Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. + "partners", // partners Magic Glen, LLC + "parts", // parts Sea Goodbye, LLC + "party", // party Blue Sky Registry Limited + "passagens", // passagens Travel Reservations SRL + "pay", // pay Amazon Registry Services, Inc. + "pccw", // pccw PCCW Enterprises Limited + "pet", // pet Afilias plc + "pfizer", // pfizer Pfizer Inc. + "pharmacy", // pharmacy National Association of Boards of Pharmacy + "phd", // phd Charleston Road Registry Inc. + "philips", // philips Koninklijke Philips N.V. + "phone", // phone Dish DBS Corporation + "photo", // photo Uniregistry, Corp. + "photography", // photography Sugar Glen, LLC + "photos", // photos Sea Corner, LLC + "physio", // physio PhysBiz Pty Ltd +// "piaget", // piaget Richemont DNS Inc. + "pics", // pics Uniregistry, Corp. + "pictet", // pictet Pictet Europe S.A. + "pictures", // pictures Foggy Sky, LLC + "pid", // pid Top Level Spectrum, Inc. + "pin", // pin Amazon Registry Services, Inc. + "ping", // ping Ping Registry Provider, Inc. + "pink", // pink Afilias Limited + "pioneer", // pioneer Pioneer Corporation + "pizza", // pizza Foggy Moon, LLC + "place", // place Snow Galley, LLC + "play", // play Charleston Road Registry Inc. + "playstation", // playstation Sony Computer Entertainment Inc. + "plumbing", // plumbing Spring Tigers, LLC + "plus", // plus Sugar Mill, LLC + "pnc", // pnc PNC Domain Co., LLC + "pohl", // pohl Deutsche Vermögensberatung Aktiengesellschaft DVAG + "poker", // poker Afilias Domains No. 5 Limited + "politie", // politie Politie Nederland + "porn", // porn ICM Registry PN LLC + "post", // post Universal Postal Union + "pramerica", // pramerica Prudential Financial, Inc. + "praxi", // praxi Praxi S.p.A. + "press", // press DotPress Inc. + "prime", // prime Amazon Registry Services, Inc. + "pro", // pro Registry Services Corporation dba RegistryPro + "prod", // prod Charleston Road Registry Inc. + "productions", // productions Magic Birch, LLC + "prof", // prof Charleston Road Registry Inc. + "progressive", // progressive Progressive Casualty Insurance Company + "promo", // promo Afilias plc + "properties", // properties Big Pass, LLC + "property", // property Uniregistry, Corp. + "protection", // protection XYZ.COM LLC + "pru", // pru Prudential Financial, Inc. + "prudential", // prudential Prudential Financial, Inc. + "pub", // pub United TLD Holdco Ltd. + "pwc", // pwc PricewaterhouseCoopers LLP + "qpon", // qpon dotCOOL, Inc. + "quebec", // quebec PointQuébec Inc + "quest", // quest Quest ION Limited + "qvc", // qvc QVC, Inc. + "racing", // racing Premier Registry Limited + "radio", // radio European Broadcasting Union (EBU) + "raid", // raid Johnson Shareholdings, Inc. + "read", // read Amazon Registry Services, Inc. + "realestate", // realestate dotRealEstate LLC + "realtor", // realtor Real Estate Domains LLC + "realty", // realty Fegistry, LLC + "recipes", // recipes Grand Island, LLC + "red", // red Afilias Limited + "redstone", // redstone Redstone Haute Couture Co., Ltd. + "redumbrella", // redumbrella Travelers TLD, LLC + "rehab", // rehab United TLD Holdco Ltd. + "reise", // reise Foggy Way, LLC + "reisen", // reisen New Cypress, LLC + "reit", // reit National Association of Real Estate Investment Trusts, Inc. + "reliance", // reliance Reliance Industries Limited + "ren", // ren Beijing Qianxiang Wangjing Technology Development Co., Ltd. + "rent", // rent XYZ.COM LLC + "rentals", // rentals Big Hollow,LLC + "repair", // repair Lone Sunset, LLC + "report", // report Binky Glen, LLC + "republican", // republican United TLD Holdco Ltd. + "rest", // rest Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable + "restaurant", // restaurant Snow Avenue, LLC + "review", // review dot Review Limited + "reviews", // reviews United TLD Holdco, Ltd. + "rexroth", // rexroth Robert Bosch GMBH + "rich", // rich I-REGISTRY Ltd., Niederlassung Deutschland + "richardli", // richardli Pacific Century Asset Management (HK) Limited + "ricoh", // ricoh Ricoh Company, Ltd. + "rightathome", // rightathome Johnson Shareholdings, Inc. + "ril", // ril Reliance Industries Limited + "rio", // rio Empresa Municipal de Informática SA - IPLANRIO + "rip", // rip United TLD Holdco Ltd. + "rmit", // rmit Royal Melbourne Institute of Technology + "rocher", // rocher Ferrero Trading Lux S.A. + "rocks", // rocks United TLD Holdco, LTD. + "rodeo", // rodeo Top Level Domain Holdings Limited + "rogers", // rogers Rogers Communications Canada Inc. + "room", // room Amazon Registry Services, Inc. + "rsvp", // rsvp Charleston Road Registry Inc. + "rugby", // rugby World Rugby Strategic Developments Limited + "ruhr", // ruhr regiodot GmbH & Co. KG + "run", // run Snow Park, LLC + "rwe", // rwe RWE AG + "ryukyu", // ryukyu BusinessRalliart inc. + "saarland", // saarland dotSaarland GmbH + "safe", // safe Amazon Registry Services, Inc. + "safety", // safety Safety Registry Services, LLC. + "sakura", // sakura SAKURA Internet Inc. + "sale", // sale United TLD Holdco, Ltd + "salon", // salon Outer Orchard, LLC + "samsclub", // samsclub Wal-Mart Stores, Inc. + "samsung", // samsung SAMSUNG SDS CO., LTD + "sandvik", // sandvik Sandvik AB + "sandvikcoromant", // sandvikcoromant Sandvik AB + "sanofi", // sanofi Sanofi + "sap", // sap SAP AG +// "sapo", // sapo PT Comunicacoes S.A. + "sarl", // sarl Delta Orchard, LLC + "sas", // sas Research IP LLC + "save", // save Amazon Registry Services, Inc. + "saxo", // saxo Saxo Bank A/S + "sbi", // sbi STATE BANK OF INDIA + "sbs", // sbs SPECIAL BROADCASTING SERVICE CORPORATION + "sca", // sca SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ) + "scb", // scb The Siam Commercial Bank Public Company Limited ("SCB") + "schaeffler", // schaeffler Schaeffler Technologies AG & Co. KG + "schmidt", // schmidt SALM S.A.S. + "scholarships", // scholarships Scholarships.com, LLC + "school", // school Little Galley, LLC + "schule", // schule Outer Moon, LLC + "schwarz", // schwarz Schwarz Domains und Services GmbH & Co. KG + "science", // science dot Science Limited + "scjohnson", // scjohnson Johnson Shareholdings, Inc. + // "scor", // scor SCOR SE (not assigned as at Version 2020062100) + "scot", // scot Dot Scot Registry Limited + "search", // search Charleston Road Registry Inc. + "seat", // seat SEAT, S.A. (Sociedad Unipersonal) + "secure", // secure Amazon Registry Services, Inc. + "security", // security XYZ.COM LLC + "seek", // seek Seek Limited + "select", // select iSelect Ltd + "sener", // sener Sener Ingeniería y Sistemas, S.A. + "services", // services Fox Castle, LLC + "ses", // ses SES + "seven", // seven Seven West Media Ltd + "sew", // sew SEW-EURODRIVE GmbH & Co KG + "sex", // sex ICM Registry SX LLC + "sexy", // sexy Uniregistry, Corp. + "sfr", // sfr Societe Francaise du Radiotelephone - SFR + "shangrila", // shangrila Shangri‐La International Hotel Management Limited + "sharp", // sharp Sharp Corporation + "shaw", // shaw Shaw Cablesystems G.P. + "shell", // shell Shell Information Technology International Inc + "shia", // shia Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. + "shiksha", // shiksha Afilias Limited + "shoes", // shoes Binky Galley, LLC + "shop", // shop GMO Registry, Inc. + "shopping", // shopping Over Keep, LLC + "shouji", // shouji QIHOO 360 TECHNOLOGY CO. LTD. + "show", // show Snow Beach, LLC + "showtime", // showtime CBS Domains Inc. + "shriram", // shriram Shriram Capital Ltd. + "silk", // silk Amazon Registry Services, Inc. + "sina", // sina Sina Corporation + "singles", // singles Fern Madison, LLC + "site", // site DotSite Inc. + "ski", // ski STARTING DOT LIMITED + "skin", // skin L'Oréal + "sky", // sky Sky International AG + "skype", // skype Microsoft Corporation + "sling", // sling Hughes Satellite Systems Corporation + "smart", // smart Smart Communications, Inc. (SMART) + "smile", // smile Amazon Registry Services, Inc. + "sncf", // sncf SNCF (Société Nationale des Chemins de fer Francais) + "soccer", // soccer Foggy Shadow, LLC + "social", // social United TLD Holdco Ltd. + "softbank", // softbank SoftBank Group Corp. + "software", // software United TLD Holdco, Ltd + "sohu", // sohu Sohu.com Limited + "solar", // solar Ruby Town, LLC + "solutions", // solutions Silver Cover, LLC + "song", // song Amazon Registry Services, Inc. + "sony", // sony Sony Corporation + "soy", // soy Charleston Road Registry Inc. + "space", // space DotSpace Inc. +// "spiegel", // spiegel SPIEGEL-Verlag Rudolf Augstein GmbH & Co. KG + "sport", // sport Global Association of International Sports Federations (GAISF) + "spot", // spot Amazon Registry Services, Inc. + "spreadbetting", // spreadbetting DOTSPREADBETTING REGISTRY LTD + "srl", // srl InterNetX Corp. +// "srt", // srt FCA US LLC. + "stada", // stada STADA Arzneimittel AG + "staples", // staples Staples, Inc. + "star", // star Star India Private Limited +// "starhub", // starhub StarHub Limited + "statebank", // statebank STATE BANK OF INDIA + "statefarm", // statefarm State Farm Mutual Automobile Insurance Company +// "statoil", // statoil Statoil ASA + "stc", // stc Saudi Telecom Company + "stcgroup", // stcgroup Saudi Telecom Company + "stockholm", // stockholm Stockholms kommun + "storage", // storage Self Storage Company LLC + "store", // store DotStore Inc. + "stream", // stream dot Stream Limited + "studio", // studio United TLD Holdco Ltd. + "study", // study OPEN UNIVERSITIES AUSTRALIA PTY LTD + "style", // style Binky Moon, LLC + "sucks", // sucks Vox Populi Registry Ltd. + "supplies", // supplies Atomic Fields, LLC + "supply", // supply Half Falls, LLC + "support", // support Grand Orchard, LLC + "surf", // surf Top Level Domain Holdings Limited + "surgery", // surgery Tin Avenue, LLC + "suzuki", // suzuki SUZUKI MOTOR CORPORATION + "swatch", // swatch The Swatch Group Ltd + "swiftcover", // swiftcover Swiftcover Insurance Services Limited + "swiss", // swiss Swiss Confederation + "sydney", // sydney State of New South Wales, Department of Premier and Cabinet + "symantec", // symantec Symantec Corporation + "systems", // systems Dash Cypress, LLC + "tab", // tab Tabcorp Holdings Limited + "taipei", // taipei Taipei City Government + "talk", // talk Amazon Registry Services, Inc. + "taobao", // taobao Alibaba Group Holding Limited + "target", // target Target Domain Holdings, LLC + "tatamotors", // tatamotors Tata Motors Ltd + "tatar", // tatar LLC "Coordination Center of Regional Domain of Tatarstan Republic" + "tattoo", // tattoo Uniregistry, Corp. + "tax", // tax Storm Orchard, LLC + "taxi", // taxi Pine Falls, LLC + "tci", // tci Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. + "tdk", // tdk TDK Corporation + "team", // team Atomic Lake, LLC + "tech", // tech Dot Tech LLC + "technology", // technology Auburn Falls, LLC + "tel", // tel Telnic Ltd. +// "telecity", // telecity TelecityGroup International Limited +// "telefonica", // telefonica Telefónica S.A. + "temasek", // temasek Temasek Holdings (Private) Limited + "tennis", // tennis Cotton Bloom, LLC + "teva", // teva Teva Pharmaceutical Industries Limited + "thd", // thd Homer TLC, Inc. + "theater", // theater Blue Tigers, LLC + "theatre", // theatre XYZ.COM LLC + "tiaa", // tiaa Teachers Insurance and Annuity Association of America + "tickets", // tickets Accent Media Limited + "tienda", // tienda Victor Manor, LLC + "tiffany", // tiffany Tiffany and Company + "tips", // tips Corn Willow, LLC + "tires", // tires Dog Edge, LLC + "tirol", // tirol punkt Tirol GmbH + "tjmaxx", // tjmaxx The TJX Companies, Inc. + "tjx", // tjx The TJX Companies, Inc. + "tkmaxx", // tkmaxx The TJX Companies, Inc. + "tmall", // tmall Alibaba Group Holding Limited + "today", // today Pearl Woods, LLC + "tokyo", // tokyo GMO Registry, Inc. + "tools", // tools Pioneer North, LLC + "top", // top Jiangsu Bangning Science & Technology Co.,Ltd. + "toray", // toray Toray Industries, Inc. + "toshiba", // toshiba TOSHIBA Corporation + "total", // total Total SA + "tours", // tours Sugar Station, LLC + "town", // town Koko Moon, LLC + "toyota", // toyota TOYOTA MOTOR CORPORATION + "toys", // toys Pioneer Orchard, LLC + "trade", // trade Elite Registry Limited + "trading", // trading DOTTRADING REGISTRY LTD + "training", // training Wild Willow, LLC + "travel", // travel Tralliance Registry Management Company, LLC. + "travelchannel", // travelchannel Lifestyle Domain Holdings, Inc. + "travelers", // travelers Travelers TLD, LLC + "travelersinsurance", // travelersinsurance Travelers TLD, LLC + "trust", // trust Artemis Internet Inc + "trv", // trv Travelers TLD, LLC + "tube", // tube Latin American Telecom LLC + "tui", // tui TUI AG + "tunes", // tunes Amazon Registry Services, Inc. + "tushu", // tushu Amazon Registry Services, Inc. + "tvs", // tvs T V SUNDRAM IYENGAR & SONS PRIVATE LIMITED + "ubank", // ubank National Australia Bank Limited + "ubs", // ubs UBS AG +// "uconnect", // uconnect FCA US LLC. + "unicom", // unicom China United Network Communications Corporation Limited + "university", // university Little Station, LLC + "uno", // uno Dot Latin LLC + "uol", // uol UBN INTERNET LTDA. + "ups", // ups UPS Market Driver, Inc. + "vacations", // vacations Atomic Tigers, LLC + "vana", // vana Lifestyle Domain Holdings, Inc. + "vanguard", // vanguard The Vanguard Group, Inc. + "vegas", // vegas Dot Vegas, Inc. + "ventures", // ventures Binky Lake, LLC + "verisign", // verisign VeriSign, Inc. + "versicherung", // versicherung dotversicherung-registry GmbH + "vet", // vet United TLD Holdco, Ltd + "viajes", // viajes Black Madison, LLC + "video", // video United TLD Holdco, Ltd + "vig", // vig VIENNA INSURANCE GROUP AG Wiener Versicherung Gruppe + "viking", // viking Viking River Cruises (Bermuda) Ltd. + "villas", // villas New Sky, LLC + "vin", // vin Holly Shadow, LLC + "vip", // vip Minds + Machines Group Limited + "virgin", // virgin Virgin Enterprises Limited + "visa", // visa Visa Worldwide Pte. Limited + "vision", // vision Koko Station, LLC +// "vista", // vista Vistaprint Limited +// "vistaprint", // vistaprint Vistaprint Limited + "viva", // viva Saudi Telecom Company + "vivo", // vivo Telefonica Brasil S.A. + "vlaanderen", // vlaanderen DNS.be vzw + "vodka", // vodka Top Level Domain Holdings Limited + "volkswagen", // volkswagen Volkswagen Group of America Inc. + "volvo", // volvo Volvo Holding Sverige Aktiebolag + "vote", // vote Monolith Registry LLC + "voting", // voting Valuetainment Corp. + "voto", // voto Monolith Registry LLC + "voyage", // voyage Ruby House, LLC + "vuelos", // vuelos Travel Reservations SRL + "wales", // wales Nominet UK + "walmart", // walmart Wal-Mart Stores, Inc. + "walter", // walter Sandvik AB + "wang", // wang Zodiac Registry Limited + "wanggou", // wanggou Amazon Registry Services, Inc. +// "warman", // warman Weir Group IP Limited + "watch", // watch Sand Shadow, LLC + "watches", // watches Richemont DNS Inc. + "weather", // weather The Weather Channel, LLC + "weatherchannel", // weatherchannel The Weather Channel, LLC + "webcam", // webcam dot Webcam Limited + "weber", // weber Saint-Gobain Weber SA + "website", // website DotWebsite Inc. + "wed", // wed Atgron, Inc. + "wedding", // wedding Top Level Domain Holdings Limited + "weibo", // weibo Sina Corporation + "weir", // weir Weir Group IP Limited + "whoswho", // whoswho Who's Who Registry + "wien", // wien punkt.wien GmbH + "wiki", // wiki Top Level Design, LLC + "williamhill", // williamhill William Hill Organization Limited + "win", // win First Registry Limited + "windows", // windows Microsoft Corporation + "wine", // wine June Station, LLC + "winners", // winners The TJX Companies, Inc. + "wme", // wme William Morris Endeavor Entertainment, LLC + "wolterskluwer", // wolterskluwer Wolters Kluwer N.V. + "woodside", // woodside Woodside Petroleum Limited + "work", // work Top Level Domain Holdings Limited + "works", // works Little Dynamite, LLC + "world", // world Bitter Fields, LLC + "wow", // wow Amazon Registry Services, Inc. + "wtc", // wtc World Trade Centers Association, Inc. + "wtf", // wtf Hidden Way, LLC + "xbox", // xbox Microsoft Corporation + "xerox", // xerox Xerox DNHC LLC + "xfinity", // xfinity Comcast IP Holdings I, LLC + "xihuan", // xihuan QIHOO 360 TECHNOLOGY CO. LTD. + "xin", // xin Elegant Leader Limited + "xn--11b4c3d", // कॉम VeriSign Sarl + "xn--1ck2e1b", // セール Amazon Registry Services, Inc. + "xn--1qqw23a", // 佛山 Guangzhou YU Wei Information Technology Co., Ltd. + "xn--30rr7y", // 慈善 Excellent First Limited + "xn--3bst00m", // 集团 Eagle Horizon Limited + "xn--3ds443g", // 在线 TLD REGISTRY LIMITED + "xn--3oq18vl8pn36a", // 大众汽车 Volkswagen (China) Investment Co., Ltd. + "xn--3pxu8k", // 点看 VeriSign Sarl + "xn--42c2d9a", // คอม VeriSign Sarl + "xn--45q11c", // 八卦 Zodiac Scorpio Limited + "xn--4gbrim", // موقع Suhub Electronic Establishment + "xn--55qw42g", // 公益 China Organizational Name Administration Center + "xn--55qx5d", // 公司 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) + "xn--5su34j936bgsg", // 香格里拉 Shangri‐La International Hotel Management Limited + "xn--5tzm5g", // 网站 Global Website TLD Asia Limited + "xn--6frz82g", // 移动 Afilias Limited + "xn--6qq986b3xl", // 我爱你 Tycoon Treasure Limited + "xn--80adxhks", // москва Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) + "xn--80aqecdr1a", // католик Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) + "xn--80asehdb", // онлайн CORE Association + "xn--80aswg", // сайт CORE Association + "xn--8y0a063a", // 联通 China United Network Communications Corporation Limited + "xn--90ae", // бг Imena.BG Plc (NAMES.BG Plc) + "xn--9dbq2a", // קום VeriSign Sarl + "xn--9et52u", // 时尚 RISE VICTORY LIMITED + "xn--9krt00a", // 微博 Sina Corporation + "xn--b4w605ferd", // 淡马锡 Temasek Holdings (Private) Limited + "xn--bck1b9a5dre4c", // ファッション Amazon Registry Services, Inc. + "xn--c1avg", // орг Public Interest Registry + "xn--c2br7g", // नेट VeriSign Sarl + "xn--cck2b3b", // ストア Amazon Registry Services, Inc. + "xn--cckwcxetd", // アマゾン Amazon Registry Services, Inc. + "xn--cg4bki", // 삼성 SAMSUNG SDS CO., LTD + "xn--czr694b", // 商标 HU YI GLOBAL INFORMATION RESOURCES(HOLDING) COMPANY.HONGKONG LIMITED + "xn--czrs0t", // 商店 Wild Island, LLC + "xn--czru2d", // 商城 Zodiac Aquarius Limited + "xn--d1acj3b", // дети The Foundation for Network Initiatives “The Smart Internet” + "xn--eckvdtc9d", // ポイント Amazon Registry Services, Inc. + "xn--efvy88h", // 新闻 Xinhua News Agency Guangdong Branch 新华通讯社广东分社 +// "xn--estv75g", // 工行 Industrial and Commercial Bank of China Limited + "xn--fct429k", // 家電 Amazon Registry Services, Inc. + "xn--fhbei", // كوم VeriSign Sarl + "xn--fiq228c5hs", // 中文网 TLD REGISTRY LIMITED + "xn--fiq64b", // 中信 CITIC Group Corporation + "xn--fjq720a", // 娱乐 Will Bloom, LLC + "xn--flw351e", // 谷歌 Charleston Road Registry Inc. + "xn--fzys8d69uvgm", // 電訊盈科 PCCW Enterprises Limited + "xn--g2xx48c", // 购物 Minds + Machines Group Limited + "xn--gckr3f0f", // クラウド Amazon Registry Services, Inc. + "xn--gk3at1e", // 通販 Amazon Registry Services, Inc. + "xn--hxt814e", // 网店 Zodiac Libra Limited + "xn--i1b6b1a6a2e", // संगठन Public Interest Registry + "xn--imr513n", // 餐厅 HU YI GLOBAL INFORMATION RESOURCES (HOLDING) COMPANY. HONGKONG LIMITED + "xn--io0a7i", // 网络 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) + "xn--j1aef", // ком VeriSign Sarl + "xn--jlq480n2rg", // 亚马逊 Amazon Registry Services, Inc. + "xn--jlq61u9w7b", // 诺基亚 Nokia Corporation + "xn--jvr189m", // 食品 Amazon Registry Services, Inc. + "xn--kcrx77d1x4a", // 飞利浦 Koninklijke Philips N.V. + "xn--kpu716f", // 手表 Richemont DNS Inc. + "xn--kput3i", // 手机 Beijing RITT-Net Technology Development Co., Ltd + "xn--mgba3a3ejt", // ارامكو Aramco Services Company + "xn--mgba7c0bbn0a", // العليان Crescent Holding GmbH + "xn--mgbaakc7dvf", // اتصالات Emirates Telecommunications Corporation (trading as Etisalat) + "xn--mgbab2bd", // بازار CORE Association +// "xn--mgbb9fbpob", // موبايلي GreenTech Consultancy Company W.L.L. + "xn--mgbca7dzdo", // ابوظبي Abu Dhabi Systems and Information Centre + "xn--mgbi4ecexp", // كاثوليك Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) + "xn--mgbt3dhd", // همراه Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. + "xn--mk1bu44c", // 닷컴 VeriSign Sarl + "xn--mxtq1m", // 政府 Net-Chinese Co., Ltd. + "xn--ngbc5azd", // شبكة International Domain Registry Pty. Ltd. + "xn--ngbe9e0a", // بيتك Kuwait Finance House + "xn--ngbrx", // عرب League of Arab States + "xn--nqv7f", // 机构 Public Interest Registry + "xn--nqv7fs00ema", // 组织机构 Public Interest Registry + "xn--nyqy26a", // 健康 Stable Tone Limited + "xn--otu796d", // 招聘 Dot Trademark TLD Holding Company Limited + "xn--p1acf", // рус Rusnames Limited + "xn--pbt977c", // 珠宝 Richemont DNS Inc. + "xn--pssy2u", // 大拿 VeriSign Sarl + "xn--q9jyb4c", // みんな Charleston Road Registry Inc. + "xn--qcka1pmc", // グーグル Charleston Road Registry Inc. + "xn--rhqv96g", // 世界 Stable Tone Limited + "xn--rovu88b", // 書籍 Amazon EU S.à r.l. + "xn--ses554g", // 网址 KNET Co., Ltd + "xn--t60b56a", // 닷넷 VeriSign Sarl + "xn--tckwe", // コム VeriSign Sarl + "xn--tiq49xqyj", // 天主教 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) + "xn--unup4y", // 游戏 Spring Fields, LLC + "xn--vermgensberater-ctb", // VERMöGENSBERATER Deutsche Vermögensberatung Aktiengesellschaft DVAG + "xn--vermgensberatung-pwb", // VERMöGENSBERATUNG Deutsche Vermögensberatung Aktiengesellschaft DVAG + "xn--vhquv", // 企业 Dash McCook, LLC + "xn--vuq861b", // 信息 Beijing Tele-info Network Technology Co., Ltd. + "xn--w4r85el8fhu5dnra", // 嘉里大酒店 Kerry Trading Co. Limited + "xn--w4rs40l", // 嘉里 Kerry Trading Co. Limited + "xn--xhq521b", // 广东 Guangzhou YU Wei Information Technology Co., Ltd. + "xn--zfr164b", // 政务 China Organizational Name Administration Center +// "xperia", // xperia Sony Mobile Communications AB + "xxx", // xxx ICM Registry LLC + "xyz", // xyz XYZ.COM LLC + "yachts", // yachts DERYachts, LLC + "yahoo", // yahoo Yahoo! Domain Services Inc. + "yamaxun", // yamaxun Amazon Registry Services, Inc. + "yandex", // yandex YANDEX, LLC + "yodobashi", // yodobashi YODOBASHI CAMERA CO.,LTD. + "yoga", // yoga Top Level Domain Holdings Limited + "yokohama", // yokohama GMO Registry, Inc. + "you", // you Amazon Registry Services, Inc. + "youtube", // youtube Charleston Road Registry Inc. + "yun", // yun QIHOO 360 TECHNOLOGY CO. LTD. + "zappos", // zappos Amazon Registry Services, Inc. + "zara", // zara Industria de Diseño Textil, S.A. (INDITEX, S.A.) + "zero", // zero Amazon Registry Services, Inc. + "zip", // zip Charleston Road Registry Inc. +// "zippo", // zippo Zadco Company + "zone", // zone Outer Falls, LLC + "zuerich", // zuerich Kanton Zürich (Canton of Zurich) +}; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static final String[] COUNTRY_CODE_TLDS = new String[] { + // Taken from Version 2020051000, Last Updated Sun May 10 07:07:01 2020 UTC + "ac", // Ascension Island + "ad", // Andorra + "ae", // United Arab Emirates + "af", // Afghanistan + "ag", // Antigua and Barbuda + "ai", // Anguilla + "al", // Albania + "am", // Armenia +// "an", // Netherlands Antilles (retired) + "ao", // Angola + "aq", // Antarctica + "ar", // Argentina + "as", // American Samoa + "at", // Austria + "au", // Australia (includes Ashmore and Cartier Islands and Coral Sea Islands) + "aw", // Aruba + "ax", // Åland + "az", // Azerbaijan + "ba", // Bosnia and Herzegovina + "bb", // Barbados + "bd", // Bangladesh + "be", // Belgium + "bf", // Burkina Faso + "bg", // Bulgaria + "bh", // Bahrain + "bi", // Burundi + "bj", // Benin + "bm", // Bermuda + "bn", // Brunei Darussalam + "bo", // Bolivia + "br", // Brazil + "bs", // Bahamas + "bt", // Bhutan + "bv", // Bouvet Island + "bw", // Botswana + "by", // Belarus + "bz", // Belize + "ca", // Canada + "cc", // Cocos (Keeling) Islands + "cd", // Democratic Republic of the Congo (formerly Zaire) + "cf", // Central African Republic + "cg", // Republic of the Congo + "ch", // Switzerland + "ci", // Côte d'Ivoire + "ck", // Cook Islands + "cl", // Chile + "cm", // Cameroon + "cn", // China, mainland + "co", // Colombia + "cr", // Costa Rica + "cu", // Cuba + "cv", // Cape Verde + "cw", // Curaçao + "cx", // Christmas Island + "cy", // Cyprus + "cz", // Czech Republic + "de", // Germany + "dj", // Djibouti + "dk", // Denmark + "dm", // Dominica + "do", // Dominican Republic + "dz", // Algeria + "ec", // Ecuador + "ee", // Estonia + "eg", // Egypt + "er", // Eritrea + "es", // Spain + "et", // Ethiopia + "eu", // European Union + "fi", // Finland + "fj", // Fiji + "fk", // Falkland Islands + "fm", // Federated States of Micronesia + "fo", // Faroe Islands + "fr", // France + "ga", // Gabon + "gb", // Great Britain (United Kingdom) + "gd", // Grenada + "ge", // Georgia + "gf", // French Guiana + "gg", // Guernsey + "gh", // Ghana + "gi", // Gibraltar + "gl", // Greenland + "gm", // The Gambia + "gn", // Guinea + "gp", // Guadeloupe + "gq", // Equatorial Guinea + "gr", // Greece + "gs", // South Georgia and the South Sandwich Islands + "gt", // Guatemala + "gu", // Guam + "gw", // Guinea-Bissau + "gy", // Guyana + "hk", // Hong Kong + "hm", // Heard Island and McDonald Islands + "hn", // Honduras + "hr", // Croatia (Hrvatska) + "ht", // Haiti + "hu", // Hungary + "id", // Indonesia + "ie", // Ireland (Éire) + "il", // Israel + "im", // Isle of Man + "in", // India + "io", // British Indian Ocean Territory + "iq", // Iraq + "ir", // Iran + "is", // Iceland + "it", // Italy + "je", // Jersey + "jm", // Jamaica + "jo", // Jordan + "jp", // Japan + "ke", // Kenya + "kg", // Kyrgyzstan + "kh", // Cambodia (Khmer) + "ki", // Kiribati + "km", // Comoros + "kn", // Saint Kitts and Nevis + "kp", // North Korea + "kr", // South Korea + "kw", // Kuwait + "ky", // Cayman Islands + "kz", // Kazakhstan + "la", // Laos (currently being marketed as the official domain for Los Angeles) + "lb", // Lebanon + "lc", // Saint Lucia + "li", // Liechtenstein + "lk", // Sri Lanka + "lr", // Liberia + "ls", // Lesotho + "lt", // Lithuania + "lu", // Luxembourg + "lv", // Latvia + "ly", // Libya + "ma", // Morocco + "mc", // Monaco + "md", // Moldova + "me", // Montenegro + "mg", // Madagascar + "mh", // Marshall Islands + "mk", // Republic of Macedonia + "ml", // Mali + "mm", // Myanmar + "mn", // Mongolia + "mo", // Macau + "mp", // Northern Mariana Islands + "mq", // Martinique + "mr", // Mauritania + "ms", // Montserrat + "mt", // Malta + "mu", // Mauritius + "mv", // Maldives + "mw", // Malawi + "mx", // Mexico + "my", // Malaysia + "mz", // Mozambique + "na", // Namibia + "nc", // New Caledonia + "ne", // Niger + "nf", // Norfolk Island + "ng", // Nigeria + "ni", // Nicaragua + "nl", // Netherlands + "no", // Norway + "np", // Nepal + "nr", // Nauru + "nu", // Niue + "nz", // New Zealand + "om", // Oman + "pa", // Panama + "pe", // Peru + "pf", // French Polynesia With Clipperton Island + "pg", // Papua New Guinea + "ph", // Philippines + "pk", // Pakistan + "pl", // Poland + "pm", // Saint-Pierre and Miquelon + "pn", // Pitcairn Islands + "pr", // Puerto Rico + "ps", // Palestinian territories (PA-controlled West Bank and Gaza Strip) + "pt", // Portugal + "pw", // Palau + "py", // Paraguay + "qa", // Qatar + "re", // Réunion + "ro", // Romania + "rs", // Serbia + "ru", // Russia + "rw", // Rwanda + "sa", // Saudi Arabia + "sb", // Solomon Islands + "sc", // Seychelles + "sd", // Sudan + "se", // Sweden + "sg", // Singapore + "sh", // Saint Helena + "si", // Slovenia + "sj", // Svalbard and Jan Mayen Islands Not in use (Norwegian dependencies; see .no) + "sk", // Slovakia + "sl", // Sierra Leone + "sm", // San Marino + "sn", // Senegal + "so", // Somalia + "sr", // Suriname + "ss", // ss National Communication Authority (NCA) + "st", // São Tomé and Príncipe + "su", // Soviet Union (deprecated) + "sv", // El Salvador + "sx", // Sint Maarten + "sy", // Syria + "sz", // Swaziland + "tc", // Turks and Caicos Islands + "td", // Chad + "tf", // French Southern and Antarctic Lands + "tg", // Togo + "th", // Thailand + "tj", // Tajikistan + "tk", // Tokelau + "tl", // East Timor (deprecated old code) + "tm", // Turkmenistan + "tn", // Tunisia + "to", // Tonga +// "tp", // East Timor (Retired) + "tr", // Turkey + "tt", // Trinidad and Tobago + "tv", // Tuvalu + "tw", // Taiwan, Republic of China + "tz", // Tanzania + "ua", // Ukraine + "ug", // Uganda + "uk", // United Kingdom + "us", // United States of America + "uy", // Uruguay + "uz", // Uzbekistan + "va", // Vatican City State + "vc", // Saint Vincent and the Grenadines + "ve", // Venezuela + "vg", // British Virgin Islands + "vi", // U.S. Virgin Islands + "vn", // Vietnam + "vu", // Vanuatu + "wf", // Wallis and Futuna + "ws", // Samoa (formerly Western Samoa) + "xn--2scrj9c", // ಭಾರತ National Internet eXchange of India + "xn--3e0b707e", // 한국 KISA (Korea Internet & Security Agency) + "xn--3hcrj9c", // ଭାରତ National Internet eXchange of India + "xn--45br5cyl", // ভাৰত National Internet eXchange of India + "xn--45brj9c", // ভারত National Internet Exchange of India + "xn--54b7fta0cc", // বাংলা Posts and Telecommunications Division + "xn--80ao21a", // қаз Association of IT Companies of Kazakhstan + "xn--90a3ac", // срб Serbian National Internet Domain Registry (RNIDS) + "xn--90ais", // ??? Reliable Software Inc. + "xn--clchc0ea0b2g2a9gcd", // சிங்கப்பூர் Singapore Network Information Centre (SGNIC) Pte Ltd + "xn--d1alf", // мкд Macedonian Academic Research Network Skopje + "xn--e1a4c", // ею EURid vzw/asbl + "xn--fiqs8s", // 中国 China Internet Network Information Center + "xn--fiqz9s", // 中國 China Internet Network Information Center + "xn--fpcrj9c3d", // భారత్ National Internet Exchange of India + "xn--fzc2c9e2c", // ලංකා LK Domain Registry + "xn--gecrj9c", // ભારત National Internet Exchange of India + "xn--h2breg3eve", // भारतम् National Internet eXchange of India + "xn--h2brj9c", // भारत National Internet Exchange of India + "xn--h2brj9c8c", // भारोत National Internet eXchange of India + "xn--j1amh", // укр Ukrainian Network Information Centre (UANIC), Inc. + "xn--j6w193g", // 香港 Hong Kong Internet Registration Corporation Ltd. + "xn--kprw13d", // 台湾 Taiwan Network Information Center (TWNIC) + "xn--kpry57d", // 台灣 Taiwan Network Information Center (TWNIC) + "xn--l1acc", // мон Datacom Co.,Ltd + "xn--lgbbat1ad8j", // الجزائر CERIST + "xn--mgb9awbf", // عمان Telecommunications Regulatory Authority (TRA) + "xn--mgba3a4f16a", // ایران Institute for Research in Fundamental Sciences (IPM) + "xn--mgbaam7a8h", // امارات Telecommunications Regulatory Authority (TRA) + "xn--mgbah1a3hjkrd", // موريتانيا Université de Nouakchott Al Aasriya + "xn--mgbai9azgqp6j", // پاکستان National Telecommunication Corporation + "xn--mgbayh7gpa", // الاردن National Information Technology Center (NITC) + "xn--mgbbh1a", // بارت National Internet eXchange of India + "xn--mgbbh1a71e", // بھارت National Internet Exchange of India + "xn--mgbc0a9azcg", // المغرب Agence Nationale de Réglementation des Télécommunications (ANRT) + "xn--mgbcpq6gpa1a", // البحرين Telecommunications Regulatory Authority (TRA) + "xn--mgberp4a5d4ar", // السعودية Communications and Information Technology Commission + "xn--mgbgu82a", // ڀارت National Internet eXchange of India + "xn--mgbpl2fh", // ????? Sudan Internet Society + "xn--mgbtx2b", // عراق Communications and Media Commission (CMC) + "xn--mgbx4cd0ab", // مليسيا MYNIC Berhad + "xn--mix891f", // 澳門 Bureau of Telecommunications Regulation (DSRT) + "xn--node", // გე Information Technologies Development Center (ITDC) + "xn--o3cw4h", // ไทย Thai Network Information Center Foundation + "xn--ogbpf8fl", // سورية National Agency for Network Services (NANS) + "xn--p1ai", // рф Coordination Center for TLD RU + "xn--pgbs0dh", // تونس Agence Tunisienne d'Internet + "xn--q7ce6a", // ລາວ Lao National Internet Center (LANIC) + "xn--qxa6a", // ευ EURid vzw/asbl + "xn--qxam", // ελ ICS-FORTH GR + "xn--rvc1e0am3e", // ഭാരതം National Internet eXchange of India + "xn--s9brj9c", // ਭਾਰਤ National Internet Exchange of India + "xn--wgbh1c", // مصر National Telecommunication Regulatory Authority - NTRA + "xn--wgbl6a", // قطر Communications Regulatory Authority + "xn--xkc2al3hye2a", // இலங்கை LK Domain Registry + "xn--xkc2dl3a5ee0h", // இந்தியா National Internet Exchange of India + "xn--y9a3aq", // ??? Internet Society + "xn--yfro4i67o", // 新加坡 Singapore Network Information Centre (SGNIC) Pte Ltd + "xn--ygbi2ammx", // فلسطين Ministry of Telecom & Information Technology (MTIT) + "ye", // Yemen + "yt", // Mayotte + "za", // South Africa + "zm", // Zambia + "zw", // Zimbabwe + }; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static final String[] LOCAL_TLDS = new String[] { + "localdomain", // Also widely used as localhost.localdomain + "localhost", // RFC2606 defined + }; + + // Additional arrays to supplement or override the built in ones. + // The PLUS arrays are valid keys, the MINUS arrays are invalid keys + + /* + * This field is used to detect whether the getInstance has been called. + * After this, the method updateTLDOverride is not allowed to be called. + * This field does not need to be volatile since it is only accessed from + * synchronized methods. + */ + private static boolean inUse = false; + + /* + * These arrays are mutable. + * They can only be updated by the updateTLDOverride method, and readers must first get an instance + * using the getInstance methods which are all (now) synchronised. + * The only other access is via getTLDEntries which is now synchronised. + */ + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static String[] countryCodeTLDsPlus = EMPTY_STRING_ARRAY; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static String[] genericTLDsPlus = EMPTY_STRING_ARRAY; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static String[] countryCodeTLDsMinus = EMPTY_STRING_ARRAY; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static String[] genericTLDsMinus = EMPTY_STRING_ARRAY; + + /** + * enum used by {@link DomainValidator#updateTLDOverride(ArrayType, String[])} + * to determine which override array to update / fetch + * @since 1.5.0 + * @since 1.5.1 made public and added read-only array references + */ + public enum ArrayType { + /** Update (or get a copy of) the GENERIC_TLDS_PLUS table containing additonal generic TLDs */ + GENERIC_PLUS, + /** Update (or get a copy of) the GENERIC_TLDS_MINUS table containing deleted generic TLDs */ + GENERIC_MINUS, + /** Update (or get a copy of) the COUNTRY_CODE_TLDS_PLUS table containing additonal country code TLDs */ + COUNTRY_CODE_PLUS, + /** Update (or get a copy of) the COUNTRY_CODE_TLDS_MINUS table containing deleted country code TLDs */ + COUNTRY_CODE_MINUS, + /** Get a copy of the generic TLDS table */ + GENERIC_RO, + /** Get a copy of the country code table */ + COUNTRY_CODE_RO, + /** Get a copy of the infrastructure table */ + INFRASTRUCTURE_RO, + /** Get a copy of the local table */ + LOCAL_RO + ; + }; + + // For use by unit test code only + static synchronized void clearTLDOverrides() { + inUse = false; + countryCodeTLDsPlus = EMPTY_STRING_ARRAY; + countryCodeTLDsMinus = EMPTY_STRING_ARRAY; + genericTLDsPlus = EMPTY_STRING_ARRAY; + genericTLDsMinus = EMPTY_STRING_ARRAY; + } + /** + * Update one of the TLD override arrays. + * This must only be done at program startup, before any instances are accessed using getInstance. + *

+ * For example: + *

+ * {@code DomainValidator.updateTLDOverride(ArrayType.GENERIC_PLUS, new String[]{"apache"})} + *

+ * To clear an override array, provide an empty array. + * + * @param table the table to update, see {@link DomainValidator.ArrayType} + * Must be one of the following + *

    + *
  • COUNTRY_CODE_MINUS
  • + *
  • COUNTRY_CODE_PLUS
  • + *
  • GENERIC_MINUS
  • + *
  • GENERIC_PLUS
  • + *
+ * @param tlds the array of TLDs, must not be null + * @throws IllegalStateException if the method is called after getInstance + * @throws IllegalArgumentException if one of the read-only tables is requested + * @since 1.5.0 + */ + public static synchronized void updateTLDOverride(ArrayType table, String [] tlds) { + if (inUse) { + throw new IllegalStateException("Can only invoke this method before calling getInstance"); + } + String [] copy = new String[tlds.length]; + // Comparisons are always done with lower-case entries + for (int i = 0; i < tlds.length; i++) { + copy[i] = tlds[i].toLowerCase(Locale.ENGLISH); + } + Arrays.sort(copy); + switch(table) { + case COUNTRY_CODE_MINUS: + countryCodeTLDsMinus = copy; + break; + case COUNTRY_CODE_PLUS: + countryCodeTLDsPlus = copy; + break; + case GENERIC_MINUS: + genericTLDsMinus = copy; + break; + case GENERIC_PLUS: + genericTLDsPlus = copy; + break; + case COUNTRY_CODE_RO: + case GENERIC_RO: + case INFRASTRUCTURE_RO: + case LOCAL_RO: + throw new IllegalArgumentException("Cannot update the table: " + table); + default: + throw new IllegalArgumentException("Unexpected enum value: " + table); + } + } + + /** + * Get a copy of the internal array. + * @param table the array type (any of the enum values) + * @return a copy of the array + * @throws IllegalArgumentException if the table type is unexpected (should not happen) + * @since 1.5.1 + */ + public static synchronized String [] getTLDEntries(ArrayType table) { + final String array[]; + switch(table) { + case COUNTRY_CODE_MINUS: + array = countryCodeTLDsMinus; + break; + case COUNTRY_CODE_PLUS: + array = countryCodeTLDsPlus; + break; + case GENERIC_MINUS: + array = genericTLDsMinus; + break; + case GENERIC_PLUS: + array = genericTLDsPlus; + break; + case GENERIC_RO: + array = GENERIC_TLDS; + break; + case COUNTRY_CODE_RO: + array = COUNTRY_CODE_TLDS; + break; + case INFRASTRUCTURE_RO: + array = INFRASTRUCTURE_TLDS; + break; + case LOCAL_RO: + array = LOCAL_TLDS; + break; + default: + throw new IllegalArgumentException("Unexpected enum value: " + table); + } + return Arrays.copyOf(array, array.length); // clone the array + } + + /** + * Converts potentially Unicode input to punycode. + * If conversion fails, returns the original input. + * + * @param input the string to convert, not null + * @return converted input, or original input if conversion fails + */ + // Needed by UrlValidator + static String unicodeToASCII(String input) { + if (isOnlyASCII(input)) { // skip possibly expensive processing + return input; + } + try { + final String ascii = IDN.toASCII(input); + if (IDNBUGHOLDER.IDN_TOASCII_PRESERVES_TRAILING_DOTS) { + return ascii; + } + final int length = input.length(); + if (length == 0) {// check there is a last character + return input; + } + // RFC3490 3.1. 1) + // Whenever dots are used as label separators, the following + // characters MUST be recognized as dots: U+002E (full stop), U+3002 + // (ideographic full stop), U+FF0E (fullwidth full stop), U+FF61 + // (halfwidth ideographic full stop). + char lastChar = input.charAt(length-1);// fetch original last char + switch(lastChar) { + case '\u002E': // "." full stop + case '\u3002': // ideographic full stop + case '\uFF0E': // fullwidth full stop + case '\uFF61': // halfwidth ideographic full stop + return ascii + "."; // restore the missing stop + default: + return ascii; + } + } catch (IllegalArgumentException e) { // input is not valid + return input; + } + } + + private static class IDNBUGHOLDER { + private static boolean keepsTrailingDot() { + final String input = "a."; // must be a valid name + return input.equals(IDN.toASCII(input)); + } + private static final boolean IDN_TOASCII_PRESERVES_TRAILING_DOTS = keepsTrailingDot(); + } + + /* + * Check if input contains only ASCII + * Treats null as all ASCII + */ + private static boolean isOnlyASCII(String input) { + if (input == null) { + return true; + } + for(int i=0; i < input.length(); i++) { + if (input.charAt(i) > 0x7F) { // CHECKSTYLE IGNORE MagicNumber + return false; + } + } + return true; + } + + /** + * Check if a sorted array contains the specified key + * + * @param sortedArray the array to search + * @param key the key to find + * @return {@code true} if the array contains the key + */ + private static boolean arrayContains(String[] sortedArray, String key) { + return Arrays.binarySearch(sortedArray, key) >= 0; + } +} diff --git a/Java/commons-validator-DomainValidator_163/metadata.json b/Java/commons-validator-DomainValidator_163/metadata.json new file mode 100644 index 000000000..c97d8cba0 --- /dev/null +++ b/Java/commons-validator-DomainValidator_163/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-DomainValidator_163", + "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/validator/routines/DomainValidator.java", + "line": 174, + "npe_method": "isValid", + "deref_field": "domain", + "npe_class": "DomainValidator", + "repo": "commons-validator", + "bug_id": "DomainValidator_163" + } +} diff --git a/Java/commons-validator-DomainValidator_163/npe.json b/Java/commons-validator-DomainValidator_163/npe.json new file mode 100644 index 000000000..30f9ac2aa --- /dev/null +++ b/Java/commons-validator-DomainValidator_163/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/DomainValidator.java", + "line": 174, + "npe_method": "isValid", + "deref_field": "domain", + "npe_class": "DomainValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-Field_346/Dockerfile b/Java/commons-validator-Field_346/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-Field_346/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-Field_346/buggy.java b/Java/commons-validator-Field_346/buggy.java new file mode 100644 index 000000000..58940b46e --- /dev/null +++ b/Java/commons-validator-Field_346/buggy.java @@ -0,0 +1,960 @@ +/* + * 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.validator; + +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.StringTokenizer; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.collections.FastHashMap; // DEPRECATED +import org.apache.commons.validator.util.ValidatorUtils; + +/** + * This contains the list of pluggable validators to run on a field and any + * message information and variables to perform the validations and generate + * error messages. Instances of this class are configured with a + * <field> xml element. + *

+ * The use of FastHashMap is deprecated and will be replaced in a future + * release. + *

+ * + * @version $Revision$ + * @see org.apache.commons.validator.Form + */ +// TODO mutable non-private fields +public class Field implements Cloneable, Serializable { + + private static final long serialVersionUID = -8502647722530192185L; + + /** + * This is the value that will be used as a key if the Arg + * name field has no value. + */ + private static final String DEFAULT_ARG = + "org.apache.commons.validator.Field.DEFAULT"; + + /** + * This indicates an indexed property is being referenced. + */ + public static final String TOKEN_INDEXED = "[]"; + + /** + * The start of a token. + */ + protected static final String TOKEN_START = "${"; + + /** + * The end of a token. + */ + protected static final String TOKEN_END = "}"; + + /** + * A Vriable token. + */ + protected static final String TOKEN_VAR = "var:"; + + /** + * The Field's property name. + */ + protected String property = null; + + /** + * The Field's indexed property name. + */ + protected String indexedProperty = null; + + /** + * The Field's indexed list property name. + */ + protected String indexedListProperty = null; + + /** + * The Field's unique key. + */ + protected String key = null; + + /** + * A comma separated list of validator's this field depends on. + */ + protected String depends = null; + + /** + * The Page Number + */ + protected int page = 0; + + /** + * The flag that indicates whether scripting should be generated + * by the client for client-side validation. + * @since Validator 1.4 + */ + protected boolean clientValidation = true; + + /** + * The order of the Field in the Form. + */ + protected int fieldOrder = 0; + + /** + * Internal representation of this.depends String as a List. This List + * gets updated whenever setDepends() gets called. This List is + * synchronized so a call to setDepends() (which clears the List) won't + * interfere with a call to isDependency(). + */ + private final List dependencyList = Collections.synchronizedList(new ArrayList()); + + /** + * @deprecated Subclasses should use getVarMap() instead. + */ + @Deprecated + protected FastHashMap hVars = new FastHashMap(); // + + /** + * @deprecated Subclasses should use getMsgMap() instead. + */ + @Deprecated + protected FastHashMap hMsgs = new FastHashMap(); // + + /** + * Holds Maps of arguments. args[0] returns the Map for the first + * replacement argument. Start with a 0 length array so that it will + * only grow to the size of the highest argument position. + * @since Validator 1.1 + */ + @SuppressWarnings("unchecked") // cannot instantiate generic array, so have to assume this is OK + protected Map[] args = new Map[0]; + + /** + * Gets the page value that the Field is associated with for + * validation. + * @return The page number. + */ + public int getPage() { + return this.page; + } + + /** + * Sets the page value that the Field is associated with for + * validation. + * @param page The page number. + */ + public void setPage(int page) { + this.page = page; + } + + /** + * Gets the position of the Field in the validation list. + * @return The field position. + */ + public int getFieldOrder() { + return this.fieldOrder; + } + + /** + * Sets the position of the Field in the validation list. + * @param fieldOrder The field position. + */ + public void setFieldOrder(int fieldOrder) { + this.fieldOrder = fieldOrder; + } + + /** + * Gets the property name of the field. + * @return The field's property name. + */ + public String getProperty() { + return this.property; + } + + /** + * Sets the property name of the field. + * @param property The field's property name. + */ + public void setProperty(String property) { + this.property = property; + } + + /** + * Gets the indexed property name of the field. This + * is the method name that can take an int as + * a parameter for indexed property value retrieval. + * @return The field's indexed property name. + */ + public String getIndexedProperty() { + return this.indexedProperty; + } + + /** + * Sets the indexed property name of the field. + * @param indexedProperty The field's indexed property name. + */ + public void setIndexedProperty(String indexedProperty) { + this.indexedProperty = indexedProperty; + } + + /** + * Gets the indexed property name of the field. This + * is the method name that will return an array or a + * Collection used to retrieve the + * list and then loop through the list performing the specified + * validations. + * @return The field's indexed List property name. + */ + public String getIndexedListProperty() { + return this.indexedListProperty; + } + + /** + * Sets the indexed property name of the field. + * @param indexedListProperty The field's indexed List property name. + */ + public void setIndexedListProperty(String indexedListProperty) { + this.indexedListProperty = indexedListProperty; + } + + /** + * Gets the validation rules for this field as a comma separated list. + * @return A comma separated list of validator names. + */ + public String getDepends() { + return this.depends; + } + + /** + * Sets the validation rules for this field as a comma separated list. + * @param depends A comma separated list of validator names. + */ + public void setDepends(String depends) { + this.depends = depends; + + this.dependencyList.clear(); + + StringTokenizer st = new StringTokenizer(depends, ","); + while (st.hasMoreTokens()) { + String depend = st.nextToken().trim(); + + if (depend != null && depend.length() > 0) { + this.dependencyList.add(depend); + } + } + } + + /** + * Add a Msg to the Field. + * @param msg A validation message. + */ + public void addMsg(Msg msg) { + getMsgMap().put(msg.getName(), msg); + } + + /** + * Retrieve a message value. + * @param key Validation key. + * @return A validation message for a specified validator. + */ + public String getMsg(String key) { + Msg msg = getMessage(key); + return (msg == null) ? null : msg.getKey(); + } + + /** + * Retrieve a message object. + * @since Validator 1.1.4 + * @param key Validation key. + * @return A validation message for a specified validator. + */ + public Msg getMessage(String key) { + return getMsgMap().get(key); + } + + /** + * The Field's messages are returned as an + * unmodifiable Map. + * @since Validator 1.1.4 + * @return Map of validation messages for the field. + */ + public Map getMessages() { + return Collections.unmodifiableMap(getMsgMap()); + } + + /** + * Determines whether client-side scripting should be generated + * for this field. The default is true + * @return true for scripting; otherwise false + * @see #setClientValidation(boolean) + * @since Validator 1.4 + */ + public boolean isClientValidation() { + return this.clientValidation; + } + + /** + * Sets the flag that determines whether client-side scripting should + * be generated for this field. + * @param clientValidation the scripting flag + * @see #isClientValidation() + * @since Validator 1.4 + */ + public void setClientValidation(boolean clientValidation) { + this.clientValidation = clientValidation; + } + + /** + * Add an Arg to the replacement argument list. + * @since Validator 1.1 + * @param arg Validation message's argument. + */ +/** + * Add an Arg to the replacement argument list. + * + * @since Validator 1.1 + * @param arg + * Validation message's argument. + */ +public void addArg(org.apache.commons.validator.Arg arg) { + // TODO this first if check can go away after arg0, etc. are removed from dtd + if (((arg == null) || (arg.getKey() == null)) || (arg.getKey().length() == 0)) { + return; + } + determineArgPosition(arg); + ensureArgsCapacity(arg); + java.util.Map argMap = this.args[arg.getPosition()]; + if (argMap == null) { + argMap = new java.util.HashMap<>(); + this.args[arg.getPosition()] = argMap; + } + { + argMap.put(/* NPEX_NULL_EXP */ + arg.getName(), arg); + } +} + + /** + * Calculate the position of the Arg + */ + private void determineArgPosition(Arg arg) { + + int position = arg.getPosition(); + + // position has been explicity set + if (position >= 0) { + return; + } + + // first arg to be added + if (args == null || args.length == 0) { + arg.setPosition(0); + return; + } + + // determine the position of the last argument with + // the same name or the last default argument + String keyName = arg.getName() == null ? DEFAULT_ARG : arg.getName(); + int lastPosition = -1; + int lastDefault = -1; + for (int i = 0; i < args.length; i++) { + if (args[i] != null && args[i].containsKey(keyName)) { + lastPosition = i; + } + if (args[i] != null && args[i].containsKey(DEFAULT_ARG)) { + lastDefault = i; + } + } + + if (lastPosition < 0) { + lastPosition = lastDefault; + } + + // allocate the next position + arg.setPosition(++lastPosition); + + } + + /** + * Ensures that the args array can hold the given arg. Resizes the array as + * necessary. + * @param arg Determine if the args array is long enough to store this arg's + * position. + */ + private void ensureArgsCapacity(Arg arg) { + if (arg.getPosition() >= this.args.length) { + @SuppressWarnings("unchecked") // cannot check this at compile time, but it is OK + Map[] newArgs = new Map[arg.getPosition() + 1]; + System.arraycopy(this.args, 0, newArgs, 0, this.args.length); + this.args = newArgs; + } + } + + /** + * Gets the default Arg object at the given position. + * @param position Validation message argument's position. + * @return The default Arg or null if not found. + * @since Validator 1.1 + */ + public Arg getArg(int position) { + return this.getArg(DEFAULT_ARG, position); + } + + /** + * Gets the Arg object at the given position. If the key + * finds a null value then the default value will be + * retrieved. + * @param key The name the Arg is stored under. If not found, the default + * Arg for the given position (if any) will be retrieved. + * @param position The Arg number to find. + * @return The Arg with the given name and position or null if not found. + * @since Validator 1.1 + */ + public Arg getArg(String key, int position) { + if ((position >= this.args.length) || (this.args[position] == null)) { + return null; + } + + Arg arg = args[position].get(key); + + // Didn't find default arg so exit, otherwise we would get into + // infinite recursion + if ((arg == null) && key.equals(DEFAULT_ARG)) { + return null; + } + + return (arg == null) ? this.getArg(position) : arg; + } + + /** + * Retrieves the Args for the given validator name. + * @param key The validator's args to retrieve. + * @return An Arg[] sorted by the Args' positions (i.e. the Arg at index 0 + * has a position of 0). + * @since Validator 1.1.1 + */ + public Arg[] getArgs(String key){ + Arg[] argList = new Arg[this.args.length]; + + for (int i = 0; i < this.args.length; i++) { + argList[i] = this.getArg(key, i); + } + + return argList; + } + + /** + * Add a Var to the Field. + * @param v The Validator Argument. + */ + public void addVar(Var v) { + this.getVarMap().put(v.getName(), v); + } + + /** + * Add a Var, based on the values passed in, to the + * Field. + * @param name Name of the validation. + * @param value The Argument's value. + * @param jsType The Javascript type. + */ + public void addVar(String name, String value, String jsType) { + this.addVar(new Var(name, value, jsType)); + } + + /** + * Retrieve a variable. + * @param mainKey The Variable's key + * @return the Variable + */ + public Var getVar(String mainKey) { + return getVarMap().get(mainKey); + } + + /** + * Retrieve a variable's value. + * @param mainKey The Variable's key + * @return the Variable's value + */ + public String getVarValue(String mainKey) { + String value = null; + + Var v = getVarMap().get(mainKey); + if (v != null) { + value = v.getValue(); + } + + return value; + } + + /** + * The Field's variables are returned as an + * unmodifiable Map. + * @return the Map of Variable's for a Field. + */ + public Map getVars() { + return Collections.unmodifiableMap(getVarMap()); + } + + /** + * Gets a unique key based on the property and indexedProperty fields. + * @return a unique key for the field. + */ + public String getKey() { + if (this.key == null) { + this.generateKey(); + } + + return this.key; + } + + /** + * Sets a unique key for the field. This can be used to change + * the key temporarily to have a unique key for an indexed field. + * @param key a unique key for the field + */ + public void setKey(String key) { + this.key = key; + } + + /** + * If there is a value specified for the indexedProperty field then + * true will be returned. Otherwise it will be + * false. + * @return Whether the Field is indexed. + */ + public boolean isIndexed() { + return (indexedListProperty != null && indexedListProperty.length() > 0); + } + + /** + * Generate correct key value. + */ + public void generateKey() { + if (this.isIndexed()) { + this.key = this.indexedListProperty + TOKEN_INDEXED + "." + this.property; + } else { + this.key = this.property; + } + } + + /** + * Replace constants with values in fields and process the depends field + * to create the dependency Map. + */ + void process(Map globalConstants, Map constants) { + this.hMsgs.setFast(false); + this.hVars.setFast(true); + + this.generateKey(); + + // Process FormSet Constants + for (Iterator> i = constants.entrySet().iterator(); i.hasNext();) { + Entry entry = i.next(); + String key1 = entry.getKey(); + String key2 = TOKEN_START + key1 + TOKEN_END; + String replaceValue = entry.getValue(); + + property = ValidatorUtils.replace(property, key2, replaceValue); + + processVars(key2, replaceValue); + + this.processMessageComponents(key2, replaceValue); + } + + // Process Global Constants + for (Iterator> i = globalConstants.entrySet().iterator(); i.hasNext();) { + Entry entry = i.next(); + String key1 = entry.getKey(); + String key2 = TOKEN_START + key1 + TOKEN_END; + String replaceValue = entry.getValue(); + + property = ValidatorUtils.replace(property, key2, replaceValue); + + processVars(key2, replaceValue); + + this.processMessageComponents(key2, replaceValue); + } + + // Process Var Constant Replacement + for (Iterator i = getVarMap().keySet().iterator(); i.hasNext();) { + String key1 = i.next(); + String key2 = TOKEN_START + TOKEN_VAR + key1 + TOKEN_END; + Var var = this.getVar(key1); + String replaceValue = var.getValue(); + + this.processMessageComponents(key2, replaceValue); + } + + hMsgs.setFast(true); + } + + /** + * Replace the vars value with the key/value pairs passed in. + */ + private void processVars(String key, String replaceValue) { + Iterator i = getVarMap().keySet().iterator(); + while (i.hasNext()) { + String varKey = i.next(); + Var var = this.getVar(varKey); + + var.setValue(ValidatorUtils.replace(var.getValue(), key, replaceValue)); + } + + } + + /** + * Replace the args key value with the key/value pairs passed in. + */ + private void processMessageComponents(String key, String replaceValue) { + String varKey = TOKEN_START + TOKEN_VAR; + // Process Messages + if (key != null && !key.startsWith(varKey)) { + for (Iterator i = getMsgMap().values().iterator(); i.hasNext();) { + Msg msg = i.next(); + msg.setKey(ValidatorUtils.replace(msg.getKey(), key, replaceValue)); + } + } + + this.processArg(key, replaceValue); + } + + /** + * Replace the arg Collection key value with the key/value + * pairs passed in. + */ + private void processArg(String key, String replaceValue) { + for (int i = 0; i < this.args.length; i++) { + + Map argMap = this.args[i]; + if (argMap == null) { + continue; + } + + Iterator iter = argMap.values().iterator(); + while (iter.hasNext()) { + Arg arg = iter.next(); + + if (arg != null) { + arg.setKey( + ValidatorUtils.replace(arg.getKey(), key, replaceValue)); + } + } + } + } + + /** + * Checks if the validator is listed as a dependency. + * @param validatorName Name of the validator to check. + * @return Whether the field is dependant on a validator. + */ + public boolean isDependency(String validatorName) { + return this.dependencyList.contains(validatorName); + } + + /** + * Gets an unmodifiable List of the dependencies in the same + * order they were defined in parameter passed to the setDepends() method. + * @return A list of the Field's dependancies. + */ + public List getDependencyList() { + return Collections.unmodifiableList(this.dependencyList); + } + + /** + * Creates and returns a copy of this object. + * @return A copy of the Field. + */ + @Override + public Object clone() { + Field field = null; + try { + field = (Field) super.clone(); + } catch(CloneNotSupportedException e) { + throw new RuntimeException(e.toString()); + } + + @SuppressWarnings("unchecked") // empty array always OK; cannot check this at compile time + final Map[] tempMap = new Map[this.args.length]; + field.args = tempMap; + for (int i = 0; i < this.args.length; i++) { + if (this.args[i] == null) { + continue; + } + + Map argMap = new HashMap<>(this.args[i]); + Iterator> iter = argMap.entrySet().iterator(); + while (iter.hasNext()) { + Entry entry = iter.next(); + String validatorName = entry.getKey(); + Arg arg = entry.getValue(); + argMap.put(validatorName, (Arg) arg.clone()); + } + field.args[i] = argMap; + } + + field.hVars = ValidatorUtils.copyFastHashMap(hVars); + field.hMsgs = ValidatorUtils.copyFastHashMap(hMsgs); + + return field; + } + + /** + * Returns a string representation of the object. + * @return A string representation of the object. + */ + @Override + public String toString() { + StringBuilder results = new StringBuilder(); + + results.append("\t\tkey = " + key + "\n"); + results.append("\t\tproperty = " + property + "\n"); + results.append("\t\tindexedProperty = " + indexedProperty + "\n"); + results.append("\t\tindexedListProperty = " + indexedListProperty + "\n"); + results.append("\t\tdepends = " + depends + "\n"); + results.append("\t\tpage = " + page + "\n"); + results.append("\t\tfieldOrder = " + fieldOrder + "\n"); + + if (hVars != null) { + results.append("\t\tVars:\n"); + for (Iterator i = getVarMap().keySet().iterator(); i.hasNext();) { + Object key1 = i.next(); + results.append("\t\t\t"); + results.append(key1); + results.append("="); + results.append(getVarMap().get(key1)); + results.append("\n"); + } + } + + return results.toString(); + } + + /** + * Returns an indexed property from the object we're validating. + * + * @param bean The bean to extract the indexed values from. + * @throws ValidatorException If there's an error looking up the property + * or, the property found is not indexed. + */ + Object[] getIndexedProperty(Object bean) throws ValidatorException { + Object indexProp = null; + + try { + indexProp = + PropertyUtils.getProperty(bean, this.getIndexedListProperty()); + + } catch(IllegalAccessException|InvocationTargetException|NoSuchMethodException e) { + throw new ValidatorException(e.getMessage()); + } + + if (indexProp instanceof Collection) { + return ((Collection) indexProp).toArray(); + + } else if (indexProp.getClass().isArray()) { + return (Object[]) indexProp; + + } else { + throw new ValidatorException(this.getKey() + " is not indexed"); + } + + } + /** + * Returns the size of an indexed property from the object we're validating. + * + * @param bean The bean to extract the indexed values from. + * @throws ValidatorException If there's an error looking up the property + * or, the property found is not indexed. + */ + private int getIndexedPropertySize(Object bean) throws ValidatorException { + Object indexProp = null; + + try { + indexProp = + PropertyUtils.getProperty(bean, this.getIndexedListProperty()); + + } catch(IllegalAccessException|InvocationTargetException|NoSuchMethodException e) { + throw new ValidatorException(e.getMessage()); + } + + if (indexProp == null) { + return 0; + } else if (indexProp instanceof Collection) { + return ((Collection)indexProp).size(); + } else if (indexProp.getClass().isArray()) { + return ((Object[])indexProp).length; + } else { + throw new ValidatorException(this.getKey() + " is not indexed"); + } + + } + + /** + * Executes the given ValidatorAction and all ValidatorActions that it + * depends on. + * @return true if the validation succeeded. + */ + private boolean validateForRule( + ValidatorAction va, + ValidatorResults results, + Map actions, + Map params, + int pos) + throws ValidatorException { + + ValidatorResult result = results.getValidatorResult(this.getKey()); + if (result != null && result.containsAction(va.getName())) { + return result.isValid(va.getName()); + } + + if (!this.runDependentValidators(va, results, actions, params, pos)) { + return false; + } + + return va.executeValidationMethod(this, params, results, pos); + } + + /** + * Calls all of the validators that this validator depends on. + * TODO ValidatorAction should know how to run its own dependencies. + * @param va Run dependent validators for this action. + * @param results + * @param actions + * @param pos + * @return true if all of the dependent validations passed. + * @throws ValidatorException If there's an error running a validator + */ + private boolean runDependentValidators( + ValidatorAction va, + ValidatorResults results, + Map actions, + Map params, + int pos) + throws ValidatorException { + + List dependentValidators = va.getDependencyList(); + + if (dependentValidators.isEmpty()) { + return true; + } + + Iterator iter = dependentValidators.iterator(); + while (iter.hasNext()) { + String depend = iter.next(); + + ValidatorAction action = actions.get(depend); + if (action == null) { + this.handleMissingAction(depend); + } + + if (!this.validateForRule(action, results, actions, params, pos)) { + return false; + } + } + + return true; + } + + /** + * Run the configured validations on this field. Run all validations + * in the depends clause over each item in turn, returning when the first + * one fails. + * @param params A Map of parameter class names to parameter values to pass + * into validation methods. + * @param actions A Map of validator names to ValidatorAction objects. + * @return A ValidatorResults object containing validation messages for + * this field. + * @throws ValidatorException If an error occurs during validation. + */ + public ValidatorResults validate(Map params, Map actions) + throws ValidatorException { + + if (this.getDepends() == null) { + return new ValidatorResults(); + } + + ValidatorResults allResults = new ValidatorResults(); + + Object bean = params.get(Validator.BEAN_PARAM); + int numberOfFieldsToValidate = + this.isIndexed() ? this.getIndexedPropertySize(bean) : 1; + + for (int fieldNumber = 0; fieldNumber < numberOfFieldsToValidate; fieldNumber++) { + + ValidatorResults results = new ValidatorResults(); + synchronized(dependencyList) { + Iterator dependencies = this.dependencyList.iterator(); + while (dependencies.hasNext()) { + String depend = dependencies.next(); + + ValidatorAction action = actions.get(depend); + if (action == null) { + this.handleMissingAction(depend); + } + + boolean good = + validateForRule(action, results, actions, params, fieldNumber); + + if (!good) { + allResults.merge(results); + return allResults; + } + } + } + allResults.merge(results); + } + + return allResults; + } + + /** + * Called when a validator name is used in a depends clause but there is + * no know ValidatorAction configured for that name. + * @param name The name of the validator in the depends list. + * @throws ValidatorException + */ + private void handleMissingAction(String name) throws ValidatorException { + throw new ValidatorException("No ValidatorAction named " + name + + " found for field " + this.getProperty()); + } + + /** + * Returns a Map of String Msg names to Msg objects. + * @since Validator 1.2.0 + * @return A Map of the Field's messages. + */ + @SuppressWarnings("unchecked") // FastHashMap does not support generics + protected Map getMsgMap() { + return hMsgs; + } + + /** + * Returns a Map of String Var names to Var objects. + * @since Validator 1.2.0 + * @return A Map of the Field's variables. + */ + @SuppressWarnings("unchecked") // FastHashMap does not support generics + protected Map getVarMap() { + return hVars; + } +} + diff --git a/Java/commons-validator-Field_346/metadata.json b/Java/commons-validator-Field_346/metadata.json new file mode 100644 index 000000000..bfa5d2914 --- /dev/null +++ b/Java/commons-validator-Field_346/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-Field_346", + "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/validator/Field.java", + "line": 352, + "npe_method": "addArg", + "deref_field": "getName", + "npe_class": "Field", + "repo": "commons-validator", + "bug_id": "Field_346" + } +} diff --git a/Java/commons-validator-Field_346/npe.json b/Java/commons-validator-Field_346/npe.json new file mode 100644 index 000000000..0edc5de27 --- /dev/null +++ b/Java/commons-validator-Field_346/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/Field.java", + "line": 352, + "npe_method": "addArg", + "deref_field": "getName", + "npe_class": "Field" +} \ No newline at end of file diff --git a/Java/commons-validator-Field_443/Dockerfile b/Java/commons-validator-Field_443/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-Field_443/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-Field_443/buggy.java b/Java/commons-validator-Field_443/buggy.java new file mode 100644 index 000000000..9aa856322 --- /dev/null +++ b/Java/commons-validator-Field_443/buggy.java @@ -0,0 +1,969 @@ +/* + * 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.validator; + +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.StringTokenizer; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.collections.FastHashMap; // DEPRECATED +import org.apache.commons.validator.util.ValidatorUtils; + +/** + * This contains the list of pluggable validators to run on a field and any + * message information and variables to perform the validations and generate + * error messages. Instances of this class are configured with a + * <field> xml element. + *

+ * The use of FastHashMap is deprecated and will be replaced in a future + * release. + *

+ * + * @version $Revision$ + * @see org.apache.commons.validator.Form + */ +// TODO mutable non-private fields +public class Field implements Cloneable, Serializable { + + private static final long serialVersionUID = -8502647722530192185L; + + /** + * This is the value that will be used as a key if the Arg + * name field has no value. + */ + private static final String DEFAULT_ARG = + "org.apache.commons.validator.Field.DEFAULT"; + + /** + * This indicates an indexed property is being referenced. + */ + public static final String TOKEN_INDEXED = "[]"; + + /** + * The start of a token. + */ + protected static final String TOKEN_START = "${"; + + /** + * The end of a token. + */ + protected static final String TOKEN_END = "}"; + + /** + * A Vriable token. + */ + protected static final String TOKEN_VAR = "var:"; + + /** + * The Field's property name. + */ + protected String property = null; + + /** + * The Field's indexed property name. + */ + protected String indexedProperty = null; + + /** + * The Field's indexed list property name. + */ + protected String indexedListProperty = null; + + /** + * The Field's unique key. + */ + protected String key = null; + + /** + * A comma separated list of validator's this field depends on. + */ + protected String depends = null; + + /** + * The Page Number + */ + protected int page = 0; + + /** + * The flag that indicates whether scripting should be generated + * by the client for client-side validation. + * @since Validator 1.4 + */ + protected boolean clientValidation = true; + + /** + * The order of the Field in the Form. + */ + protected int fieldOrder = 0; + + /** + * Internal representation of this.depends String as a List. This List + * gets updated whenever setDepends() gets called. This List is + * synchronized so a call to setDepends() (which clears the List) won't + * interfere with a call to isDependency(). + */ + private final List dependencyList = Collections.synchronizedList(new ArrayList()); + + /** + * @deprecated Subclasses should use getVarMap() instead. + */ + @Deprecated + protected FastHashMap hVars = new FastHashMap(); // + + /** + * @deprecated Subclasses should use getMsgMap() instead. + */ + @Deprecated + protected FastHashMap hMsgs = new FastHashMap(); // + + /** + * Holds Maps of arguments. args[0] returns the Map for the first + * replacement argument. Start with a 0 length array so that it will + * only grow to the size of the highest argument position. + * @since Validator 1.1 + */ + @SuppressWarnings("unchecked") // cannot instantiate generic array, so have to assume this is OK + protected Map[] args = new Map[0]; + + /** + * Gets the page value that the Field is associated with for + * validation. + * @return The page number. + */ + public int getPage() { + return this.page; + } + + /** + * Sets the page value that the Field is associated with for + * validation. + * @param page The page number. + */ + public void setPage(int page) { + this.page = page; + } + + /** + * Gets the position of the Field in the validation list. + * @return The field position. + */ + public int getFieldOrder() { + return this.fieldOrder; + } + + /** + * Sets the position of the Field in the validation list. + * @param fieldOrder The field position. + */ + public void setFieldOrder(int fieldOrder) { + this.fieldOrder = fieldOrder; + } + + /** + * Gets the property name of the field. + * @return The field's property name. + */ + public String getProperty() { + return this.property; + } + + /** + * Sets the property name of the field. + * @param property The field's property name. + */ + public void setProperty(String property) { + this.property = property; + } + + /** + * Gets the indexed property name of the field. This + * is the method name that can take an int as + * a parameter for indexed property value retrieval. + * @return The field's indexed property name. + */ + public String getIndexedProperty() { + return this.indexedProperty; + } + + /** + * Sets the indexed property name of the field. + * @param indexedProperty The field's indexed property name. + */ + public void setIndexedProperty(String indexedProperty) { + this.indexedProperty = indexedProperty; + } + + /** + * Gets the indexed property name of the field. This + * is the method name that will return an array or a + * Collection used to retrieve the + * list and then loop through the list performing the specified + * validations. + * @return The field's indexed List property name. + */ + public String getIndexedListProperty() { + return this.indexedListProperty; + } + + /** + * Sets the indexed property name of the field. + * @param indexedListProperty The field's indexed List property name. + */ + public void setIndexedListProperty(String indexedListProperty) { + this.indexedListProperty = indexedListProperty; + } + + /** + * Gets the validation rules for this field as a comma separated list. + * @return A comma separated list of validator names. + */ + public String getDepends() { + return this.depends; + } + + /** + * Sets the validation rules for this field as a comma separated list. + * @param depends A comma separated list of validator names. + */ + public void setDepends(String depends) { + this.depends = depends; + + this.dependencyList.clear(); + + StringTokenizer st = new StringTokenizer(depends, ","); + while (st.hasMoreTokens()) { + String depend = st.nextToken().trim(); + + if (depend != null && depend.length() > 0) { + this.dependencyList.add(depend); + } + } + } + + /** + * Add a Msg to the Field. + * @param msg A validation message. + */ + public void addMsg(Msg msg) { + getMsgMap().put(msg.getName(), msg); + } + + /** + * Retrieve a message value. + * @param key Validation key. + * @return A validation message for a specified validator. + */ + public String getMsg(String key) { + Msg msg = getMessage(key); + return (msg == null) ? null : msg.getKey(); + } + + /** + * Retrieve a message object. + * @since Validator 1.1.4 + * @param key Validation key. + * @return A validation message for a specified validator. + */ + public Msg getMessage(String key) { + return getMsgMap().get(key); + } + + /** + * The Field's messages are returned as an + * unmodifiable Map. + * @since Validator 1.1.4 + * @return Map of validation messages for the field. + */ + public Map getMessages() { + return Collections.unmodifiableMap(getMsgMap()); + } + + /** + * Determines whether client-side scripting should be generated + * for this field. The default is true + * @return true for scripting; otherwise false + * @see #setClientValidation(boolean) + * @since Validator 1.4 + */ + public boolean isClientValidation() { + return this.clientValidation; + } + + /** + * Sets the flag that determines whether client-side scripting should + * be generated for this field. + * @param clientValidation the scripting flag + * @see #isClientValidation() + * @since Validator 1.4 + */ + public void setClientValidation(boolean clientValidation) { + this.clientValidation = clientValidation; + } + + /** + * Add an Arg to the replacement argument list. + * @since Validator 1.1 + * @param arg Validation message's argument. + */ + public void addArg(Arg arg) { + // TODO this first if check can go away after arg0, etc. are removed from dtd + if (arg == null || arg.getKey() == null || arg.getKey().length() == 0) { + return; + } + + determineArgPosition(arg); + ensureArgsCapacity(arg); + + Map argMap = this.args[arg.getPosition()]; + if (argMap == null) { + argMap = new HashMap<>(); + this.args[arg.getPosition()] = argMap; + } + + if (arg.getName() == null) { + argMap.put(DEFAULT_ARG, arg); + } else { + argMap.put(arg.getName(), arg); + } + + } + + /** + * Calculate the position of the Arg + */ + private void determineArgPosition(Arg arg) { + + int position = arg.getPosition(); + + // position has been explicity set + if (position >= 0) { + return; + } + + // first arg to be added + if (args == null || args.length == 0) { + arg.setPosition(0); + return; + } + + // determine the position of the last argument with + // the same name or the last default argument + String keyName = arg.getName() == null ? DEFAULT_ARG : arg.getName(); + int lastPosition = -1; + int lastDefault = -1; + for (int i = 0; i < args.length; i++) { + if (args[i] != null && args[i].containsKey(keyName)) { + lastPosition = i; + } + if (args[i] != null && args[i].containsKey(DEFAULT_ARG)) { + lastDefault = i; + } + } + + if (lastPosition < 0) { + lastPosition = lastDefault; + } + + // allocate the next position + arg.setPosition(++lastPosition); + + } + + /** + * Ensures that the args array can hold the given arg. Resizes the array as + * necessary. + * @param arg Determine if the args array is long enough to store this arg's + * position. + */ + private void ensureArgsCapacity(Arg arg) { + if (arg.getPosition() >= this.args.length) { + @SuppressWarnings("unchecked") // cannot check this at compile time, but it is OK + Map[] newArgs = new Map[arg.getPosition() + 1]; + System.arraycopy(this.args, 0, newArgs, 0, this.args.length); + this.args = newArgs; + } + } + + /** + * Gets the default Arg object at the given position. + * @param position Validation message argument's position. + * @return The default Arg or null if not found. + * @since Validator 1.1 + */ + public Arg getArg(int position) { + return this.getArg(DEFAULT_ARG, position); + } + + /** + * Gets the Arg object at the given position. If the key + * finds a null value then the default value will be + * retrieved. + * @param key The name the Arg is stored under. If not found, the default + * Arg for the given position (if any) will be retrieved. + * @param position The Arg number to find. + * @return The Arg with the given name and position or null if not found. + * @since Validator 1.1 + */ +/** + * Gets the Arg object at the given position. If the key + * finds a null value then the default value will be + * retrieved. + * + * @param key + * The name the Arg is stored under. If not found, the default + * Arg for the given position (if any) will be retrieved. + * @param position + * The Arg number to find. + * @return The Arg with the given name and position or null if not found. + * @since Validator 1.1 + */ +public org.apache.commons.validator.Arg getArg(java.lang.String key, int position) { + if ((position >= this.args.length) || (this.args[position] == null)) { + return null; + } + org.apache.commons.validator.Arg arg = args[position].get(key); + // Didn't find default arg so exit, otherwise we would get into + // infinite recursion + if ((/* NPEX_NULL_EXP */ + arg == null) && key.equals(org.apache.commons.validator.Field.DEFAULT_ARG)) { + return null; + } + return arg; +} + + /** + * Retrieves the Args for the given validator name. + * @param key The validator's args to retrieve. + * @return An Arg[] sorted by the Args' positions (i.e. the Arg at index 0 + * has a position of 0). + * @since Validator 1.1.1 + */ + public Arg[] getArgs(String key){ + Arg[] argList = new Arg[this.args.length]; + + for (int i = 0; i < this.args.length; i++) { + argList[i] = this.getArg(key, i); + } + + return argList; + } + + /** + * Add a Var to the Field. + * @param v The Validator Argument. + */ + public void addVar(Var v) { + this.getVarMap().put(v.getName(), v); + } + + /** + * Add a Var, based on the values passed in, to the + * Field. + * @param name Name of the validation. + * @param value The Argument's value. + * @param jsType The Javascript type. + */ + public void addVar(String name, String value, String jsType) { + this.addVar(new Var(name, value, jsType)); + } + + /** + * Retrieve a variable. + * @param mainKey The Variable's key + * @return the Variable + */ + public Var getVar(String mainKey) { + return getVarMap().get(mainKey); + } + + /** + * Retrieve a variable's value. + * @param mainKey The Variable's key + * @return the Variable's value + */ + public String getVarValue(String mainKey) { + String value = null; + + Var v = getVarMap().get(mainKey); + if (v != null) { + value = v.getValue(); + } + + return value; + } + + /** + * The Field's variables are returned as an + * unmodifiable Map. + * @return the Map of Variable's for a Field. + */ + public Map getVars() { + return Collections.unmodifiableMap(getVarMap()); + } + + /** + * Gets a unique key based on the property and indexedProperty fields. + * @return a unique key for the field. + */ + public String getKey() { + if (this.key == null) { + this.generateKey(); + } + + return this.key; + } + + /** + * Sets a unique key for the field. This can be used to change + * the key temporarily to have a unique key for an indexed field. + * @param key a unique key for the field + */ + public void setKey(String key) { + this.key = key; + } + + /** + * If there is a value specified for the indexedProperty field then + * true will be returned. Otherwise it will be + * false. + * @return Whether the Field is indexed. + */ + public boolean isIndexed() { + return (indexedListProperty != null && indexedListProperty.length() > 0); + } + + /** + * Generate correct key value. + */ + public void generateKey() { + if (this.isIndexed()) { + this.key = this.indexedListProperty + TOKEN_INDEXED + "." + this.property; + } else { + this.key = this.property; + } + } + + /** + * Replace constants with values in fields and process the depends field + * to create the dependency Map. + */ + void process(Map globalConstants, Map constants) { + this.hMsgs.setFast(false); + this.hVars.setFast(true); + + this.generateKey(); + + // Process FormSet Constants + for (Iterator> i = constants.entrySet().iterator(); i.hasNext();) { + Entry entry = i.next(); + String key1 = entry.getKey(); + String key2 = TOKEN_START + key1 + TOKEN_END; + String replaceValue = entry.getValue(); + + property = ValidatorUtils.replace(property, key2, replaceValue); + + processVars(key2, replaceValue); + + this.processMessageComponents(key2, replaceValue); + } + + // Process Global Constants + for (Iterator> i = globalConstants.entrySet().iterator(); i.hasNext();) { + Entry entry = i.next(); + String key1 = entry.getKey(); + String key2 = TOKEN_START + key1 + TOKEN_END; + String replaceValue = entry.getValue(); + + property = ValidatorUtils.replace(property, key2, replaceValue); + + processVars(key2, replaceValue); + + this.processMessageComponents(key2, replaceValue); + } + + // Process Var Constant Replacement + for (Iterator i = getVarMap().keySet().iterator(); i.hasNext();) { + String key1 = i.next(); + String key2 = TOKEN_START + TOKEN_VAR + key1 + TOKEN_END; + Var var = this.getVar(key1); + String replaceValue = var.getValue(); + + this.processMessageComponents(key2, replaceValue); + } + + hMsgs.setFast(true); + } + + /** + * Replace the vars value with the key/value pairs passed in. + */ + private void processVars(String key, String replaceValue) { + Iterator i = getVarMap().keySet().iterator(); + while (i.hasNext()) { + String varKey = i.next(); + Var var = this.getVar(varKey); + + var.setValue(ValidatorUtils.replace(var.getValue(), key, replaceValue)); + } + + } + + /** + * Replace the args key value with the key/value pairs passed in. + */ + private void processMessageComponents(String key, String replaceValue) { + String varKey = TOKEN_START + TOKEN_VAR; + // Process Messages + if (key != null && !key.startsWith(varKey)) { + for (Iterator i = getMsgMap().values().iterator(); i.hasNext();) { + Msg msg = i.next(); + msg.setKey(ValidatorUtils.replace(msg.getKey(), key, replaceValue)); + } + } + + this.processArg(key, replaceValue); + } + + /** + * Replace the arg Collection key value with the key/value + * pairs passed in. + */ + private void processArg(String key, String replaceValue) { + for (int i = 0; i < this.args.length; i++) { + + Map argMap = this.args[i]; + if (argMap == null) { + continue; + } + + Iterator iter = argMap.values().iterator(); + while (iter.hasNext()) { + Arg arg = iter.next(); + + if (arg != null) { + arg.setKey( + ValidatorUtils.replace(arg.getKey(), key, replaceValue)); + } + } + } + } + + /** + * Checks if the validator is listed as a dependency. + * @param validatorName Name of the validator to check. + * @return Whether the field is dependant on a validator. + */ + public boolean isDependency(String validatorName) { + return this.dependencyList.contains(validatorName); + } + + /** + * Gets an unmodifiable List of the dependencies in the same + * order they were defined in parameter passed to the setDepends() method. + * @return A list of the Field's dependancies. + */ + public List getDependencyList() { + return Collections.unmodifiableList(this.dependencyList); + } + + /** + * Creates and returns a copy of this object. + * @return A copy of the Field. + */ + @Override + public Object clone() { + Field field = null; + try { + field = (Field) super.clone(); + } catch(CloneNotSupportedException e) { + throw new RuntimeException(e.toString()); + } + + @SuppressWarnings("unchecked") // empty array always OK; cannot check this at compile time + final Map[] tempMap = new Map[this.args.length]; + field.args = tempMap; + for (int i = 0; i < this.args.length; i++) { + if (this.args[i] == null) { + continue; + } + + Map argMap = new HashMap<>(this.args[i]); + Iterator> iter = argMap.entrySet().iterator(); + while (iter.hasNext()) { + Entry entry = iter.next(); + String validatorName = entry.getKey(); + Arg arg = entry.getValue(); + argMap.put(validatorName, (Arg) arg.clone()); + } + field.args[i] = argMap; + } + + field.hVars = ValidatorUtils.copyFastHashMap(hVars); + field.hMsgs = ValidatorUtils.copyFastHashMap(hMsgs); + + return field; + } + + /** + * Returns a string representation of the object. + * @return A string representation of the object. + */ + @Override + public String toString() { + StringBuilder results = new StringBuilder(); + + results.append("\t\tkey = " + key + "\n"); + results.append("\t\tproperty = " + property + "\n"); + results.append("\t\tindexedProperty = " + indexedProperty + "\n"); + results.append("\t\tindexedListProperty = " + indexedListProperty + "\n"); + results.append("\t\tdepends = " + depends + "\n"); + results.append("\t\tpage = " + page + "\n"); + results.append("\t\tfieldOrder = " + fieldOrder + "\n"); + + if (hVars != null) { + results.append("\t\tVars:\n"); + for (Iterator i = getVarMap().keySet().iterator(); i.hasNext();) { + Object key1 = i.next(); + results.append("\t\t\t"); + results.append(key1); + results.append("="); + results.append(getVarMap().get(key1)); + results.append("\n"); + } + } + + return results.toString(); + } + + /** + * Returns an indexed property from the object we're validating. + * + * @param bean The bean to extract the indexed values from. + * @throws ValidatorException If there's an error looking up the property + * or, the property found is not indexed. + */ + Object[] getIndexedProperty(Object bean) throws ValidatorException { + Object indexProp = null; + + try { + indexProp = + PropertyUtils.getProperty(bean, this.getIndexedListProperty()); + + } catch(IllegalAccessException|InvocationTargetException|NoSuchMethodException e) { + throw new ValidatorException(e.getMessage()); + } + + if (indexProp instanceof Collection) { + return ((Collection) indexProp).toArray(); + + } else if (indexProp.getClass().isArray()) { + return (Object[]) indexProp; + + } else { + throw new ValidatorException(this.getKey() + " is not indexed"); + } + + } + /** + * Returns the size of an indexed property from the object we're validating. + * + * @param bean The bean to extract the indexed values from. + * @throws ValidatorException If there's an error looking up the property + * or, the property found is not indexed. + */ + private int getIndexedPropertySize(Object bean) throws ValidatorException { + Object indexProp = null; + + try { + indexProp = + PropertyUtils.getProperty(bean, this.getIndexedListProperty()); + + } catch(IllegalAccessException|InvocationTargetException|NoSuchMethodException e) { + throw new ValidatorException(e.getMessage()); + } + + if (indexProp == null) { + return 0; + } else if (indexProp instanceof Collection) { + return ((Collection)indexProp).size(); + } else if (indexProp.getClass().isArray()) { + return ((Object[])indexProp).length; + } else { + throw new ValidatorException(this.getKey() + " is not indexed"); + } + + } + + /** + * Executes the given ValidatorAction and all ValidatorActions that it + * depends on. + * @return true if the validation succeeded. + */ + private boolean validateForRule( + ValidatorAction va, + ValidatorResults results, + Map actions, + Map params, + int pos) + throws ValidatorException { + + ValidatorResult result = results.getValidatorResult(this.getKey()); + if (result != null && result.containsAction(va.getName())) { + return result.isValid(va.getName()); + } + + if (!this.runDependentValidators(va, results, actions, params, pos)) { + return false; + } + + return va.executeValidationMethod(this, params, results, pos); + } + + /** + * Calls all of the validators that this validator depends on. + * TODO ValidatorAction should know how to run its own dependencies. + * @param va Run dependent validators for this action. + * @param results + * @param actions + * @param pos + * @return true if all of the dependent validations passed. + * @throws ValidatorException If there's an error running a validator + */ + private boolean runDependentValidators( + ValidatorAction va, + ValidatorResults results, + Map actions, + Map params, + int pos) + throws ValidatorException { + + List dependentValidators = va.getDependencyList(); + + if (dependentValidators.isEmpty()) { + return true; + } + + Iterator iter = dependentValidators.iterator(); + while (iter.hasNext()) { + String depend = iter.next(); + + ValidatorAction action = actions.get(depend); + if (action == null) { + this.handleMissingAction(depend); + } + + if (!this.validateForRule(action, results, actions, params, pos)) { + return false; + } + } + + return true; + } + + /** + * Run the configured validations on this field. Run all validations + * in the depends clause over each item in turn, returning when the first + * one fails. + * @param params A Map of parameter class names to parameter values to pass + * into validation methods. + * @param actions A Map of validator names to ValidatorAction objects. + * @return A ValidatorResults object containing validation messages for + * this field. + * @throws ValidatorException If an error occurs during validation. + */ + public ValidatorResults validate(Map params, Map actions) + throws ValidatorException { + + if (this.getDepends() == null) { + return new ValidatorResults(); + } + + ValidatorResults allResults = new ValidatorResults(); + + Object bean = params.get(Validator.BEAN_PARAM); + int numberOfFieldsToValidate = + this.isIndexed() ? this.getIndexedPropertySize(bean) : 1; + + for (int fieldNumber = 0; fieldNumber < numberOfFieldsToValidate; fieldNumber++) { + + ValidatorResults results = new ValidatorResults(); + synchronized(dependencyList) { + Iterator dependencies = this.dependencyList.iterator(); + while (dependencies.hasNext()) { + String depend = dependencies.next(); + + ValidatorAction action = actions.get(depend); + if (action == null) { + this.handleMissingAction(depend); + } + + boolean good = + validateForRule(action, results, actions, params, fieldNumber); + + if (!good) { + allResults.merge(results); + return allResults; + } + } + } + allResults.merge(results); + } + + return allResults; + } + + /** + * Called when a validator name is used in a depends clause but there is + * no know ValidatorAction configured for that name. + * @param name The name of the validator in the depends list. + * @throws ValidatorException + */ + private void handleMissingAction(String name) throws ValidatorException { + throw new ValidatorException("No ValidatorAction named " + name + + " found for field " + this.getProperty()); + } + + /** + * Returns a Map of String Msg names to Msg objects. + * @since Validator 1.2.0 + * @return A Map of the Field's messages. + */ + @SuppressWarnings("unchecked") // FastHashMap does not support generics + protected Map getMsgMap() { + return hMsgs; + } + + /** + * Returns a Map of String Var names to Var objects. + * @since Validator 1.2.0 + * @return A Map of the Field's variables. + */ + @SuppressWarnings("unchecked") // FastHashMap does not support generics + protected Map getVarMap() { + return hVars; + } +} + diff --git a/Java/commons-validator-Field_443/metadata.json b/Java/commons-validator-Field_443/metadata.json new file mode 100644 index 000000000..0eb539e78 --- /dev/null +++ b/Java/commons-validator-Field_443/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-Field_443", + "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/validator/Field.java", + "line": 451, + "npe_method": "getArg", + "deref_field": "arg", + "npe_class": "Field", + "repo": "commons-validator", + "bug_id": "Field_443" + } +} diff --git a/Java/commons-validator-Field_443/npe.json b/Java/commons-validator-Field_443/npe.json new file mode 100644 index 000000000..d6e6eb6b3 --- /dev/null +++ b/Java/commons-validator-Field_443/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/Field.java", + "line": 451, + "npe_method": "getArg", + "deref_field": "arg", + "npe_class": "Field" +} \ No newline at end of file diff --git a/Java/commons-validator-Field_500/Dockerfile b/Java/commons-validator-Field_500/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-Field_500/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-Field_500/buggy.java b/Java/commons-validator-Field_500/buggy.java new file mode 100644 index 000000000..223b495cf --- /dev/null +++ b/Java/commons-validator-Field_500/buggy.java @@ -0,0 +1,964 @@ +/* + * 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.validator; + +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.StringTokenizer; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.collections.FastHashMap; // DEPRECATED +import org.apache.commons.validator.util.ValidatorUtils; + +/** + * This contains the list of pluggable validators to run on a field and any + * message information and variables to perform the validations and generate + * error messages. Instances of this class are configured with a + * <field> xml element. + *

+ * The use of FastHashMap is deprecated and will be replaced in a future + * release. + *

+ * + * @version $Revision$ + * @see org.apache.commons.validator.Form + */ +// TODO mutable non-private fields +public class Field implements Cloneable, Serializable { + + private static final long serialVersionUID = -8502647722530192185L; + + /** + * This is the value that will be used as a key if the Arg + * name field has no value. + */ + private static final String DEFAULT_ARG = + "org.apache.commons.validator.Field.DEFAULT"; + + /** + * This indicates an indexed property is being referenced. + */ + public static final String TOKEN_INDEXED = "[]"; + + /** + * The start of a token. + */ + protected static final String TOKEN_START = "${"; + + /** + * The end of a token. + */ + protected static final String TOKEN_END = "}"; + + /** + * A Vriable token. + */ + protected static final String TOKEN_VAR = "var:"; + + /** + * The Field's property name. + */ + protected String property = null; + + /** + * The Field's indexed property name. + */ + protected String indexedProperty = null; + + /** + * The Field's indexed list property name. + */ + protected String indexedListProperty = null; + + /** + * The Field's unique key. + */ + protected String key = null; + + /** + * A comma separated list of validator's this field depends on. + */ + protected String depends = null; + + /** + * The Page Number + */ + protected int page = 0; + + /** + * The flag that indicates whether scripting should be generated + * by the client for client-side validation. + * @since Validator 1.4 + */ + protected boolean clientValidation = true; + + /** + * The order of the Field in the Form. + */ + protected int fieldOrder = 0; + + /** + * Internal representation of this.depends String as a List. This List + * gets updated whenever setDepends() gets called. This List is + * synchronized so a call to setDepends() (which clears the List) won't + * interfere with a call to isDependency(). + */ + private final List dependencyList = Collections.synchronizedList(new ArrayList()); + + /** + * @deprecated Subclasses should use getVarMap() instead. + */ + @Deprecated + protected FastHashMap hVars = new FastHashMap(); // + + /** + * @deprecated Subclasses should use getMsgMap() instead. + */ + @Deprecated + protected FastHashMap hMsgs = new FastHashMap(); // + + /** + * Holds Maps of arguments. args[0] returns the Map for the first + * replacement argument. Start with a 0 length array so that it will + * only grow to the size of the highest argument position. + * @since Validator 1.1 + */ + @SuppressWarnings("unchecked") // cannot instantiate generic array, so have to assume this is OK + protected Map[] args = new Map[0]; + + /** + * Gets the page value that the Field is associated with for + * validation. + * @return The page number. + */ + public int getPage() { + return this.page; + } + + /** + * Sets the page value that the Field is associated with for + * validation. + * @param page The page number. + */ + public void setPage(int page) { + this.page = page; + } + + /** + * Gets the position of the Field in the validation list. + * @return The field position. + */ + public int getFieldOrder() { + return this.fieldOrder; + } + + /** + * Sets the position of the Field in the validation list. + * @param fieldOrder The field position. + */ + public void setFieldOrder(int fieldOrder) { + this.fieldOrder = fieldOrder; + } + + /** + * Gets the property name of the field. + * @return The field's property name. + */ + public String getProperty() { + return this.property; + } + + /** + * Sets the property name of the field. + * @param property The field's property name. + */ + public void setProperty(String property) { + this.property = property; + } + + /** + * Gets the indexed property name of the field. This + * is the method name that can take an int as + * a parameter for indexed property value retrieval. + * @return The field's indexed property name. + */ + public String getIndexedProperty() { + return this.indexedProperty; + } + + /** + * Sets the indexed property name of the field. + * @param indexedProperty The field's indexed property name. + */ + public void setIndexedProperty(String indexedProperty) { + this.indexedProperty = indexedProperty; + } + + /** + * Gets the indexed property name of the field. This + * is the method name that will return an array or a + * Collection used to retrieve the + * list and then loop through the list performing the specified + * validations. + * @return The field's indexed List property name. + */ + public String getIndexedListProperty() { + return this.indexedListProperty; + } + + /** + * Sets the indexed property name of the field. + * @param indexedListProperty The field's indexed List property name. + */ + public void setIndexedListProperty(String indexedListProperty) { + this.indexedListProperty = indexedListProperty; + } + + /** + * Gets the validation rules for this field as a comma separated list. + * @return A comma separated list of validator names. + */ + public String getDepends() { + return this.depends; + } + + /** + * Sets the validation rules for this field as a comma separated list. + * @param depends A comma separated list of validator names. + */ + public void setDepends(String depends) { + this.depends = depends; + + this.dependencyList.clear(); + + StringTokenizer st = new StringTokenizer(depends, ","); + while (st.hasMoreTokens()) { + String depend = st.nextToken().trim(); + + if (depend != null && depend.length() > 0) { + this.dependencyList.add(depend); + } + } + } + + /** + * Add a Msg to the Field. + * @param msg A validation message. + */ + public void addMsg(Msg msg) { + getMsgMap().put(msg.getName(), msg); + } + + /** + * Retrieve a message value. + * @param key Validation key. + * @return A validation message for a specified validator. + */ + public String getMsg(String key) { + Msg msg = getMessage(key); + return (msg == null) ? null : msg.getKey(); + } + + /** + * Retrieve a message object. + * @since Validator 1.1.4 + * @param key Validation key. + * @return A validation message for a specified validator. + */ + public Msg getMessage(String key) { + return getMsgMap().get(key); + } + + /** + * The Field's messages are returned as an + * unmodifiable Map. + * @since Validator 1.1.4 + * @return Map of validation messages for the field. + */ + public Map getMessages() { + return Collections.unmodifiableMap(getMsgMap()); + } + + /** + * Determines whether client-side scripting should be generated + * for this field. The default is true + * @return true for scripting; otherwise false + * @see #setClientValidation(boolean) + * @since Validator 1.4 + */ + public boolean isClientValidation() { + return this.clientValidation; + } + + /** + * Sets the flag that determines whether client-side scripting should + * be generated for this field. + * @param clientValidation the scripting flag + * @see #isClientValidation() + * @since Validator 1.4 + */ + public void setClientValidation(boolean clientValidation) { + this.clientValidation = clientValidation; + } + + /** + * Add an Arg to the replacement argument list. + * @since Validator 1.1 + * @param arg Validation message's argument. + */ + public void addArg(Arg arg) { + // TODO this first if check can go away after arg0, etc. are removed from dtd + if (arg == null || arg.getKey() == null || arg.getKey().length() == 0) { + return; + } + + determineArgPosition(arg); + ensureArgsCapacity(arg); + + Map argMap = this.args[arg.getPosition()]; + if (argMap == null) { + argMap = new HashMap<>(); + this.args[arg.getPosition()] = argMap; + } + + if (arg.getName() == null) { + argMap.put(DEFAULT_ARG, arg); + } else { + argMap.put(arg.getName(), arg); + } + + } + + /** + * Calculate the position of the Arg + */ + private void determineArgPosition(Arg arg) { + + int position = arg.getPosition(); + + // position has been explicity set + if (position >= 0) { + return; + } + + // first arg to be added + if (args == null || args.length == 0) { + arg.setPosition(0); + return; + } + + // determine the position of the last argument with + // the same name or the last default argument + String keyName = arg.getName() == null ? DEFAULT_ARG : arg.getName(); + int lastPosition = -1; + int lastDefault = -1; + for (int i = 0; i < args.length; i++) { + if (args[i] != null && args[i].containsKey(keyName)) { + lastPosition = i; + } + if (args[i] != null && args[i].containsKey(DEFAULT_ARG)) { + lastDefault = i; + } + } + + if (lastPosition < 0) { + lastPosition = lastDefault; + } + + // allocate the next position + arg.setPosition(++lastPosition); + + } + + /** + * Ensures that the args array can hold the given arg. Resizes the array as + * necessary. + * @param arg Determine if the args array is long enough to store this arg's + * position. + */ + private void ensureArgsCapacity(Arg arg) { + if (arg.getPosition() >= this.args.length) { + @SuppressWarnings("unchecked") // cannot check this at compile time, but it is OK + Map[] newArgs = new Map[arg.getPosition() + 1]; + System.arraycopy(this.args, 0, newArgs, 0, this.args.length); + this.args = newArgs; + } + } + + /** + * Gets the default Arg object at the given position. + * @param position Validation message argument's position. + * @return The default Arg or null if not found. + * @since Validator 1.1 + */ + public Arg getArg(int position) { + return this.getArg(DEFAULT_ARG, position); + } + + /** + * Gets the Arg object at the given position. If the key + * finds a null value then the default value will be + * retrieved. + * @param key The name the Arg is stored under. If not found, the default + * Arg for the given position (if any) will be retrieved. + * @param position The Arg number to find. + * @return The Arg with the given name and position or null if not found. + * @since Validator 1.1 + */ + public Arg getArg(String key, int position) { + if ((position >= this.args.length) || (this.args[position] == null)) { + return null; + } + + Arg arg = args[position].get(key); + + // Didn't find default arg so exit, otherwise we would get into + // infinite recursion + if ((arg == null) && key.equals(DEFAULT_ARG)) { + return null; + } + + return (arg == null) ? this.getArg(position) : arg; + } + + /** + * Retrieves the Args for the given validator name. + * @param key The validator's args to retrieve. + * @return An Arg[] sorted by the Args' positions (i.e. the Arg at index 0 + * has a position of 0). + * @since Validator 1.1.1 + */ + public Arg[] getArgs(String key){ + Arg[] argList = new Arg[this.args.length]; + + for (int i = 0; i < this.args.length; i++) { + argList[i] = this.getArg(key, i); + } + + return argList; + } + + /** + * Add a Var to the Field. + * @param v The Validator Argument. + */ + public void addVar(Var v) { + this.getVarMap().put(v.getName(), v); + } + + /** + * Add a Var, based on the values passed in, to the + * Field. + * @param name Name of the validation. + * @param value The Argument's value. + * @param jsType The Javascript type. + */ + public void addVar(String name, String value, String jsType) { + this.addVar(new Var(name, value, jsType)); + } + + /** + * Retrieve a variable. + * @param mainKey The Variable's key + * @return the Variable + */ + public Var getVar(String mainKey) { + return getVarMap().get(mainKey); + } + + /** + * Retrieve a variable's value. + * @param mainKey The Variable's key + * @return the Variable's value + */ +/** + * Retrieve a variable's value. + * + * @param mainKey + * The Variable's key + * @return the Variable's value + */ +public java.lang.String getVarValue(java.lang.String mainKey) { + java.lang.String value = null; + org.apache.commons.validator.Var v = getVarMap().get(mainKey); + { + value = /* NPEX_NULL_EXP */ + v.getValue(); + } + return value; +} + + /** + * The Field's variables are returned as an + * unmodifiable Map. + * @return the Map of Variable's for a Field. + */ + public Map getVars() { + return Collections.unmodifiableMap(getVarMap()); + } + + /** + * Gets a unique key based on the property and indexedProperty fields. + * @return a unique key for the field. + */ + public String getKey() { + if (this.key == null) { + this.generateKey(); + } + + return this.key; + } + + /** + * Sets a unique key for the field. This can be used to change + * the key temporarily to have a unique key for an indexed field. + * @param key a unique key for the field + */ + public void setKey(String key) { + this.key = key; + } + + /** + * If there is a value specified for the indexedProperty field then + * true will be returned. Otherwise it will be + * false. + * @return Whether the Field is indexed. + */ + public boolean isIndexed() { + return (indexedListProperty != null && indexedListProperty.length() > 0); + } + + /** + * Generate correct key value. + */ + public void generateKey() { + if (this.isIndexed()) { + this.key = this.indexedListProperty + TOKEN_INDEXED + "." + this.property; + } else { + this.key = this.property; + } + } + + /** + * Replace constants with values in fields and process the depends field + * to create the dependency Map. + */ + void process(Map globalConstants, Map constants) { + this.hMsgs.setFast(false); + this.hVars.setFast(true); + + this.generateKey(); + + // Process FormSet Constants + for (Iterator> i = constants.entrySet().iterator(); i.hasNext();) { + Entry entry = i.next(); + String key1 = entry.getKey(); + String key2 = TOKEN_START + key1 + TOKEN_END; + String replaceValue = entry.getValue(); + + property = ValidatorUtils.replace(property, key2, replaceValue); + + processVars(key2, replaceValue); + + this.processMessageComponents(key2, replaceValue); + } + + // Process Global Constants + for (Iterator> i = globalConstants.entrySet().iterator(); i.hasNext();) { + Entry entry = i.next(); + String key1 = entry.getKey(); + String key2 = TOKEN_START + key1 + TOKEN_END; + String replaceValue = entry.getValue(); + + property = ValidatorUtils.replace(property, key2, replaceValue); + + processVars(key2, replaceValue); + + this.processMessageComponents(key2, replaceValue); + } + + // Process Var Constant Replacement + for (Iterator i = getVarMap().keySet().iterator(); i.hasNext();) { + String key1 = i.next(); + String key2 = TOKEN_START + TOKEN_VAR + key1 + TOKEN_END; + Var var = this.getVar(key1); + String replaceValue = var.getValue(); + + this.processMessageComponents(key2, replaceValue); + } + + hMsgs.setFast(true); + } + + /** + * Replace the vars value with the key/value pairs passed in. + */ + private void processVars(String key, String replaceValue) { + Iterator i = getVarMap().keySet().iterator(); + while (i.hasNext()) { + String varKey = i.next(); + Var var = this.getVar(varKey); + + var.setValue(ValidatorUtils.replace(var.getValue(), key, replaceValue)); + } + + } + + /** + * Replace the args key value with the key/value pairs passed in. + */ + private void processMessageComponents(String key, String replaceValue) { + String varKey = TOKEN_START + TOKEN_VAR; + // Process Messages + if (key != null && !key.startsWith(varKey)) { + for (Iterator i = getMsgMap().values().iterator(); i.hasNext();) { + Msg msg = i.next(); + msg.setKey(ValidatorUtils.replace(msg.getKey(), key, replaceValue)); + } + } + + this.processArg(key, replaceValue); + } + + /** + * Replace the arg Collection key value with the key/value + * pairs passed in. + */ + private void processArg(String key, String replaceValue) { + for (int i = 0; i < this.args.length; i++) { + + Map argMap = this.args[i]; + if (argMap == null) { + continue; + } + + Iterator iter = argMap.values().iterator(); + while (iter.hasNext()) { + Arg arg = iter.next(); + + if (arg != null) { + arg.setKey( + ValidatorUtils.replace(arg.getKey(), key, replaceValue)); + } + } + } + } + + /** + * Checks if the validator is listed as a dependency. + * @param validatorName Name of the validator to check. + * @return Whether the field is dependant on a validator. + */ + public boolean isDependency(String validatorName) { + return this.dependencyList.contains(validatorName); + } + + /** + * Gets an unmodifiable List of the dependencies in the same + * order they were defined in parameter passed to the setDepends() method. + * @return A list of the Field's dependancies. + */ + public List getDependencyList() { + return Collections.unmodifiableList(this.dependencyList); + } + + /** + * Creates and returns a copy of this object. + * @return A copy of the Field. + */ + @Override + public Object clone() { + Field field = null; + try { + field = (Field) super.clone(); + } catch(CloneNotSupportedException e) { + throw new RuntimeException(e.toString()); + } + + @SuppressWarnings("unchecked") // empty array always OK; cannot check this at compile time + final Map[] tempMap = new Map[this.args.length]; + field.args = tempMap; + for (int i = 0; i < this.args.length; i++) { + if (this.args[i] == null) { + continue; + } + + Map argMap = new HashMap<>(this.args[i]); + Iterator> iter = argMap.entrySet().iterator(); + while (iter.hasNext()) { + Entry entry = iter.next(); + String validatorName = entry.getKey(); + Arg arg = entry.getValue(); + argMap.put(validatorName, (Arg) arg.clone()); + } + field.args[i] = argMap; + } + + field.hVars = ValidatorUtils.copyFastHashMap(hVars); + field.hMsgs = ValidatorUtils.copyFastHashMap(hMsgs); + + return field; + } + + /** + * Returns a string representation of the object. + * @return A string representation of the object. + */ + @Override + public String toString() { + StringBuilder results = new StringBuilder(); + + results.append("\t\tkey = " + key + "\n"); + results.append("\t\tproperty = " + property + "\n"); + results.append("\t\tindexedProperty = " + indexedProperty + "\n"); + results.append("\t\tindexedListProperty = " + indexedListProperty + "\n"); + results.append("\t\tdepends = " + depends + "\n"); + results.append("\t\tpage = " + page + "\n"); + results.append("\t\tfieldOrder = " + fieldOrder + "\n"); + + if (hVars != null) { + results.append("\t\tVars:\n"); + for (Iterator i = getVarMap().keySet().iterator(); i.hasNext();) { + Object key1 = i.next(); + results.append("\t\t\t"); + results.append(key1); + results.append("="); + results.append(getVarMap().get(key1)); + results.append("\n"); + } + } + + return results.toString(); + } + + /** + * Returns an indexed property from the object we're validating. + * + * @param bean The bean to extract the indexed values from. + * @throws ValidatorException If there's an error looking up the property + * or, the property found is not indexed. + */ + Object[] getIndexedProperty(Object bean) throws ValidatorException { + Object indexProp = null; + + try { + indexProp = + PropertyUtils.getProperty(bean, this.getIndexedListProperty()); + + } catch(IllegalAccessException|InvocationTargetException|NoSuchMethodException e) { + throw new ValidatorException(e.getMessage()); + } + + if (indexProp instanceof Collection) { + return ((Collection) indexProp).toArray(); + + } else if (indexProp.getClass().isArray()) { + return (Object[]) indexProp; + + } else { + throw new ValidatorException(this.getKey() + " is not indexed"); + } + + } + /** + * Returns the size of an indexed property from the object we're validating. + * + * @param bean The bean to extract the indexed values from. + * @throws ValidatorException If there's an error looking up the property + * or, the property found is not indexed. + */ + private int getIndexedPropertySize(Object bean) throws ValidatorException { + Object indexProp = null; + + try { + indexProp = + PropertyUtils.getProperty(bean, this.getIndexedListProperty()); + + } catch(IllegalAccessException|InvocationTargetException|NoSuchMethodException e) { + throw new ValidatorException(e.getMessage()); + } + + if (indexProp == null) { + return 0; + } else if (indexProp instanceof Collection) { + return ((Collection)indexProp).size(); + } else if (indexProp.getClass().isArray()) { + return ((Object[])indexProp).length; + } else { + throw new ValidatorException(this.getKey() + " is not indexed"); + } + + } + + /** + * Executes the given ValidatorAction and all ValidatorActions that it + * depends on. + * @return true if the validation succeeded. + */ + private boolean validateForRule( + ValidatorAction va, + ValidatorResults results, + Map actions, + Map params, + int pos) + throws ValidatorException { + + ValidatorResult result = results.getValidatorResult(this.getKey()); + if (result != null && result.containsAction(va.getName())) { + return result.isValid(va.getName()); + } + + if (!this.runDependentValidators(va, results, actions, params, pos)) { + return false; + } + + return va.executeValidationMethod(this, params, results, pos); + } + + /** + * Calls all of the validators that this validator depends on. + * TODO ValidatorAction should know how to run its own dependencies. + * @param va Run dependent validators for this action. + * @param results + * @param actions + * @param pos + * @return true if all of the dependent validations passed. + * @throws ValidatorException If there's an error running a validator + */ + private boolean runDependentValidators( + ValidatorAction va, + ValidatorResults results, + Map actions, + Map params, + int pos) + throws ValidatorException { + + List dependentValidators = va.getDependencyList(); + + if (dependentValidators.isEmpty()) { + return true; + } + + Iterator iter = dependentValidators.iterator(); + while (iter.hasNext()) { + String depend = iter.next(); + + ValidatorAction action = actions.get(depend); + if (action == null) { + this.handleMissingAction(depend); + } + + if (!this.validateForRule(action, results, actions, params, pos)) { + return false; + } + } + + return true; + } + + /** + * Run the configured validations on this field. Run all validations + * in the depends clause over each item in turn, returning when the first + * one fails. + * @param params A Map of parameter class names to parameter values to pass + * into validation methods. + * @param actions A Map of validator names to ValidatorAction objects. + * @return A ValidatorResults object containing validation messages for + * this field. + * @throws ValidatorException If an error occurs during validation. + */ + public ValidatorResults validate(Map params, Map actions) + throws ValidatorException { + + if (this.getDepends() == null) { + return new ValidatorResults(); + } + + ValidatorResults allResults = new ValidatorResults(); + + Object bean = params.get(Validator.BEAN_PARAM); + int numberOfFieldsToValidate = + this.isIndexed() ? this.getIndexedPropertySize(bean) : 1; + + for (int fieldNumber = 0; fieldNumber < numberOfFieldsToValidate; fieldNumber++) { + + ValidatorResults results = new ValidatorResults(); + synchronized(dependencyList) { + Iterator dependencies = this.dependencyList.iterator(); + while (dependencies.hasNext()) { + String depend = dependencies.next(); + + ValidatorAction action = actions.get(depend); + if (action == null) { + this.handleMissingAction(depend); + } + + boolean good = + validateForRule(action, results, actions, params, fieldNumber); + + if (!good) { + allResults.merge(results); + return allResults; + } + } + } + allResults.merge(results); + } + + return allResults; + } + + /** + * Called when a validator name is used in a depends clause but there is + * no know ValidatorAction configured for that name. + * @param name The name of the validator in the depends list. + * @throws ValidatorException + */ + private void handleMissingAction(String name) throws ValidatorException { + throw new ValidatorException("No ValidatorAction named " + name + + " found for field " + this.getProperty()); + } + + /** + * Returns a Map of String Msg names to Msg objects. + * @since Validator 1.2.0 + * @return A Map of the Field's messages. + */ + @SuppressWarnings("unchecked") // FastHashMap does not support generics + protected Map getMsgMap() { + return hMsgs; + } + + /** + * Returns a Map of String Var names to Var objects. + * @since Validator 1.2.0 + * @return A Map of the Field's variables. + */ + @SuppressWarnings("unchecked") // FastHashMap does not support generics + protected Map getVarMap() { + return hVars; + } +} + diff --git a/Java/commons-validator-Field_500/metadata.json b/Java/commons-validator-Field_500/metadata.json new file mode 100644 index 000000000..4cb2a1f73 --- /dev/null +++ b/Java/commons-validator-Field_500/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-Field_500", + "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/validator/Field.java", + "line": 508, + "npe_method": "getVarValue", + "deref_field": "v", + "npe_class": "Field", + "repo": "commons-validator", + "bug_id": "Field_500" + } +} diff --git a/Java/commons-validator-Field_500/npe.json b/Java/commons-validator-Field_500/npe.json new file mode 100644 index 000000000..9a204d394 --- /dev/null +++ b/Java/commons-validator-Field_500/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/Field.java", + "line": 508, + "npe_method": "getVarValue", + "deref_field": "v", + "npe_class": "Field" +} \ No newline at end of file diff --git a/Java/commons-validator-IBANCheckDigit_102/Dockerfile b/Java/commons-validator-IBANCheckDigit_102/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-IBANCheckDigit_102/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-IBANCheckDigit_102/buggy.java b/Java/commons-validator-IBANCheckDigit_102/buggy.java new file mode 100644 index 000000000..caa0dd217 --- /dev/null +++ b/Java/commons-validator-IBANCheckDigit_102/buggy.java @@ -0,0 +1,153 @@ +/* + * 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.validator.routines.checkdigit; + +import java.io.Serializable; + +/** + * IBAN (International Bank Account Number) Check Digit calculation/validation. + *

+ * This routine is based on the ISO 7064 Mod 97,10 check digit calculation routine. + *

+ * The two check digit characters in a IBAN number are the third and fourth characters + * in the code. For check digit calculation/validation the first four characters are moved + * to the end of the code. + * So CCDDnnnnnnn becomes nnnnnnnCCDD (where + * CC is the country code and DD is the check digit). For + * check digit calculation the check digit value should be set to zero (i.e. + * CC00nnnnnnn in this example. + *

+ * Note: the class does not check the format of the IBAN number, only the check digits. + *

+ * For further information see + * Wikipedia - + * IBAN number. + * + * @version $Revision$ + * @since Validator 1.4 + */ +public final class IBANCheckDigit implements CheckDigit, Serializable { + + private static final int MIN_CODE_LEN = 5; + + private static final long serialVersionUID = -3600191725934382801L; + + private static final int MAX_ALPHANUMERIC_VALUE = 35; // Character.getNumericValue('Z') + + /** Singleton IBAN Number Check Digit instance */ + public static final CheckDigit IBAN_CHECK_DIGIT = new IBANCheckDigit(); + + private static final long MAX = 999999999; + + private static final long MODULUS = 97; + + /** + * Construct Check Digit routine for IBAN Numbers. + */ + public IBANCheckDigit() { + } + + /** + * Validate the check digit of an IBAN code. + * + * @param code The code to validate + * @return true if the check digit is valid, otherwise + * false + */ + @Override + public boolean isValid(String code) { + if (code == null || code.length() < MIN_CODE_LEN) { + return false; + } + String check = code.substring(2,4); // CHECKSTYLE IGNORE MagicNumber + if ("00".equals(check) || "01".equals(check) || "99".equals(check)) { + return false; + } + try { + int modulusResult = calculateModulus(code); + return (modulusResult == 1); + } catch (CheckDigitException ex) { + return false; + } + } + + /** + * Calculate the Check Digit for an IBAN code. + *

+ * Note: The check digit is the third and fourth + * characters and is set to the value "00". + * + * @param code The code to calculate the Check Digit for + * @return The calculated Check Digit as 2 numeric decimal characters, e.g. "42" + * @throws CheckDigitException if an error occurs calculating + * the check digit for the specified code + */ + @Override +/** + * Calculate the Check Digit for an IBAN code. + *

+ * Note: The check digit is the third and fourth + * characters and is set to the value "00". + * + * @param code + * The code to calculate the Check Digit for + * @return The calculated Check Digit as 2 numeric decimal characters, e.g. "42" + * @throws CheckDigitException + * if an error occurs calculating + * the check digit for the specified code + */ +public java.lang.String calculate(java.lang.String code) throws org.apache.commons.validator.routines.checkdigit.CheckDigitException { + if ((code == null) || (code.length() < org.apache.commons.validator.routines.checkdigit.IBANCheckDigit.MIN_CODE_LEN)) { + throw new org.apache.commons.validator.routines.checkdigit.CheckDigitException("Invalid Code length=" + /* NPEX_NULL_EXP */ + code.length()); + } + code = (code.substring(0, 2) + "00") + code.substring(4);// CHECKSTYLE IGNORE MagicNumber + + int modulusResult = calculateModulus(code); + int charValue = 98 - modulusResult;// CHECKSTYLE IGNORE MagicNumber + + java.lang.String checkDigit = java.lang.Integer.toString(charValue); + return charValue > 9 ? checkDigit : "0" + checkDigit;// CHECKSTYLE IGNORE MagicNumber + +} + + /** + * Calculate the modulus for a code. + * + * @param code The code to calculate the modulus for. + * @return The modulus value + * @throws CheckDigitException if an error occurs calculating the modulus + * for the specified code + */ + private int calculateModulus(String code) throws CheckDigitException { + String reformattedCode = code.substring(4) + code.substring(0, 4); // CHECKSTYLE IGNORE MagicNumber + long total = 0; + for (int i = 0; i < reformattedCode.length(); i++) { + int charValue = Character.getNumericValue(reformattedCode.charAt(i)); + if (charValue < 0 || charValue > MAX_ALPHANUMERIC_VALUE) { + throw new CheckDigitException("Invalid Character[" + + i + "] = '" + charValue + "'"); + } + total = (charValue > 9 ? total * 100 : total * 10) + charValue; // CHECKSTYLE IGNORE MagicNumber + if (total > MAX) { + total = total % MODULUS; + } + } + return (int)(total % MODULUS); + } + +} diff --git a/Java/commons-validator-IBANCheckDigit_102/metadata.json b/Java/commons-validator-IBANCheckDigit_102/metadata.json new file mode 100644 index 000000000..f762441f8 --- /dev/null +++ b/Java/commons-validator-IBANCheckDigit_102/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-IBANCheckDigit_102", + "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/validator/routines/checkdigit/IBANCheckDigit.java", + "line": 116, + "npe_method": "calculate", + "deref_field": "code", + "npe_class": "IBANCheckDigit", + "repo": "commons-validator", + "bug_id": "IBANCheckDigit_102" + } +} diff --git a/Java/commons-validator-IBANCheckDigit_102/npe.json b/Java/commons-validator-IBANCheckDigit_102/npe.json new file mode 100644 index 000000000..2f02c4a06 --- /dev/null +++ b/Java/commons-validator-IBANCheckDigit_102/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/checkdigit/IBANCheckDigit.java", + "line": 116, + "npe_method": "calculate", + "deref_field": "code", + "npe_class": "IBANCheckDigit" +} \ No newline at end of file diff --git a/Java/commons-validator-ISBNCheckDigit_95/Dockerfile b/Java/commons-validator-ISBNCheckDigit_95/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-ISBNCheckDigit_95/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-ISBNCheckDigit_95/buggy.java b/Java/commons-validator-ISBNCheckDigit_95/buggy.java new file mode 100644 index 000000000..0ae6597b4 --- /dev/null +++ b/Java/commons-validator-ISBNCheckDigit_95/buggy.java @@ -0,0 +1,124 @@ +/* + * 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.validator.routines.checkdigit; + +import java.io.Serializable; + +/** + * Combined ISBN-10 / ISBN-13 Check Digit calculation/validation. + *

+ * This implementation validates/calculates ISBN check digits + * based on the length of the code passed to it - delegating + * either to the {@link ISBNCheckDigit#ISBN10_CHECK_DIGIT} or the + * {@link ISBNCheckDigit#ISBN13_CHECK_DIGIT} routines to perform the actual + * validation/calculation. + *

+ * N.B. From 1st January 2007 the book industry will start to use a new 13 digit + * ISBN number (rather than this 10 digit ISBN number) which uses the EAN-13 / UPC + * standard. + * + * @version $Revision$ + * @since Validator 1.4 + */ +public final class ISBNCheckDigit implements CheckDigit, Serializable { + + private static final long serialVersionUID = 1391849166205184558L; + + /** Singleton ISBN-10 Check Digit instance */ + public static final CheckDigit ISBN10_CHECK_DIGIT = ISBN10CheckDigit.ISBN10_CHECK_DIGIT; + + /** Singleton ISBN-13 Check Digit instance */ + public static final CheckDigit ISBN13_CHECK_DIGIT = EAN13CheckDigit.EAN13_CHECK_DIGIT; + + /** Singleton combined ISBN-10 / ISBN-13 Check Digit instance */ + public static final CheckDigit ISBN_CHECK_DIGIT = new ISBNCheckDigit(); + + /** + * Calculate an ISBN-10 or ISBN-13 check digit, depending + * on the length of the code. + *

+ * If the length of the code is 9, it is treated as an ISBN-10 + * code or if the length of the code is 12, it is treated as an ISBN-13 + * code. + * + * @param code The ISBN code to validate (should have a length of + * 9 or 12) + * @return The ISBN-10 check digit if the length is 9 or an ISBN-13 + * check digit if the length is 12. + * @throws CheckDigitException if the code is missing, or an invalid + * length (i.e. not 9 or 12) or if there is an error calculating the + * check digit. + */ + @Override + public String calculate(String code) throws CheckDigitException { + if (code == null || code.length() == 0) { + throw new CheckDigitException("ISBN Code is missing"); + } else if (code.length() == 9) { // CHECKSTYLE IGNORE MagicNumber + return ISBN10_CHECK_DIGIT.calculate(code); + } else if (code.length() == 12) { // CHECKSTYLE IGNORE MagicNumber + return ISBN13_CHECK_DIGIT.calculate(code); + } else { + throw new CheckDigitException("Invalid ISBN Length = " + code.length()); + } + } + + /** + *

Validate an ISBN-10 or ISBN-13 check digit, depending + * on the length of the code.

+ *

+ * If the length of the code is 10, it is treated as an ISBN-10 + * code or ff the length of the code is 13, it is treated as an ISBN-13 + * code. + * + * @param code The ISBN code to validate (should have a length of + * 10 or 13) + * @return true if the code has a length of 10 and is + * a valid ISBN-10 check digit or the code has a length of 13 and is + * a valid ISBN-13 check digit - otherwise false. + */ + @Override +/** + *

Validate an ISBN-10 or ISBN-13 check digit, depending + * on the length of the code.

+ *

+ * If the length of the code is 10, it is treated as an ISBN-10 + * code or ff the length of the code is 13, it is treated as an ISBN-13 + * code. + * + * @param code + * The ISBN code to validate (should have a length of + * 10 or 13) + * @return true if the code has a length of 10 and is +a valid ISBN-10 check digit or the code has a length of 13 and is +a valid ISBN-13 check digit - otherwise false. + */ +public boolean isValid(java.lang.String code) { + { + if (/* NPEX_NULL_EXP */ + code.length() == 10) { + // CHECKSTYLE IGNORE MagicNumber + return org.apache.commons.validator.routines.checkdigit.ISBNCheckDigit.ISBN10_CHECK_DIGIT.isValid(code); + } else if (code.length() == 13) { + // CHECKSTYLE IGNORE MagicNumber + return org.apache.commons.validator.routines.checkdigit.ISBNCheckDigit.ISBN13_CHECK_DIGIT.isValid(code); + } else { + return false; + } + } +} + +} diff --git a/Java/commons-validator-ISBNCheckDigit_95/metadata.json b/Java/commons-validator-ISBNCheckDigit_95/metadata.json new file mode 100644 index 000000000..27404d187 --- /dev/null +++ b/Java/commons-validator-ISBNCheckDigit_95/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-ISBNCheckDigit_95", + "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/validator/routines/checkdigit/ISBNCheckDigit.java", + "line": 112, + "npe_method": "isValid", + "deref_field": "code", + "npe_class": "ISBNCheckDigit", + "repo": "commons-validator", + "bug_id": "ISBNCheckDigit_95" + } +} diff --git a/Java/commons-validator-ISBNCheckDigit_95/npe.json b/Java/commons-validator-ISBNCheckDigit_95/npe.json new file mode 100644 index 000000000..20bb53f92 --- /dev/null +++ b/Java/commons-validator-ISBNCheckDigit_95/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/checkdigit/ISBNCheckDigit.java", + "line": 112, + "npe_method": "isValid", + "deref_field": "code", + "npe_class": "ISBNCheckDigit" +} \ No newline at end of file diff --git a/Java/commons-validator-ISBNValidator_220/Dockerfile b/Java/commons-validator-ISBNValidator_220/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-ISBNValidator_220/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-ISBNValidator_220/buggy.java b/Java/commons-validator-ISBNValidator_220/buggy.java new file mode 100644 index 000000000..916cb0f87 --- /dev/null +++ b/Java/commons-validator-ISBNValidator_220/buggy.java @@ -0,0 +1,283 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; +import org.apache.commons.validator.routines.checkdigit.EAN13CheckDigit; +import org.apache.commons.validator.routines.checkdigit.ISBN10CheckDigit; +import org.apache.commons.validator.routines.checkdigit.CheckDigitException; + +/** + * ISBN-10 and ISBN-13 Code Validation. + *

+ * This validator validates the code is either a valid ISBN-10 + * (using a {@link CodeValidator} with the {@link ISBN10CheckDigit}) + * or a valid ISBN-13 code (using a {@link CodeValidator} with the + * the {@link EAN13CheckDigit} routine). + *

+ * The validate() methods return the ISBN code with formatting + * characters removed if valid or null if invalid. + *

+ * This validator also provides the facility to convert ISBN-10 codes to + * ISBN-13 if the convert property is true. + *

+ * From 1st January 2007 the book industry will start to use a new 13 digit + * ISBN number (rather than this 10 digit ISBN number). ISBN-13 codes are + * EAN + * codes, for more information see:

+ * + * + * + *

ISBN-13s are either prefixed with 978 or 979. 978 prefixes are only assigned + * to the ISBN agency. 979 prefixes may be assigned to ISBNs or ISMNs + * (International + * Standard Music Numbers). + *

    + *
  • 979-0 are assigned to the ISMN agency
  • + *
  • 979-10, 979-11, 979-12 are assigned to the ISBN agency
  • + *
+ * All other 979 prefixed EAN-13 numbers have not yet been assigned to an agency. The + * validator validates all 13 digit codes with 978 or 979 prefixes. + * + * @version $Revision$ + * @since Validator 1.4 + */ +public class ISBNValidator implements Serializable { + + private static final int ISBN_10_LEN = 10; + + private static final long serialVersionUID = 4319515687976420405L; + + private static final String SEP = "(?:\\-|\\s)"; + private static final String GROUP = "(\\d{1,5})"; + private static final String PUBLISHER = "(\\d{1,7})"; + private static final String TITLE = "(\\d{1,6})"; + + /** + * ISBN-10 consists of 4 groups of numbers separated by either dashes (-) + * or spaces. The first group is 1-5 characters, second 1-7, third 1-6, + * and fourth is 1 digit or an X. + */ + static final String ISBN10_REGEX = + "^(?:(\\d{9}[0-9X])|(?:" + GROUP + SEP + PUBLISHER + SEP + TITLE + SEP + "([0-9X])))$"; + + /** + * ISBN-13 consists of 5 groups of numbers separated by either dashes (-) + * or spaces. The first group is 978 or 979, the second group is + * 1-5 characters, third 1-7, fourth 1-6, and fifth is 1 digit. + */ + static final String ISBN13_REGEX = + "^(978|979)(?:(\\d{10})|(?:" + SEP + GROUP + SEP + PUBLISHER + SEP + TITLE + SEP + "([0-9])))$"; + + /** ISBN Code Validator (which converts ISBN-10 codes to ISBN-13 */ + private static final ISBNValidator ISBN_VALIDATOR = new ISBNValidator(); + + /** ISBN Code Validator (which converts ISBN-10 codes to ISBN-13 */ + private static final ISBNValidator ISBN_VALIDATOR_NO_CONVERT = new ISBNValidator(false); + + + /** ISBN-10 Code Validator */ + private final CodeValidator isbn10Validator = new CodeValidator(ISBN10_REGEX, 10, ISBN10CheckDigit.ISBN10_CHECK_DIGIT); + + /** ISBN-13 Code Validator */ + private final CodeValidator isbn13Validator = new CodeValidator(ISBN13_REGEX, 13, EAN13CheckDigit.EAN13_CHECK_DIGIT); + + private final boolean convert; + + /** + * Return a singleton instance of the ISBN validator which + * converts ISBN-10 codes to ISBN-13. + * + * @return A singleton instance of the ISBN validator. + */ + public static ISBNValidator getInstance() { + return ISBN_VALIDATOR; + } + + /** + * Return a singleton instance of the ISBN validator specifying + * whether ISBN-10 codes should be converted to ISBN-13. + * + * @param convert true if valid ISBN-10 codes + * should be converted to ISBN-13 codes or false + * if valid ISBN-10 codes should be returned unchanged. + * @return A singleton instance of the ISBN validator. + */ + public static ISBNValidator getInstance(boolean convert) { + return (convert ? ISBN_VALIDATOR : ISBN_VALIDATOR_NO_CONVERT); + } + + /** + * Construct an ISBN validator which converts ISBN-10 codes + * to ISBN-13. + */ + public ISBNValidator() { + this(true); + } + + /** + * Construct an ISBN validator indicating whether + * ISBN-10 codes should be converted to ISBN-13. + * + * @param convert true if valid ISBN-10 codes + * should be converted to ISBN-13 codes or false + * if valid ISBN-10 codes should be returned unchanged. + */ + public ISBNValidator(boolean convert) { + this.convert = convert; + } + + /** + * Check the code is either a valid ISBN-10 or ISBN-13 code. + * + * @param code The code to validate. + * @return true if a valid ISBN-10 or + * ISBN-13 code, otherwise false. + */ + public boolean isValid(String code) { + return (isValidISBN13(code) || isValidISBN10(code)); + } + + /** + * Check the code is a valid ISBN-10 code. + * + * @param code The code to validate. + * @return true if a valid ISBN-10 + * code, otherwise false. + */ + public boolean isValidISBN10(String code) { + return isbn10Validator.isValid(code); + } + + /** + * Check the code is a valid ISBN-13 code. + * + * @param code The code to validate. + * @return true if a valid ISBN-13 + * code, otherwise false. + */ + public boolean isValidISBN13(String code) { + return isbn13Validator.isValid(code); + } + + /** + * Check the code is either a valid ISBN-10 or ISBN-13 code. + *

+ * If valid, this method returns the ISBN code with + * formatting characters removed (i.e. space or hyphen). + *

+ * Converts an ISBN-10 codes to ISBN-13 if + * convertToISBN13 is true. + * + * @param code The code to validate. + * @return A valid ISBN code if valid, otherwise null. + */ + public String validate(String code) { + String result = validateISBN13(code); + if (result == null) { + result = validateISBN10(code); + if (result != null && convert) { + result = convertToISBN13(result); + } + } + return result; + } + + /** + * Check the code is a valid ISBN-10 code. + *

+ * If valid, this method returns the ISBN-10 code with + * formatting characters removed (i.e. space or hyphen). + * + * @param code The code to validate. + * @return A valid ISBN-10 code if valid, + * otherwise null. + */ +/** + * Check the code is a valid ISBN-10 code. + *

+ * If valid, this method returns the ISBN-10 code with + * formatting characters removed (i.e. space or hyphen). + * + * @param code + * The code to validate. + * @return A valid ISBN-10 code if valid, +otherwise null. + */ +public java.lang.String validateISBN10(java.lang.String code) { + java.lang.Object result = isbn10Validator.validate(code); + return /* NPEX_NULL_EXP */ + result.toString(); +} + + /** + * Check the code is a valid ISBN-13 code. + *

+ * If valid, this method returns the ISBN-13 code with + * formatting characters removed (i.e. space or hyphen). + * + * @param code The code to validate. + * @return A valid ISBN-13 code if valid, + * otherwise null. + */ + public String validateISBN13(String code) { + Object result = isbn13Validator.validate(code); + return (result == null ? null : result.toString()); + } + + /** + * Convert an ISBN-10 code to an ISBN-13 code. + *

+ * This method requires a valid ISBN-10 with NO formatting + * characters. + * + * @param isbn10 The ISBN-10 code to convert + * @return A converted ISBN-13 code or null + * if the ISBN-10 code is not valid + */ + public String convertToISBN13(String isbn10) { + + if (isbn10 == null) { + return null; + } + + String input = isbn10.trim(); + if (input.length() != ISBN_10_LEN) { + throw new IllegalArgumentException("Invalid length " + input.length() + " for '" + input + "'"); + } + + // Calculate the new ISBN-13 code (drop the original checkdigit) + String isbn13 = "978" + input.substring(0, ISBN_10_LEN - 1); + try { + String checkDigit = isbn13Validator.getCheckDigit().calculate(isbn13); + isbn13 += checkDigit; + return isbn13; + } catch (CheckDigitException e) { + throw new IllegalArgumentException("Check digit error for '" + input + "' - " + e.getMessage()); + } + + } + +} diff --git a/Java/commons-validator-ISBNValidator_220/metadata.json b/Java/commons-validator-ISBNValidator_220/metadata.json new file mode 100644 index 000000000..83ebd9dc7 --- /dev/null +++ b/Java/commons-validator-ISBNValidator_220/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-ISBNValidator_220", + "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/validator/routines/ISBNValidator.java", + "line": 232, + "npe_method": "validateISBN10", + "deref_field": "result", + "npe_class": "ISBNValidator", + "repo": "commons-validator", + "bug_id": "ISBNValidator_220" + } +} diff --git a/Java/commons-validator-ISBNValidator_220/npe.json b/Java/commons-validator-ISBNValidator_220/npe.json new file mode 100644 index 000000000..950d40cee --- /dev/null +++ b/Java/commons-validator-ISBNValidator_220/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/ISBNValidator.java", + "line": 232, + "npe_method": "validateISBN10", + "deref_field": "result", + "npe_class": "ISBNValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-ISBNValidator_250/Dockerfile b/Java/commons-validator-ISBNValidator_250/Dockerfile new file mode 100644 index 000000000..2cb6b10d1 --- /dev/null +++ b/Java/commons-validator-ISBNValidator_250/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-ISBNValidator_250/buggy.java b/Java/commons-validator-ISBNValidator_250/buggy.java new file mode 100644 index 000000000..a839c09a7 --- /dev/null +++ b/Java/commons-validator-ISBNValidator_250/buggy.java @@ -0,0 +1,278 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; +import org.apache.commons.validator.routines.checkdigit.EAN13CheckDigit; +import org.apache.commons.validator.routines.checkdigit.ISBN10CheckDigit; +import org.apache.commons.validator.routines.checkdigit.CheckDigitException; + +/** + * ISBN-10 and ISBN-13 Code Validation. + *

+ * This validator validates the code is either a valid ISBN-10 + * (using a {@link CodeValidator} with the {@link ISBN10CheckDigit}) + * or a valid ISBN-13 code (using a {@link CodeValidator} with the + * the {@link EAN13CheckDigit} routine). + *

+ * The validate() methods return the ISBN code with formatting + * characters removed if valid or null if invalid. + *

+ * This validator also provides the facility to convert ISBN-10 codes to + * ISBN-13 if the convert property is true. + *

+ * From 1st January 2007 the book industry will start to use a new 13 digit + * ISBN number (rather than this 10 digit ISBN number). ISBN-13 codes are + * EAN + * codes, for more information see:

+ * + * + * + *

ISBN-13s are either prefixed with 978 or 979. 978 prefixes are only assigned + * to the ISBN agency. 979 prefixes may be assigned to ISBNs or ISMNs + * (International + * Standard Music Numbers). + *

    + *
  • 979-0 are assigned to the ISMN agency
  • + *
  • 979-10, 979-11, 979-12 are assigned to the ISBN agency
  • + *
+ * All other 979 prefixed EAN-13 numbers have not yet been assigned to an agency. The + * validator validates all 13 digit codes with 978 or 979 prefixes. + * + * @version $Revision$ + * @since Validator 1.4 + */ +public class ISBNValidator implements Serializable { + + private static final int ISBN_10_LEN = 10; + + private static final long serialVersionUID = 4319515687976420405L; + + private static final String SEP = "(?:\\-|\\s)"; + private static final String GROUP = "(\\d{1,5})"; + private static final String PUBLISHER = "(\\d{1,7})"; + private static final String TITLE = "(\\d{1,6})"; + + /** + * ISBN-10 consists of 4 groups of numbers separated by either dashes (-) + * or spaces. The first group is 1-5 characters, second 1-7, third 1-6, + * and fourth is 1 digit or an X. + */ + static final String ISBN10_REGEX = + "^(?:(\\d{9}[0-9X])|(?:" + GROUP + SEP + PUBLISHER + SEP + TITLE + SEP + "([0-9X])))$"; + + /** + * ISBN-13 consists of 5 groups of numbers separated by either dashes (-) + * or spaces. The first group is 978 or 979, the second group is + * 1-5 characters, third 1-7, fourth 1-6, and fifth is 1 digit. + */ + static final String ISBN13_REGEX = + "^(978|979)(?:(\\d{10})|(?:" + SEP + GROUP + SEP + PUBLISHER + SEP + TITLE + SEP + "([0-9])))$"; + + /** ISBN Code Validator (which converts ISBN-10 codes to ISBN-13 */ + private static final ISBNValidator ISBN_VALIDATOR = new ISBNValidator(); + + /** ISBN Code Validator (which converts ISBN-10 codes to ISBN-13 */ + private static final ISBNValidator ISBN_VALIDATOR_NO_CONVERT = new ISBNValidator(false); + + + /** ISBN-10 Code Validator */ + private final CodeValidator isbn10Validator = new CodeValidator(ISBN10_REGEX, 10, ISBN10CheckDigit.ISBN10_CHECK_DIGIT); + + /** ISBN-13 Code Validator */ + private final CodeValidator isbn13Validator = new CodeValidator(ISBN13_REGEX, 13, EAN13CheckDigit.EAN13_CHECK_DIGIT); + + private final boolean convert; + + /** + * Return a singleton instance of the ISBN validator which + * converts ISBN-10 codes to ISBN-13. + * + * @return A singleton instance of the ISBN validator. + */ + public static ISBNValidator getInstance() { + return ISBN_VALIDATOR; + } + + /** + * Return a singleton instance of the ISBN validator specifying + * whether ISBN-10 codes should be converted to ISBN-13. + * + * @param convert true if valid ISBN-10 codes + * should be converted to ISBN-13 codes or false + * if valid ISBN-10 codes should be returned unchanged. + * @return A singleton instance of the ISBN validator. + */ + public static ISBNValidator getInstance(boolean convert) { + return (convert ? ISBN_VALIDATOR : ISBN_VALIDATOR_NO_CONVERT); + } + + /** + * Construct an ISBN validator which converts ISBN-10 codes + * to ISBN-13. + */ + public ISBNValidator() { + this(true); + } + + /** + * Construct an ISBN validator indicating whether + * ISBN-10 codes should be converted to ISBN-13. + * + * @param convert true if valid ISBN-10 codes + * should be converted to ISBN-13 codes or false + * if valid ISBN-10 codes should be returned unchanged. + */ + public ISBNValidator(boolean convert) { + this.convert = convert; + } + + /** + * Check the code is either a valid ISBN-10 or ISBN-13 code. + * + * @param code The code to validate. + * @return true if a valid ISBN-10 or + * ISBN-13 code, otherwise false. + */ + public boolean isValid(String code) { + return (isValidISBN13(code) || isValidISBN10(code)); + } + + /** + * Check the code is a valid ISBN-10 code. + * + * @param code The code to validate. + * @return true if a valid ISBN-10 + * code, otherwise false. + */ + public boolean isValidISBN10(String code) { + return isbn10Validator.isValid(code); + } + + /** + * Check the code is a valid ISBN-13 code. + * + * @param code The code to validate. + * @return true if a valid ISBN-13 + * code, otherwise false. + */ + public boolean isValidISBN13(String code) { + return isbn13Validator.isValid(code); + } + + /** + * Check the code is either a valid ISBN-10 or ISBN-13 code. + *

+ * If valid, this method returns the ISBN code with + * formatting characters removed (i.e. space or hyphen). + *

+ * Converts an ISBN-10 codes to ISBN-13 if + * convertToISBN13 is true. + * + * @param code The code to validate. + * @return A valid ISBN code if valid, otherwise null. + */ + public String validate(String code) { + String result = validateISBN13(code); + if (result == null) { + result = validateISBN10(code); + if (result != null && convert) { + result = convertToISBN13(result); + } + } + return result; + } + + /** + * Check the code is a valid ISBN-10 code. + *

+ * If valid, this method returns the ISBN-10 code with + * formatting characters removed (i.e. space or hyphen). + * + * @param code The code to validate. + * @return A valid ISBN-10 code if valid, + * otherwise null. + */ + public String validateISBN10(String code) { + Object result = isbn10Validator.validate(code); + return (result == null ? null : result.toString()); + } + + /** + * Check the code is a valid ISBN-13 code. + *

+ * If valid, this method returns the ISBN-13 code with + * formatting characters removed (i.e. space or hyphen). + * + * @param code The code to validate. + * @return A valid ISBN-13 code if valid, + * otherwise null. + */ + public String validateISBN13(String code) { + Object result = isbn13Validator.validate(code); + return (result == null ? null : result.toString()); + } + + /** + * Convert an ISBN-10 code to an ISBN-13 code. + *

+ * This method requires a valid ISBN-10 with NO formatting + * characters. + * + * @param isbn10 The ISBN-10 code to convert + * @return A converted ISBN-13 code or null + * if the ISBN-10 code is not valid + */ +/** + * Convert an ISBN-10 code to an ISBN-13 code. + *

+ * This method requires a valid ISBN-10 with NO formatting + * characters. + * + * @param isbn10 + * The ISBN-10 code to convert + * @return A converted ISBN-13 code or null +if the ISBN-10 code is not valid + */ +public java.lang.String convertToISBN13(java.lang.String isbn10) { + { + java.lang.String input = /* NPEX_NULL_EXP */ + isbn10.trim(); + if (input.length() != org.apache.commons.validator.routines.ISBNValidator.ISBN_10_LEN) { + throw new java.lang.IllegalArgumentException(((("Invalid length " + input.length()) + " for '") + input) + "'"); + } + // Calculate the new ISBN-13 code (drop the original checkdigit) + java.lang.String isbn13 = "978" + input.substring(0, org.apache.commons.validator.routines.ISBNValidator.ISBN_10_LEN - 1); + try { + java.lang.String checkDigit = isbn13Validator.getCheckDigit().calculate(isbn13); + isbn13 += checkDigit; + return isbn13; + } catch (org.apache.commons.validator.routines.checkdigit.CheckDigitException e) { + throw new java.lang.IllegalArgumentException((("Check digit error for '" + input) + "' - ") + e.getMessage()); + } + } +} + +} diff --git a/Java/commons-validator-ISBNValidator_250/metadata.json b/Java/commons-validator-ISBNValidator_250/metadata.json new file mode 100644 index 000000000..9f04eb060 --- /dev/null +++ b/Java/commons-validator-ISBNValidator_250/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-ISBNValidator_250", + "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/validator/routines/ISBNValidator.java", + "line": 262, + "npe_method": "convertToISBN13", + "deref_field": "isbn10", + "npe_class": "ISBNValidator", + "repo": "commons-validator", + "bug_id": "ISBNValidator_250" + } +} diff --git a/Java/commons-validator-ISBNValidator_250/npe.json b/Java/commons-validator-ISBNValidator_250/npe.json new file mode 100644 index 000000000..eec029e0b --- /dev/null +++ b/Java/commons-validator-ISBNValidator_250/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/ISBNValidator.java", + "line": 262, + "npe_method": "convertToISBN13", + "deref_field": "isbn10", + "npe_class": "ISBNValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-ISSNValidator_149/Dockerfile b/Java/commons-validator-ISSNValidator_149/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-ISSNValidator_149/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-ISSNValidator_149/buggy.java b/Java/commons-validator-ISSNValidator_149/buggy.java new file mode 100644 index 000000000..7a1d29610 --- /dev/null +++ b/Java/commons-validator-ISSNValidator_149/buggy.java @@ -0,0 +1,214 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; + +import org.apache.commons.validator.routines.checkdigit.CheckDigitException; +import org.apache.commons.validator.routines.checkdigit.EAN13CheckDigit; +import org.apache.commons.validator.routines.checkdigit.ISSNCheckDigit; + +/** + * International Standard Serial Number (ISSN) + * is an eight-digit serial number used to + * uniquely identify a serial publication. + *

+ * The format is:
+ * 
+ * ISSN dddd-dddC
+ * where:
+ * d = decimal digit (0-9)
+ * C = checksum (0-9 or X)
+ * 
+ * The checksum is formed by adding the first 7 digits multiplied by
+ * the position in the entire number (counting from the right).
+ * 
+ * For example, abcd-efg would be 8a + 7b + 6c + 5d + 4e +3f +2g.
+ * The check digit is modulus 11, where the value 10 is represented by 'X'
+ * For example:
+ * ISSN 0317-8471
+ * ISSN 1050-124X
+ *
+ * This class strips off the 'ISSN ' prefix if it is present before passing
+ * the remainder to the checksum routine.
+ * 
+ * 
+ *

+ * Note: the {@link #isValid(String)} and {@link #validate(String)} methods strip off any leading + * or trailing spaces before doing the validation. + * To ensure that only a valid code (without 'ISSN ' prefix) is passed to a method, + * use the following code: + *

+ * Object valid = validator.validate(input); 
+ * if (valid != null) {
+ *    some_method(valid.toString());
+ * }
+ * 
+ * @since 1.5.0 + */ +public class ISSNValidator implements Serializable { + + private static final long serialVersionUID = 4319515687976420405L; + + private static final String ISSN_REGEX = "(?:ISSN )?(\\d{4})-(\\d{3}[0-9X])$"; // We don't include the '-' in the code, so it is 8 chars + + private static final int ISSN_LEN = 8; + + private static final String ISSN_PREFIX = "977"; + + private static final String EAN_ISSN_REGEX = "^(977)(?:(\\d{10}))$"; + + private static final int EAN_ISSN_LEN = 13; + + private static final CodeValidator VALIDATOR = new CodeValidator(ISSN_REGEX, ISSN_LEN, ISSNCheckDigit.ISSN_CHECK_DIGIT); + + private static final CodeValidator EAN_VALIDATOR = new CodeValidator(EAN_ISSN_REGEX, EAN_ISSN_LEN, EAN13CheckDigit.EAN13_CHECK_DIGIT); + + /** ISSN Code Validator */ + private static final ISSNValidator ISSN_VALIDATOR = new ISSNValidator(); + + /** + * Return a singleton instance of the ISSN validator + * + * @return A singleton instance of the ISSN validator. + */ + public static ISSNValidator getInstance() { + return ISSN_VALIDATOR; + } + + /** + * Check the code is a valid EAN code. + *

+ * If valid, this method returns the EAN code + * + * @param code The code to validate. + * @return A valid EAN code if valid, otherwise null. + */ + public Object validateEan(String code) { + return EAN_VALIDATOR.validate(code); + } + + /** + * Check the code is a valid ISSN code after any transformation + * by the validate routine. + * @param code The code to validate. + * @return true if a valid ISSN + * code, otherwise false. + */ + public boolean isValid(String code) { + return VALIDATOR.isValid(code); + } + + /** + * Check the code is valid ISSN code. + *

+ * If valid, this method returns the ISSN code with + * the 'ISSN ' prefix removed (if it was present) + * + * @param code The code to validate. + * @return A valid ISSN code if valid, otherwise null. + */ + public Object validate(String code) { + return VALIDATOR.validate(code); + } + + /** + * Convert an ISSN code to an EAN-13 code. + *

+ * This method requires a valid ISSN code. + * It may contain a leading 'ISSN ' prefix, + * as the input is passed through the {@link #validate(String)} + * method. + * + * @param issn The ISSN code to convert + * @param suffix the two digit suffix, e.g. "00" + * @return A converted EAN-13 code or null + * if the input ISSN code is not valid + */ +/** + * Convert an ISSN code to an EAN-13 code. + *

+ * This method requires a valid ISSN code. + * It may contain a leading 'ISSN ' prefix, + * as the input is passed through the {@link #validate(String)} + * method. + * + * @param issn + * The ISSN code to convert + * @param suffix + * the two digit suffix, e.g. "00" + * @return A converted EAN-13 code or null +if the input ISSN code is not valid + */ +public java.lang.String convertToEAN13(java.lang.String issn, java.lang.String suffix) { + if ((suffix == null) || (!suffix.matches("\\d\\d"))) { + throw new java.lang.IllegalArgumentException(("Suffix must be two digits: '" + suffix) + "'"); + } + java.lang.Object result = validate(issn); + { + // Calculate the new EAN-13 code + final java.lang.String input = /* NPEX_NULL_EXP */ + result.toString(); + java.lang.String ean13 = (org.apache.commons.validator.routines.ISSNValidator.ISSN_PREFIX + input.substring(0, input.length() - 1)) + suffix; + try { + java.lang.String checkDigit = org.apache.commons.validator.routines.checkdigit.EAN13CheckDigit.EAN13_CHECK_DIGIT.calculate(ean13); + ean13 += checkDigit; + return ean13; + } catch (org.apache.commons.validator.routines.checkdigit.CheckDigitException e) { + // Should not happen + throw new java.lang.IllegalArgumentException((("Check digit error for '" + ean13) + "' - ") + e.getMessage()); + } + } +} + + /** + * Extract an ISSN code from an ISSN-EAN-13 code. + *

+ * This method requires a valid ISSN-EAN-13 code with NO formatting + * characters. + * That is a 13 digit EAN-13 code with the '977' prefix + * + * @param ean13 The ISSN code to convert + * @return A valid ISSN code or null + * if the input ISSN EAN-13 code is not valid + */ + public String extractFromEAN13(String ean13) { + String input = ean13.trim(); + if (input.length() != EAN_ISSN_LEN ) { + throw new IllegalArgumentException("Invalid length " + input.length() + " for '" + input + "'"); + } + if (!input.startsWith(ISSN_PREFIX)) { + throw new IllegalArgumentException("Prefix must be " + ISSN_PREFIX + " to contain an ISSN: '" + ean13 + "'"); + } + Object result = validateEan(input); + if (result == null) { + return null; + } + // Calculate the ISSN code + input = result.toString(); + try { + //CHECKSTYLE:OFF: MagicNumber + String issnBase = input.substring(3,10); // TODO: how to derive these + //CHECKSTYLE:ON: MagicNumber + String checkDigit = ISSNCheckDigit.ISSN_CHECK_DIGIT.calculate(issnBase); + String issn = issnBase + checkDigit; + return issn; + } catch (CheckDigitException e) { // Should not happen + throw new IllegalArgumentException("Check digit error for '" + ean13 + "' - " + e.getMessage()); + } + } +} diff --git a/Java/commons-validator-ISSNValidator_149/metadata.json b/Java/commons-validator-ISSNValidator_149/metadata.json new file mode 100644 index 000000000..f9f54386d --- /dev/null +++ b/Java/commons-validator-ISSNValidator_149/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-ISSNValidator_149", + "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/validator/routines/ISSNValidator.java", + "line": 165, + "npe_method": "convertToEAN13", + "deref_field": "result", + "npe_class": "ISSNValidator", + "repo": "commons-validator", + "bug_id": "ISSNValidator_149" + } +} diff --git a/Java/commons-validator-ISSNValidator_149/npe.json b/Java/commons-validator-ISSNValidator_149/npe.json new file mode 100644 index 000000000..be1826c01 --- /dev/null +++ b/Java/commons-validator-ISSNValidator_149/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/ISSNValidator.java", + "line": 165, + "npe_method": "convertToEAN13", + "deref_field": "result", + "npe_class": "ISSNValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-ISSNValidator_186/Dockerfile b/Java/commons-validator-ISSNValidator_186/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-ISSNValidator_186/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-ISSNValidator_186/buggy.java b/Java/commons-validator-ISSNValidator_186/buggy.java new file mode 100644 index 000000000..b6f5d039f --- /dev/null +++ b/Java/commons-validator-ISSNValidator_186/buggy.java @@ -0,0 +1,216 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; + +import org.apache.commons.validator.routines.checkdigit.CheckDigitException; +import org.apache.commons.validator.routines.checkdigit.EAN13CheckDigit; +import org.apache.commons.validator.routines.checkdigit.ISSNCheckDigit; + +/** + * International Standard Serial Number (ISSN) + * is an eight-digit serial number used to + * uniquely identify a serial publication. + *

+ * The format is:
+ * 
+ * ISSN dddd-dddC
+ * where:
+ * d = decimal digit (0-9)
+ * C = checksum (0-9 or X)
+ * 
+ * The checksum is formed by adding the first 7 digits multiplied by
+ * the position in the entire number (counting from the right).
+ * 
+ * For example, abcd-efg would be 8a + 7b + 6c + 5d + 4e +3f +2g.
+ * The check digit is modulus 11, where the value 10 is represented by 'X'
+ * For example:
+ * ISSN 0317-8471
+ * ISSN 1050-124X
+ *
+ * This class strips off the 'ISSN ' prefix if it is present before passing
+ * the remainder to the checksum routine.
+ * 
+ * 
+ *

+ * Note: the {@link #isValid(String)} and {@link #validate(String)} methods strip off any leading + * or trailing spaces before doing the validation. + * To ensure that only a valid code (without 'ISSN ' prefix) is passed to a method, + * use the following code: + *

+ * Object valid = validator.validate(input); 
+ * if (valid != null) {
+ *    some_method(valid.toString());
+ * }
+ * 
+ * @since 1.5.0 + */ +public class ISSNValidator implements Serializable { + + private static final long serialVersionUID = 4319515687976420405L; + + private static final String ISSN_REGEX = "(?:ISSN )?(\\d{4})-(\\d{3}[0-9X])$"; // We don't include the '-' in the code, so it is 8 chars + + private static final int ISSN_LEN = 8; + + private static final String ISSN_PREFIX = "977"; + + private static final String EAN_ISSN_REGEX = "^(977)(?:(\\d{10}))$"; + + private static final int EAN_ISSN_LEN = 13; + + private static final CodeValidator VALIDATOR = new CodeValidator(ISSN_REGEX, ISSN_LEN, ISSNCheckDigit.ISSN_CHECK_DIGIT); + + private static final CodeValidator EAN_VALIDATOR = new CodeValidator(EAN_ISSN_REGEX, EAN_ISSN_LEN, EAN13CheckDigit.EAN13_CHECK_DIGIT); + + /** ISSN Code Validator */ + private static final ISSNValidator ISSN_VALIDATOR = new ISSNValidator(); + + /** + * Return a singleton instance of the ISSN validator + * + * @return A singleton instance of the ISSN validator. + */ + public static ISSNValidator getInstance() { + return ISSN_VALIDATOR; + } + + /** + * Check the code is a valid EAN code. + *

+ * If valid, this method returns the EAN code + * + * @param code The code to validate. + * @return A valid EAN code if valid, otherwise null. + */ + public Object validateEan(String code) { + return EAN_VALIDATOR.validate(code); + } + + /** + * Check the code is a valid ISSN code after any transformation + * by the validate routine. + * @param code The code to validate. + * @return true if a valid ISSN + * code, otherwise false. + */ + public boolean isValid(String code) { + return VALIDATOR.isValid(code); + } + + /** + * Check the code is valid ISSN code. + *

+ * If valid, this method returns the ISSN code with + * the 'ISSN ' prefix removed (if it was present) + * + * @param code The code to validate. + * @return A valid ISSN code if valid, otherwise null. + */ + public Object validate(String code) { + return VALIDATOR.validate(code); + } + + /** + * Convert an ISSN code to an EAN-13 code. + *

+ * This method requires a valid ISSN code. + * It may contain a leading 'ISSN ' prefix, + * as the input is passed through the {@link #validate(String)} + * method. + * + * @param issn The ISSN code to convert + * @param suffix the two digit suffix, e.g. "00" + * @return A converted EAN-13 code or null + * if the input ISSN code is not valid + */ + public String convertToEAN13(String issn, String suffix) { + + if (suffix == null || !suffix.matches("\\d\\d")) { + throw new IllegalArgumentException("Suffix must be two digits: '" + suffix + "'"); + } + + Object result = validate(issn); + if (result == null) { + return null; + } + + // Calculate the new EAN-13 code + final String input = result.toString(); + String ean13 = ISSN_PREFIX + input.substring(0, input.length() -1) + suffix; + try { + String checkDigit = EAN13CheckDigit.EAN13_CHECK_DIGIT.calculate(ean13); + ean13 += checkDigit; + return ean13; + } catch (CheckDigitException e) { // Should not happen + throw new IllegalArgumentException("Check digit error for '" + ean13 + "' - " + e.getMessage()); + } + + } + + /** + * Extract an ISSN code from an ISSN-EAN-13 code. + *

+ * This method requires a valid ISSN-EAN-13 code with NO formatting + * characters. + * That is a 13 digit EAN-13 code with the '977' prefix + * + * @param ean13 The ISSN code to convert + * @return A valid ISSN code or null + * if the input ISSN EAN-13 code is not valid + */ +/** + * Extract an ISSN code from an ISSN-EAN-13 code. + *

+ * This method requires a valid ISSN-EAN-13 code with NO formatting + * characters. + * That is a 13 digit EAN-13 code with the '977' prefix + * + * @param ean13 + * The ISSN code to convert + * @return A valid ISSN code or null +if the input ISSN EAN-13 code is not valid + */ +public java.lang.String extractFromEAN13(java.lang.String ean13) { + java.lang.String input = ean13.trim(); + if (input.length() != org.apache.commons.validator.routines.ISSNValidator.EAN_ISSN_LEN) { + throw new java.lang.IllegalArgumentException(((("Invalid length " + input.length()) + " for '") + input) + "'"); + } + if (!input.startsWith(org.apache.commons.validator.routines.ISSNValidator.ISSN_PREFIX)) { + throw new java.lang.IllegalArgumentException(((("Prefix must be " + org.apache.commons.validator.routines.ISSNValidator.ISSN_PREFIX) + " to contain an ISSN: '") + ean13) + "'"); + } + java.lang.Object result = validateEan(input); + { + // Calculate the ISSN code + input = /* NPEX_NULL_EXP */ + result.toString(); + try { + // CHECKSTYLE:OFF: MagicNumber + java.lang.String issnBase = input.substring(3, 10);// TODO: how to derive these + + // CHECKSTYLE:ON: MagicNumber + java.lang.String checkDigit = org.apache.commons.validator.routines.checkdigit.ISSNCheckDigit.ISSN_CHECK_DIGIT.calculate(issnBase); + java.lang.String issn = issnBase + checkDigit; + return issn; + } catch (org.apache.commons.validator.routines.checkdigit.CheckDigitException e) { + // Should not happen + throw new java.lang.IllegalArgumentException((("Check digit error for '" + ean13) + "' - ") + e.getMessage()); + } + } +} +} diff --git a/Java/commons-validator-ISSNValidator_186/metadata.json b/Java/commons-validator-ISSNValidator_186/metadata.json new file mode 100644 index 000000000..a49ef887d --- /dev/null +++ b/Java/commons-validator-ISSNValidator_186/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-ISSNValidator_186", + "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/validator/routines/ISSNValidator.java", + "line": 201, + "npe_method": "extractFromEAN13", + "deref_field": "result", + "npe_class": "ISSNValidator", + "repo": "commons-validator", + "bug_id": "ISSNValidator_186" + } +} diff --git a/Java/commons-validator-ISSNValidator_186/npe.json b/Java/commons-validator-ISSNValidator_186/npe.json new file mode 100644 index 000000000..67163d37d --- /dev/null +++ b/Java/commons-validator-ISSNValidator_186/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/ISSNValidator.java", + "line": 201, + "npe_method": "extractFromEAN13", + "deref_field": "result", + "npe_class": "ISSNValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-InetAddressValidator_90/Dockerfile b/Java/commons-validator-InetAddressValidator_90/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-InetAddressValidator_90/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-InetAddressValidator_90/buggy.java b/Java/commons-validator-InetAddressValidator_90/buggy.java new file mode 100644 index 000000000..e1ee70340 --- /dev/null +++ b/Java/commons-validator-InetAddressValidator_90/buggy.java @@ -0,0 +1,189 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + *

InetAddress validation and conversion routines (java.net.InetAddress).

+ * + *

This class provides methods to validate a candidate IP address. + * + *

+ * This class is a Singleton; you can retrieve the instance via the {@link #getInstance()} method. + *

+ * + * @version $Revision$ + * @since Validator 1.4 + */ +public class InetAddressValidator implements Serializable { + + private static final int IPV4_MAX_OCTET_VALUE = 255; + + private static final int MAX_UNSIGNED_SHORT = 0xffff; + + private static final int BASE_16 = 16; + + private static final long serialVersionUID = -919201640201914789L; + + private static final String IPV4_REGEX = + "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$"; + + // Max number of hex groups (separated by :) in an IPV6 address + private static final int IPV6_MAX_HEX_GROUPS = 8; + + // Max hex digits in each IPv6 group + private static final int IPV6_MAX_HEX_DIGITS_PER_GROUP = 4; + + /** + * Singleton instance of this class. + */ + private static final InetAddressValidator VALIDATOR = new InetAddressValidator(); + + /** IPv4 RegexValidator */ + private final RegexValidator ipv4Validator = new RegexValidator(IPV4_REGEX); + + /** + * Returns the singleton instance of this validator. + * @return the singleton instance of this validator + */ + public static InetAddressValidator getInstance() { + return VALIDATOR; + } + + /** + * Checks if the specified string is a valid IP address. + * @param inetAddress the string to validate + * @return true if the string validates as an IP address + */ + public boolean isValid(String inetAddress) { + return isValidInet4Address(inetAddress) || isValidInet6Address(inetAddress); + } + + /** + * Validates an IPv4 address. Returns true if valid. + * @param inet4Address the IPv4 address to validate + * @return true if the argument contains a valid IPv4 address + */ +/** + * Validates an IPv4 address. Returns true if valid. + * + * @param inet4Address + * the IPv4 address to validate + * @return true if the argument contains a valid IPv4 address + */ +public boolean isValidInet4Address(java.lang.String inet4Address) { + // verify that address conforms to generic IPv4 format + java.lang.String[] groups = ipv4Validator.match(inet4Address); + { + // verify that address subgroups are legal + for (java.lang.String ipSegment : /* NPEX_NULL_EXP */ + groups) { + if ((ipSegment == null) || (ipSegment.length() == 0)) { + return false; + } + int iIpSegment = 0; + try { + iIpSegment = java.lang.Integer.parseInt(ipSegment); + } catch (java.lang.NumberFormatException e) { + return false; + } + if (iIpSegment > org.apache.commons.validator.routines.InetAddressValidator.IPV4_MAX_OCTET_VALUE) { + return false; + } + if ((ipSegment.length() > 1) && ipSegment.startsWith("0")) { + return false; + } + } + return true; + } +} + + /** + * Validates an IPv6 address. Returns true if valid. + * @param inet6Address the IPv6 address to validate + * @return true if the argument contains a valid IPv6 address + * + * @since 1.4.1 + */ + public boolean isValidInet6Address(String inet6Address) { + boolean containsCompressedZeroes = inet6Address.contains("::"); + if (containsCompressedZeroes && (inet6Address.indexOf("::") != inet6Address.lastIndexOf("::"))) { + return false; + } + if ((inet6Address.startsWith(":") && !inet6Address.startsWith("::")) + || (inet6Address.endsWith(":") && !inet6Address.endsWith("::"))) { + return false; + } + String[] octets = inet6Address.split(":"); + if (containsCompressedZeroes) { + List octetList = new ArrayList(Arrays.asList(octets)); + if (inet6Address.endsWith("::")) { + // String.split() drops ending empty segments + octetList.add(""); + } else if (inet6Address.startsWith("::") && !octetList.isEmpty()) { + octetList.remove(0); + } + octets = octetList.toArray(new String[octetList.size()]); + } + if (octets.length > IPV6_MAX_HEX_GROUPS) { + return false; + } + int validOctets = 0; + int emptyOctets = 0; // consecutive empty chunks + for (int index = 0; index < octets.length; index++) { + String octet = octets[index]; + if (octet.length() == 0) { + emptyOctets++; + if (emptyOctets > 1) { + return false; + } + } else { + emptyOctets = 0; + // Is last chunk an IPv4 address? + if (index == octets.length - 1 && octet.contains(".")) { + if (!isValidInet4Address(octet)) { + return false; + } + validOctets += 2; + continue; + } + if (octet.length() > IPV6_MAX_HEX_DIGITS_PER_GROUP) { + return false; + } + int octetInt = 0; + try { + octetInt = Integer.parseInt(octet, BASE_16); + } catch (NumberFormatException e) { + return false; + } + if (octetInt < 0 || octetInt > MAX_UNSIGNED_SHORT) { + return false; + } + } + validOctets++; + } + if (validOctets > IPV6_MAX_HEX_GROUPS || (validOctets < IPV6_MAX_HEX_GROUPS && !containsCompressedZeroes)) { + return false; + } + return true; + } +} diff --git a/Java/commons-validator-InetAddressValidator_90/metadata.json b/Java/commons-validator-InetAddressValidator_90/metadata.json new file mode 100644 index 000000000..9f6924e02 --- /dev/null +++ b/Java/commons-validator-InetAddressValidator_90/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-InetAddressValidator_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/validator/routines/InetAddressValidator.java", + "line": 99, + "npe_method": "isValidInet4Address", + "deref_field": "groups", + "npe_class": "InetAddressValidator", + "repo": "commons-validator", + "bug_id": "InetAddressValidator_90" + } +} diff --git a/Java/commons-validator-InetAddressValidator_90/npe.json b/Java/commons-validator-InetAddressValidator_90/npe.json new file mode 100644 index 000000000..cbca15bbb --- /dev/null +++ b/Java/commons-validator-InetAddressValidator_90/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/InetAddressValidator.java", + "line": 99, + "npe_method": "isValidInet4Address", + "deref_field": "groups", + "npe_class": "InetAddressValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-PercentValidator_120/Dockerfile b/Java/commons-validator-PercentValidator_120/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-PercentValidator_120/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-PercentValidator_120/buggy.java b/Java/commons-validator-PercentValidator_120/buggy.java new file mode 100644 index 000000000..b66612459 --- /dev/null +++ b/Java/commons-validator-PercentValidator_120/buggy.java @@ -0,0 +1,138 @@ +/* + * 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.validator.routines; + +import java.text.DecimalFormat; +import java.text.Format; +import java.math.BigDecimal; + +/** + *

Percentage Validation and Conversion routines (java.math.BigDecimal).

+ * + *

This is one implementation of a percent validator that has the following features:

+ *
    + *
  • It is lenient about the presence of the percent symbol
  • + *
  • It converts the percent to a java.math.BigDecimal
  • + *
+ * + *

However any of the number validators can be used for percent validation. + * For example, if you wanted a percent validator that converts to a + * java.lang.Float then you can simply instantiate an + * FloatValidator with the appropriate format type:

+ * + *

... = new FloatValidator(false, FloatValidator.PERCENT_FORMAT);

+ * + *

Pick the appropriate validator, depending on the type (i.e Float, Double or BigDecimal) + * you want the percent converted to. Please note, it makes no sense to use + * one of the validators that doesn't handle fractions (i.e. byte, short, integer, long + * and BigInteger) since percentages are converted to fractions (i.e 50% is + * converted to 0.5).

+ * + * @version $Revision$ + * @since Validator 1.3.0 + */ +public class PercentValidator extends BigDecimalValidator { + + private static final long serialVersionUID = -3508241924961535772L; + + private static final PercentValidator VALIDATOR = new PercentValidator(); + + /** DecimalFormat's percent (thousand multiplier) symbol */ + private static final char PERCENT_SYMBOL = '%'; + + private static final BigDecimal POINT_ZERO_ONE = new BigDecimal("0.01"); + + /** + * Return a singleton instance of this validator. + * @return A singleton instance of the PercentValidator. + */ + public static BigDecimalValidator getInstance() { + return VALIDATOR; + } + + /** + * Construct a strict instance. + */ + public PercentValidator() { + this(true); + } + + /** + * Construct an instance with the specified strict setting. + * + * @param strict true if strict + * Format parsing should be used. + */ + public PercentValidator(boolean strict) { + super(strict, PERCENT_FORMAT, true); + } + + /** + *

Parse the value with the specified Format.

+ * + *

This implementation is lenient whether the currency symbol + * is present or not. The default NumberFormat + * behavior is for the parsing to "fail" if the currency + * symbol is missing. This method re-parses with a format + * without the currency symbol if it fails initially.

+ * + * @param value The value to be parsed. + * @param formatter The Format to parse the value with. + * @return The parsed value if valid or null if invalid. + */ + @Override +/** + *

Parse the value with the specified Format.

+ * + *

This implementation is lenient whether the currency symbol + * is present or not. The default NumberFormat + * behavior is for the parsing to "fail" if the currency + * symbol is missing. This method re-parses with a format + * without the currency symbol if it fails initially.

+ * + * @param value + * The value to be parsed. + * @param formatter + * The Format to parse the value with. + * @return The parsed value if valid or null if invalid. + */ +protected java.lang.Object parse(java.lang.String value, java.text.Format formatter) { + // Initial parse of the value + java.math.BigDecimal parsedValue = ((java.math.BigDecimal) (super.parse(value, formatter))); + if ((parsedValue != null) || (!(formatter instanceof java.text.DecimalFormat))) { + return parsedValue; + } + // Re-parse using a pattern without the percent symbol + java.text.DecimalFormat decimalFormat = ((java.text.DecimalFormat) (formatter)); + java.lang.String pattern = decimalFormat.toPattern(); + if (pattern.indexOf(org.apache.commons.validator.routines.PercentValidator.PERCENT_SYMBOL) >= 0) { + java.lang.StringBuilder buffer = new java.lang.StringBuilder(pattern.length()); + for (int i = 0; i < pattern.length(); i++) { + if (pattern.charAt(i) != org.apache.commons.validator.routines.PercentValidator.PERCENT_SYMBOL) { + buffer.append(pattern.charAt(i)); + } + } + decimalFormat.applyPattern(buffer.toString()); + parsedValue = ((java.math.BigDecimal) (super.parse(value, decimalFormat))); + { + parsedValue = /* NPEX_NULL_EXP */ + parsedValue.multiply(org.apache.commons.validator.routines.PercentValidator.POINT_ZERO_ONE); + } + } + return parsedValue; +} +} diff --git a/Java/commons-validator-PercentValidator_120/metadata.json b/Java/commons-validator-PercentValidator_120/metadata.json new file mode 100644 index 000000000..213e9af34 --- /dev/null +++ b/Java/commons-validator-PercentValidator_120/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-PercentValidator_120", + "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/validator/routines/PercentValidator.java", + "line": 133, + "npe_method": "parse", + "deref_field": "parsedValue", + "npe_class": "PercentValidator", + "repo": "commons-validator", + "bug_id": "PercentValidator_120" + } +} diff --git a/Java/commons-validator-PercentValidator_120/npe.json b/Java/commons-validator-PercentValidator_120/npe.json new file mode 100644 index 000000000..426b5f7ec --- /dev/null +++ b/Java/commons-validator-PercentValidator_120/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/PercentValidator.java", + "line": 133, + "npe_method": "parse", + "deref_field": "parsedValue", + "npe_class": "PercentValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-RegexValidator_142/Dockerfile b/Java/commons-validator-RegexValidator_142/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-RegexValidator_142/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-RegexValidator_142/buggy.java b/Java/commons-validator-RegexValidator_142/buggy.java new file mode 100644 index 000000000..9b9c996e3 --- /dev/null +++ b/Java/commons-validator-RegexValidator_142/buggy.java @@ -0,0 +1,238 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +/** + * Regular Expression validation (using JDK 1.4+ regex support). + *

+ * Construct the validator either for a single regular expression or a set (array) of + * regular expressions. By default validation is case sensitive but constructors + * are provided to allow case in-sensitive validation. For example to create + * a validator which does case in-sensitive validation for a set of regular + * expressions: + *

+ *
+ * 
+ * String[] regexs = new String[] {...};
+ * RegexValidator validator = new RegexValidator(regexs, false);
+ * 
+ * 
+ * + *
    + *
  • Validate true or false:
  • + *
  • + *
      + *
    • boolean valid = validator.isValid(value);
    • + *
    + *
  • + *
  • Validate returning an aggregated String of the matched groups:
  • + *
  • + *
      + *
    • String result = validator.validate(value);
    • + *
    + *
  • + *
  • Validate returning the matched groups:
  • + *
  • + *
      + *
    • String[] result = validator.match(value);
    • + *
    + *
  • + *
+ * + * Note that patterns are matched against the entire input. + * + *

+ * Cached instances pre-compile and re-use {@link Pattern}(s) - which according + * to the {@link Pattern} API are safe to use in a multi-threaded environment. + *

+ * + * @version $Revision$ + * @since Validator 1.4 + */ +public class RegexValidator implements Serializable { + + private static final long serialVersionUID = -8832409930574867162L; + + private final Pattern[] patterns; + + /** + * Construct a case sensitive validator for a single + * regular expression. + * + * @param regex The regular expression this validator will + * validate against + */ + public RegexValidator(String regex) { + this(regex, true); + } + + /** + * Construct a validator for a single regular expression + * with the specified case sensitivity. + * + * @param regex The regular expression this validator will + * validate against + * @param caseSensitive when true matching is case + * sensitive, otherwise matching is case in-sensitive + */ + public RegexValidator(String regex, boolean caseSensitive) { + this(new String[] {regex}, caseSensitive); + } + + /** + * Construct a case sensitive validator that matches any one + * of the set of regular expressions. + * + * @param regexs The set of regular expressions this validator will + * validate against + */ + public RegexValidator(String[] regexs) { + this(regexs, true); + } + + /** + * Construct a validator that matches any one of the set of regular + * expressions with the specified case sensitivity. + * + * @param regexs The set of regular expressions this validator will + * validate against + * @param caseSensitive when true matching is case + * sensitive, otherwise matching is case in-sensitive + */ + public RegexValidator(String[] regexs, boolean caseSensitive) { + if (regexs == null || regexs.length == 0) { + throw new IllegalArgumentException("Regular expressions are missing"); + } + patterns = new Pattern[regexs.length]; + int flags = (caseSensitive ? 0: Pattern.CASE_INSENSITIVE); + for (int i = 0; i < regexs.length; i++) { + if (regexs[i] == null || regexs[i].length() == 0) { + throw new IllegalArgumentException("Regular expression[" + i + "] is missing"); + } + patterns[i] = Pattern.compile(regexs[i], flags); + } + } + + /** + * Validate a value against the set of regular expressions. + * + * @param value The value to validate. + * @return true if the value is valid + * otherwise false. + */ +/** + * Validate a value against the set of regular expressions. + * + * @param value + * The value to validate. + * @return true if the value is valid +otherwise false. + */ +public boolean isValid(java.lang.String value) { + { + for (int i = 0; i < patterns.length; i++) { + if (patterns[i].matcher(/* NPEX_NULL_EXP */ + value).matches()) { + return true; + } + } + return false; + } +} + + /** + * Validate a value against the set of regular expressions + * returning the array of matched groups. + * + * @param value The value to validate. + * @return String array of the groups matched if + * valid or null if invalid + */ + public String[] match(String value) { + if (value == null) { + return null; + } + for (int i = 0; i < patterns.length; i++) { + Matcher matcher = patterns[i].matcher(value); + if (matcher.matches()) { + int count = matcher.groupCount(); + String[] groups = new String[count]; + for (int j = 0; j < count; j++) { + groups[j] = matcher.group(j+1); + } + return groups; + } + } + return null; + } + + + /** + * Validate a value against the set of regular expressions + * returning a String value of the aggregated groups. + * + * @param value The value to validate. + * @return Aggregated String value comprised of the + * groups matched if valid or null if invalid + */ + public String validate(String value) { + if (value == null) { + return null; + } + for (int i = 0; i < patterns.length; i++) { + Matcher matcher = patterns[i].matcher(value); + if (matcher.matches()) { + int count = matcher.groupCount(); + if (count == 1) { + return matcher.group(1); + } + StringBuilder buffer = new StringBuilder(); + for (int j = 0; j < count; j++) { + String component = matcher.group(j+1); + if (component != null) { + buffer.append(component); + } + } + return buffer.toString(); + } + } + return null; + } + + /** + * Provide a String representation of this validator. + * @return A String representation of this validator + */ + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("RegexValidator{"); + for (int i = 0; i < patterns.length; i++) { + if (i > 0) { + buffer.append(","); + } + buffer.append(patterns[i].pattern()); + } + buffer.append("}"); + return buffer.toString(); + } + +} diff --git a/Java/commons-validator-RegexValidator_142/metadata.json b/Java/commons-validator-RegexValidator_142/metadata.json new file mode 100644 index 000000000..d42035986 --- /dev/null +++ b/Java/commons-validator-RegexValidator_142/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-RegexValidator_142", + "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/validator/routines/RegexValidator.java", + "line": 153, + "npe_method": "isValid", + "deref_field": "value", + "npe_class": "RegexValidator", + "repo": "commons-validator", + "bug_id": "RegexValidator_142" + } +} diff --git a/Java/commons-validator-RegexValidator_142/npe.json b/Java/commons-validator-RegexValidator_142/npe.json new file mode 100644 index 000000000..3be2dc3fe --- /dev/null +++ b/Java/commons-validator-RegexValidator_142/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/RegexValidator.java", + "line": 153, + "npe_method": "isValid", + "deref_field": "value", + "npe_class": "RegexValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-RegexValidator_162/Dockerfile b/Java/commons-validator-RegexValidator_162/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-RegexValidator_162/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-RegexValidator_162/buggy.java b/Java/commons-validator-RegexValidator_162/buggy.java new file mode 100644 index 000000000..5309e3156 --- /dev/null +++ b/Java/commons-validator-RegexValidator_162/buggy.java @@ -0,0 +1,239 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +/** + * Regular Expression validation (using JDK 1.4+ regex support). + *

+ * Construct the validator either for a single regular expression or a set (array) of + * regular expressions. By default validation is case sensitive but constructors + * are provided to allow case in-sensitive validation. For example to create + * a validator which does case in-sensitive validation for a set of regular + * expressions: + *

+ *
+ * 
+ * String[] regexs = new String[] {...};
+ * RegexValidator validator = new RegexValidator(regexs, false);
+ * 
+ * 
+ * + *
    + *
  • Validate true or false:
  • + *
  • + *
      + *
    • boolean valid = validator.isValid(value);
    • + *
    + *
  • + *
  • Validate returning an aggregated String of the matched groups:
  • + *
  • + *
      + *
    • String result = validator.validate(value);
    • + *
    + *
  • + *
  • Validate returning the matched groups:
  • + *
  • + *
      + *
    • String[] result = validator.match(value);
    • + *
    + *
  • + *
+ * + * Note that patterns are matched against the entire input. + * + *

+ * Cached instances pre-compile and re-use {@link Pattern}(s) - which according + * to the {@link Pattern} API are safe to use in a multi-threaded environment. + *

+ * + * @version $Revision$ + * @since Validator 1.4 + */ +public class RegexValidator implements Serializable { + + private static final long serialVersionUID = -8832409930574867162L; + + private final Pattern[] patterns; + + /** + * Construct a case sensitive validator for a single + * regular expression. + * + * @param regex The regular expression this validator will + * validate against + */ + public RegexValidator(String regex) { + this(regex, true); + } + + /** + * Construct a validator for a single regular expression + * with the specified case sensitivity. + * + * @param regex The regular expression this validator will + * validate against + * @param caseSensitive when true matching is case + * sensitive, otherwise matching is case in-sensitive + */ + public RegexValidator(String regex, boolean caseSensitive) { + this(new String[] {regex}, caseSensitive); + } + + /** + * Construct a case sensitive validator that matches any one + * of the set of regular expressions. + * + * @param regexs The set of regular expressions this validator will + * validate against + */ + public RegexValidator(String[] regexs) { + this(regexs, true); + } + + /** + * Construct a validator that matches any one of the set of regular + * expressions with the specified case sensitivity. + * + * @param regexs The set of regular expressions this validator will + * validate against + * @param caseSensitive when true matching is case + * sensitive, otherwise matching is case in-sensitive + */ + public RegexValidator(String[] regexs, boolean caseSensitive) { + if (regexs == null || regexs.length == 0) { + throw new IllegalArgumentException("Regular expressions are missing"); + } + patterns = new Pattern[regexs.length]; + int flags = (caseSensitive ? 0: Pattern.CASE_INSENSITIVE); + for (int i = 0; i < regexs.length; i++) { + if (regexs[i] == null || regexs[i].length() == 0) { + throw new IllegalArgumentException("Regular expression[" + i + "] is missing"); + } + patterns[i] = Pattern.compile(regexs[i], flags); + } + } + + /** + * Validate a value against the set of regular expressions. + * + * @param value The value to validate. + * @return true if the value is valid + * otherwise false. + */ + public boolean isValid(String value) { + if (value == null) { + return false; + } + for (int i = 0; i < patterns.length; i++) { + if (patterns[i].matcher(value).matches()) { + return true; + } + } + return false; + } + + /** + * Validate a value against the set of regular expressions + * returning the array of matched groups. + * + * @param value The value to validate. + * @return String array of the groups matched if + * valid or null if invalid + */ +/** + * Validate a value against the set of regular expressions + * returning the array of matched groups. + * + * @param value + * The value to validate. + * @return String array of the groups matched if +valid or null if invalid + */ +public java.lang.String[] match(java.lang.String value) { + { + for (int i = 0; i < patterns.length; i++) { + java.util.regex.Matcher matcher = patterns[i].matcher(/* NPEX_NULL_EXP */ + value); + if (matcher.matches()) { + int count = matcher.groupCount(); + java.lang.String[] groups = new java.lang.String[count]; + for (int j = 0; j < count; j++) { + groups[j] = matcher.group(j + 1); + } + return groups; + } + } + return null; + } +} + + + /** + * Validate a value against the set of regular expressions + * returning a String value of the aggregated groups. + * + * @param value The value to validate. + * @return Aggregated String value comprised of the + * groups matched if valid or null if invalid + */ + public String validate(String value) { + if (value == null) { + return null; + } + for (int i = 0; i < patterns.length; i++) { + Matcher matcher = patterns[i].matcher(value); + if (matcher.matches()) { + int count = matcher.groupCount(); + if (count == 1) { + return matcher.group(1); + } + StringBuilder buffer = new StringBuilder(); + for (int j = 0; j < count; j++) { + String component = matcher.group(j+1); + if (component != null) { + buffer.append(component); + } + } + return buffer.toString(); + } + } + return null; + } + + /** + * Provide a String representation of this validator. + * @return A String representation of this validator + */ + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("RegexValidator{"); + for (int i = 0; i < patterns.length; i++) { + if (i > 0) { + buffer.append(","); + } + buffer.append(patterns[i].pattern()); + } + buffer.append("}"); + return buffer.toString(); + } + +} diff --git a/Java/commons-validator-RegexValidator_162/metadata.json b/Java/commons-validator-RegexValidator_162/metadata.json new file mode 100644 index 000000000..d75bbbddd --- /dev/null +++ b/Java/commons-validator-RegexValidator_162/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-RegexValidator_162", + "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/validator/routines/RegexValidator.java", + "line": 174, + "npe_method": "match", + "deref_field": "value", + "npe_class": "RegexValidator", + "repo": "commons-validator", + "bug_id": "RegexValidator_162" + } +} diff --git a/Java/commons-validator-RegexValidator_162/npe.json b/Java/commons-validator-RegexValidator_162/npe.json new file mode 100644 index 000000000..1dba8bde1 --- /dev/null +++ b/Java/commons-validator-RegexValidator_162/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/RegexValidator.java", + "line": 174, + "npe_method": "match", + "deref_field": "value", + "npe_class": "RegexValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-RegexValidator_189/Dockerfile b/Java/commons-validator-RegexValidator_189/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-RegexValidator_189/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-RegexValidator_189/buggy.java b/Java/commons-validator-RegexValidator_189/buggy.java new file mode 100644 index 000000000..2e62ab741 --- /dev/null +++ b/Java/commons-validator-RegexValidator_189/buggy.java @@ -0,0 +1,239 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +/** + * Regular Expression validation (using JDK 1.4+ regex support). + *

+ * Construct the validator either for a single regular expression or a set (array) of + * regular expressions. By default validation is case sensitive but constructors + * are provided to allow case in-sensitive validation. For example to create + * a validator which does case in-sensitive validation for a set of regular + * expressions: + *

+ *
+ * 
+ * String[] regexs = new String[] {...};
+ * RegexValidator validator = new RegexValidator(regexs, false);
+ * 
+ * 
+ * + *
    + *
  • Validate true or false:
  • + *
  • + *
      + *
    • boolean valid = validator.isValid(value);
    • + *
    + *
  • + *
  • Validate returning an aggregated String of the matched groups:
  • + *
  • + *
      + *
    • String result = validator.validate(value);
    • + *
    + *
  • + *
  • Validate returning the matched groups:
  • + *
  • + *
      + *
    • String[] result = validator.match(value);
    • + *
    + *
  • + *
+ * + * Note that patterns are matched against the entire input. + * + *

+ * Cached instances pre-compile and re-use {@link Pattern}(s) - which according + * to the {@link Pattern} API are safe to use in a multi-threaded environment. + *

+ * + * @version $Revision$ + * @since Validator 1.4 + */ +public class RegexValidator implements Serializable { + + private static final long serialVersionUID = -8832409930574867162L; + + private final Pattern[] patterns; + + /** + * Construct a case sensitive validator for a single + * regular expression. + * + * @param regex The regular expression this validator will + * validate against + */ + public RegexValidator(String regex) { + this(regex, true); + } + + /** + * Construct a validator for a single regular expression + * with the specified case sensitivity. + * + * @param regex The regular expression this validator will + * validate against + * @param caseSensitive when true matching is case + * sensitive, otherwise matching is case in-sensitive + */ + public RegexValidator(String regex, boolean caseSensitive) { + this(new String[] {regex}, caseSensitive); + } + + /** + * Construct a case sensitive validator that matches any one + * of the set of regular expressions. + * + * @param regexs The set of regular expressions this validator will + * validate against + */ + public RegexValidator(String[] regexs) { + this(regexs, true); + } + + /** + * Construct a validator that matches any one of the set of regular + * expressions with the specified case sensitivity. + * + * @param regexs The set of regular expressions this validator will + * validate against + * @param caseSensitive when true matching is case + * sensitive, otherwise matching is case in-sensitive + */ + public RegexValidator(String[] regexs, boolean caseSensitive) { + if (regexs == null || regexs.length == 0) { + throw new IllegalArgumentException("Regular expressions are missing"); + } + patterns = new Pattern[regexs.length]; + int flags = (caseSensitive ? 0: Pattern.CASE_INSENSITIVE); + for (int i = 0; i < regexs.length; i++) { + if (regexs[i] == null || regexs[i].length() == 0) { + throw new IllegalArgumentException("Regular expression[" + i + "] is missing"); + } + patterns[i] = Pattern.compile(regexs[i], flags); + } + } + + /** + * Validate a value against the set of regular expressions. + * + * @param value The value to validate. + * @return true if the value is valid + * otherwise false. + */ + public boolean isValid(String value) { + if (value == null) { + return false; + } + for (int i = 0; i < patterns.length; i++) { + if (patterns[i].matcher(value).matches()) { + return true; + } + } + return false; + } + + /** + * Validate a value against the set of regular expressions + * returning the array of matched groups. + * + * @param value The value to validate. + * @return String array of the groups matched if + * valid or null if invalid + */ + public String[] match(String value) { + if (value == null) { + return null; + } + for (int i = 0; i < patterns.length; i++) { + Matcher matcher = patterns[i].matcher(value); + if (matcher.matches()) { + int count = matcher.groupCount(); + String[] groups = new String[count]; + for (int j = 0; j < count; j++) { + groups[j] = matcher.group(j+1); + } + return groups; + } + } + return null; + } + + + /** + * Validate a value against the set of regular expressions + * returning a String value of the aggregated groups. + * + * @param value The value to validate. + * @return Aggregated String value comprised of the + * groups matched if valid or null if invalid + */ +/** + * Validate a value against the set of regular expressions + * returning a String value of the aggregated groups. + * + * @param value + * The value to validate. + * @return Aggregated String value comprised of the +groups matched if valid or null if invalid + */ +public java.lang.String validate(java.lang.String value) { + { + for (int i = 0; i < patterns.length; i++) { + java.util.regex.Matcher matcher = patterns[i].matcher(/* NPEX_NULL_EXP */ + value); + if (matcher.matches()) { + int count = matcher.groupCount(); + if (count == 1) { + return matcher.group(1); + } + java.lang.StringBuilder buffer = new java.lang.StringBuilder(); + for (int j = 0; j < count; j++) { + java.lang.String component = matcher.group(j + 1); + if (component != null) { + buffer.append(component); + } + } + return buffer.toString(); + } + } + return null; + } +} + + /** + * Provide a String representation of this validator. + * @return A String representation of this validator + */ + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("RegexValidator{"); + for (int i = 0; i < patterns.length; i++) { + if (i > 0) { + buffer.append(","); + } + buffer.append(patterns[i].pattern()); + } + buffer.append("}"); + return buffer.toString(); + } + +} diff --git a/Java/commons-validator-RegexValidator_189/metadata.json b/Java/commons-validator-RegexValidator_189/metadata.json new file mode 100644 index 000000000..366795428 --- /dev/null +++ b/Java/commons-validator-RegexValidator_189/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-RegexValidator_189", + "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/validator/routines/RegexValidator.java", + "line": 201, + "npe_method": "validate", + "deref_field": "value", + "npe_class": "RegexValidator", + "repo": "commons-validator", + "bug_id": "RegexValidator_189" + } +} diff --git a/Java/commons-validator-RegexValidator_189/npe.json b/Java/commons-validator-RegexValidator_189/npe.json new file mode 100644 index 000000000..c52d496e8 --- /dev/null +++ b/Java/commons-validator-RegexValidator_189/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/RegexValidator.java", + "line": 201, + "npe_method": "validate", + "deref_field": "value", + "npe_class": "RegexValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-RegexValidator_202/Dockerfile b/Java/commons-validator-RegexValidator_202/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-RegexValidator_202/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-RegexValidator_202/buggy.java b/Java/commons-validator-RegexValidator_202/buggy.java new file mode 100644 index 000000000..e7f84d37c --- /dev/null +++ b/Java/commons-validator-RegexValidator_202/buggy.java @@ -0,0 +1,240 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +/** + * Regular Expression validation (using JDK 1.4+ regex support). + *

+ * Construct the validator either for a single regular expression or a set (array) of + * regular expressions. By default validation is case sensitive but constructors + * are provided to allow case in-sensitive validation. For example to create + * a validator which does case in-sensitive validation for a set of regular + * expressions: + *

+ *
+ * 
+ * String[] regexs = new String[] {...};
+ * RegexValidator validator = new RegexValidator(regexs, false);
+ * 
+ * 
+ * + *
    + *
  • Validate true or false:
  • + *
  • + *
      + *
    • boolean valid = validator.isValid(value);
    • + *
    + *
  • + *
  • Validate returning an aggregated String of the matched groups:
  • + *
  • + *
      + *
    • String result = validator.validate(value);
    • + *
    + *
  • + *
  • Validate returning the matched groups:
  • + *
  • + *
      + *
    • String[] result = validator.match(value);
    • + *
    + *
  • + *
+ * + * Note that patterns are matched against the entire input. + * + *

+ * Cached instances pre-compile and re-use {@link Pattern}(s) - which according + * to the {@link Pattern} API are safe to use in a multi-threaded environment. + *

+ * + * @version $Revision$ + * @since Validator 1.4 + */ +public class RegexValidator implements Serializable { + + private static final long serialVersionUID = -8832409930574867162L; + + private final Pattern[] patterns; + + /** + * Construct a case sensitive validator for a single + * regular expression. + * + * @param regex The regular expression this validator will + * validate against + */ + public RegexValidator(String regex) { + this(regex, true); + } + + /** + * Construct a validator for a single regular expression + * with the specified case sensitivity. + * + * @param regex The regular expression this validator will + * validate against + * @param caseSensitive when true matching is case + * sensitive, otherwise matching is case in-sensitive + */ + public RegexValidator(String regex, boolean caseSensitive) { + this(new String[] {regex}, caseSensitive); + } + + /** + * Construct a case sensitive validator that matches any one + * of the set of regular expressions. + * + * @param regexs The set of regular expressions this validator will + * validate against + */ + public RegexValidator(String[] regexs) { + this(regexs, true); + } + + /** + * Construct a validator that matches any one of the set of regular + * expressions with the specified case sensitivity. + * + * @param regexs The set of regular expressions this validator will + * validate against + * @param caseSensitive when true matching is case + * sensitive, otherwise matching is case in-sensitive + */ + public RegexValidator(String[] regexs, boolean caseSensitive) { + if (regexs == null || regexs.length == 0) { + throw new IllegalArgumentException("Regular expressions are missing"); + } + patterns = new Pattern[regexs.length]; + int flags = (caseSensitive ? 0: Pattern.CASE_INSENSITIVE); + for (int i = 0; i < regexs.length; i++) { + if (regexs[i] == null || regexs[i].length() == 0) { + throw new IllegalArgumentException("Regular expression[" + i + "] is missing"); + } + patterns[i] = Pattern.compile(regexs[i], flags); + } + } + + /** + * Validate a value against the set of regular expressions. + * + * @param value The value to validate. + * @return true if the value is valid + * otherwise false. + */ + public boolean isValid(String value) { + if (value == null) { + return false; + } + for (int i = 0; i < patterns.length; i++) { + if (patterns[i].matcher(value).matches()) { + return true; + } + } + return false; + } + + /** + * Validate a value against the set of regular expressions + * returning the array of matched groups. + * + * @param value The value to validate. + * @return String array of the groups matched if + * valid or null if invalid + */ + public String[] match(String value) { + if (value == null) { + return null; + } + for (int i = 0; i < patterns.length; i++) { + Matcher matcher = patterns[i].matcher(value); + if (matcher.matches()) { + int count = matcher.groupCount(); + String[] groups = new String[count]; + for (int j = 0; j < count; j++) { + groups[j] = matcher.group(j+1); + } + return groups; + } + } + return null; + } + + + /** + * Validate a value against the set of regular expressions + * returning a String value of the aggregated groups. + * + * @param value The value to validate. + * @return Aggregated String value comprised of the + * groups matched if valid or null if invalid + */ +/** + * Validate a value against the set of regular expressions + * returning a String value of the aggregated groups. + * + * @param value + * The value to validate. + * @return Aggregated String value comprised of the +groups matched if valid or null if invalid + */ +public java.lang.String validate(java.lang.String value) { + if (value == null) { + return null; + } + for (int i = 0; i < patterns.length; i++) { + java.util.regex.Matcher matcher = patterns[i].matcher(value); + if (matcher.matches()) { + int count = matcher.groupCount(); + if (count == 1) { + return matcher.group(1); + } + java.lang.StringBuilder buffer = new java.lang.StringBuilder(); + for (int j = 0; j < count; j++) { + java.lang.String component = matcher.group(j + 1); + { + buffer.append(/* NPEX_NULL_EXP */ + component); + } + } + return buffer.toString(); + } + } + return null; +} + + /** + * Provide a String representation of this validator. + * @return A String representation of this validator + */ + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("RegexValidator{"); + for (int i = 0; i < patterns.length; i++) { + if (i > 0) { + buffer.append(","); + } + buffer.append(patterns[i].pattern()); + } + buffer.append("}"); + return buffer.toString(); + } + +} diff --git a/Java/commons-validator-RegexValidator_202/metadata.json b/Java/commons-validator-RegexValidator_202/metadata.json new file mode 100644 index 000000000..f7c523ad6 --- /dev/null +++ b/Java/commons-validator-RegexValidator_202/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-RegexValidator_202", + "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/validator/routines/RegexValidator.java", + "line": 213, + "npe_method": "validate", + "deref_field": "component", + "npe_class": "RegexValidator", + "repo": "commons-validator", + "bug_id": "RegexValidator_202" + } +} diff --git a/Java/commons-validator-RegexValidator_202/npe.json b/Java/commons-validator-RegexValidator_202/npe.json new file mode 100644 index 000000000..4e26ecba6 --- /dev/null +++ b/Java/commons-validator-RegexValidator_202/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/routines/RegexValidator.java", + "line": 213, + "npe_method": "validate", + "deref_field": "component", + "npe_class": "RegexValidator" +} \ No newline at end of file diff --git a/Java/commons-validator-TimeValidatorTest_315/Dockerfile b/Java/commons-validator-TimeValidatorTest_315/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-TimeValidatorTest_315/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-TimeValidatorTest_315/buggy.java b/Java/commons-validator-TimeValidatorTest_315/buggy.java new file mode 100644 index 000000000..de5d25607 --- /dev/null +++ b/Java/commons-validator-TimeValidatorTest_315/buggy.java @@ -0,0 +1,353 @@ +/* + * 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.validator.routines; + +import junit.framework.TestCase; + +import java.util.Date; +import java.util.Calendar; +import java.util.Locale; +import java.util.TimeZone; + +/** + * Test Case for TimeValidator. + * + * @version $Revision$ + */ +public class TimeValidatorTest extends TestCase { + + protected static final TimeZone GMT = TimeZone.getTimeZone("GMT"); // 0 offset + protected static final TimeZone EST = TimeZone.getTimeZone("EST"); // - 5 hours + + protected TimeValidator validator; + + protected String[] patternValid = new String[] { + "23-59-59" + ,"00-00-00" + ,"00-00-01" + ,"0-0-0" + ,"1-12-1" + ,"10-49-18" + ,"16-23-46"}; + protected Date[] patternExpect = new Date[] { + createDate(null, 235959, 0) + ,createDate(null, 0, 0) + ,createDate(null, 1, 0) + ,createDate(null, 0, 0) + ,createDate(null, 11201, 0) + ,createDate(null, 104918, 0) + ,createDate(null, 162346, 0)}; + protected String[] localeValid = new String[] { + "23:59" + ,"00:00" + ,"00:01" + ,"0:0" + ,"1:12" + ,"10:49" + ,"16:23"}; + protected Date[] localeExpect = new Date[] { + createDate(null, 235900, 0) + ,createDate(null, 0, 0) + ,createDate(null, 100, 0) + ,createDate(null, 0, 0) + ,createDate(null, 11200, 0) + ,createDate(null, 104900, 0) + ,createDate(null, 162300, 0)}; + protected String[] patternInvalid = new String[] { + "24-00-00" // midnight + ,"24-00-01" // past midnight + ,"25-02-03" // invalid hour + ,"10-61-31" // invalid minute + ,"10-01-61" // invalid second + ,"05:02-29" // invalid sep + ,"0X-01:01" // invalid sep + ,"05-0X-01" // invalid char + ,"10-01-0X" // invalid char + ,"01:01:05" // invalid pattern + ,"10-10" // invalid pattern + ,"10--10" // invalid pattern + ,"10-10-"}; // invalid pattern + protected String[] localeInvalid = new String[] { + "24:00" // midnight + ,"24:00" // past midnight + ,"25:02" // invalid hour + ,"10:61" // invalid minute + ,"05-02" // invalid sep + ,"0X:01" // invalid sep + ,"05:0X" // invalid char + ,"01-01" // invalid pattern + ,"10:" // invalid pattern + ,"10::1" // invalid pattern + ,"10:1:"}; // invalid pattern + + private Locale origDefault; + private TimeZone defaultZone; + + /** + * Constructor + * @param name test name + */ + public TimeValidatorTest(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + validator = new TimeValidator(); + defaultZone = TimeZone.getDefault(); + origDefault = Locale.getDefault(); + } + + /** + * Tear down + * @throws Exception + */ + @Override + protected void tearDown() throws Exception { + super.tearDown(); + validator = null; + Locale.setDefault(origDefault); + TimeZone.setDefault(defaultZone); + } + + /** + * Test Valid Dates with "pattern" validation + */ + public void testPatternValid() { + for (int i = 0; i < patternValid.length; i++) { + String text = i + " value=[" +patternValid[i]+"] failed "; + Calendar calendar = validator.validate(patternValid[i], "HH-mm-ss"); + assertNotNull("validateObj() " + text, calendar); + Date date = calendar.getTime(); + assertTrue("isValid() " + text, validator.isValid(patternValid[i], "HH-mm-ss")); + assertEquals("compare " + text, patternExpect[i], date); + } + } + + /** + * Test Invalid Dates with "pattern" validation + */ + public void testPatternInvalid() { + for (int i = 0; i < patternInvalid.length; i++) { + String text = i + " value=[" +patternInvalid[i]+"] passed "; + Object date = validator.validate(patternInvalid[i], "HH-mm-ss"); + assertNull("validate() " + text + date, date); + assertFalse("isValid() " + text, validator.isValid(patternInvalid[i], "HH-mm-ss")); + } + } + + /** + * Test Valid Dates with "locale" validation + */ + public void testLocaleValid() { + for (int i = 0; i < localeValid.length; i++) { + String text = i + " value=[" +localeValid[i]+"] failed "; + Calendar calendar = validator.validate(localeValid[i], Locale.UK); + assertNotNull("validate() " + text, calendar); + Date date = calendar.getTime(); + assertTrue("isValid() " + text, validator.isValid(localeValid[i], Locale.UK)); + assertEquals("compare " + text, localeExpect[i], date); + } + } + + /** + * Test Invalid Dates with "locale" validation + */ + public void testLocaleInvalid() { + for (int i = 0; i < localeInvalid.length; i++) { + String text = i + " value=[" +localeInvalid[i]+"] passed "; + Object date = validator.validate(localeInvalid[i], Locale.US); + assertNull("validate() " + text + date, date); + assertFalse("isValid() " + text, validator.isValid(localeInvalid[i], Locale.UK)); + } + } + + /** + * Test time zone methods. + */ + public void testTimeZone() { + // Set the default Locale & TimeZone + Locale.setDefault(Locale.UK); + TimeZone.setDefault(GMT); + + Calendar result = null; + + // Default Locale, Default TimeZone + result = validator.validate("18:01"); + assertNotNull("default result", result); + assertEquals("default zone", GMT, result.getTimeZone()); + assertEquals("default hour", 18, result.get(Calendar.HOUR_OF_DAY)); + assertEquals("default minute", 01, result.get(Calendar.MINUTE)); + result = null; + + // Default Locale, diff TimeZone + result = validator.validate("16:49", EST); + assertNotNull("zone result", result); + assertEquals("zone zone", EST, result.getTimeZone()); + assertEquals("zone hour", 16, result.get(Calendar.HOUR_OF_DAY)); + assertEquals("zone minute", 49, result.get(Calendar.MINUTE)); + result = null; + + // Pattern, diff TimeZone + result = validator.validate("14-34", "HH-mm", EST); + assertNotNull("pattern result", result); + assertEquals("pattern zone", EST, result.getTimeZone()); + assertEquals("pattern hour", 14, result.get(Calendar.HOUR_OF_DAY)); + assertEquals("pattern minute", 34, result.get(Calendar.MINUTE)); + result = null; + + // Locale, diff TimeZone + result = validator.validate("7:18 PM", Locale.US, EST); + assertNotNull("locale result", result); + assertEquals("locale zone", EST, result.getTimeZone()); + assertEquals("locale hour", 19, result.get(Calendar.HOUR_OF_DAY)); + assertEquals("locale minute", 18, result.get(Calendar.MINUTE)); + result = null; + + // Locale & Pattern, diff TimeZone + result = validator.validate("31/Dez/05 21-05", "dd/MMM/yy HH-mm", Locale.GERMAN, EST); + assertNotNull("pattern result", result); + assertEquals("pattern zone", EST, result.getTimeZone()); + assertEquals("pattern day", 2005, result.get(Calendar.YEAR)); + assertEquals("pattern day", 11, result.get(Calendar.MONTH)); // months are 0-11 + assertEquals("pattern day", 31, result.get(Calendar.DATE)); + assertEquals("pattern hour", 21, result.get(Calendar.HOUR_OF_DAY)); + assertEquals("pattern minute", 05, result.get(Calendar.MINUTE)); + result = null; + + // Locale & Pattern, default TimeZone + result = validator.validate("31/Dez/05 21-05", "dd/MMM/yy HH-mm", Locale.GERMAN); + assertNotNull("pattern result", result); + assertEquals("pattern zone", GMT, result.getTimeZone()); + assertEquals("pattern day", 2005, result.get(Calendar.YEAR)); + assertEquals("pattern day", 11, result.get(Calendar.MONTH)); // months are 0-11 + assertEquals("pattern day", 31, result.get(Calendar.DATE)); + assertEquals("pattern hour", 21, result.get(Calendar.HOUR_OF_DAY)); + assertEquals("pattern minute", 05, result.get(Calendar.MINUTE)); + result = null; + + } + + /** + * Test Invalid Dates with "locale" validation + */ + public void testFormat() { + // Set the default Locale + Locale.setDefault(Locale.UK); + + Object test = TimeValidator.getInstance().validate("16:49:23", "HH:mm:ss"); + assertNotNull("Test Date ", test); + assertEquals("Format pattern", "16-49-23", validator.format(test, "HH-mm-ss")); + assertEquals("Format locale", "4:49 PM", validator.format(test, Locale.US)); + assertEquals("Format default", "16:49", validator.format(test)); + + } + + /** + * Test compare date methods + */ + public void testCompare() { + int testTime = 154523; + int min = 100; + int hour = 10000; + + Calendar milliGreater = createTime(GMT, testTime, 500); // > milli sec + Calendar value = createTime(GMT, testTime, 400); // test value + Calendar milliLess = createTime(GMT, testTime, 300); // < milli sec + + Calendar secGreater = createTime(GMT, testTime + 1, 100); // +1 sec + Calendar secLess = createTime(GMT, testTime - 1, 100); // -1 sec + + Calendar minGreater = createTime(GMT, testTime + min, 100); // +1 min + Calendar minLess = createTime(GMT, testTime - min, 100); // -1 min + + Calendar hourGreater = createTime(GMT, testTime + hour, 100); // +1 hour + Calendar hourLess = createTime(GMT, testTime - hour, 100); // -1 hour + + assertEquals("mili LT", -1, validator.compareTime(value, milliGreater)); // > milli + assertEquals("mili EQ", 0, validator.compareTime(value, value)); // same time + assertEquals("mili GT", 1, validator.compareTime(value, milliLess)); // < milli + + assertEquals("secs LT", -1, validator.compareSeconds(value, secGreater)); // +1 sec + assertEquals("secs =1", 0, validator.compareSeconds(value, milliGreater)); // > milli + assertEquals("secs =2", 0, validator.compareSeconds(value, value)); // same time + assertEquals("secs =3", 0, validator.compareSeconds(value, milliLess)); // < milli + assertEquals("secs GT", 1, validator.compareSeconds(value, secLess)); // -1 sec + + assertEquals("mins LT", -1, validator.compareMinutes(value, minGreater)); // +1 min + assertEquals("mins =1", 0, validator.compareMinutes(value, secGreater)); // +1 sec + assertEquals("mins =2", 0, validator.compareMinutes(value, value)); // same time + assertEquals("mins =3", 0, validator.compareMinutes(value, secLess)); // -1 sec + assertEquals("mins GT", 1, validator.compareMinutes(value, minLess)); // -1 min + + assertEquals("hour LT", -1, validator.compareHours(value, hourGreater)); // +1 hour + assertEquals("hour =1", 0, validator.compareHours(value, minGreater)); // +1 min + assertEquals("hour =2", 0, validator.compareHours(value, value)); // same time + assertEquals("hour =3", 0, validator.compareHours(value, minLess)); // -1 min + assertEquals("hour GT", 1, validator.compareHours(value, hourLess)); // -1 hour + + } + + /** + * Create a calendar instance for a specified time zone, date and time. + * + * @param zone The time zone + * @param time the time in HH:mm:ss format + * @param millisecond the milliseconds + * @return the new Calendar instance. + */ +/** + * Create a calendar instance for a specified time zone, date and time. + * + * @param zone + * The time zone + * @param time + * the time in HH:mm:ss format + * @param millisecond + * the milliseconds + * @return the new Calendar instance. + */ +protected static java.util.Calendar createTime(java.util.TimeZone zone, int time, int millisecond) { + java.util.Calendar calendar = java.util.Calendar.getInstance(/* NPEX_NULL_EXP */ + zone); + int hour = (time / 10000) * 10000; + int min = ((time / 100) * 100) - hour; + int sec = time - (hour + min); + calendar.set(java.util.Calendar.YEAR, 1970); + calendar.set(java.util.Calendar.MONTH, 0); + calendar.set(java.util.Calendar.DATE, 1); + calendar.set(java.util.Calendar.HOUR_OF_DAY, hour / 10000); + calendar.set(java.util.Calendar.MINUTE, min / 100); + calendar.set(java.util.Calendar.SECOND, sec); + calendar.set(java.util.Calendar.MILLISECOND, millisecond); + return calendar; +} + + /** + * Create a date instance for a specified time zone, date and time. + * + * @param zone The time zone + * @param time the time in HH:mm:ss format + * @param millisecond the milliseconds + * @return the new Date instance. + */ + protected static Date createDate(TimeZone zone, int time, int millisecond) { + Calendar calendar = createTime(zone, time, millisecond); + return calendar.getTime(); + } +} diff --git a/Java/commons-validator-TimeValidatorTest_315/metadata.json b/Java/commons-validator-TimeValidatorTest_315/metadata.json new file mode 100644 index 000000000..38c807c07 --- /dev/null +++ b/Java/commons-validator-TimeValidatorTest_315/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-TimeValidatorTest_315", + "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/test/java/org/apache/commons/validator/routines/TimeValidatorTest.java", + "line": 327, + "npe_method": "createTime", + "deref_field": "zone", + "npe_class": "TimeValidatorTest", + "repo": "commons-validator", + "bug_id": "TimeValidatorTest_315" + } +} diff --git a/Java/commons-validator-TimeValidatorTest_315/npe.json b/Java/commons-validator-TimeValidatorTest_315/npe.json new file mode 100644 index 000000000..1c48c729d --- /dev/null +++ b/Java/commons-validator-TimeValidatorTest_315/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/test/java/org/apache/commons/validator/routines/TimeValidatorTest.java", + "line": 327, + "npe_method": "createTime", + "deref_field": "zone", + "npe_class": "TimeValidatorTest" +} \ No newline at end of file diff --git a/Java/commons-validator-UrlValidator_351/Dockerfile b/Java/commons-validator-UrlValidator_351/Dockerfile new file mode 100644 index 000000000..c4cefe629 --- /dev/null +++ b/Java/commons-validator-UrlValidator_351/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:commons-validator + +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-validator-UrlValidator_351/buggy.java b/Java/commons-validator-UrlValidator_351/buggy.java new file mode 100644 index 000000000..43e0c20f1 --- /dev/null +++ b/Java/commons-validator-UrlValidator_351/buggy.java @@ -0,0 +1,584 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + *

URL Validation routines.

+ * Behavior of validation is modified by passing in options: + *
    + *
  • ALLOW_2_SLASHES - [FALSE] Allows double '/' characters in the path + * component.
  • + *
  • NO_FRAGMENT- [FALSE] By default fragments are allowed, if this option is + * included then fragments are flagged as illegal.
  • + *
  • ALLOW_ALL_SCHEMES - [FALSE] By default only http, https, and ftp are + * considered valid schemes. Enabling this option will let any scheme pass validation.
  • + *
+ * + *

Originally based in on php script by Debbie Dyer, validation.php v1.2b, Date: 03/07/02, + * http://javascript.internet.com. However, this validation now bears little resemblance + * to the php original.

+ *
+ *   Example of usage:
+ *   Construct a UrlValidator with valid schemes of "http", and "https".
+ *
+ *    String[] schemes = {"http","https"}.
+ *    UrlValidator urlValidator = new UrlValidator(schemes);
+ *    if (urlValidator.isValid("ftp://foo.bar.com/")) {
+ *       System.out.println("url is valid");
+ *    } else {
+ *       System.out.println("url is invalid");
+ *    }
+ *
+ *    prints "url is invalid"
+ *   If instead the default constructor is used.
+ *
+ *    UrlValidator urlValidator = new UrlValidator();
+ *    if (urlValidator.isValid("ftp://foo.bar.com/")) {
+ *       System.out.println("url is valid");
+ *    } else {
+ *       System.out.println("url is invalid");
+ *    }
+ *
+ *   prints out "url is valid"
+ *  
+ * + * @see + * + * Uniform Resource Identifiers (URI): Generic Syntax + * + * + * @version $Revision$ + * @since Validator 1.4 + */ +public class UrlValidator implements Serializable { + + private static final long serialVersionUID = 7557161713937335013L; + + private static final int MAX_UNSIGNED_16_BIT_INT = 0xFFFF; // port max + + /** + * Allows all validly formatted schemes to pass validation instead of + * supplying a set of valid schemes. + */ + public static final long ALLOW_ALL_SCHEMES = 1 << 0; + + /** + * Allow two slashes in the path component of the URL. + */ + public static final long ALLOW_2_SLASHES = 1 << 1; + + /** + * Enabling this options disallows any URL fragments. + */ + public static final long NO_FRAGMENTS = 1 << 2; + + /** + * Allow local URLs, such as http://localhost/ or http://machine/ . + * This enables a broad-brush check, for complex local machine name + * validation requirements you should create your validator with + * a {@link RegexValidator} instead ({@link #UrlValidator(RegexValidator, long)}) + */ + public static final long ALLOW_LOCAL_URLS = 1 << 3; // CHECKSTYLE IGNORE MagicNumber + + /** + * This expression derived/taken from the BNF for URI (RFC2396). + */ + private static final String URL_REGEX = + "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?"; + // 12 3 4 5 6 7 8 9 + private static final Pattern URL_PATTERN = Pattern.compile(URL_REGEX); + + /** + * Schema/Protocol (ie. http:, ftp:, file:, etc). + */ + private static final int PARSE_URL_SCHEME = 2; + + /** + * Includes hostname/ip and port number. + */ + private static final int PARSE_URL_AUTHORITY = 4; + + private static final int PARSE_URL_PATH = 5; + + private static final int PARSE_URL_QUERY = 7; + + private static final int PARSE_URL_FRAGMENT = 9; + + /** + * Protocol scheme (e.g. http, ftp, https). + */ + private static final String SCHEME_REGEX = "^\\p{Alpha}[\\p{Alnum}\\+\\-\\.]*"; + private static final Pattern SCHEME_PATTERN = Pattern.compile(SCHEME_REGEX); + + // Drop numeric, and "+-." for now + // TODO does not allow for optional userinfo. + // Validation of character set is done by isValidAuthority + private static final String AUTHORITY_CHARS_REGEX = "\\p{Alnum}\\-\\."; // allows for IPV4 but not IPV6 + private static final String IPV6_REGEX = "[0-9a-fA-F:]+"; // do this as separate match because : could cause ambiguity with port prefix + + // userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) + // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + // We assume that password has the same valid chars as user info + private static final String USERINFO_CHARS_REGEX = "[a-zA-Z0-9%-._~!$&'()*+,;=]"; + // since neither ':' nor '@' are allowed chars, we don't need to use non-greedy matching + private static final String USERINFO_FIELD_REGEX = + USERINFO_CHARS_REGEX + "+" + // At least one character for the name + "(?::" + USERINFO_CHARS_REGEX + "*)?@"; // colon and password may be absent + private static final String AUTHORITY_REGEX = + "(?:\\[("+IPV6_REGEX+")\\]|(?:(?:"+USERINFO_FIELD_REGEX+")?([" + AUTHORITY_CHARS_REGEX + "]*)))(?::(\\d*))?(.*)?"; + // 1 e.g. user:pass@ 2 3 4 + private static final Pattern AUTHORITY_PATTERN = Pattern.compile(AUTHORITY_REGEX); + + private static final int PARSE_AUTHORITY_IPV6 = 1; + + private static final int PARSE_AUTHORITY_HOST_IP = 2; // excludes userinfo, if present + + private static final int PARSE_AUTHORITY_PORT = 3; // excludes leading colon + + /** + * Should always be empty. The code currently allows spaces. + */ + private static final int PARSE_AUTHORITY_EXTRA = 4; + + private static final String PATH_REGEX = "^(/[-\\w:@&?=+,.!/~*'%$_;\\(\\)]*)?$"; + private static final Pattern PATH_PATTERN = Pattern.compile(PATH_REGEX); + + private static final String QUERY_REGEX = "^(\\S*)$"; + private static final Pattern QUERY_PATTERN = Pattern.compile(QUERY_REGEX); + + /** + * Holds the set of current validation options. + */ + private final long options; + + /** + * The set of schemes that are allowed to be in a URL. + */ + private final Set allowedSchemes; // Must be lower-case + + /** + * Regular expressions used to manually validate authorities if IANA + * domain name validation isn't desired. + */ + private final RegexValidator authorityValidator; + + /** + * If no schemes are provided, default to this set. + */ + private static final String[] DEFAULT_SCHEMES = {"http", "https", "ftp"}; // Must be lower-case + + /** + * Singleton instance of this class with default schemes and options. + */ + private static final UrlValidator DEFAULT_URL_VALIDATOR = new UrlValidator(); + + /** + * Returns the singleton instance of this class with default schemes and options. + * @return singleton instance with default schemes and options + */ + public static UrlValidator getInstance() { + return DEFAULT_URL_VALIDATOR; + } + + /** + * Create a UrlValidator with default properties. + */ + public UrlValidator() { + this(null); + } + + /** + * Behavior of validation is modified by passing in several strings options: + * @param schemes Pass in one or more url schemes to consider valid, passing in + * a null will default to "http,https,ftp" being valid. + * If a non-null schemes is specified then all valid schemes must + * be specified. Setting the ALLOW_ALL_SCHEMES option will + * ignore the contents of schemes. + */ + public UrlValidator(String[] schemes) { + this(schemes, 0L); + } + + /** + * Initialize a UrlValidator with the given validation options. + * @param options The options should be set using the public constants declared in + * this class. To set multiple options you simply add them together. For example, + * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options. + */ + public UrlValidator(long options) { + this(null, null, options); + } + + /** + * Behavior of validation is modified by passing in options: + * @param schemes The set of valid schemes. Ignored if the ALLOW_ALL_SCHEMES option is set. + * @param options The options should be set using the public constants declared in + * this class. To set multiple options you simply add them together. For example, + * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options. + */ + public UrlValidator(String[] schemes, long options) { + this(schemes, null, options); + } + + /** + * Initialize a UrlValidator with the given validation options. + * @param authorityValidator Regular expression validator used to validate the authority part + * This allows the user to override the standard set of domains. + * @param options Validation options. Set using the public constants of this class. + * To set multiple options, simply add them together: + *

ALLOW_2_SLASHES + NO_FRAGMENTS

+ * enables both of those options. + */ + public UrlValidator(RegexValidator authorityValidator, long options) { + this(null, authorityValidator, options); + } + + /** + * Customizable constructor. Validation behavior is modifed by passing in options. + * @param schemes the set of valid schemes. Ignored if the ALLOW_ALL_SCHEMES option is set. + * @param authorityValidator Regular expression validator used to validate the authority part + * @param options Validation options. Set using the public constants of this class. + * To set multiple options, simply add them together: + *

ALLOW_2_SLASHES + NO_FRAGMENTS

+ * enables both of those options. + */ + public UrlValidator(String[] schemes, RegexValidator authorityValidator, long options) { + this.options = options; + + if (isOn(ALLOW_ALL_SCHEMES)) { + allowedSchemes = Collections.emptySet(); + } else { + if (schemes == null) { + schemes = DEFAULT_SCHEMES; + } + allowedSchemes = new HashSet(schemes.length); + for(int i=0; i < schemes.length; i++) { + allowedSchemes.add(schemes[i].toLowerCase(Locale.ENGLISH)); + } + } + + this.authorityValidator = authorityValidator; + } + + /** + *

Checks if a field has a valid url address.

+ * + * Note that the method calls #isValidAuthority() + * which checks that the domain is valid. + * + * @param value The value validation is being performed on. A null + * value is considered invalid. + * @return true if the url is valid. + */ + public boolean isValid(String value) { + if (value == null) { + return false; + } + + // Check the whole url address structure + Matcher urlMatcher = URL_PATTERN.matcher(value); + if (!urlMatcher.matches()) { + return false; + } + + String scheme = urlMatcher.group(PARSE_URL_SCHEME); + if (!isValidScheme(scheme)) { + return false; + } + + String authority = urlMatcher.group(PARSE_URL_AUTHORITY); + if ("file".equals(scheme) && (authority == null || "".equals(authority))) {// Special case - file: allows an empty authority + return true; // this is a local file - nothing more to do here + } else if ("file".equals(scheme) && authority != null && authority.contains(":")) { + return false; + } else { + // Validate the authority + if (!isValidAuthority(authority)) { + return false; + } + } + + if (!isValidPath(urlMatcher.group(PARSE_URL_PATH))) { + return false; + } + + if (!isValidQuery(urlMatcher.group(PARSE_URL_QUERY))) { + return false; + } + + if (!isValidFragment(urlMatcher.group(PARSE_URL_FRAGMENT))) { + return false; + } + + return true; + } + + /** + * Validate scheme. If schemes[] was initialized to a non null, + * then only those schemes are allowed. + * Otherwise the default schemes are "http", "https", "ftp". + * Matching is case-blind. + * @param scheme The scheme to validate. A null value is considered + * invalid. + * @return true if valid. + */ +/** + * Validate scheme. If schemes[] was initialized to a non null, + * then only those schemes are allowed. + * Otherwise the default schemes are "http", "https", "ftp". + * Matching is case-blind. + * + * @param scheme + * The scheme to validate. A null value is considered + * invalid. + * @return true if valid. + */ +protected boolean isValidScheme(java.lang.String scheme) { + { + // TODO could be removed if external schemes were checked in the ctor before being stored + if (!org.apache.commons.validator.routines.UrlValidator.SCHEME_PATTERN.matcher(/* NPEX_NULL_EXP */ + scheme).matches()) { + return false; + } + if (isOff(org.apache.commons.validator.routines.UrlValidator.ALLOW_ALL_SCHEMES) && (!allowedSchemes.contains(scheme.toLowerCase(java.util.Locale.ENGLISH)))) { + return false; + } + return true; + } +} + + /** + * Returns true if the authority is properly formatted. An authority is the combination + * of hostname and port. A null authority value is considered invalid. + * Note: this implementation validates the domain unless a RegexValidator was provided. + * If a RegexValidator was supplied and it matches, then the authority is regarded + * as valid with no further checks, otherwise the method checks against the + * AUTHORITY_PATTERN and the DomainValidator (ALLOW_LOCAL_URLS) + * @param authority Authority value to validate, alllows IDN + * @return true if authority (hostname and port) is valid. + */ + protected boolean isValidAuthority(String authority) { + if (authority == null) { + return false; + } + + // check manual authority validation if specified + if (authorityValidator != null && authorityValidator.isValid(authority)) { + return true; + } + // convert to ASCII if possible + final String authorityASCII = DomainValidator.unicodeToASCII(authority); + + Matcher authorityMatcher = AUTHORITY_PATTERN.matcher(authorityASCII); + if (!authorityMatcher.matches()) { + return false; + } + + // We have to process IPV6 separately because that is parsed in a different group + String ipv6 = authorityMatcher.group(PARSE_AUTHORITY_IPV6); + if (ipv6 != null) { + InetAddressValidator inetAddressValidator = InetAddressValidator.getInstance(); + if (!inetAddressValidator.isValidInet6Address(ipv6)) { + return false; + } + } else { + String hostLocation = authorityMatcher.group(PARSE_AUTHORITY_HOST_IP); + // check if authority is hostname or IP address: + // try a hostname first since that's much more likely + DomainValidator domainValidator = DomainValidator.getInstance(isOn(ALLOW_LOCAL_URLS)); + if (!domainValidator.isValid(hostLocation)) { + // try an IPv4 address + InetAddressValidator inetAddressValidator = InetAddressValidator.getInstance(); + if (!inetAddressValidator.isValidInet4Address(hostLocation)) { + // isn't IPv4, so the URL is invalid + return false; + } + } + String port = authorityMatcher.group(PARSE_AUTHORITY_PORT); + if (port != null && port.length() > 0) { + try { + int iPort = Integer.parseInt(port); + if (iPort < 0 || iPort > MAX_UNSIGNED_16_BIT_INT) { + return false; + } + } catch (NumberFormatException nfe) { + return false; // this can happen for big numbers + } + } + } + + String extra = authorityMatcher.group(PARSE_AUTHORITY_EXTRA); + if (extra != null && extra.trim().length() > 0){ + return false; + } + + return true; + } + + /** + * Returns true if the path is valid. A null value is considered invalid. + * @param path Path value to validate. + * @return true if path is valid. + */ + protected boolean isValidPath(String path) { + if (path == null) { + return false; + } + + if (!PATH_PATTERN.matcher(path).matches()) { + return false; + } + + try { + // Don't omit host otherwise leading path may be taken as host if it starts with // + URI uri = new URI(null,"localhost",path,null); + String norm = uri.normalize().getPath(); + if (norm.startsWith("/../") // Trying to go via the parent dir + || norm.equals("/..")) { // Trying to go to the parent dir + return false; + } + } catch (URISyntaxException e) { + return false; + } + + int slash2Count = countToken("//", path); + if (isOff(ALLOW_2_SLASHES) && (slash2Count > 0)) { + return false; + } + + return true; + } + + /** + * Returns true if the query is null or it's a properly formatted query string. + * @param query Query value to validate. + * @return true if query is valid. + */ + protected boolean isValidQuery(String query) { + if (query == null) { + return true; + } + + return QUERY_PATTERN.matcher(query).matches(); + } + + /** + * Returns true if the given fragment is null or fragments are allowed. + * @param fragment Fragment value to validate. + * @return true if fragment is valid. + */ + protected boolean isValidFragment(String fragment) { + if (fragment == null) { + return true; + } + + return isOff(NO_FRAGMENTS); + } + + /** + * Returns the number of times the token appears in the target. + * @param token Token value to be counted. + * @param target Target value to count tokens in. + * @return the number of tokens. + */ + protected int countToken(String token, String target) { + int tokenIndex = 0; + int count = 0; + while (tokenIndex != -1) { + tokenIndex = target.indexOf(token, tokenIndex); + if (tokenIndex > -1) { + tokenIndex++; + count++; + } + } + return count; + } + + /** + * Tests whether the given flag is on. If the flag is not a power of 2 + * (ie. 3) this tests whether the combination of flags is on. + * + * @param flag Flag value to check. + * + * @return whether the specified flag value is on. + */ + private boolean isOn(long flag) { + return (options & flag) > 0; + } + + /** + * Tests whether the given flag is off. If the flag is not a power of 2 + * (ie. 3) this tests whether the combination of flags is off. + * + * @param flag Flag value to check. + * + * @return whether the specified flag value is off. + */ + private boolean isOff(long flag) { + return (options & flag) == 0; + } + + // Unit test access to pattern matcher + Matcher matchURL(String value) { + return URL_PATTERN.matcher(value); + } + + /** + * Validator for checking URL parsing + * @param args - URLs to validate + */ + public static void main(String[] args) { + UrlValidator val = new UrlValidator(new String[] { "file", "http", "https" }, UrlValidator.ALLOW_LOCAL_URLS); + for(String arg: args) { + Matcher m = val.matchURL(arg); + if (m.matches()) { + System.out.printf("%s has %d parts%n",arg,m.groupCount()); + for(int i=1;i 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-validator-UrlValidator_378/buggy.java b/Java/commons-validator-UrlValidator_378/buggy.java new file mode 100644 index 000000000..eb594d07d --- /dev/null +++ b/Java/commons-validator-UrlValidator_378/buggy.java @@ -0,0 +1,584 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + *

URL Validation routines.

+ * Behavior of validation is modified by passing in options: + *
    + *
  • ALLOW_2_SLASHES - [FALSE] Allows double '/' characters in the path + * component.
  • + *
  • NO_FRAGMENT- [FALSE] By default fragments are allowed, if this option is + * included then fragments are flagged as illegal.
  • + *
  • ALLOW_ALL_SCHEMES - [FALSE] By default only http, https, and ftp are + * considered valid schemes. Enabling this option will let any scheme pass validation.
  • + *
+ * + *

Originally based in on php script by Debbie Dyer, validation.php v1.2b, Date: 03/07/02, + * http://javascript.internet.com. However, this validation now bears little resemblance + * to the php original.

+ *
+ *   Example of usage:
+ *   Construct a UrlValidator with valid schemes of "http", and "https".
+ *
+ *    String[] schemes = {"http","https"}.
+ *    UrlValidator urlValidator = new UrlValidator(schemes);
+ *    if (urlValidator.isValid("ftp://foo.bar.com/")) {
+ *       System.out.println("url is valid");
+ *    } else {
+ *       System.out.println("url is invalid");
+ *    }
+ *
+ *    prints "url is invalid"
+ *   If instead the default constructor is used.
+ *
+ *    UrlValidator urlValidator = new UrlValidator();
+ *    if (urlValidator.isValid("ftp://foo.bar.com/")) {
+ *       System.out.println("url is valid");
+ *    } else {
+ *       System.out.println("url is invalid");
+ *    }
+ *
+ *   prints out "url is valid"
+ *  
+ * + * @see + * + * Uniform Resource Identifiers (URI): Generic Syntax + * + * + * @version $Revision$ + * @since Validator 1.4 + */ +public class UrlValidator implements Serializable { + + private static final long serialVersionUID = 7557161713937335013L; + + private static final int MAX_UNSIGNED_16_BIT_INT = 0xFFFF; // port max + + /** + * Allows all validly formatted schemes to pass validation instead of + * supplying a set of valid schemes. + */ + public static final long ALLOW_ALL_SCHEMES = 1 << 0; + + /** + * Allow two slashes in the path component of the URL. + */ + public static final long ALLOW_2_SLASHES = 1 << 1; + + /** + * Enabling this options disallows any URL fragments. + */ + public static final long NO_FRAGMENTS = 1 << 2; + + /** + * Allow local URLs, such as http://localhost/ or http://machine/ . + * This enables a broad-brush check, for complex local machine name + * validation requirements you should create your validator with + * a {@link RegexValidator} instead ({@link #UrlValidator(RegexValidator, long)}) + */ + public static final long ALLOW_LOCAL_URLS = 1 << 3; // CHECKSTYLE IGNORE MagicNumber + + /** + * This expression derived/taken from the BNF for URI (RFC2396). + */ + private static final String URL_REGEX = + "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?"; + // 12 3 4 5 6 7 8 9 + private static final Pattern URL_PATTERN = Pattern.compile(URL_REGEX); + + /** + * Schema/Protocol (ie. http:, ftp:, file:, etc). + */ + private static final int PARSE_URL_SCHEME = 2; + + /** + * Includes hostname/ip and port number. + */ + private static final int PARSE_URL_AUTHORITY = 4; + + private static final int PARSE_URL_PATH = 5; + + private static final int PARSE_URL_QUERY = 7; + + private static final int PARSE_URL_FRAGMENT = 9; + + /** + * Protocol scheme (e.g. http, ftp, https). + */ + private static final String SCHEME_REGEX = "^\\p{Alpha}[\\p{Alnum}\\+\\-\\.]*"; + private static final Pattern SCHEME_PATTERN = Pattern.compile(SCHEME_REGEX); + + // Drop numeric, and "+-." for now + // TODO does not allow for optional userinfo. + // Validation of character set is done by isValidAuthority + private static final String AUTHORITY_CHARS_REGEX = "\\p{Alnum}\\-\\."; // allows for IPV4 but not IPV6 + private static final String IPV6_REGEX = "[0-9a-fA-F:]+"; // do this as separate match because : could cause ambiguity with port prefix + + // userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) + // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + // We assume that password has the same valid chars as user info + private static final String USERINFO_CHARS_REGEX = "[a-zA-Z0-9%-._~!$&'()*+,;=]"; + // since neither ':' nor '@' are allowed chars, we don't need to use non-greedy matching + private static final String USERINFO_FIELD_REGEX = + USERINFO_CHARS_REGEX + "+" + // At least one character for the name + "(?::" + USERINFO_CHARS_REGEX + "*)?@"; // colon and password may be absent + private static final String AUTHORITY_REGEX = + "(?:\\[("+IPV6_REGEX+")\\]|(?:(?:"+USERINFO_FIELD_REGEX+")?([" + AUTHORITY_CHARS_REGEX + "]*)))(?::(\\d*))?(.*)?"; + // 1 e.g. user:pass@ 2 3 4 + private static final Pattern AUTHORITY_PATTERN = Pattern.compile(AUTHORITY_REGEX); + + private static final int PARSE_AUTHORITY_IPV6 = 1; + + private static final int PARSE_AUTHORITY_HOST_IP = 2; // excludes userinfo, if present + + private static final int PARSE_AUTHORITY_PORT = 3; // excludes leading colon + + /** + * Should always be empty. The code currently allows spaces. + */ + private static final int PARSE_AUTHORITY_EXTRA = 4; + + private static final String PATH_REGEX = "^(/[-\\w:@&?=+,.!/~*'%$_;\\(\\)]*)?$"; + private static final Pattern PATH_PATTERN = Pattern.compile(PATH_REGEX); + + private static final String QUERY_REGEX = "^(\\S*)$"; + private static final Pattern QUERY_PATTERN = Pattern.compile(QUERY_REGEX); + + /** + * Holds the set of current validation options. + */ + private final long options; + + /** + * The set of schemes that are allowed to be in a URL. + */ + private final Set allowedSchemes; // Must be lower-case + + /** + * Regular expressions used to manually validate authorities if IANA + * domain name validation isn't desired. + */ + private final RegexValidator authorityValidator; + + /** + * If no schemes are provided, default to this set. + */ + private static final String[] DEFAULT_SCHEMES = {"http", "https", "ftp"}; // Must be lower-case + + /** + * Singleton instance of this class with default schemes and options. + */ + private static final UrlValidator DEFAULT_URL_VALIDATOR = new UrlValidator(); + + /** + * Returns the singleton instance of this class with default schemes and options. + * @return singleton instance with default schemes and options + */ + public static UrlValidator getInstance() { + return DEFAULT_URL_VALIDATOR; + } + + /** + * Create a UrlValidator with default properties. + */ + public UrlValidator() { + this(null); + } + + /** + * Behavior of validation is modified by passing in several strings options: + * @param schemes Pass in one or more url schemes to consider valid, passing in + * a null will default to "http,https,ftp" being valid. + * If a non-null schemes is specified then all valid schemes must + * be specified. Setting the ALLOW_ALL_SCHEMES option will + * ignore the contents of schemes. + */ + public UrlValidator(String[] schemes) { + this(schemes, 0L); + } + + /** + * Initialize a UrlValidator with the given validation options. + * @param options The options should be set using the public constants declared in + * this class. To set multiple options you simply add them together. For example, + * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options. + */ + public UrlValidator(long options) { + this(null, null, options); + } + + /** + * Behavior of validation is modified by passing in options: + * @param schemes The set of valid schemes. Ignored if the ALLOW_ALL_SCHEMES option is set. + * @param options The options should be set using the public constants declared in + * this class. To set multiple options you simply add them together. For example, + * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options. + */ + public UrlValidator(String[] schemes, long options) { + this(schemes, null, options); + } + + /** + * Initialize a UrlValidator with the given validation options. + * @param authorityValidator Regular expression validator used to validate the authority part + * This allows the user to override the standard set of domains. + * @param options Validation options. Set using the public constants of this class. + * To set multiple options, simply add them together: + *

ALLOW_2_SLASHES + NO_FRAGMENTS

+ * enables both of those options. + */ + public UrlValidator(RegexValidator authorityValidator, long options) { + this(null, authorityValidator, options); + } + + /** + * Customizable constructor. Validation behavior is modifed by passing in options. + * @param schemes the set of valid schemes. Ignored if the ALLOW_ALL_SCHEMES option is set. + * @param authorityValidator Regular expression validator used to validate the authority part + * @param options Validation options. Set using the public constants of this class. + * To set multiple options, simply add them together: + *

ALLOW_2_SLASHES + NO_FRAGMENTS

+ * enables both of those options. + */ + public UrlValidator(String[] schemes, RegexValidator authorityValidator, long options) { + this.options = options; + + if (isOn(ALLOW_ALL_SCHEMES)) { + allowedSchemes = Collections.emptySet(); + } else { + if (schemes == null) { + schemes = DEFAULT_SCHEMES; + } + allowedSchemes = new HashSet(schemes.length); + for(int i=0; i < schemes.length; i++) { + allowedSchemes.add(schemes[i].toLowerCase(Locale.ENGLISH)); + } + } + + this.authorityValidator = authorityValidator; + } + + /** + *

Checks if a field has a valid url address.

+ * + * Note that the method calls #isValidAuthority() + * which checks that the domain is valid. + * + * @param value The value validation is being performed on. A null + * value is considered invalid. + * @return true if the url is valid. + */ + public boolean isValid(String value) { + if (value == null) { + return false; + } + + // Check the whole url address structure + Matcher urlMatcher = URL_PATTERN.matcher(value); + if (!urlMatcher.matches()) { + return false; + } + + String scheme = urlMatcher.group(PARSE_URL_SCHEME); + if (!isValidScheme(scheme)) { + return false; + } + + String authority = urlMatcher.group(PARSE_URL_AUTHORITY); + if ("file".equals(scheme) && (authority == null || "".equals(authority))) {// Special case - file: allows an empty authority + return true; // this is a local file - nothing more to do here + } else if ("file".equals(scheme) && authority != null && authority.contains(":")) { + return false; + } else { + // Validate the authority + if (!isValidAuthority(authority)) { + return false; + } + } + + if (!isValidPath(urlMatcher.group(PARSE_URL_PATH))) { + return false; + } + + if (!isValidQuery(urlMatcher.group(PARSE_URL_QUERY))) { + return false; + } + + if (!isValidFragment(urlMatcher.group(PARSE_URL_FRAGMENT))) { + return false; + } + + return true; + } + + /** + * Validate scheme. If schemes[] was initialized to a non null, + * then only those schemes are allowed. + * Otherwise the default schemes are "http", "https", "ftp". + * Matching is case-blind. + * @param scheme The scheme to validate. A null value is considered + * invalid. + * @return true if valid. + */ + protected boolean isValidScheme(String scheme) { + if (scheme == null) { + return false; + } + + // TODO could be removed if external schemes were checked in the ctor before being stored + if (!SCHEME_PATTERN.matcher(scheme).matches()) { + return false; + } + + if (isOff(ALLOW_ALL_SCHEMES) && !allowedSchemes.contains(scheme.toLowerCase(Locale.ENGLISH))) { + return false; + } + + return true; + } + + /** + * Returns true if the authority is properly formatted. An authority is the combination + * of hostname and port. A null authority value is considered invalid. + * Note: this implementation validates the domain unless a RegexValidator was provided. + * If a RegexValidator was supplied and it matches, then the authority is regarded + * as valid with no further checks, otherwise the method checks against the + * AUTHORITY_PATTERN and the DomainValidator (ALLOW_LOCAL_URLS) + * @param authority Authority value to validate, alllows IDN + * @return true if authority (hostname and port) is valid. + */ +/** + * Returns true if the authority is properly formatted. An authority is the combination + * of hostname and port. A null authority value is considered invalid. + * Note: this implementation validates the domain unless a RegexValidator was provided. + * If a RegexValidator was supplied and it matches, then the authority is regarded + * as valid with no further checks, otherwise the method checks against the + * AUTHORITY_PATTERN and the DomainValidator (ALLOW_LOCAL_URLS) + * + * @param authority + * Authority value to validate, alllows IDN + * @return true if authority (hostname and port) is valid. + */ +protected boolean isValidAuthority(java.lang.String authority) { + { + // check manual authority validation if specified + if ((authorityValidator != null) && authorityValidator.isValid(/* NPEX_NULL_EXP */ + authority)) { + return true; + } + // convert to ASCII if possible + final java.lang.String authorityASCII = org.apache.commons.validator.routines.DomainValidator.unicodeToASCII(authority); + java.util.regex.Matcher authorityMatcher = org.apache.commons.validator.routines.UrlValidator.AUTHORITY_PATTERN.matcher(authorityASCII); + if (!authorityMatcher.matches()) { + return false; + } + // We have to process IPV6 separately because that is parsed in a different group + java.lang.String ipv6 = authorityMatcher.group(org.apache.commons.validator.routines.UrlValidator.PARSE_AUTHORITY_IPV6); + if (ipv6 != null) { + org.apache.commons.validator.routines.InetAddressValidator inetAddressValidator = org.apache.commons.validator.routines.InetAddressValidator.getInstance(); + if (!inetAddressValidator.isValidInet6Address(ipv6)) { + return false; + } + } else { + java.lang.String hostLocation = authorityMatcher.group(org.apache.commons.validator.routines.UrlValidator.PARSE_AUTHORITY_HOST_IP); + // check if authority is hostname or IP address: + // try a hostname first since that's much more likely + org.apache.commons.validator.routines.DomainValidator domainValidator = org.apache.commons.validator.routines.DomainValidator.getInstance(isOn(org.apache.commons.validator.routines.UrlValidator.ALLOW_LOCAL_URLS)); + if (!domainValidator.isValid(hostLocation)) { + // try an IPv4 address + org.apache.commons.validator.routines.InetAddressValidator inetAddressValidator = org.apache.commons.validator.routines.InetAddressValidator.getInstance(); + if (!inetAddressValidator.isValidInet4Address(hostLocation)) { + // isn't IPv4, so the URL is invalid + return false; + } + } + java.lang.String port = authorityMatcher.group(org.apache.commons.validator.routines.UrlValidator.PARSE_AUTHORITY_PORT); + if ((port != null) && (port.length() > 0)) { + try { + int iPort = java.lang.Integer.parseInt(port); + if ((iPort < 0) || (iPort > org.apache.commons.validator.routines.UrlValidator.MAX_UNSIGNED_16_BIT_INT)) { + return false; + } + } catch (java.lang.NumberFormatException nfe) { + return false;// this can happen for big numbers + + } + } + } + java.lang.String extra = authorityMatcher.group(org.apache.commons.validator.routines.UrlValidator.PARSE_AUTHORITY_EXTRA); + if ((extra != null) && (extra.trim().length() > 0)) { + return false; + } + return true; + } +} + + /** + * Returns true if the path is valid. A null value is considered invalid. + * @param path Path value to validate. + * @return true if path is valid. + */ + protected boolean isValidPath(String path) { + if (path == null) { + return false; + } + + if (!PATH_PATTERN.matcher(path).matches()) { + return false; + } + + try { + // Don't omit host otherwise leading path may be taken as host if it starts with // + URI uri = new URI(null,"localhost",path,null); + String norm = uri.normalize().getPath(); + if (norm.startsWith("/../") // Trying to go via the parent dir + || norm.equals("/..")) { // Trying to go to the parent dir + return false; + } + } catch (URISyntaxException e) { + return false; + } + + int slash2Count = countToken("//", path); + if (isOff(ALLOW_2_SLASHES) && (slash2Count > 0)) { + return false; + } + + return true; + } + + /** + * Returns true if the query is null or it's a properly formatted query string. + * @param query Query value to validate. + * @return true if query is valid. + */ + protected boolean isValidQuery(String query) { + if (query == null) { + return true; + } + + return QUERY_PATTERN.matcher(query).matches(); + } + + /** + * Returns true if the given fragment is null or fragments are allowed. + * @param fragment Fragment value to validate. + * @return true if fragment is valid. + */ + protected boolean isValidFragment(String fragment) { + if (fragment == null) { + return true; + } + + return isOff(NO_FRAGMENTS); + } + + /** + * Returns the number of times the token appears in the target. + * @param token Token value to be counted. + * @param target Target value to count tokens in. + * @return the number of tokens. + */ + protected int countToken(String token, String target) { + int tokenIndex = 0; + int count = 0; + while (tokenIndex != -1) { + tokenIndex = target.indexOf(token, tokenIndex); + if (tokenIndex > -1) { + tokenIndex++; + count++; + } + } + return count; + } + + /** + * Tests whether the given flag is on. If the flag is not a power of 2 + * (ie. 3) this tests whether the combination of flags is on. + * + * @param flag Flag value to check. + * + * @return whether the specified flag value is on. + */ + private boolean isOn(long flag) { + return (options & flag) > 0; + } + + /** + * Tests whether the given flag is off. If the flag is not a power of 2 + * (ie. 3) this tests whether the combination of flags is off. + * + * @param flag Flag value to check. + * + * @return whether the specified flag value is off. + */ + private boolean isOff(long flag) { + return (options & flag) == 0; + } + + // Unit test access to pattern matcher + Matcher matchURL(String value) { + return URL_PATTERN.matcher(value); + } + + /** + * Validator for checking URL parsing + * @param args - URLs to validate + */ + public static void main(String[] args) { + UrlValidator val = new UrlValidator(new String[] { "file", "http", "https" }, UrlValidator.ALLOW_LOCAL_URLS); + for(String arg: args) { + Matcher m = val.matchURL(arg); + if (m.matches()) { + System.out.printf("%s has %d parts%n",arg,m.groupCount()); + for(int i=1;i 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-validator-UrlValidator_396/buggy.java b/Java/commons-validator-UrlValidator_396/buggy.java new file mode 100644 index 000000000..528f1bd99 --- /dev/null +++ b/Java/commons-validator-UrlValidator_396/buggy.java @@ -0,0 +1,560 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + *

URL Validation routines.

+ * Behavior of validation is modified by passing in options: + *
    + *
  • ALLOW_2_SLASHES - [FALSE] Allows double '/' characters in the path + * component.
  • + *
  • NO_FRAGMENT- [FALSE] By default fragments are allowed, if this option is + * included then fragments are flagged as illegal.
  • + *
  • ALLOW_ALL_SCHEMES - [FALSE] By default only http, https, and ftp are + * considered valid schemes. Enabling this option will let any scheme pass validation.
  • + *
+ * + *

Originally based in on php script by Debbie Dyer, validation.php v1.2b, Date: 03/07/02, + * http://javascript.internet.com. However, this validation now bears little resemblance + * to the php original.

+ *
+ *   Example of usage:
+ *   Construct a UrlValidator with valid schemes of "http", and "https".
+ *
+ *    String[] schemes = {"http","https"}.
+ *    UrlValidator urlValidator = new UrlValidator(schemes);
+ *    if (urlValidator.isValid("ftp://foo.bar.com/")) {
+ *       System.out.println("url is valid");
+ *    } else {
+ *       System.out.println("url is invalid");
+ *    }
+ *
+ *    prints "url is invalid"
+ *   If instead the default constructor is used.
+ *
+ *    UrlValidator urlValidator = new UrlValidator();
+ *    if (urlValidator.isValid("ftp://foo.bar.com/")) {
+ *       System.out.println("url is valid");
+ *    } else {
+ *       System.out.println("url is invalid");
+ *    }
+ *
+ *   prints out "url is valid"
+ *  
+ * + * @see + * + * Uniform Resource Identifiers (URI): Generic Syntax + * + * + * @version $Revision$ + * @since Validator 1.4 + */ +public class UrlValidator implements Serializable { + + private static final long serialVersionUID = 7557161713937335013L; + + private static final int MAX_UNSIGNED_16_BIT_INT = 0xFFFF; // port max + + /** + * Allows all validly formatted schemes to pass validation instead of + * supplying a set of valid schemes. + */ + public static final long ALLOW_ALL_SCHEMES = 1 << 0; + + /** + * Allow two slashes in the path component of the URL. + */ + public static final long ALLOW_2_SLASHES = 1 << 1; + + /** + * Enabling this options disallows any URL fragments. + */ + public static final long NO_FRAGMENTS = 1 << 2; + + /** + * Allow local URLs, such as http://localhost/ or http://machine/ . + * This enables a broad-brush check, for complex local machine name + * validation requirements you should create your validator with + * a {@link RegexValidator} instead ({@link #UrlValidator(RegexValidator, long)}) + */ + public static final long ALLOW_LOCAL_URLS = 1 << 3; // CHECKSTYLE IGNORE MagicNumber + + /** + * This expression derived/taken from the BNF for URI (RFC2396). + */ + private static final String URL_REGEX = + "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?"; + // 12 3 4 5 6 7 8 9 + private static final Pattern URL_PATTERN = Pattern.compile(URL_REGEX); + + /** + * Schema/Protocol (ie. http:, ftp:, file:, etc). + */ + private static final int PARSE_URL_SCHEME = 2; + + /** + * Includes hostname/ip and port number. + */ + private static final int PARSE_URL_AUTHORITY = 4; + + private static final int PARSE_URL_PATH = 5; + + private static final int PARSE_URL_QUERY = 7; + + private static final int PARSE_URL_FRAGMENT = 9; + + /** + * Protocol scheme (e.g. http, ftp, https). + */ + private static final String SCHEME_REGEX = "^\\p{Alpha}[\\p{Alnum}\\+\\-\\.]*"; + private static final Pattern SCHEME_PATTERN = Pattern.compile(SCHEME_REGEX); + + // Drop numeric, and "+-." for now + // TODO does not allow for optional userinfo. + // Validation of character set is done by isValidAuthority + private static final String AUTHORITY_CHARS_REGEX = "\\p{Alnum}\\-\\."; // allows for IPV4 but not IPV6 + private static final String IPV6_REGEX = "[0-9a-fA-F:]+"; // do this as separate match because : could cause ambiguity with port prefix + + // userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) + // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + // We assume that password has the same valid chars as user info + private static final String USERINFO_CHARS_REGEX = "[a-zA-Z0-9%-._~!$&'()*+,;=]"; + // since neither ':' nor '@' are allowed chars, we don't need to use non-greedy matching + private static final String USERINFO_FIELD_REGEX = + USERINFO_CHARS_REGEX + "+" + // At least one character for the name + "(?::" + USERINFO_CHARS_REGEX + "*)?@"; // colon and password may be absent + private static final String AUTHORITY_REGEX = + "(?:\\[("+IPV6_REGEX+")\\]|(?:(?:"+USERINFO_FIELD_REGEX+")?([" + AUTHORITY_CHARS_REGEX + "]*)))(?::(\\d*))?(.*)?"; + // 1 e.g. user:pass@ 2 3 4 + private static final Pattern AUTHORITY_PATTERN = Pattern.compile(AUTHORITY_REGEX); + + private static final int PARSE_AUTHORITY_IPV6 = 1; + + private static final int PARSE_AUTHORITY_HOST_IP = 2; // excludes userinfo, if present + + private static final int PARSE_AUTHORITY_PORT = 3; // excludes leading colon + + /** + * Should always be empty. The code currently allows spaces. + */ + private static final int PARSE_AUTHORITY_EXTRA = 4; + + private static final String PATH_REGEX = "^(/[-\\w:@&?=+,.!/~*'%$_;\\(\\)]*)?$"; + private static final Pattern PATH_PATTERN = Pattern.compile(PATH_REGEX); + + private static final String QUERY_REGEX = "^(\\S*)$"; + private static final Pattern QUERY_PATTERN = Pattern.compile(QUERY_REGEX); + + /** + * Holds the set of current validation options. + */ + private final long options; + + /** + * The set of schemes that are allowed to be in a URL. + */ + private final Set allowedSchemes; // Must be lower-case + + /** + * Regular expressions used to manually validate authorities if IANA + * domain name validation isn't desired. + */ + private final RegexValidator authorityValidator; + + /** + * If no schemes are provided, default to this set. + */ + private static final String[] DEFAULT_SCHEMES = {"http", "https", "ftp"}; // Must be lower-case + + /** + * Singleton instance of this class with default schemes and options. + */ + private static final UrlValidator DEFAULT_URL_VALIDATOR = new UrlValidator(); + + /** + * Returns the singleton instance of this class with default schemes and options. + * @return singleton instance with default schemes and options + */ + public static UrlValidator getInstance() { + return DEFAULT_URL_VALIDATOR; + } + + /** + * Create a UrlValidator with default properties. + */ + public UrlValidator() { + this(null); + } + + /** + * Behavior of validation is modified by passing in several strings options: + * @param schemes Pass in one or more url schemes to consider valid, passing in + * a null will default to "http,https,ftp" being valid. + * If a non-null schemes is specified then all valid schemes must + * be specified. Setting the ALLOW_ALL_SCHEMES option will + * ignore the contents of schemes. + */ + public UrlValidator(String[] schemes) { + this(schemes, 0L); + } + + /** + * Initialize a UrlValidator with the given validation options. + * @param options The options should be set using the public constants declared in + * this class. To set multiple options you simply add them together. For example, + * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options. + */ + public UrlValidator(long options) { + this(null, null, options); + } + + /** + * Behavior of validation is modified by passing in options: + * @param schemes The set of valid schemes. Ignored if the ALLOW_ALL_SCHEMES option is set. + * @param options The options should be set using the public constants declared in + * this class. To set multiple options you simply add them together. For example, + * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options. + */ + public UrlValidator(String[] schemes, long options) { + this(schemes, null, options); + } + + /** + * Initialize a UrlValidator with the given validation options. + * @param authorityValidator Regular expression validator used to validate the authority part + * This allows the user to override the standard set of domains. + * @param options Validation options. Set using the public constants of this class. + * To set multiple options, simply add them together: + *

ALLOW_2_SLASHES + NO_FRAGMENTS

+ * enables both of those options. + */ + public UrlValidator(RegexValidator authorityValidator, long options) { + this(null, authorityValidator, options); + } + + /** + * Customizable constructor. Validation behavior is modifed by passing in options. + * @param schemes the set of valid schemes. Ignored if the ALLOW_ALL_SCHEMES option is set. + * @param authorityValidator Regular expression validator used to validate the authority part + * @param options Validation options. Set using the public constants of this class. + * To set multiple options, simply add them together: + *

ALLOW_2_SLASHES + NO_FRAGMENTS

+ * enables both of those options. + */ + public UrlValidator(String[] schemes, RegexValidator authorityValidator, long options) { + this.options = options; + + if (isOn(ALLOW_ALL_SCHEMES)) { + allowedSchemes = Collections.emptySet(); + } else { + if (schemes == null) { + schemes = DEFAULT_SCHEMES; + } + allowedSchemes = new HashSet(schemes.length); + for(int i=0; i < schemes.length; i++) { + allowedSchemes.add(schemes[i].toLowerCase(Locale.ENGLISH)); + } + } + + this.authorityValidator = authorityValidator; + } + + /** + *

Checks if a field has a valid url address.

+ * + * Note that the method calls #isValidAuthority() + * which checks that the domain is valid. + * + * @param value The value validation is being performed on. A null + * value is considered invalid. + * @return true if the url is valid. + */ + public boolean isValid(String value) { + if (value == null) { + return false; + } + + // Check the whole url address structure + Matcher urlMatcher = URL_PATTERN.matcher(value); + if (!urlMatcher.matches()) { + return false; + } + + String scheme = urlMatcher.group(PARSE_URL_SCHEME); + if (!isValidScheme(scheme)) { + return false; + } + + String authority = urlMatcher.group(PARSE_URL_AUTHORITY); + if ("file".equals(scheme) && (authority == null || "".equals(authority))) {// Special case - file: allows an empty authority + return true; // this is a local file - nothing more to do here + } else if ("file".equals(scheme) && authority != null && authority.contains(":")) { + return false; + } else { + // Validate the authority + if (!isValidAuthority(authority)) { + return false; + } + } + + if (!isValidPath(urlMatcher.group(PARSE_URL_PATH))) { + return false; + } + + if (!isValidQuery(urlMatcher.group(PARSE_URL_QUERY))) { + return false; + } + + if (!isValidFragment(urlMatcher.group(PARSE_URL_FRAGMENT))) { + return false; + } + + return true; + } + + /** + * Validate scheme. If schemes[] was initialized to a non null, + * then only those schemes are allowed. + * Otherwise the default schemes are "http", "https", "ftp". + * Matching is case-blind. + * @param scheme The scheme to validate. A null value is considered + * invalid. + * @return true if valid. + */ + protected boolean isValidScheme(String scheme) { + if (scheme == null) { + return false; + } + + // TODO could be removed if external schemes were checked in the ctor before being stored + if (!SCHEME_PATTERN.matcher(scheme).matches()) { + return false; + } + + if (isOff(ALLOW_ALL_SCHEMES) && !allowedSchemes.contains(scheme.toLowerCase(Locale.ENGLISH))) { + return false; + } + + return true; + } + + /** + * Returns true if the authority is properly formatted. An authority is the combination + * of hostname and port. A null authority value is considered invalid. + * Note: this implementation validates the domain unless a RegexValidator was provided. + * If a RegexValidator was supplied and it matches, then the authority is regarded + * as valid with no further checks, otherwise the method checks against the + * AUTHORITY_PATTERN and the DomainValidator (ALLOW_LOCAL_URLS) + * @param authority Authority value to validate, alllows IDN + * @return true if authority (hostname and port) is valid. + */ +/** + * Returns true if the authority is properly formatted. An authority is the combination + * of hostname and port. A null authority value is considered invalid. + * Note: this implementation validates the domain unless a RegexValidator was provided. + * If a RegexValidator was supplied and it matches, then the authority is regarded + * as valid with no further checks, otherwise the method checks against the + * AUTHORITY_PATTERN and the DomainValidator (ALLOW_LOCAL_URLS) + * + * @param authority + * Authority value to validate, alllows IDN + * @return true if authority (hostname and port) is valid. + */ +protected boolean isValidAuthority(java.lang.String authority) { + if (authority == null) { + return false; + } + // check manual authority validation if specified + if ((authorityValidator != null) && authorityValidator.isValid(authority)) { + return true; + } + // convert to ASCII if possible + final java.lang.String authorityASCII = org.apache.commons.validator.routines.DomainValidator.unicodeToASCII(authority); + java.util.regex.Matcher authorityMatcher = org.apache.commons.validator.routines.UrlValidator.AUTHORITY_PATTERN.matcher(authorityASCII); + if (!authorityMatcher.matches()) { + return false; + } + // We have to process IPV6 separately because that is parsed in a different group + java.lang.String ipv6 = authorityMatcher.group(org.apache.commons.validator.routines.UrlValidator.PARSE_AUTHORITY_IPV6); + { + org.apache.commons.validator.routines.InetAddressValidator inetAddressValidator = org.apache.commons.validator.routines.InetAddressValidator.getInstance(); + if (!inetAddressValidator.isValidInet6Address(/* NPEX_NULL_EXP */ + ipv6)) { + return false; + } + } + java.lang.String extra = authorityMatcher.group(org.apache.commons.validator.routines.UrlValidator.PARSE_AUTHORITY_EXTRA); + if ((extra != null) && (extra.trim().length() > 0)) { + return false; + } + return true; +} + + /** + * Returns true if the path is valid. A null value is considered invalid. + * @param path Path value to validate. + * @return true if path is valid. + */ + protected boolean isValidPath(String path) { + if (path == null) { + return false; + } + + if (!PATH_PATTERN.matcher(path).matches()) { + return false; + } + + try { + // Don't omit host otherwise leading path may be taken as host if it starts with // + URI uri = new URI(null,"localhost",path,null); + String norm = uri.normalize().getPath(); + if (norm.startsWith("/../") // Trying to go via the parent dir + || norm.equals("/..")) { // Trying to go to the parent dir + return false; + } + } catch (URISyntaxException e) { + return false; + } + + int slash2Count = countToken("//", path); + if (isOff(ALLOW_2_SLASHES) && (slash2Count > 0)) { + return false; + } + + return true; + } + + /** + * Returns true if the query is null or it's a properly formatted query string. + * @param query Query value to validate. + * @return true if query is valid. + */ + protected boolean isValidQuery(String query) { + if (query == null) { + return true; + } + + return QUERY_PATTERN.matcher(query).matches(); + } + + /** + * Returns true if the given fragment is null or fragments are allowed. + * @param fragment Fragment value to validate. + * @return true if fragment is valid. + */ + protected boolean isValidFragment(String fragment) { + if (fragment == null) { + return true; + } + + return isOff(NO_FRAGMENTS); + } + + /** + * Returns the number of times the token appears in the target. + * @param token Token value to be counted. + * @param target Target value to count tokens in. + * @return the number of tokens. + */ + protected int countToken(String token, String target) { + int tokenIndex = 0; + int count = 0; + while (tokenIndex != -1) { + tokenIndex = target.indexOf(token, tokenIndex); + if (tokenIndex > -1) { + tokenIndex++; + count++; + } + } + return count; + } + + /** + * Tests whether the given flag is on. If the flag is not a power of 2 + * (ie. 3) this tests whether the combination of flags is on. + * + * @param flag Flag value to check. + * + * @return whether the specified flag value is on. + */ + private boolean isOn(long flag) { + return (options & flag) > 0; + } + + /** + * Tests whether the given flag is off. If the flag is not a power of 2 + * (ie. 3) this tests whether the combination of flags is off. + * + * @param flag Flag value to check. + * + * @return whether the specified flag value is off. + */ + private boolean isOff(long flag) { + return (options & flag) == 0; + } + + // Unit test access to pattern matcher + Matcher matchURL(String value) { + return URL_PATTERN.matcher(value); + } + + /** + * Validator for checking URL parsing + * @param args - URLs to validate + */ + public static void main(String[] args) { + UrlValidator val = new UrlValidator(new String[] { "file", "http", "https" }, UrlValidator.ALLOW_LOCAL_URLS); + for(String arg: args) { + Matcher m = val.matchURL(arg); + if (m.matches()) { + System.out.printf("%s has %d parts%n",arg,m.groupCount()); + for(int i=1;i 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-validator-UrlValidator_475/buggy.java b/Java/commons-validator-UrlValidator_475/buggy.java new file mode 100644 index 000000000..54237845c --- /dev/null +++ b/Java/commons-validator-UrlValidator_475/buggy.java @@ -0,0 +1,582 @@ +/* + * 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.validator.routines; + +import java.io.Serializable; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + *

URL Validation routines.

+ * Behavior of validation is modified by passing in options: + *
    + *
  • ALLOW_2_SLASHES - [FALSE] Allows double '/' characters in the path + * component.
  • + *
  • NO_FRAGMENT- [FALSE] By default fragments are allowed, if this option is + * included then fragments are flagged as illegal.
  • + *
  • ALLOW_ALL_SCHEMES - [FALSE] By default only http, https, and ftp are + * considered valid schemes. Enabling this option will let any scheme pass validation.
  • + *
+ * + *

Originally based in on php script by Debbie Dyer, validation.php v1.2b, Date: 03/07/02, + * http://javascript.internet.com. However, this validation now bears little resemblance + * to the php original.

+ *
+ *   Example of usage:
+ *   Construct a UrlValidator with valid schemes of "http", and "https".
+ *
+ *    String[] schemes = {"http","https"}.
+ *    UrlValidator urlValidator = new UrlValidator(schemes);
+ *    if (urlValidator.isValid("ftp://foo.bar.com/")) {
+ *       System.out.println("url is valid");
+ *    } else {
+ *       System.out.println("url is invalid");
+ *    }
+ *
+ *    prints "url is invalid"
+ *   If instead the default constructor is used.
+ *
+ *    UrlValidator urlValidator = new UrlValidator();
+ *    if (urlValidator.isValid("ftp://foo.bar.com/")) {
+ *       System.out.println("url is valid");
+ *    } else {
+ *       System.out.println("url is invalid");
+ *    }
+ *
+ *   prints out "url is valid"
+ *  
+ * + * @see + * + * Uniform Resource Identifiers (URI): Generic Syntax + * + * + * @version $Revision$ + * @since Validator 1.4 + */ +public class UrlValidator implements Serializable { + + private static final long serialVersionUID = 7557161713937335013L; + + private static final int MAX_UNSIGNED_16_BIT_INT = 0xFFFF; // port max + + /** + * Allows all validly formatted schemes to pass validation instead of + * supplying a set of valid schemes. + */ + public static final long ALLOW_ALL_SCHEMES = 1 << 0; + + /** + * Allow two slashes in the path component of the URL. + */ + public static final long ALLOW_2_SLASHES = 1 << 1; + + /** + * Enabling this options disallows any URL fragments. + */ + public static final long NO_FRAGMENTS = 1 << 2; + + /** + * Allow local URLs, such as http://localhost/ or http://machine/ . + * This enables a broad-brush check, for complex local machine name + * validation requirements you should create your validator with + * a {@link RegexValidator} instead ({@link #UrlValidator(RegexValidator, long)}) + */ + public static final long ALLOW_LOCAL_URLS = 1 << 3; // CHECKSTYLE IGNORE MagicNumber + + /** + * This expression derived/taken from the BNF for URI (RFC2396). + */ + private static final String URL_REGEX = + "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?"; + // 12 3 4 5 6 7 8 9 + private static final Pattern URL_PATTERN = Pattern.compile(URL_REGEX); + + /** + * Schema/Protocol (ie. http:, ftp:, file:, etc). + */ + private static final int PARSE_URL_SCHEME = 2; + + /** + * Includes hostname/ip and port number. + */ + private static final int PARSE_URL_AUTHORITY = 4; + + private static final int PARSE_URL_PATH = 5; + + private static final int PARSE_URL_QUERY = 7; + + private static final int PARSE_URL_FRAGMENT = 9; + + /** + * Protocol scheme (e.g. http, ftp, https). + */ + private static final String SCHEME_REGEX = "^\\p{Alpha}[\\p{Alnum}\\+\\-\\.]*"; + private static final Pattern SCHEME_PATTERN = Pattern.compile(SCHEME_REGEX); + + // Drop numeric, and "+-." for now + // TODO does not allow for optional userinfo. + // Validation of character set is done by isValidAuthority + private static final String AUTHORITY_CHARS_REGEX = "\\p{Alnum}\\-\\."; // allows for IPV4 but not IPV6 + private static final String IPV6_REGEX = "[0-9a-fA-F:]+"; // do this as separate match because : could cause ambiguity with port prefix + + // userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) + // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + // We assume that password has the same valid chars as user info + private static final String USERINFO_CHARS_REGEX = "[a-zA-Z0-9%-._~!$&'()*+,;=]"; + // since neither ':' nor '@' are allowed chars, we don't need to use non-greedy matching + private static final String USERINFO_FIELD_REGEX = + USERINFO_CHARS_REGEX + "+" + // At least one character for the name + "(?::" + USERINFO_CHARS_REGEX + "*)?@"; // colon and password may be absent + private static final String AUTHORITY_REGEX = + "(?:\\[("+IPV6_REGEX+")\\]|(?:(?:"+USERINFO_FIELD_REGEX+")?([" + AUTHORITY_CHARS_REGEX + "]*)))(?::(\\d*))?(.*)?"; + // 1 e.g. user:pass@ 2 3 4 + private static final Pattern AUTHORITY_PATTERN = Pattern.compile(AUTHORITY_REGEX); + + private static final int PARSE_AUTHORITY_IPV6 = 1; + + private static final int PARSE_AUTHORITY_HOST_IP = 2; // excludes userinfo, if present + + private static final int PARSE_AUTHORITY_PORT = 3; // excludes leading colon + + /** + * Should always be empty. The code currently allows spaces. + */ + private static final int PARSE_AUTHORITY_EXTRA = 4; + + private static final String PATH_REGEX = "^(/[-\\w:@&?=+,.!/~*'%$_;\\(\\)]*)?$"; + private static final Pattern PATH_PATTERN = Pattern.compile(PATH_REGEX); + + private static final String QUERY_REGEX = "^(\\S*)$"; + private static final Pattern QUERY_PATTERN = Pattern.compile(QUERY_REGEX); + + /** + * Holds the set of current validation options. + */ + private final long options; + + /** + * The set of schemes that are allowed to be in a URL. + */ + private final Set allowedSchemes; // Must be lower-case + + /** + * Regular expressions used to manually validate authorities if IANA + * domain name validation isn't desired. + */ + private final RegexValidator authorityValidator; + + /** + * If no schemes are provided, default to this set. + */ + private static final String[] DEFAULT_SCHEMES = {"http", "https", "ftp"}; // Must be lower-case + + /** + * Singleton instance of this class with default schemes and options. + */ + private static final UrlValidator DEFAULT_URL_VALIDATOR = new UrlValidator(); + + /** + * Returns the singleton instance of this class with default schemes and options. + * @return singleton instance with default schemes and options + */ + public static UrlValidator getInstance() { + return DEFAULT_URL_VALIDATOR; + } + + /** + * Create a UrlValidator with default properties. + */ + public UrlValidator() { + this(null); + } + + /** + * Behavior of validation is modified by passing in several strings options: + * @param schemes Pass in one or more url schemes to consider valid, passing in + * a null will default to "http,https,ftp" being valid. + * If a non-null schemes is specified then all valid schemes must + * be specified. Setting the ALLOW_ALL_SCHEMES option will + * ignore the contents of schemes. + */ + public UrlValidator(String[] schemes) { + this(schemes, 0L); + } + + /** + * Initialize a UrlValidator with the given validation options. + * @param options The options should be set using the public constants declared in + * this class. To set multiple options you simply add them together. For example, + * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options. + */ + public UrlValidator(long options) { + this(null, null, options); + } + + /** + * Behavior of validation is modified by passing in options: + * @param schemes The set of valid schemes. Ignored if the ALLOW_ALL_SCHEMES option is set. + * @param options The options should be set using the public constants declared in + * this class. To set multiple options you simply add them together. For example, + * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options. + */ + public UrlValidator(String[] schemes, long options) { + this(schemes, null, options); + } + + /** + * Initialize a UrlValidator with the given validation options. + * @param authorityValidator Regular expression validator used to validate the authority part + * This allows the user to override the standard set of domains. + * @param options Validation options. Set using the public constants of this class. + * To set multiple options, simply add them together: + *

ALLOW_2_SLASHES + NO_FRAGMENTS

+ * enables both of those options. + */ + public UrlValidator(RegexValidator authorityValidator, long options) { + this(null, authorityValidator, options); + } + + /** + * Customizable constructor. Validation behavior is modifed by passing in options. + * @param schemes the set of valid schemes. Ignored if the ALLOW_ALL_SCHEMES option is set. + * @param authorityValidator Regular expression validator used to validate the authority part + * @param options Validation options. Set using the public constants of this class. + * To set multiple options, simply add them together: + *

ALLOW_2_SLASHES + NO_FRAGMENTS

+ * enables both of those options. + */ + public UrlValidator(String[] schemes, RegexValidator authorityValidator, long options) { + this.options = options; + + if (isOn(ALLOW_ALL_SCHEMES)) { + allowedSchemes = Collections.emptySet(); + } else { + if (schemes == null) { + schemes = DEFAULT_SCHEMES; + } + allowedSchemes = new HashSet(schemes.length); + for(int i=0; i < schemes.length; i++) { + allowedSchemes.add(schemes[i].toLowerCase(Locale.ENGLISH)); + } + } + + this.authorityValidator = authorityValidator; + } + + /** + *

Checks if a field has a valid url address.

+ * + * Note that the method calls #isValidAuthority() + * which checks that the domain is valid. + * + * @param value The value validation is being performed on. A null + * value is considered invalid. + * @return true if the url is valid. + */ + public boolean isValid(String value) { + if (value == null) { + return false; + } + + // Check the whole url address structure + Matcher urlMatcher = URL_PATTERN.matcher(value); + if (!urlMatcher.matches()) { + return false; + } + + String scheme = urlMatcher.group(PARSE_URL_SCHEME); + if (!isValidScheme(scheme)) { + return false; + } + + String authority = urlMatcher.group(PARSE_URL_AUTHORITY); + if ("file".equals(scheme) && (authority == null || "".equals(authority))) {// Special case - file: allows an empty authority + return true; // this is a local file - nothing more to do here + } else if ("file".equals(scheme) && authority != null && authority.contains(":")) { + return false; + } else { + // Validate the authority + if (!isValidAuthority(authority)) { + return false; + } + } + + if (!isValidPath(urlMatcher.group(PARSE_URL_PATH))) { + return false; + } + + if (!isValidQuery(urlMatcher.group(PARSE_URL_QUERY))) { + return false; + } + + if (!isValidFragment(urlMatcher.group(PARSE_URL_FRAGMENT))) { + return false; + } + + return true; + } + + /** + * Validate scheme. If schemes[] was initialized to a non null, + * then only those schemes are allowed. + * Otherwise the default schemes are "http", "https", "ftp". + * Matching is case-blind. + * @param scheme The scheme to validate. A null value is considered + * invalid. + * @return true if valid. + */ + protected boolean isValidScheme(String scheme) { + if (scheme == null) { + return false; + } + + // TODO could be removed if external schemes were checked in the ctor before being stored + if (!SCHEME_PATTERN.matcher(scheme).matches()) { + return false; + } + + if (isOff(ALLOW_ALL_SCHEMES) && !allowedSchemes.contains(scheme.toLowerCase(Locale.ENGLISH))) { + return false; + } + + return true; + } + + /** + * Returns true if the authority is properly formatted. An authority is the combination + * of hostname and port. A null authority value is considered invalid. + * Note: this implementation validates the domain unless a RegexValidator was provided. + * If a RegexValidator was supplied and it matches, then the authority is regarded + * as valid with no further checks, otherwise the method checks against the + * AUTHORITY_PATTERN and the DomainValidator (ALLOW_LOCAL_URLS) + * @param authority Authority value to validate, alllows IDN + * @return true if authority (hostname and port) is valid. + */ + protected boolean isValidAuthority(String authority) { + if (authority == null) { + return false; + } + + // check manual authority validation if specified + if (authorityValidator != null && authorityValidator.isValid(authority)) { + return true; + } + // convert to ASCII if possible + final String authorityASCII = DomainValidator.unicodeToASCII(authority); + + Matcher authorityMatcher = AUTHORITY_PATTERN.matcher(authorityASCII); + if (!authorityMatcher.matches()) { + return false; + } + + // We have to process IPV6 separately because that is parsed in a different group + String ipv6 = authorityMatcher.group(PARSE_AUTHORITY_IPV6); + if (ipv6 != null) { + InetAddressValidator inetAddressValidator = InetAddressValidator.getInstance(); + if (!inetAddressValidator.isValidInet6Address(ipv6)) { + return false; + } + } else { + String hostLocation = authorityMatcher.group(PARSE_AUTHORITY_HOST_IP); + // check if authority is hostname or IP address: + // try a hostname first since that's much more likely + DomainValidator domainValidator = DomainValidator.getInstance(isOn(ALLOW_LOCAL_URLS)); + if (!domainValidator.isValid(hostLocation)) { + // try an IPv4 address + InetAddressValidator inetAddressValidator = InetAddressValidator.getInstance(); + if (!inetAddressValidator.isValidInet4Address(hostLocation)) { + // isn't IPv4, so the URL is invalid + return false; + } + } + String port = authorityMatcher.group(PARSE_AUTHORITY_PORT); + if (port != null && port.length() > 0) { + try { + int iPort = Integer.parseInt(port); + if (iPort < 0 || iPort > MAX_UNSIGNED_16_BIT_INT) { + return false; + } + } catch (NumberFormatException nfe) { + return false; // this can happen for big numbers + } + } + } + + String extra = authorityMatcher.group(PARSE_AUTHORITY_EXTRA); + if (extra != null && extra.trim().length() > 0){ + return false; + } + + return true; + } + + /** + * Returns true if the path is valid. A null value is considered invalid. + * @param path Path value to validate. + * @return true if path is valid. + */ + protected boolean isValidPath(String path) { + if (path == null) { + return false; + } + + if (!PATH_PATTERN.matcher(path).matches()) { + return false; + } + + try { + // Don't omit host otherwise leading path may be taken as host if it starts with // + URI uri = new URI(null,"localhost",path,null); + String norm = uri.normalize().getPath(); + if (norm.startsWith("/../") // Trying to go via the parent dir + || norm.equals("/..")) { // Trying to go to the parent dir + return false; + } + } catch (URISyntaxException e) { + return false; + } + + int slash2Count = countToken("//", path); + if (isOff(ALLOW_2_SLASHES) && (slash2Count > 0)) { + return false; + } + + return true; + } + + /** + * Returns true if the query is null or it's a properly formatted query string. + * @param query Query value to validate. + * @return true if query is valid. + */ +/** + * Returns true if the query is null or it's a properly formatted query string. + * + * @param query + * Query value to validate. + * @return true if query is valid. + */ +protected boolean isValidQuery(java.lang.String query) { + { + return org.apache.commons.validator.routines.UrlValidator.QUERY_PATTERN.matcher(/* NPEX_NULL_EXP */ + query).matches(); + } +} + + /** + * Returns true if the given fragment is null or fragments are allowed. + * @param fragment Fragment value to validate. + * @return true if fragment is valid. + */ + protected boolean isValidFragment(String fragment) { + if (fragment == null) { + return true; + } + + return isOff(NO_FRAGMENTS); + } + + /** + * Returns the number of times the token appears in the target. + * @param token Token value to be counted. + * @param target Target value to count tokens in. + * @return the number of tokens. + */ + protected int countToken(String token, String target) { + int tokenIndex = 0; + int count = 0; + while (tokenIndex != -1) { + tokenIndex = target.indexOf(token, tokenIndex); + if (tokenIndex > -1) { + tokenIndex++; + count++; + } + } + return count; + } + + /** + * Tests whether the given flag is on. If the flag is not a power of 2 + * (ie. 3) this tests whether the combination of flags is on. + * + * @param flag Flag value to check. + * + * @return whether the specified flag value is on. + */ + private boolean isOn(long flag) { + return (options & flag) > 0; + } + + /** + * Tests whether the given flag is off. If the flag is not a power of 2 + * (ie. 3) this tests whether the combination of flags is off. + * + * @param flag Flag value to check. + * + * @return whether the specified flag value is off. + */ + private boolean isOff(long flag) { + return (options & flag) == 0; + } + + // Unit test access to pattern matcher + Matcher matchURL(String value) { + return URL_PATTERN.matcher(value); + } + + /** + * Validator for checking URL parsing + * @param args - URLs to validate + */ + public static void main(String[] args) { + UrlValidator val = new UrlValidator(new String[] { "file", "http", "https" }, UrlValidator.ALLOW_LOCAL_URLS); + for(String arg: args) { + Matcher m = val.matchURL(arg); + if (m.matches()) { + System.out.printf("%s has %d parts%n",arg,m.groupCount()); + for(int i=1;i 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-validator-ValidatorUtils_115/buggy.java b/Java/commons-validator-ValidatorUtils_115/buggy.java new file mode 100644 index 000000000..dc1c81f41 --- /dev/null +++ b/Java/commons-validator-ValidatorUtils_115/buggy.java @@ -0,0 +1,207 @@ +/* + * 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.validator.util; + +import java.lang.reflect.InvocationTargetException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.collections.FastHashMap; // DEPRECATED +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.validator.Arg; +import org.apache.commons.validator.Msg; +import org.apache.commons.validator.Var; + +/** + * Basic utility methods. + *

+ * The use of FastHashMap is deprecated and will be replaced in a future + * release. + *

+ * + * @version $Revision$ + */ +public class ValidatorUtils { + + private static final Log LOG = LogFactory.getLog(ValidatorUtils.class); + + /** + *

Replace part of a String with another value.

+ * + * @param value String to perform the replacement on. + * @param key The name of the constant. + * @param replaceValue The value of the constant. + * + * @return The modified value. + */ + public static String replace(String value, String key, String replaceValue) { + + if (value == null || key == null || replaceValue == null) { + return value; + } + + int pos = value.indexOf(key); + + if (pos < 0) { + return value; + } + + int length = value.length(); + int start = pos; + int end = pos + key.length(); + + if (length == key.length()) { + value = replaceValue; + + } else if (end == length) { + value = value.substring(0, start) + replaceValue; + + } else { + value = + value.substring(0, start) + + replaceValue + + replace(value.substring(end), key, replaceValue); + } + + return value; + } + + /** + * Convenience method for getting a value from a bean property as a + * String. If the property is a String[] or + * Collection and it is empty, an empty String + * "" is returned. Otherwise, property.toString() is returned. This method + * may return null if there was an error retrieving the + * property. + * + * @param bean The bean object. + * @param property The name of the property to access. + * + * @return The value of the property. + */ +/** + * Convenience method for getting a value from a bean property as a + * String. If the property is a String[] or + * Collection and it is empty, an empty String + * "" is returned. Otherwise, property.toString() is returned. This method + * may return null if there was an error retrieving the + * property. + * + * @param bean + * The bean object. + * @param property + * The name of the property to access. + * @return The value of the property. + */ +public static java.lang.String getValueAsString(java.lang.Object bean, java.lang.String property) { + java.lang.Object value = null; + try { + value = org.apache.commons.beanutils.PropertyUtils.getProperty(bean, property); + } catch (java.lang.IllegalAccessException e) { + org.apache.commons.validator.util.ValidatorUtils.LOG.error(e.getMessage(), e); + } catch (java.lang.reflect.InvocationTargetException e) { + org.apache.commons.validator.util.ValidatorUtils.LOG.error(e.getMessage(), e); + } catch (java.lang.NoSuchMethodException e) { + org.apache.commons.validator.util.ValidatorUtils.LOG.error(e.getMessage(), e); + } + { + if (/* NPEX_NULL_EXP */ + value instanceof java.lang.String[]) { + return ((java.lang.String[]) (value)).length > 0 ? value.toString() : ""; + } else if (value instanceof java.util.Collection) { + return ((java.util.Collection) (value)).isEmpty() ? "" : value.toString(); + } else { + return value.toString(); + } + } +} + + /** + * Makes a deep copy of a FastHashMap if the values + * are Msg, Arg, + * or Var. Otherwise it is a shallow copy. + * + * @param map FastHashMap to copy. + * @return FastHashMap A copy of the FastHashMap that was + * passed in. + * @deprecated This method is not part of Validator's public API. Validator + * will use it internally until FastHashMap references are removed. Use + * copyMap() instead. + */ + @Deprecated + public static FastHashMap copyFastHashMap(FastHashMap map) { + FastHashMap results = new FastHashMap(); + + @SuppressWarnings("unchecked") // FastHashMap is not generic + Iterator> i = map.entrySet().iterator(); + while (i.hasNext()) { + Entry entry = i.next(); + String key = entry.getKey(); + Object value = entry.getValue(); + + if (value instanceof Msg) { + results.put(key, ((Msg) value).clone()); + } else if (value instanceof Arg) { + results.put(key, ((Arg) value).clone()); + } else if (value instanceof Var) { + results.put(key, ((Var) value).clone()); + } else { + results.put(key, value); + } + } + + results.setFast(true); + return results; + } + + /** + * Makes a deep copy of a Map if the values are + * Msg, Arg, or Var. Otherwise, + * it is a shallow copy. + * + * @param map The source Map to copy. + * + * @return A copy of the Map that was passed in. + */ + public static Map copyMap(Map map) { + Map results = new HashMap(); + + Iterator> i = map.entrySet().iterator(); + while (i.hasNext()) { + Entry entry = i.next(); + String key = entry.getKey(); + Object value = entry.getValue(); + + if (value instanceof Msg) { + results.put(key, ((Msg) value).clone()); + } else if (value instanceof Arg) { + results.put(key, ((Arg) value).clone()); + } else if (value instanceof Var) { + results.put(key, ((Var) value).clone()); + } else { + results.put(key, value); + } + } + return results; + } + +} diff --git a/Java/commons-validator-ValidatorUtils_115/metadata.json b/Java/commons-validator-ValidatorUtils_115/metadata.json new file mode 100644 index 000000000..9e032201a --- /dev/null +++ b/Java/commons-validator-ValidatorUtils_115/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "commons-validator-ValidatorUtils_115", + "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/validator/util/ValidatorUtils.java", + "line": 128, + "npe_method": "getValueAsString", + "deref_field": "value", + "npe_class": "ValidatorUtils", + "repo": "commons-validator", + "bug_id": "ValidatorUtils_115" + } +} diff --git a/Java/commons-validator-ValidatorUtils_115/npe.json b/Java/commons-validator-ValidatorUtils_115/npe.json new file mode 100644 index 000000000..9d6363412 --- /dev/null +++ b/Java/commons-validator-ValidatorUtils_115/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/commons/validator/util/ValidatorUtils.java", + "line": 128, + "npe_method": "getValueAsString", + "deref_field": "value", + "npe_class": "ValidatorUtils" +} \ No newline at end of file diff --git a/Java/directory-mavibot-BooleanArrayComparator_59/Dockerfile b/Java/directory-mavibot-BooleanArrayComparator_59/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-BooleanArrayComparator_59/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-BooleanArrayComparator_59/buggy.java b/Java/directory-mavibot-BooleanArrayComparator_59/buggy.java new file mode 100644 index 000000000..7fd96648f --- /dev/null +++ b/Java/directory-mavibot-BooleanArrayComparator_59/buggy.java @@ -0,0 +1,103 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares boolean arrays. A boolean is considered as below the other one if the first boolean + * is false when the second one is true. + * + * @author Apache Directory Project + */ +public class BooleanArrayComparator implements Comparator +{ + /** A static instance of a BooleanArrayComparator */ + public static final BooleanArrayComparator INSTANCE = new BooleanArrayComparator(); + + /** + * A private constructor of the BooleanArrayComparator class + */ + private BooleanArrayComparator() + { + } + + + /** + * Compare two boolean arrays. + * + * @param booleanArray1 First boolean array + * @param booleanArray2 Second boolean array + * @return 1 if booleanArray1 > booleanArray2, 0 if booleanArray1 == booleanArray2, -1 if booleanArray1 < booleanArray2 + */ +/** + * Compare two boolean arrays. + * + * @param booleanArray1 + * First boolean array + * @param booleanArray2 + * Second boolean array + * @return 1 if booleanArray1 > booleanArray2, 0 if booleanArray1 == booleanArray2, -1 if booleanArray1 < booleanArray2 + */ +public int compare(boolean[] booleanArray1, boolean[] booleanArray2) { + if (booleanArray1 == booleanArray2) { + return 0; + } + { + if (booleanArray2 == null) { + return 1; + } + if (/* NPEX_NULL_EXP */ + booleanArray1.length < booleanArray2.length) { + return -1; + } + if (booleanArray1.length > booleanArray2.length) { + return 1; + } + for (int pos = 0; pos < booleanArray1.length; pos++) { + int comp = compare(booleanArray1[pos], booleanArray2[pos]); + if (comp != 0) { + return comp; + } + } + return 0; + } +} + + + private int compare( boolean boolean1, boolean boolean2 ) + { + if ( boolean1 == boolean2 ) + { + return 0; + } + + if ( boolean1 ) + { + return 1; + } + else + { + return -1; + } + } +} diff --git a/Java/directory-mavibot-BooleanArrayComparator_59/metadata.json b/Java/directory-mavibot-BooleanArrayComparator_59/metadata.json new file mode 100644 index 000000000..f4915d480 --- /dev/null +++ b/Java/directory-mavibot-BooleanArrayComparator_59/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-BooleanArrayComparator_59", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/BooleanArrayComparator.java", + "line": 70, + "npe_method": "compare", + "deref_field": "booleanArray1", + "npe_class": "BooleanArrayComparator", + "repo": "directory-mavibot", + "bug_id": "BooleanArrayComparator_59" + } +} diff --git a/Java/directory-mavibot-BooleanArrayComparator_59/npe.json b/Java/directory-mavibot-BooleanArrayComparator_59/npe.json new file mode 100644 index 000000000..37b476aaf --- /dev/null +++ b/Java/directory-mavibot-BooleanArrayComparator_59/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/BooleanArrayComparator.java", + "line": 70, + "npe_method": "compare", + "deref_field": "booleanArray1", + "npe_class": "BooleanArrayComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-BooleanArrayComparator_64/Dockerfile b/Java/directory-mavibot-BooleanArrayComparator_64/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-BooleanArrayComparator_64/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-BooleanArrayComparator_64/buggy.java b/Java/directory-mavibot-BooleanArrayComparator_64/buggy.java new file mode 100644 index 000000000..633a8a4ba --- /dev/null +++ b/Java/directory-mavibot-BooleanArrayComparator_64/buggy.java @@ -0,0 +1,103 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares boolean arrays. A boolean is considered as below the other one if the first boolean + * is false when the second one is true. + * + * @author Apache Directory Project + */ +public class BooleanArrayComparator implements Comparator +{ + /** A static instance of a BooleanArrayComparator */ + public static final BooleanArrayComparator INSTANCE = new BooleanArrayComparator(); + + /** + * A private constructor of the BooleanArrayComparator class + */ + private BooleanArrayComparator() + { + } + + + /** + * Compare two boolean arrays. + * + * @param booleanArray1 First boolean array + * @param booleanArray2 Second boolean array + * @return 1 if booleanArray1 > booleanArray2, 0 if booleanArray1 == booleanArray2, -1 if booleanArray1 < booleanArray2 + */ +/** + * Compare two boolean arrays. + * + * @param booleanArray1 + * First boolean array + * @param booleanArray2 + * Second boolean array + * @return 1 if booleanArray1 > booleanArray2, 0 if booleanArray1 == booleanArray2, -1 if booleanArray1 < booleanArray2 + */ +public int compare(boolean[] booleanArray1, boolean[] booleanArray2) { + if (booleanArray1 == booleanArray2) { + return 0; + } + if (booleanArray1 == null) { + return -1; + } + { + if (booleanArray1.length < /* NPEX_NULL_EXP */ + booleanArray2.length) { + return -1; + } + if (booleanArray1.length > booleanArray2.length) { + return 1; + } + for (int pos = 0; pos < booleanArray1.length; pos++) { + int comp = compare(booleanArray1[pos], booleanArray2[pos]); + if (comp != 0) { + return comp; + } + } + return 0; + } +} + + + private int compare( boolean boolean1, boolean boolean2 ) + { + if ( boolean1 == boolean2 ) + { + return 0; + } + + if ( boolean1 ) + { + return 1; + } + else + { + return -1; + } + } +} diff --git a/Java/directory-mavibot-BooleanArrayComparator_64/metadata.json b/Java/directory-mavibot-BooleanArrayComparator_64/metadata.json new file mode 100644 index 000000000..561b86e99 --- /dev/null +++ b/Java/directory-mavibot-BooleanArrayComparator_64/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-BooleanArrayComparator_64", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/BooleanArrayComparator.java", + "line": 70, + "npe_method": "compare", + "deref_field": "booleanArray2", + "npe_class": "BooleanArrayComparator", + "repo": "directory-mavibot", + "bug_id": "BooleanArrayComparator_64" + } +} diff --git a/Java/directory-mavibot-BooleanArrayComparator_64/npe.json b/Java/directory-mavibot-BooleanArrayComparator_64/npe.json new file mode 100644 index 000000000..957dea032 --- /dev/null +++ b/Java/directory-mavibot-BooleanArrayComparator_64/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/BooleanArrayComparator.java", + "line": 70, + "npe_method": "compare", + "deref_field": "booleanArray2", + "npe_class": "BooleanArrayComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-BooleanComparator_58/Dockerfile b/Java/directory-mavibot-BooleanComparator_58/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-BooleanComparator_58/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-BooleanComparator_58/buggy.java b/Java/directory-mavibot-BooleanComparator_58/buggy.java new file mode 100644 index 000000000..c3191217b --- /dev/null +++ b/Java/directory-mavibot-BooleanComparator_58/buggy.java @@ -0,0 +1,72 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares booleans + * + * @author Apache Directory Project + */ +public class BooleanComparator implements Comparator +{ + /** A static instance of a BooleanComparator */ + public static final BooleanComparator INSTANCE = new BooleanComparator(); + + /** + * A private constructor of the BooleanComparator class + */ + private BooleanComparator() + { + } + + + /** + * Compare two booleans. + * + * @param boolean1 First boolean + * @param boolean2 Second boolean + * @return 1 if boolean1 > boolean2, 0 if boolean1 == boolean2, -1 if boolean1 < boolean2 + */ +/** + * Compare two booleans. + * + * @param boolean1 + * First boolean + * @param boolean2 + * Second boolean + * @return 1 if boolean1 > boolean2, 0 if boolean1 == boolean2, -1 if boolean1 < boolean2 + */ +public int compare(java.lang.Boolean boolean1, java.lang.Boolean boolean2) { + if (boolean1 == boolean2) { + return 0; + } + { + if (boolean2 == null) { + return 1; + } + return /* NPEX_NULL_EXP */ + boolean1.compareTo(boolean2); + } +} +} diff --git a/Java/directory-mavibot-BooleanComparator_58/metadata.json b/Java/directory-mavibot-BooleanComparator_58/metadata.json new file mode 100644 index 000000000..7e015e144 --- /dev/null +++ b/Java/directory-mavibot-BooleanComparator_58/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-BooleanComparator_58", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/BooleanComparator.java", + "line": 69, + "npe_method": "compare", + "deref_field": "boolean1", + "npe_class": "BooleanComparator", + "repo": "directory-mavibot", + "bug_id": "BooleanComparator_58" + } +} diff --git a/Java/directory-mavibot-BooleanComparator_58/npe.json b/Java/directory-mavibot-BooleanComparator_58/npe.json new file mode 100644 index 000000000..7e9c2990d --- /dev/null +++ b/Java/directory-mavibot-BooleanComparator_58/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/BooleanComparator.java", + "line": 69, + "npe_method": "compare", + "deref_field": "boolean1", + "npe_class": "BooleanComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-BooleanComparator_63/Dockerfile b/Java/directory-mavibot-BooleanComparator_63/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-BooleanComparator_63/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-BooleanComparator_63/buggy.java b/Java/directory-mavibot-BooleanComparator_63/buggy.java new file mode 100644 index 000000000..264131e56 --- /dev/null +++ b/Java/directory-mavibot-BooleanComparator_63/buggy.java @@ -0,0 +1,72 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares booleans + * + * @author Apache Directory Project + */ +public class BooleanComparator implements Comparator +{ + /** A static instance of a BooleanComparator */ + public static final BooleanComparator INSTANCE = new BooleanComparator(); + + /** + * A private constructor of the BooleanComparator class + */ + private BooleanComparator() + { + } + + + /** + * Compare two booleans. + * + * @param boolean1 First boolean + * @param boolean2 Second boolean + * @return 1 if boolean1 > boolean2, 0 if boolean1 == boolean2, -1 if boolean1 < boolean2 + */ +/** + * Compare two booleans. + * + * @param boolean1 + * First boolean + * @param boolean2 + * Second boolean + * @return 1 if boolean1 > boolean2, 0 if boolean1 == boolean2, -1 if boolean1 < boolean2 + */ +public int compare(java.lang.Boolean boolean1, java.lang.Boolean boolean2) { + if (boolean1 == boolean2) { + return 0; + } + if (boolean1 == null) { + return -1; + } + { + return boolean1.compareTo(/* NPEX_NULL_EXP */ + boolean2); + } +} +} diff --git a/Java/directory-mavibot-BooleanComparator_63/metadata.json b/Java/directory-mavibot-BooleanComparator_63/metadata.json new file mode 100644 index 000000000..b54d62361 --- /dev/null +++ b/Java/directory-mavibot-BooleanComparator_63/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-BooleanComparator_63", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/BooleanComparator.java", + "line": 69, + "npe_method": "compare", + "deref_field": "boolean2", + "npe_class": "BooleanComparator", + "repo": "directory-mavibot", + "bug_id": "BooleanComparator_63" + } +} diff --git a/Java/directory-mavibot-BooleanComparator_63/npe.json b/Java/directory-mavibot-BooleanComparator_63/npe.json new file mode 100644 index 000000000..4db5dbf17 --- /dev/null +++ b/Java/directory-mavibot-BooleanComparator_63/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/BooleanComparator.java", + "line": 69, + "npe_method": "compare", + "deref_field": "boolean2", + "npe_class": "BooleanComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-BulkDataSorter_184/Dockerfile b/Java/directory-mavibot-BulkDataSorter_184/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-BulkDataSorter_184/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-BulkDataSorter_184/buggy.java b/Java/directory-mavibot-BulkDataSorter_184/buggy.java new file mode 100644 index 000000000..e53305326 --- /dev/null +++ b/Java/directory-mavibot-BulkDataSorter_184/buggy.java @@ -0,0 +1,244 @@ +/* + * 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.directory.mavibot.btree.memory; + + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.UUID; + +import org.apache.directory.mavibot.btree.Tuple; +import org.apache.directory.mavibot.btree.util.TupleReaderWriter; + + +/** + * A utility class for sorting a large number of keys before building a BTree using {@link InMemoryBTreeBuilder}. + * + * @author Apache Directory Project + */ +public class BulkDataSorter +{ + private File workDir; + + private int splitAfter = 1000; + + private Comparator> tupleComparator; + + private TupleReaderWriter readerWriter; + + private boolean sorted; + + + public BulkDataSorter( TupleReaderWriter readerWriter, Comparator> tupleComparator, + int splitAfter ) + { + if ( splitAfter <= 0 ) + { + throw new IllegalArgumentException( "Value of splitAfter parameter cannot be null" ); + } + + this.splitAfter = splitAfter; + + this.workDir = new File( System.getProperty( "java.io.tmpdir" ), System.currentTimeMillis() + "-sort" ); + workDir.mkdir(); + + this.readerWriter = readerWriter; + this.tupleComparator = tupleComparator; + } + + + public void sort( File dataFile ) throws IOException + { + int i = 0; + + Tuple[] arr = ( Tuple[] ) Array.newInstance( Tuple.class, splitAfter ); + + Tuple t = null; + + DataInputStream in = new DataInputStream( new FileInputStream( dataFile ) ); + + while ( ( t = readerWriter.readUnsortedTuple( in ) ) != null ) + { + arr[i++] = t; + + if ( ( i % splitAfter ) == 0 ) + { + i = 0; + Arrays.sort( arr, tupleComparator ); + + storeSortedData( arr ); + } + } + + if ( i != 0 ) + { + Tuple[] tmp = ( Tuple[] ) Array.newInstance( Tuple.class, i ); + System.arraycopy( arr, 0, tmp, 0, i ); + Arrays.sort( tmp, tupleComparator ); + + storeSortedData( tmp ); + } + + sorted = true; + } + + + private void storeSortedData( Tuple[] arr ) throws IOException + { + File tempFile = File.createTempFile( UUID.randomUUID().toString(), ".batch", workDir ); + DataOutputStream out = new DataOutputStream( new FileOutputStream( tempFile ) ); + + for ( Tuple t : arr ) + { + readerWriter.storeSortedTuple( t, out ); + } + + out.flush(); + out.close(); + } + + + public File getWorkDir() + { + return workDir; + } + + + public Iterator> getMergeSortedTuples() throws IOException + { + if ( !sorted ) + { + throw new IllegalStateException( "Data is not sorted" ); + } + + File[] batches = workDir.listFiles(); + + if ( batches.length == 0 ) + { + return Collections.EMPTY_LIST.iterator(); + } + + final DataInputStream[] streams = new DataInputStream[batches.length]; + + for ( int i = 0; i < batches.length; i++ ) + { + streams[i] = new DataInputStream( new FileInputStream( batches[i] ) ); + } + + Iterator> itr = new Iterator>() + { + private Tuple[] heads = ( Tuple[] ) Array.newInstance( Tuple.class, streams.length ); + + private Tuple candidate = null; + + private boolean closed; + + private int candidatePos = -1; + + + @Override +public boolean hasNext() { + if (closed) { + throw new java.lang.IllegalStateException("No elements to read"); + } + org.apache.directory.mavibot.btree.Tuple available = null; + for (int i = 0; i < streams.length; i++) { + if (heads[i] == null) { + heads[i] = readerWriter.readUnsortedTuple(streams[i]); + } + { + if ((/* NPEX_NULL_EXP */ + available != null) && (heads[i] != null)) { + int comp = tupleComparator.compare(heads[i], available); + if (comp <= 0) { + available = heads[i]; + candidatePos = i; + } + } + } + } + heads[candidatePos] = null; + if (available == null) { + for (int i = 0; i < streams.length; i++) { + if (heads[i] != null) { + available = heads[i]; + heads[i] = readerWriter.readUnsortedTuple(streams[i]); + break; + } + } + } + if (available != null) { + candidate = available; + return true; + } + // finally close the streams + for (java.io.DataInputStream in : streams) { + try { + in.close(); + } catch (java.lang.Exception e) { + e.printStackTrace(); + } + } + closed = true; + return false; +} + + + @Override + public Tuple next() + { + if ( candidate == null ) + { + if ( !closed ) + { + hasNext(); + } + } + + if ( candidate == null ) + { + throw new NoSuchElementException( "No tuples found" ); + } + + return candidate; + } + + + @Override + public void remove() + { + throw new UnsupportedOperationException( "Not supported" ); + } + + }; + + return itr; + } +} diff --git a/Java/directory-mavibot-BulkDataSorter_184/metadata.json b/Java/directory-mavibot-BulkDataSorter_184/metadata.json new file mode 100644 index 000000000..ed25ab4e8 --- /dev/null +++ b/Java/directory-mavibot-BulkDataSorter_184/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-BulkDataSorter_184", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/memory/BulkDataSorter.java", + "line": 178, + "npe_method": "hasNext", + "deref_field": "available", + "npe_class": "1", + "repo": "directory-mavibot", + "bug_id": "BulkDataSorter_184" + } +} diff --git a/Java/directory-mavibot-BulkDataSorter_184/npe.json b/Java/directory-mavibot-BulkDataSorter_184/npe.json new file mode 100644 index 000000000..9f4aa354f --- /dev/null +++ b/Java/directory-mavibot-BulkDataSorter_184/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/memory/BulkDataSorter.java", + "line": 178, + "npe_method": "hasNext", + "deref_field": "available", + "npe_class": "1" +} \ No newline at end of file diff --git a/Java/directory-mavibot-ByteArrayComparator_58/Dockerfile b/Java/directory-mavibot-ByteArrayComparator_58/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-ByteArrayComparator_58/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-ByteArrayComparator_58/buggy.java b/Java/directory-mavibot-ByteArrayComparator_58/buggy.java new file mode 100644 index 000000000..6c4ec8c6a --- /dev/null +++ b/Java/directory-mavibot-ByteArrayComparator_58/buggy.java @@ -0,0 +1,101 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares byte arrays. + * + * @author Apache Directory Project + */ +public class ByteArrayComparator implements Comparator +{ + /** A static instance of a ByteArrayComparator */ + public static final ByteArrayComparator INSTANCE = new ByteArrayComparator(); + + /** + * A private constructor of the ByteArrayComparator class + */ + private ByteArrayComparator() + { + } + + + /** + * Compare two byte arrays. + * + * @param byteArray1 First byteArray + * @param byteArray2 Second byteArray + * @return 1 if byteArray1 > byteArray2, 0 if byteArray1 == byteArray2, -1 if byteArray1 < byteArray2 + */ +/** + * Compare two byte arrays. + * + * @param byteArray1 + * First byteArray + * @param byteArray2 + * Second byteArray + * @return 1 if byteArray1 > byteArray2, 0 if byteArray1 == byteArray2, -1 if byteArray1 < byteArray2 + */ +public int compare(byte[] byteArray1, byte[] byteArray2) { + if (byteArray1 == byteArray2) { + return 0; + } + { + if (byteArray2 == null) { + return 1; + } else if (/* NPEX_NULL_EXP */ + byteArray1.length < byteArray2.length) { + int pos = 0; + for (byte b1 : byteArray1) { + byte b2 = byteArray2[pos]; + if (b1 == b2) { + pos++; + } else if (b1 < b2) { + return -1; + } else { + return 1; + } + } + return -1; + } else { + int pos = 0; + for (byte b2 : byteArray2) { + byte b1 = byteArray1[pos]; + if (b1 == b2) { + pos++; + } else if (b1 < b2) { + return -1; + } else { + return 1; + } + } + if (pos < byteArray1.length) { + return 1; + } else { + return 0; + } + } + } +} +} diff --git a/Java/directory-mavibot-ByteArrayComparator_58/metadata.json b/Java/directory-mavibot-ByteArrayComparator_58/metadata.json new file mode 100644 index 000000000..e24c9c727 --- /dev/null +++ b/Java/directory-mavibot-ByteArrayComparator_58/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-ByteArrayComparator_58", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ByteArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "byteArray1", + "npe_class": "ByteArrayComparator", + "repo": "directory-mavibot", + "bug_id": "ByteArrayComparator_58" + } +} diff --git a/Java/directory-mavibot-ByteArrayComparator_58/npe.json b/Java/directory-mavibot-ByteArrayComparator_58/npe.json new file mode 100644 index 000000000..2839fb8f1 --- /dev/null +++ b/Java/directory-mavibot-ByteArrayComparator_58/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ByteArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "byteArray1", + "npe_class": "ByteArrayComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-ByteArrayComparator_64/Dockerfile b/Java/directory-mavibot-ByteArrayComparator_64/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-ByteArrayComparator_64/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-ByteArrayComparator_64/buggy.java b/Java/directory-mavibot-ByteArrayComparator_64/buggy.java new file mode 100644 index 000000000..110e620e2 --- /dev/null +++ b/Java/directory-mavibot-ByteArrayComparator_64/buggy.java @@ -0,0 +1,102 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares byte arrays. + * + * @author Apache Directory Project + */ +public class ByteArrayComparator implements Comparator +{ + /** A static instance of a ByteArrayComparator */ + public static final ByteArrayComparator INSTANCE = new ByteArrayComparator(); + + /** + * A private constructor of the ByteArrayComparator class + */ + private ByteArrayComparator() + { + } + + + /** + * Compare two byte arrays. + * + * @param byteArray1 First byteArray + * @param byteArray2 Second byteArray + * @return 1 if byteArray1 > byteArray2, 0 if byteArray1 == byteArray2, -1 if byteArray1 < byteArray2 + */ +/** + * Compare two byte arrays. + * + * @param byteArray1 + * First byteArray + * @param byteArray2 + * Second byteArray + * @return 1 if byteArray1 > byteArray2, 0 if byteArray1 == byteArray2, -1 if byteArray1 < byteArray2 + */ +public int compare(byte[] byteArray1, byte[] byteArray2) { + if (byteArray1 == byteArray2) { + return 0; + } + { + { + if (/* NPEX_NULL_EXP */ + byteArray1.length < /* NPEX_NULL_EXP */ + byteArray2.length) { + int pos = 0; + for (byte b1 : byteArray1) { + byte b2 = byteArray2[pos]; + if (b1 == b2) { + pos++; + } else if (b1 < b2) { + return -1; + } else { + return 1; + } + } + return -1; + } else { + int pos = 0; + for (byte b2 : byteArray2) { + byte b1 = byteArray1[pos]; + if (b1 == b2) { + pos++; + } else if (b1 < b2) { + return -1; + } else { + return 1; + } + } + if (pos < byteArray1.length) { + return 1; + } else { + return 0; + } + } + } + } +} +} diff --git a/Java/directory-mavibot-ByteArrayComparator_64/metadata.json b/Java/directory-mavibot-ByteArrayComparator_64/metadata.json new file mode 100644 index 000000000..85685c61d --- /dev/null +++ b/Java/directory-mavibot-ByteArrayComparator_64/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-ByteArrayComparator_64", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ByteArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "byteArray2", + "npe_class": "ByteArrayComparator", + "repo": "directory-mavibot", + "bug_id": "ByteArrayComparator_64" + } +} diff --git a/Java/directory-mavibot-ByteArrayComparator_64/npe.json b/Java/directory-mavibot-ByteArrayComparator_64/npe.json new file mode 100644 index 000000000..6e64cf137 --- /dev/null +++ b/Java/directory-mavibot-ByteArrayComparator_64/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ByteArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "byteArray2", + "npe_class": "ByteArrayComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-ByteComparator_58/Dockerfile b/Java/directory-mavibot-ByteComparator_58/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-ByteComparator_58/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-ByteComparator_58/buggy.java b/Java/directory-mavibot-ByteComparator_58/buggy.java new file mode 100644 index 000000000..445fa8b56 --- /dev/null +++ b/Java/directory-mavibot-ByteComparator_58/buggy.java @@ -0,0 +1,78 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares bytes + * + * @author Apache Directory Project + */ +public class ByteComparator implements Comparator +{ + /** A static instance of a ByteComparator */ + public static final ByteComparator INSTANCE = new ByteComparator(); + + /** + * A private constructor of the ByteComparator class + */ + private ByteComparator() + { + } + + + /** + * Compare two bytes. + * + * @param byte1 First byte + * @param byte2 Second byte + * @return 1 if byte1 > byte2, 0 if byte1 == byte2, -1 if byte1 < byte2 + */ +/** + * Compare two bytes. + * + * @param byte1 + * First byte + * @param byte2 + * Second byte + * @return 1 if byte1 > byte2, 0 if byte1 == byte2, -1 if byte1 < byte2 + */ +public int compare(java.lang.Byte byte1, java.lang.Byte byte2) { + if (byte1 == byte2) { + return 0; + } + { + if (byte2 == null) { + return 1; + } + if (/* NPEX_NULL_EXP */ + byte1 < byte2) { + return -1; + } else if (byte1 > byte2) { + return 1; + } else { + return 0; + } + } +} +} diff --git a/Java/directory-mavibot-ByteComparator_58/metadata.json b/Java/directory-mavibot-ByteComparator_58/metadata.json new file mode 100644 index 000000000..efabd6a33 --- /dev/null +++ b/Java/directory-mavibot-ByteComparator_58/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-ByteComparator_58", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ByteComparator.java", + "line": 69, + "npe_method": "compare", + "deref_field": "byte1", + "npe_class": "ByteComparator", + "repo": "directory-mavibot", + "bug_id": "ByteComparator_58" + } +} diff --git a/Java/directory-mavibot-ByteComparator_58/npe.json b/Java/directory-mavibot-ByteComparator_58/npe.json new file mode 100644 index 000000000..01e80a53a --- /dev/null +++ b/Java/directory-mavibot-ByteComparator_58/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ByteComparator.java", + "line": 69, + "npe_method": "compare", + "deref_field": "byte1", + "npe_class": "ByteComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-ByteComparator_63/Dockerfile b/Java/directory-mavibot-ByteComparator_63/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-ByteComparator_63/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-ByteComparator_63/buggy.java b/Java/directory-mavibot-ByteComparator_63/buggy.java new file mode 100644 index 000000000..0f68792c3 --- /dev/null +++ b/Java/directory-mavibot-ByteComparator_63/buggy.java @@ -0,0 +1,78 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares bytes + * + * @author Apache Directory Project + */ +public class ByteComparator implements Comparator +{ + /** A static instance of a ByteComparator */ + public static final ByteComparator INSTANCE = new ByteComparator(); + + /** + * A private constructor of the ByteComparator class + */ + private ByteComparator() + { + } + + + /** + * Compare two bytes. + * + * @param byte1 First byte + * @param byte2 Second byte + * @return 1 if byte1 > byte2, 0 if byte1 == byte2, -1 if byte1 < byte2 + */ +/** + * Compare two bytes. + * + * @param byte1 + * First byte + * @param byte2 + * Second byte + * @return 1 if byte1 > byte2, 0 if byte1 == byte2, -1 if byte1 < byte2 + */ +public int compare(java.lang.Byte byte1, java.lang.Byte byte2) { + if (byte1 == byte2) { + return 0; + } + if (byte1 == null) { + return -1; + } + { + if (byte1 < /* NPEX_NULL_EXP */ + byte2) { + return -1; + } else if (byte1 > byte2) { + return 1; + } else { + return 0; + } + } +} +} diff --git a/Java/directory-mavibot-ByteComparator_63/metadata.json b/Java/directory-mavibot-ByteComparator_63/metadata.json new file mode 100644 index 000000000..d6c4ab24e --- /dev/null +++ b/Java/directory-mavibot-ByteComparator_63/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-ByteComparator_63", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ByteComparator.java", + "line": 69, + "npe_method": "compare", + "deref_field": "byte2", + "npe_class": "ByteComparator", + "repo": "directory-mavibot", + "bug_id": "ByteComparator_63" + } +} diff --git a/Java/directory-mavibot-ByteComparator_63/npe.json b/Java/directory-mavibot-ByteComparator_63/npe.json new file mode 100644 index 000000000..512e938f8 --- /dev/null +++ b/Java/directory-mavibot-ByteComparator_63/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ByteComparator.java", + "line": 69, + "npe_method": "compare", + "deref_field": "byte2", + "npe_class": "ByteComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-CharArrayComparator_58/Dockerfile b/Java/directory-mavibot-CharArrayComparator_58/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-CharArrayComparator_58/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-CharArrayComparator_58/buggy.java b/Java/directory-mavibot-CharArrayComparator_58/buggy.java new file mode 100644 index 000000000..dc3a6c58e --- /dev/null +++ b/Java/directory-mavibot-CharArrayComparator_58/buggy.java @@ -0,0 +1,101 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares char arrays + * + * @author Apache Directory Project + */ +public class CharArrayComparator implements Comparator +{ + /** A static instance of a CharArrayComparator */ + public static final CharArrayComparator INSTANCE = new CharArrayComparator(); + + /** + * A private constructor of the CharArrayComparator class + */ + private CharArrayComparator() + { + } + + + /** + * Compare two char arrays. + * + * @param charArray1 First char array + * @param charArray2 Second char array + * @return 1 if charArray1 > charArray2, 0 if charArray1 == charArray2, -1 if charArray1 < charArray2 + */ +/** + * Compare two char arrays. + * + * @param charArray1 + * First char array + * @param charArray2 + * Second char array + * @return 1 if charArray1 > charArray2, 0 if charArray1 == charArray2, -1 if charArray1 < charArray2 + */ +public int compare(char[] charArray1, char[] charArray2) { + if (charArray1 == charArray2) { + return 0; + } + { + if (charArray2 == null) { + return 1; + } else if (/* NPEX_NULL_EXP */ + charArray1.length < charArray2.length) { + int pos = 0; + for (char char1 : charArray1) { + char char2 = charArray2[pos]; + if (char1 == char2) { + pos++; + } else if (char1 < char2) { + return -1; + } else { + return 1; + } + } + return -1; + } else { + int pos = 0; + for (char char2 : charArray2) { + char char1 = charArray1[pos]; + if (char1 == char2) { + pos++; + } else if (char1 < char2) { + return -1; + } else { + return 1; + } + } + if (pos < charArray1.length) { + return 1; + } else { + return 0; + } + } + } +} +} diff --git a/Java/directory-mavibot-CharArrayComparator_58/metadata.json b/Java/directory-mavibot-CharArrayComparator_58/metadata.json new file mode 100644 index 000000000..17823293f --- /dev/null +++ b/Java/directory-mavibot-CharArrayComparator_58/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-CharArrayComparator_58", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/CharArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "charArray1", + "npe_class": "CharArrayComparator", + "repo": "directory-mavibot", + "bug_id": "CharArrayComparator_58" + } +} diff --git a/Java/directory-mavibot-CharArrayComparator_58/npe.json b/Java/directory-mavibot-CharArrayComparator_58/npe.json new file mode 100644 index 000000000..ffd067d46 --- /dev/null +++ b/Java/directory-mavibot-CharArrayComparator_58/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/CharArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "charArray1", + "npe_class": "CharArrayComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-CharArrayComparator_71/Dockerfile b/Java/directory-mavibot-CharArrayComparator_71/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-CharArrayComparator_71/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-CharArrayComparator_71/buggy.java b/Java/directory-mavibot-CharArrayComparator_71/buggy.java new file mode 100644 index 000000000..99ff01ba1 --- /dev/null +++ b/Java/directory-mavibot-CharArrayComparator_71/buggy.java @@ -0,0 +1,102 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares char arrays + * + * @author Apache Directory Project + */ +public class CharArrayComparator implements Comparator +{ + /** A static instance of a CharArrayComparator */ + public static final CharArrayComparator INSTANCE = new CharArrayComparator(); + + /** + * A private constructor of the CharArrayComparator class + */ + private CharArrayComparator() + { + } + + + /** + * Compare two char arrays. + * + * @param charArray1 First char array + * @param charArray2 Second char array + * @return 1 if charArray1 > charArray2, 0 if charArray1 == charArray2, -1 if charArray1 < charArray2 + */ +/** + * Compare two char arrays. + * + * @param charArray1 + * First char array + * @param charArray2 + * Second char array + * @return 1 if charArray1 > charArray2, 0 if charArray1 == charArray2, -1 if charArray1 < charArray2 + */ +public int compare(char[] charArray1, char[] charArray2) { + if (charArray1 == charArray2) { + return 0; + } + { + { + if (/* NPEX_NULL_EXP */ + charArray1.length < /* NPEX_NULL_EXP */ + charArray2.length) { + int pos = 0; + for (char char1 : charArray1) { + char char2 = charArray2[pos]; + if (char1 == char2) { + pos++; + } else if (char1 < char2) { + return -1; + } else { + return 1; + } + } + return -1; + } else { + int pos = 0; + for (char char2 : charArray2) { + char char1 = charArray1[pos]; + if (char1 == char2) { + pos++; + } else if (char1 < char2) { + return -1; + } else { + return 1; + } + } + if (pos < charArray1.length) { + return 1; + } else { + return 0; + } + } + } + } +} +} diff --git a/Java/directory-mavibot-CharArrayComparator_71/metadata.json b/Java/directory-mavibot-CharArrayComparator_71/metadata.json new file mode 100644 index 000000000..dc2c89c8c --- /dev/null +++ b/Java/directory-mavibot-CharArrayComparator_71/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-CharArrayComparator_71", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/CharArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "charArray2", + "npe_class": "CharArrayComparator", + "repo": "directory-mavibot", + "bug_id": "CharArrayComparator_71" + } +} diff --git a/Java/directory-mavibot-CharArrayComparator_71/npe.json b/Java/directory-mavibot-CharArrayComparator_71/npe.json new file mode 100644 index 000000000..6545dabda --- /dev/null +++ b/Java/directory-mavibot-CharArrayComparator_71/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/CharArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "charArray2", + "npe_class": "CharArrayComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-CharComparator_58/Dockerfile b/Java/directory-mavibot-CharComparator_58/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-CharComparator_58/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-CharComparator_58/buggy.java b/Java/directory-mavibot-CharComparator_58/buggy.java new file mode 100644 index 000000000..458688aed --- /dev/null +++ b/Java/directory-mavibot-CharComparator_58/buggy.java @@ -0,0 +1,77 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares chars + * + * @author Apache Directory Project + */ +public class CharComparator implements Comparator +{ + /** A static instance of a CharComparator */ + public static final CharComparator INSTANCE = new CharComparator(); + + /** + * A private constructor of the CharComparator class + */ + private CharComparator() + { + } + + + /** + * Compare two chars. + * + * @param char1 First char + * @param char2 Second char + * @return 1 if char1 > char2, 0 if char1 == char2, -1 if char1 < char2 + */ +/** + * Compare two chars. + * + * @param char1 + * First char + * @param char2 + * Second char + * @return 1 if char1 > char2, 0 if char1 == char2, -1 if char1 < char2 + */ +public int compare(java.lang.Character char1, java.lang.Character char2) { + if (char1 == char2) { + return 0; + } + { + if (char2 == null) { + return 1; + } else if (/* NPEX_NULL_EXP */ + char1 < char2) { + return -1; + } else if (char1 > char2) { + return 1; + } else { + return 0; + } + } +} +} diff --git a/Java/directory-mavibot-CharComparator_58/metadata.json b/Java/directory-mavibot-CharComparator_58/metadata.json new file mode 100644 index 000000000..8abb7d539 --- /dev/null +++ b/Java/directory-mavibot-CharComparator_58/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-CharComparator_58", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/CharComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "char1", + "npe_class": "CharComparator", + "repo": "directory-mavibot", + "bug_id": "CharComparator_58" + } +} diff --git a/Java/directory-mavibot-CharComparator_58/npe.json b/Java/directory-mavibot-CharComparator_58/npe.json new file mode 100644 index 000000000..aace852ca --- /dev/null +++ b/Java/directory-mavibot-CharComparator_58/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/CharComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "char1", + "npe_class": "CharComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-CharComparator_71/Dockerfile b/Java/directory-mavibot-CharComparator_71/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-CharComparator_71/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-CharComparator_71/buggy.java b/Java/directory-mavibot-CharComparator_71/buggy.java new file mode 100644 index 000000000..545fc4d6c --- /dev/null +++ b/Java/directory-mavibot-CharComparator_71/buggy.java @@ -0,0 +1,78 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares chars + * + * @author Apache Directory Project + */ +public class CharComparator implements Comparator +{ + /** A static instance of a CharComparator */ + public static final CharComparator INSTANCE = new CharComparator(); + + /** + * A private constructor of the CharComparator class + */ + private CharComparator() + { + } + + + /** + * Compare two chars. + * + * @param char1 First char + * @param char2 Second char + * @return 1 if char1 > char2, 0 if char1 == char2, -1 if char1 < char2 + */ +/** + * Compare two chars. + * + * @param char1 + * First char + * @param char2 + * Second char + * @return 1 if char1 > char2, 0 if char1 == char2, -1 if char1 < char2 + */ +public int compare(java.lang.Character char1, java.lang.Character char2) { + if (char1 == char2) { + return 0; + } + { + { + if (/* NPEX_NULL_EXP */ + char1 < /* NPEX_NULL_EXP */ + char2) { + return -1; + } else if (char1 > char2) { + return 1; + } else { + return 0; + } + } + } +} +} diff --git a/Java/directory-mavibot-CharComparator_71/metadata.json b/Java/directory-mavibot-CharComparator_71/metadata.json new file mode 100644 index 000000000..89aa5787f --- /dev/null +++ b/Java/directory-mavibot-CharComparator_71/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-CharComparator_71", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/CharComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "char2", + "npe_class": "CharComparator", + "repo": "directory-mavibot", + "bug_id": "CharComparator_71" + } +} diff --git a/Java/directory-mavibot-CharComparator_71/npe.json b/Java/directory-mavibot-CharComparator_71/npe.json new file mode 100644 index 000000000..c849c435c --- /dev/null +++ b/Java/directory-mavibot-CharComparator_71/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/CharComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "char2", + "npe_class": "CharComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-IntArrayComparator_58/Dockerfile b/Java/directory-mavibot-IntArrayComparator_58/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-IntArrayComparator_58/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-IntArrayComparator_58/buggy.java b/Java/directory-mavibot-IntArrayComparator_58/buggy.java new file mode 100644 index 000000000..0028c22a3 --- /dev/null +++ b/Java/directory-mavibot-IntArrayComparator_58/buggy.java @@ -0,0 +1,101 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares int arrays + * + * @author Apache Directory Project + */ +public class IntArrayComparator implements Comparator +{ + /** A static instance of a IntArrayComparator */ + public static final IntArrayComparator INSTANCE = new IntArrayComparator(); + + /** + * A private constructor of the IntArrayComparator class + */ + private IntArrayComparator() + { + } + + + /** + * Compare two long arrays. + * + * @param intArray1 First int array + * @param intArray2 Second int array + * @return 1 if intArray1 > intArray2, 0 if intArray1 == intArray2, -1 if intArray1 < intArray2 + */ +/** + * Compare two long arrays. + * + * @param intArray1 + * First int array + * @param intArray2 + * Second int array + * @return 1 if intArray1 > intArray2, 0 if intArray1 == intArray2, -1 if intArray1 < intArray2 + */ +public int compare(int[] intArray1, int[] intArray2) { + if (intArray1 == intArray2) { + return 0; + } + { + if (intArray2 == null) { + return 1; + } else if (/* NPEX_NULL_EXP */ + intArray1.length < intArray2.length) { + int pos = 0; + for (int int1 : intArray1) { + int int2 = intArray2[pos]; + if (int1 == int2) { + pos++; + } else if (int1 < int2) { + return -1; + } else { + return 1; + } + } + return -1; + } else { + int pos = 0; + for (int int2 : intArray2) { + int int1 = intArray1[pos]; + if (int1 == int2) { + pos++; + } else if (int1 < int2) { + return -1; + } else { + return 1; + } + } + if (pos < intArray1.length) { + return 1; + } else { + return 0; + } + } + } +} +} diff --git a/Java/directory-mavibot-IntArrayComparator_58/metadata.json b/Java/directory-mavibot-IntArrayComparator_58/metadata.json new file mode 100644 index 000000000..1ea53bf1d --- /dev/null +++ b/Java/directory-mavibot-IntArrayComparator_58/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-IntArrayComparator_58", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/IntArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "intArray1", + "npe_class": "IntArrayComparator", + "repo": "directory-mavibot", + "bug_id": "IntArrayComparator_58" + } +} diff --git a/Java/directory-mavibot-IntArrayComparator_58/npe.json b/Java/directory-mavibot-IntArrayComparator_58/npe.json new file mode 100644 index 000000000..8bd8d9056 --- /dev/null +++ b/Java/directory-mavibot-IntArrayComparator_58/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/IntArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "intArray1", + "npe_class": "IntArrayComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-IntArrayComparator_71/Dockerfile b/Java/directory-mavibot-IntArrayComparator_71/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-IntArrayComparator_71/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-IntArrayComparator_71/buggy.java b/Java/directory-mavibot-IntArrayComparator_71/buggy.java new file mode 100644 index 000000000..02da4c294 --- /dev/null +++ b/Java/directory-mavibot-IntArrayComparator_71/buggy.java @@ -0,0 +1,102 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares int arrays + * + * @author Apache Directory Project + */ +public class IntArrayComparator implements Comparator +{ + /** A static instance of a IntArrayComparator */ + public static final IntArrayComparator INSTANCE = new IntArrayComparator(); + + /** + * A private constructor of the IntArrayComparator class + */ + private IntArrayComparator() + { + } + + + /** + * Compare two long arrays. + * + * @param intArray1 First int array + * @param intArray2 Second int array + * @return 1 if intArray1 > intArray2, 0 if intArray1 == intArray2, -1 if intArray1 < intArray2 + */ +/** + * Compare two long arrays. + * + * @param intArray1 + * First int array + * @param intArray2 + * Second int array + * @return 1 if intArray1 > intArray2, 0 if intArray1 == intArray2, -1 if intArray1 < intArray2 + */ +public int compare(int[] intArray1, int[] intArray2) { + if (intArray1 == intArray2) { + return 0; + } + { + { + if (/* NPEX_NULL_EXP */ + intArray1.length < /* NPEX_NULL_EXP */ + intArray2.length) { + int pos = 0; + for (int int1 : intArray1) { + int int2 = intArray2[pos]; + if (int1 == int2) { + pos++; + } else if (int1 < int2) { + return -1; + } else { + return 1; + } + } + return -1; + } else { + int pos = 0; + for (int int2 : intArray2) { + int int1 = intArray1[pos]; + if (int1 == int2) { + pos++; + } else if (int1 < int2) { + return -1; + } else { + return 1; + } + } + if (pos < intArray1.length) { + return 1; + } else { + return 0; + } + } + } + } +} +} diff --git a/Java/directory-mavibot-IntArrayComparator_71/metadata.json b/Java/directory-mavibot-IntArrayComparator_71/metadata.json new file mode 100644 index 000000000..1c5db9bc4 --- /dev/null +++ b/Java/directory-mavibot-IntArrayComparator_71/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-IntArrayComparator_71", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/IntArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "intArray2", + "npe_class": "IntArrayComparator", + "repo": "directory-mavibot", + "bug_id": "IntArrayComparator_71" + } +} diff --git a/Java/directory-mavibot-IntArrayComparator_71/npe.json b/Java/directory-mavibot-IntArrayComparator_71/npe.json new file mode 100644 index 000000000..76f8536a3 --- /dev/null +++ b/Java/directory-mavibot-IntArrayComparator_71/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/IntArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "intArray2", + "npe_class": "IntArrayComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-IntComparator_58/Dockerfile b/Java/directory-mavibot-IntComparator_58/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-IntComparator_58/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-IntComparator_58/buggy.java b/Java/directory-mavibot-IntComparator_58/buggy.java new file mode 100644 index 000000000..beadd150b --- /dev/null +++ b/Java/directory-mavibot-IntComparator_58/buggy.java @@ -0,0 +1,73 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares integers + * + * @author Apache Directory Project + */ +public class IntComparator implements Comparator +{ + /** A static instance of a IntComparator */ + public static final IntComparator INSTANCE = new IntComparator(); + + /** + * A private constructor of the IntComparator class + */ + private IntComparator() + { + } + + + /** + * Compare two integers. + * + * @param integer1 First integer + * @param integer2 Second integer + * @return 1 if integer1 > integer2, 0 if integer1 == integer2, -1 if integer1 < integer2 + */ +/** + * Compare two integers. + * + * @param integer1 + * First integer + * @param integer2 + * Second integer + * @return 1 if integer1 > integer2, 0 if integer1 == integer2, -1 if integer1 < integer2 + */ +public int compare(java.lang.Integer integer1, java.lang.Integer integer2) { + if (integer1 == integer2) { + return 0; + } + { + if (integer2 == null) { + return 1; + } else { + return /* NPEX_NULL_EXP */ + integer1.compareTo(integer2); + } + } +} +} diff --git a/Java/directory-mavibot-IntComparator_58/metadata.json b/Java/directory-mavibot-IntComparator_58/metadata.json new file mode 100644 index 000000000..3cefea70f --- /dev/null +++ b/Java/directory-mavibot-IntComparator_58/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-IntComparator_58", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/IntComparator.java", + "line": 69, + "npe_method": "compare", + "deref_field": "integer1", + "npe_class": "IntComparator", + "repo": "directory-mavibot", + "bug_id": "IntComparator_58" + } +} diff --git a/Java/directory-mavibot-IntComparator_58/npe.json b/Java/directory-mavibot-IntComparator_58/npe.json new file mode 100644 index 000000000..0a131c875 --- /dev/null +++ b/Java/directory-mavibot-IntComparator_58/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/IntComparator.java", + "line": 69, + "npe_method": "compare", + "deref_field": "integer1", + "npe_class": "IntComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-IntComparator_71/Dockerfile b/Java/directory-mavibot-IntComparator_71/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-IntComparator_71/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-IntComparator_71/buggy.java b/Java/directory-mavibot-IntComparator_71/buggy.java new file mode 100644 index 000000000..167d6651b --- /dev/null +++ b/Java/directory-mavibot-IntComparator_71/buggy.java @@ -0,0 +1,72 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares integers + * + * @author Apache Directory Project + */ +public class IntComparator implements Comparator +{ + /** A static instance of a IntComparator */ + public static final IntComparator INSTANCE = new IntComparator(); + + /** + * A private constructor of the IntComparator class + */ + private IntComparator() + { + } + + + /** + * Compare two integers. + * + * @param integer1 First integer + * @param integer2 Second integer + * @return 1 if integer1 > integer2, 0 if integer1 == integer2, -1 if integer1 < integer2 + */ +/** + * Compare two integers. + * + * @param integer1 + * First integer + * @param integer2 + * Second integer + * @return 1 if integer1 > integer2, 0 if integer1 == integer2, -1 if integer1 < integer2 + */ +public int compare(java.lang.Integer integer1, java.lang.Integer integer2) { + if (integer1 == integer2) { + return 0; + } + { + { + return /* NPEX_NULL_EXP */ + integer1.compareTo(/* NPEX_NULL_EXP */ + integer2); + } + } +} +} diff --git a/Java/directory-mavibot-IntComparator_71/metadata.json b/Java/directory-mavibot-IntComparator_71/metadata.json new file mode 100644 index 000000000..4bd6252ba --- /dev/null +++ b/Java/directory-mavibot-IntComparator_71/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-IntComparator_71", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/IntComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "integer2", + "npe_class": "IntComparator", + "repo": "directory-mavibot", + "bug_id": "IntComparator_71" + } +} diff --git a/Java/directory-mavibot-IntComparator_71/npe.json b/Java/directory-mavibot-IntComparator_71/npe.json new file mode 100644 index 000000000..14f393628 --- /dev/null +++ b/Java/directory-mavibot-IntComparator_71/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/IntComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "integer2", + "npe_class": "IntComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-LongArrayComparator_58/Dockerfile b/Java/directory-mavibot-LongArrayComparator_58/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-LongArrayComparator_58/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-LongArrayComparator_58/buggy.java b/Java/directory-mavibot-LongArrayComparator_58/buggy.java new file mode 100644 index 000000000..7f7badeb4 --- /dev/null +++ b/Java/directory-mavibot-LongArrayComparator_58/buggy.java @@ -0,0 +1,101 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares long arrays + * + * @author Apache Directory Project + */ +public class LongArrayComparator implements Comparator +{ + /** A static instance of a LongArrayComparator */ + public static final LongArrayComparator INSTANCE = new LongArrayComparator(); + + /** + * A private constructor of the LongArrayComparator class + */ + private LongArrayComparator() + { + } + + + /** + * Compare two long arrays. + * + * @param longArray1 First long array + * @param longArray2 Second long array + * @return 1 if longArray1 > longArray2, 0 if longArray1 == longArray2, -1 if longArray1 < longArray2 + */ +/** + * Compare two long arrays. + * + * @param longArray1 + * First long array + * @param longArray2 + * Second long array + * @return 1 if longArray1 > longArray2, 0 if longArray1 == longArray2, -1 if longArray1 < longArray2 + */ +public int compare(long[] longArray1, long[] longArray2) { + if (longArray1 == longArray2) { + return 0; + } + { + if (longArray2 == null) { + return 1; + } else if (/* NPEX_NULL_EXP */ + longArray1.length < longArray2.length) { + int pos = 0; + for (long long1 : longArray1) { + long long2 = longArray2[pos]; + if (long1 == long2) { + pos++; + } else if (long1 < long2) { + return -1; + } else { + return 1; + } + } + return -1; + } else { + int pos = 0; + for (long long2 : longArray2) { + long long1 = longArray1[pos]; + if (long1 == long2) { + pos++; + } else if (long1 < long2) { + return -1; + } else { + return 1; + } + } + if (pos < longArray1.length) { + return 1; + } else { + return 0; + } + } + } +} +} diff --git a/Java/directory-mavibot-LongArrayComparator_58/metadata.json b/Java/directory-mavibot-LongArrayComparator_58/metadata.json new file mode 100644 index 000000000..30f81dd82 --- /dev/null +++ b/Java/directory-mavibot-LongArrayComparator_58/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-LongArrayComparator_58", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/LongArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "longArray1", + "npe_class": "LongArrayComparator", + "repo": "directory-mavibot", + "bug_id": "LongArrayComparator_58" + } +} diff --git a/Java/directory-mavibot-LongArrayComparator_58/npe.json b/Java/directory-mavibot-LongArrayComparator_58/npe.json new file mode 100644 index 000000000..51ccc2313 --- /dev/null +++ b/Java/directory-mavibot-LongArrayComparator_58/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/LongArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "longArray1", + "npe_class": "LongArrayComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-LongArrayComparator_71/Dockerfile b/Java/directory-mavibot-LongArrayComparator_71/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-LongArrayComparator_71/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-LongArrayComparator_71/buggy.java b/Java/directory-mavibot-LongArrayComparator_71/buggy.java new file mode 100644 index 000000000..e4b5d7257 --- /dev/null +++ b/Java/directory-mavibot-LongArrayComparator_71/buggy.java @@ -0,0 +1,102 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares long arrays + * + * @author Apache Directory Project + */ +public class LongArrayComparator implements Comparator +{ + /** A static instance of a LongArrayComparator */ + public static final LongArrayComparator INSTANCE = new LongArrayComparator(); + + /** + * A private constructor of the LongArrayComparator class + */ + private LongArrayComparator() + { + } + + + /** + * Compare two long arrays. + * + * @param longArray1 First long array + * @param longArray2 Second long array + * @return 1 if longArray1 > longArray2, 0 if longArray1 == longArray2, -1 if longArray1 < longArray2 + */ +/** + * Compare two long arrays. + * + * @param longArray1 + * First long array + * @param longArray2 + * Second long array + * @return 1 if longArray1 > longArray2, 0 if longArray1 == longArray2, -1 if longArray1 < longArray2 + */ +public int compare(long[] longArray1, long[] longArray2) { + if (longArray1 == longArray2) { + return 0; + } + { + { + if (/* NPEX_NULL_EXP */ + longArray1.length < /* NPEX_NULL_EXP */ + longArray2.length) { + int pos = 0; + for (long long1 : longArray1) { + long long2 = longArray2[pos]; + if (long1 == long2) { + pos++; + } else if (long1 < long2) { + return -1; + } else { + return 1; + } + } + return -1; + } else { + int pos = 0; + for (long long2 : longArray2) { + long long1 = longArray1[pos]; + if (long1 == long2) { + pos++; + } else if (long1 < long2) { + return -1; + } else { + return 1; + } + } + if (pos < longArray1.length) { + return 1; + } else { + return 0; + } + } + } + } +} +} diff --git a/Java/directory-mavibot-LongArrayComparator_71/metadata.json b/Java/directory-mavibot-LongArrayComparator_71/metadata.json new file mode 100644 index 000000000..a380261f6 --- /dev/null +++ b/Java/directory-mavibot-LongArrayComparator_71/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-LongArrayComparator_71", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/LongArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "longArray2", + "npe_class": "LongArrayComparator", + "repo": "directory-mavibot", + "bug_id": "LongArrayComparator_71" + } +} diff --git a/Java/directory-mavibot-LongArrayComparator_71/npe.json b/Java/directory-mavibot-LongArrayComparator_71/npe.json new file mode 100644 index 000000000..76fd46663 --- /dev/null +++ b/Java/directory-mavibot-LongArrayComparator_71/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/LongArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "longArray2", + "npe_class": "LongArrayComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-LongComparator_56/Dockerfile b/Java/directory-mavibot-LongComparator_56/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-LongComparator_56/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-LongComparator_56/buggy.java b/Java/directory-mavibot-LongComparator_56/buggy.java new file mode 100644 index 000000000..aca1a52e1 --- /dev/null +++ b/Java/directory-mavibot-LongComparator_56/buggy.java @@ -0,0 +1,75 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares Longs + * + * @author Apache Directory Project + */ +public class LongComparator implements Comparator +{ + /** A static instance of a LongComparator */ + public static final LongComparator INSTANCE = new LongComparator(); + + /** + * A private constructor of the BooleanArrayComparator class + */ + private LongComparator() + { + } + /** + * Compare two longs. + * + * @param long1 First long + * @param long2 Second long + * @return 1 if long1 > long2, 0 if long1 == long2, -1 if long1 < long2 + */ +/** + * Compare two longs. + * + * @param long1 + * First long + * @param long2 + * Second long + * @return 1 if long1 > long2, 0 if long1 == long2, -1 if long1 < long2 + */ +public int compare(java.lang.Long long1, java.lang.Long long2) { + if (long1 == long2) { + return 0; + } + { + if (long2 == null) { + return 1; + } else if (/* NPEX_NULL_EXP */ + long1 < long2) { + return -1; + } else if (long1 > long2) { + return 1; + } else { + return 0; + } + } +} +} diff --git a/Java/directory-mavibot-LongComparator_56/metadata.json b/Java/directory-mavibot-LongComparator_56/metadata.json new file mode 100644 index 000000000..772265b16 --- /dev/null +++ b/Java/directory-mavibot-LongComparator_56/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-LongComparator_56", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/LongComparator.java", + "line": 66, + "npe_method": "compare", + "deref_field": "long1", + "npe_class": "LongComparator", + "repo": "directory-mavibot", + "bug_id": "LongComparator_56" + } +} diff --git a/Java/directory-mavibot-LongComparator_56/npe.json b/Java/directory-mavibot-LongComparator_56/npe.json new file mode 100644 index 000000000..8060d8f21 --- /dev/null +++ b/Java/directory-mavibot-LongComparator_56/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/LongComparator.java", + "line": 66, + "npe_method": "compare", + "deref_field": "long1", + "npe_class": "LongComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-LongComparator_69/Dockerfile b/Java/directory-mavibot-LongComparator_69/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-LongComparator_69/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-LongComparator_69/buggy.java b/Java/directory-mavibot-LongComparator_69/buggy.java new file mode 100644 index 000000000..8fde8c7e4 --- /dev/null +++ b/Java/directory-mavibot-LongComparator_69/buggy.java @@ -0,0 +1,76 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares Longs + * + * @author Apache Directory Project + */ +public class LongComparator implements Comparator +{ + /** A static instance of a LongComparator */ + public static final LongComparator INSTANCE = new LongComparator(); + + /** + * A private constructor of the BooleanArrayComparator class + */ + private LongComparator() + { + } + /** + * Compare two longs. + * + * @param long1 First long + * @param long2 Second long + * @return 1 if long1 > long2, 0 if long1 == long2, -1 if long1 < long2 + */ +/** + * Compare two longs. + * + * @param long1 + * First long + * @param long2 + * Second long + * @return 1 if long1 > long2, 0 if long1 == long2, -1 if long1 < long2 + */ +public int compare(java.lang.Long long1, java.lang.Long long2) { + if (long1 == long2) { + return 0; + } + { + { + if (/* NPEX_NULL_EXP */ + long1 < /* NPEX_NULL_EXP */ + long2) { + return -1; + } else if (long1 > long2) { + return 1; + } else { + return 0; + } + } + } +} +} diff --git a/Java/directory-mavibot-LongComparator_69/metadata.json b/Java/directory-mavibot-LongComparator_69/metadata.json new file mode 100644 index 000000000..26c9c9887 --- /dev/null +++ b/Java/directory-mavibot-LongComparator_69/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-LongComparator_69", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/LongComparator.java", + "line": 66, + "npe_method": "compare", + "deref_field": "long2", + "npe_class": "LongComparator", + "repo": "directory-mavibot", + "bug_id": "LongComparator_69" + } +} diff --git a/Java/directory-mavibot-LongComparator_69/npe.json b/Java/directory-mavibot-LongComparator_69/npe.json new file mode 100644 index 000000000..934d7ed83 --- /dev/null +++ b/Java/directory-mavibot-LongComparator_69/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/LongComparator.java", + "line": 66, + "npe_method": "compare", + "deref_field": "long2", + "npe_class": "LongComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-ShortArrayComparator_58/Dockerfile b/Java/directory-mavibot-ShortArrayComparator_58/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-ShortArrayComparator_58/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-ShortArrayComparator_58/buggy.java b/Java/directory-mavibot-ShortArrayComparator_58/buggy.java new file mode 100644 index 000000000..6e92e266b --- /dev/null +++ b/Java/directory-mavibot-ShortArrayComparator_58/buggy.java @@ -0,0 +1,101 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares short arrays + * + * @author Apache Directory Project + */ +public class ShortArrayComparator implements Comparator +{ + /** A static instance of a ShortArrayComparator */ + public static final ShortArrayComparator INSTANCE = new ShortArrayComparator(); + + /** + * A private constructor of the ShortArrayComparator class + */ + private ShortArrayComparator() + { + } + + + /** + * Compare two short arrays. + * + * @param shortArray1 First short array + * @param shortArray2 Second short array + * @return 1 if shortArray1 > shortArray2, 0 if shortArray1 == shortArray2, -1 if shortArray1 < shortArray2 + */ +/** + * Compare two short arrays. + * + * @param shortArray1 + * First short array + * @param shortArray2 + * Second short array + * @return 1 if shortArray1 > shortArray2, 0 if shortArray1 == shortArray2, -1 if shortArray1 < shortArray2 + */ +public int compare(short[] shortArray1, short[] shortArray2) { + if (shortArray1 == shortArray2) { + return 0; + } + { + if (shortArray2 == null) { + return 1; + } else if (/* NPEX_NULL_EXP */ + shortArray1.length < shortArray2.length) { + int pos = 0; + for (short short1 : shortArray1) { + short short2 = shortArray2[pos]; + if (short1 == short2) { + pos++; + } else if (short1 < short2) { + return -1; + } else { + return 1; + } + } + return -1; + } else { + int pos = 0; + for (short short2 : shortArray2) { + short short1 = shortArray1[pos]; + if (short1 == short2) { + pos++; + } else if (short1 < short2) { + return -1; + } else { + return 1; + } + } + if (pos < shortArray1.length) { + return 1; + } else { + return 0; + } + } + } +} +} diff --git a/Java/directory-mavibot-ShortArrayComparator_58/metadata.json b/Java/directory-mavibot-ShortArrayComparator_58/metadata.json new file mode 100644 index 000000000..ef438f56f --- /dev/null +++ b/Java/directory-mavibot-ShortArrayComparator_58/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-ShortArrayComparator_58", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ShortArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "shortArray1", + "npe_class": "ShortArrayComparator", + "repo": "directory-mavibot", + "bug_id": "ShortArrayComparator_58" + } +} diff --git a/Java/directory-mavibot-ShortArrayComparator_58/npe.json b/Java/directory-mavibot-ShortArrayComparator_58/npe.json new file mode 100644 index 000000000..0d50a73c8 --- /dev/null +++ b/Java/directory-mavibot-ShortArrayComparator_58/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ShortArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "shortArray1", + "npe_class": "ShortArrayComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-ShortArrayComparator_71/Dockerfile b/Java/directory-mavibot-ShortArrayComparator_71/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-ShortArrayComparator_71/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-ShortArrayComparator_71/buggy.java b/Java/directory-mavibot-ShortArrayComparator_71/buggy.java new file mode 100644 index 000000000..a09406fe1 --- /dev/null +++ b/Java/directory-mavibot-ShortArrayComparator_71/buggy.java @@ -0,0 +1,102 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares short arrays + * + * @author Apache Directory Project + */ +public class ShortArrayComparator implements Comparator +{ + /** A static instance of a ShortArrayComparator */ + public static final ShortArrayComparator INSTANCE = new ShortArrayComparator(); + + /** + * A private constructor of the ShortArrayComparator class + */ + private ShortArrayComparator() + { + } + + + /** + * Compare two short arrays. + * + * @param shortArray1 First short array + * @param shortArray2 Second short array + * @return 1 if shortArray1 > shortArray2, 0 if shortArray1 == shortArray2, -1 if shortArray1 < shortArray2 + */ +/** + * Compare two short arrays. + * + * @param shortArray1 + * First short array + * @param shortArray2 + * Second short array + * @return 1 if shortArray1 > shortArray2, 0 if shortArray1 == shortArray2, -1 if shortArray1 < shortArray2 + */ +public int compare(short[] shortArray1, short[] shortArray2) { + if (shortArray1 == shortArray2) { + return 0; + } + { + { + if (/* NPEX_NULL_EXP */ + shortArray1.length < /* NPEX_NULL_EXP */ + shortArray2.length) { + int pos = 0; + for (short short1 : shortArray1) { + short short2 = shortArray2[pos]; + if (short1 == short2) { + pos++; + } else if (short1 < short2) { + return -1; + } else { + return 1; + } + } + return -1; + } else { + int pos = 0; + for (short short2 : shortArray2) { + short short1 = shortArray1[pos]; + if (short1 == short2) { + pos++; + } else if (short1 < short2) { + return -1; + } else { + return 1; + } + } + if (pos < shortArray1.length) { + return 1; + } else { + return 0; + } + } + } + } +} +} diff --git a/Java/directory-mavibot-ShortArrayComparator_71/metadata.json b/Java/directory-mavibot-ShortArrayComparator_71/metadata.json new file mode 100644 index 000000000..82ea00b39 --- /dev/null +++ b/Java/directory-mavibot-ShortArrayComparator_71/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-ShortArrayComparator_71", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ShortArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "shortArray2", + "npe_class": "ShortArrayComparator", + "repo": "directory-mavibot", + "bug_id": "ShortArrayComparator_71" + } +} diff --git a/Java/directory-mavibot-ShortArrayComparator_71/npe.json b/Java/directory-mavibot-ShortArrayComparator_71/npe.json new file mode 100644 index 000000000..3e739f979 --- /dev/null +++ b/Java/directory-mavibot-ShortArrayComparator_71/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ShortArrayComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "shortArray2", + "npe_class": "ShortArrayComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-ShortComparator_58/Dockerfile b/Java/directory-mavibot-ShortComparator_58/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-ShortComparator_58/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-ShortComparator_58/buggy.java b/Java/directory-mavibot-ShortComparator_58/buggy.java new file mode 100644 index 000000000..803154eb9 --- /dev/null +++ b/Java/directory-mavibot-ShortComparator_58/buggy.java @@ -0,0 +1,77 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares shorts + * + * @author Apache Directory Project + */ +public class ShortComparator implements Comparator +{ + /** A static instance of a ShortComparator */ + public static final ShortComparator INSTANCE = new ShortComparator(); + + /** + * A private constructor of the ShortComparator class + */ + private ShortComparator() + { + } + + + /** + * Compare two shorts. + * + * @param short1 First short + * @param short2 Second short + * @return 1 if short1 > short2, 0 if short1 == short2, -1 if short1 < short2 + */ +/** + * Compare two shorts. + * + * @param short1 + * First short + * @param short2 + * Second short + * @return 1 if short1 > short2, 0 if short1 == short2, -1 if short1 < short2 + */ +public int compare(java.lang.Short short1, java.lang.Short short2) { + if (short1 == short2) { + return 0; + } + { + if (short2 == null) { + return 1; + } else if (/* NPEX_NULL_EXP */ + short1 < short2) { + return -1; + } else if (short1 > short2) { + return 1; + } else { + return 0; + } + } +} +} diff --git a/Java/directory-mavibot-ShortComparator_58/metadata.json b/Java/directory-mavibot-ShortComparator_58/metadata.json new file mode 100644 index 000000000..bfcda6707 --- /dev/null +++ b/Java/directory-mavibot-ShortComparator_58/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-ShortComparator_58", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ShortComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "short1", + "npe_class": "ShortComparator", + "repo": "directory-mavibot", + "bug_id": "ShortComparator_58" + } +} diff --git a/Java/directory-mavibot-ShortComparator_58/npe.json b/Java/directory-mavibot-ShortComparator_58/npe.json new file mode 100644 index 000000000..969eebc81 --- /dev/null +++ b/Java/directory-mavibot-ShortComparator_58/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ShortComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "short1", + "npe_class": "ShortComparator" +} \ No newline at end of file diff --git a/Java/directory-mavibot-ShortComparator_71/Dockerfile b/Java/directory-mavibot-ShortComparator_71/Dockerfile new file mode 100644 index 000000000..475a2481d --- /dev/null +++ b/Java/directory-mavibot-ShortComparator_71/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:directory-mavibot + +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/directory-mavibot-ShortComparator_71/buggy.java b/Java/directory-mavibot-ShortComparator_71/buggy.java new file mode 100644 index 000000000..85d6b82da --- /dev/null +++ b/Java/directory-mavibot-ShortComparator_71/buggy.java @@ -0,0 +1,78 @@ +/* + * 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.directory.mavibot.btree.comparator; + + +import java.util.Comparator; + + +/** + * Compares shorts + * + * @author Apache Directory Project + */ +public class ShortComparator implements Comparator +{ + /** A static instance of a ShortComparator */ + public static final ShortComparator INSTANCE = new ShortComparator(); + + /** + * A private constructor of the ShortComparator class + */ + private ShortComparator() + { + } + + + /** + * Compare two shorts. + * + * @param short1 First short + * @param short2 Second short + * @return 1 if short1 > short2, 0 if short1 == short2, -1 if short1 < short2 + */ +/** + * Compare two shorts. + * + * @param short1 + * First short + * @param short2 + * Second short + * @return 1 if short1 > short2, 0 if short1 == short2, -1 if short1 < short2 + */ +public int compare(java.lang.Short short1, java.lang.Short short2) { + if (short1 == short2) { + return 0; + } + { + { + if (/* NPEX_NULL_EXP */ + short1 < /* NPEX_NULL_EXP */ + short2) { + return -1; + } else if (short1 > short2) { + return 1; + } else { + return 0; + } + } + } +} +} diff --git a/Java/directory-mavibot-ShortComparator_71/metadata.json b/Java/directory-mavibot-ShortComparator_71/metadata.json new file mode 100644 index 000000000..841b342bd --- /dev/null +++ b/Java/directory-mavibot-ShortComparator_71/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "directory-mavibot-ShortComparator_71", + "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": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ShortComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "short2", + "npe_class": "ShortComparator", + "repo": "directory-mavibot", + "bug_id": "ShortComparator_71" + } +} diff --git a/Java/directory-mavibot-ShortComparator_71/npe.json b/Java/directory-mavibot-ShortComparator_71/npe.json new file mode 100644 index 000000000..21fe013b7 --- /dev/null +++ b/Java/directory-mavibot-ShortComparator_71/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/ShortComparator.java", + "line": 68, + "npe_method": "compare", + "deref_field": "short2", + "npe_class": "ShortComparator" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_126/Dockerfile b/Java/geronimo-jcache-simple-CDIJCacheHelper_126/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_126/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CDIJCacheHelper_126/buggy.java b/Java/geronimo-jcache-simple-CDIJCacheHelper_126/buggy.java new file mode 100644 index 000000000..4af9dcbc0 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_126/buggy.java @@ -0,0 +1,535 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; + +import javax.annotation.PreDestroy; +import javax.cache.annotation.CacheDefaults; +import javax.cache.annotation.CacheKey; +import javax.cache.annotation.CacheKeyGenerator; +import javax.cache.annotation.CachePut; +import javax.cache.annotation.CacheRemove; +import javax.cache.annotation.CacheRemoveAll; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.CacheValue; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; + +@ApplicationScoped +public class CDIJCacheHelper { + + private static final Logger LOGGER = Logger.getLogger(CDIJCacheHelper.class.getName()); + + private static final boolean CLOSE_CACHE = !Boolean.getBoolean("org.apache.geronimo.jcache.simple.cdi.skip-close"); + + private final CacheKeyGeneratorImpl defaultCacheKeyGenerator = new CacheKeyGeneratorImpl(); + + private final Collection> toRelease = new ArrayList>(); + + private final ConcurrentMap methods = new ConcurrentHashMap(); + + private volatile CacheResolverFactoryImpl defaultCacheResolverFactory = null; // lazy to not create any cache if not needed + + @Inject + private BeanManager beanManager; + + @PreDestroy + private void release() { + if (CLOSE_CACHE && defaultCacheResolverFactory != null) { + defaultCacheResolverFactory.release(); + } + for (final CreationalContext cc : toRelease) { + try { + cc.release(); + } catch (final RuntimeException re) { + LOGGER.warning(re.getMessage()); + } + } + } + + public MethodMeta findMeta(final InvocationContext ic) { + final Method mtd = ic.getMethod(); + final Class refType = findKeyType(ic.getTarget()); + final MethodKey key = new MethodKey(refType, mtd); + MethodMeta methodMeta = methods.get(key); + if (methodMeta == null) { + synchronized (this) { + methodMeta = methods.get(key); + if (methodMeta == null) { + methodMeta = createMeta(ic); + methods.put(key, methodMeta); + } + } + } + return methodMeta; + } + + private Class findKeyType(final Object target) { + if (null == target) { + return null; + } + return target.getClass(); + } + + // it is unlikely we have all annotations but for now we have a single meta model +// it is unlikely we have all annotations but for now we have a single meta model +private org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta createMeta(final javax.interceptor.InvocationContext ic) { + final javax.cache.annotation.CacheDefaults defaults = findDefaults(ic.getTarget() == null ? null : ic.getTarget().getClass(), ic.getMethod()); + final java.lang.Class[] parameterTypes = ic.getMethod().getParameterTypes(); + final java.lang.annotation.Annotation[][] parameterAnnotations = ic.getMethod().getParameterAnnotations(); + final java.util.List> annotations = new java.util.ArrayList>(); + for (final java.lang.annotation.Annotation[] parameterAnnotation : parameterAnnotations) { + final java.util.Set set = new java.util.HashSet(parameterAnnotation.length); + set.addAll(java.util.Arrays.asList(parameterAnnotation)); + annotations.add(set); + } + final java.util.Set mtdAnnotations = new java.util.HashSet(); + mtdAnnotations.addAll(java.util.Arrays.asList(ic.getMethod().getAnnotations())); + final javax.cache.annotation.CacheResult cacheResult = ic.getMethod().getAnnotation(javax.cache.annotation.CacheResult.class); + final java.lang.String cacheResultCacheResultName = defaultName(ic.getMethod(), defaults, /* NPEX_NULL_EXP */ + cacheResult.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheResultCacheResolverFactory = (cacheResult == null) ? null : cacheResolverFactoryFor(defaults, cacheResult.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheResultCacheKeyGenerator = (cacheResult == null) ? null : cacheKeyGeneratorFor(defaults, cacheResult.cacheKeyGenerator()); + final javax.cache.annotation.CachePut cachePut = ic.getMethod().getAnnotation(javax.cache.annotation.CachePut.class); + final java.lang.String cachePutCachePutName = (cachePut == null) ? null : defaultName(ic.getMethod(), defaults, cachePut.cacheName()); + final javax.cache.annotation.CacheResolverFactory cachePutCacheResolverFactory = (cachePut == null) ? null : cacheResolverFactoryFor(defaults, cachePut.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cachePutCacheKeyGenerator = (cachePut == null) ? null : cacheKeyGeneratorFor(defaults, cachePut.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemove cacheRemove = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemove.class); + final java.lang.String cacheRemoveCacheRemoveName = (cacheRemove == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemove.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveCacheResolverFactory = (cacheRemove == null) ? null : cacheResolverFactoryFor(defaults, cacheRemove.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheRemoveCacheKeyGenerator = (cacheRemove == null) ? null : cacheKeyGeneratorFor(defaults, cacheRemove.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemoveAll cacheRemoveAll = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemoveAll.class); + final java.lang.String cacheRemoveAllCacheRemoveAllName = (cacheRemoveAll == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemoveAll.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveAllCacheResolverFactory = (cacheRemoveAll == null) ? null : cacheResolverFactoryFor(defaults, cacheRemoveAll.cacheResolverFactory()); + return new org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta(parameterTypes, annotations, mtdAnnotations, keyParameterIndexes(ic.getMethod()), getValueParameter(annotations), cacheResultCacheResultName, cacheResultCacheResolverFactory, cacheResultCacheKeyGenerator, cacheResult, cachePutCachePutName, cachePutCacheResolverFactory, cachePutCacheKeyGenerator, (cachePut != null) && cachePut.afterInvocation(), cachePut, cacheRemoveCacheRemoveName, cacheRemoveCacheResolverFactory, cacheRemoveCacheKeyGenerator, (cacheRemove != null) && cacheRemove.afterInvocation(), cacheRemove, cacheRemoveAllCacheRemoveAllName, cacheRemoveAllCacheResolverFactory, cacheRemoveAll, java.util.concurrent.CompletionStage.class.isAssignableFrom(ic.getMethod().getReturnType())); +} + + private Integer getValueParameter(final List> annotations) { + int idx = 0; + for (final Set set : annotations) { + for (final Annotation a : set) { + if (a.annotationType() == CacheValue.class) { + return idx; + } + } + } + return -1; + } + + private String defaultName(final Method method, final CacheDefaults defaults, final String cacheName) { + if (!cacheName.isEmpty()) { + return cacheName; + } + if (defaults != null) { + final String name = defaults.cacheName(); + if (!name.isEmpty()) { + return name; + } + } + + final StringBuilder name = new StringBuilder(method.getDeclaringClass().getName()); + name.append("."); + name.append(method.getName()); + name.append("("); + final Class[] parameterTypes = method.getParameterTypes(); + for (int pIdx = 0; pIdx < parameterTypes.length; pIdx++) { + name.append(parameterTypes[pIdx].getName()); + if ((pIdx + 1) < parameterTypes.length) { + name.append(","); + } + } + name.append(")"); + return name.toString(); + } + + private CacheDefaults findDefaults(final Class targetType, final Method method) { + if (Proxy.isProxyClass(targetType)) // target doesnt hold annotations + { + final Class api = method.getDeclaringClass(); + for (final Class type : targetType.getInterfaces()) { + if (!api.isAssignableFrom(type)) { + continue; + } + return extractDefaults(type); + } + } + return extractDefaults(targetType); + } + + private CacheDefaults extractDefaults(final Class type) { + CacheDefaults annotation = null; + Class clazz = type; + while (clazz != null && clazz != Object.class) { + annotation = clazz.getAnnotation(CacheDefaults.class); + if (annotation != null) { + break; + } + clazz = clazz.getSuperclass(); + } + return annotation; + } + + public boolean isIncluded(final Class aClass, final Class[] in, final Class[] out) { + if (in.length == 0 && out.length == 0) { + return false; + } + for (final Class potentialIn : in) { + if (potentialIn.isAssignableFrom(aClass)) { + for (final Class potentialOut : out) { + if (potentialOut.isAssignableFrom(aClass)) { + return false; + } + } + return true; + } + } + return false; + } + + private CacheKeyGenerator cacheKeyGeneratorFor(final CacheDefaults defaults, + final Class cacheKeyGenerator) { + if (!CacheKeyGenerator.class.equals(cacheKeyGenerator)) { + return instance(cacheKeyGenerator); + } + if (defaults != null) { + final Class defaultCacheKeyGenerator = defaults.cacheKeyGenerator(); + if (!CacheKeyGenerator.class.equals(defaultCacheKeyGenerator)) { + return instance(defaultCacheKeyGenerator); + } + } + return defaultCacheKeyGenerator; + } + + private CacheResolverFactory cacheResolverFactoryFor(final CacheDefaults defaults, + final Class cacheResolverFactory) { + if (!CacheResolverFactory.class.equals(cacheResolverFactory)) { + return instance(cacheResolverFactory); + } + if (defaults != null) { + final Class defaultCacheResolverFactory = defaults.cacheResolverFactory(); + if (!CacheResolverFactory.class.equals(defaultCacheResolverFactory)) { + return instance(defaultCacheResolverFactory); + } + } + return defaultCacheResolverFactory(); + } + + private T instance(final Class type) { + final Set> beans = beanManager.getBeans(type); + if (beans.isEmpty()) { + if (CacheKeyGenerator.class == type) { + return (T) defaultCacheKeyGenerator; + } + if (CacheResolverFactory.class == type) { + return (T) defaultCacheResolverFactory(); + } + return null; + } + final Bean bean = beanManager.resolve(beans); + final CreationalContext context = beanManager.createCreationalContext(bean); + final Class scope = bean.getScope(); + final boolean normalScope = beanManager.isNormalScope(scope); + try { + final Object reference = beanManager.getReference(bean, bean.getBeanClass(), context); + if (!normalScope) { + toRelease.add(context); + } + return (T) reference; + } finally { + if (normalScope) { // TODO: release at the right moment, @PreDestroy? question is: do we assume it is thread safe? + context.release(); + } + } + } + + private CacheResolverFactoryImpl defaultCacheResolverFactory() { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + synchronized (this) { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + defaultCacheResolverFactory = new CacheResolverFactoryImpl(); + } + return defaultCacheResolverFactory; + } + + private Integer[] keyParameterIndexes(final Method method) { + final List keys = new LinkedList(); + final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + + // first check if keys are specified explicitely + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheKey.class)) { + keys.add(i); + break; + } + } + } + + // if not then use all parameters but value ones + if (keys.isEmpty()) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + boolean value = false; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheValue.class)) { + value = true; + break; + } + } + if (!value) { + keys.add(i); + } + } + } + return keys.toArray(new Integer[keys.size()]); + } + + private static final class MethodKey { + + private final Class base; + + private final Method delegate; + + private final int hash; + + private MethodKey(final Class base, final Method delegate) { + this.base = base; // we need a class to ensure inheritance don't fall in the same key + this.delegate = delegate; + this.hash = 31 * delegate.hashCode() + (base == null ? 0 : base.hashCode()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MethodKey classKey = MethodKey.class.cast(o); + return delegate.equals(classKey.delegate) + && ((base == null && classKey.base == null) || (base != null && base.equals(classKey.base))); + } + + @Override + public int hashCode() { + return hash; + } + } + + // TODO: split it in 5? + public static class MethodMeta { + + private final Class[] parameterTypes; + + private final List> parameterAnnotations; + + private final Set annotations; + + private final Integer[] keysIndices; + + private final Integer valueIndex; + + private final String cacheResultCacheName; + + private final CacheResolverFactory cacheResultResolverFactory; + + private final CacheKeyGenerator cacheResultKeyGenerator; + + private final CacheResult cacheResult; + + private final String cachePutCacheName; + + private final CacheResolverFactory cachePutResolverFactory; + + private final CacheKeyGenerator cachePutKeyGenerator; + + private final boolean cachePutAfter; + + private final CachePut cachePut; + + private final String cacheRemoveCacheName; + + private final CacheResolverFactory cacheRemoveResolverFactory; + + private final CacheKeyGenerator cacheRemoveKeyGenerator; + + private final boolean cacheRemoveAfter; + + private final CacheRemove cacheRemove; + + private final String cacheRemoveAllCacheName; + + private final CacheResolverFactory cacheRemoveAllResolverFactory; + + private final CacheRemoveAll cacheRemoveAll; + + private final boolean completionStage; + + public MethodMeta(Class[] parameterTypes, List> parameterAnnotations, Set annotations, + Integer[] keysIndices, Integer valueIndex, String cacheResultCacheName, + CacheResolverFactory cacheResultResolverFactory, CacheKeyGenerator cacheResultKeyGenerator, + CacheResult cacheResult, String cachePutCacheName, CacheResolverFactory cachePutResolverFactory, + CacheKeyGenerator cachePutKeyGenerator, boolean cachePutAfter, CachePut cachePut, String cacheRemoveCacheName, + CacheResolverFactory cacheRemoveResolverFactory, CacheKeyGenerator cacheRemoveKeyGenerator, + boolean cacheRemoveAfter, CacheRemove cacheRemove, String cacheRemoveAllCacheName, + CacheResolverFactory cacheRemoveAllResolverFactory, CacheRemoveAll cacheRemoveAll, + boolean completionStage) { + this.parameterTypes = parameterTypes; + this.parameterAnnotations = parameterAnnotations; + this.annotations = annotations; + this.keysIndices = keysIndices; + this.valueIndex = valueIndex; + this.cacheResultCacheName = cacheResultCacheName; + this.cacheResultResolverFactory = cacheResultResolverFactory; + this.cacheResultKeyGenerator = cacheResultKeyGenerator; + this.cacheResult = cacheResult; + this.cachePutCacheName = cachePutCacheName; + this.cachePutResolverFactory = cachePutResolverFactory; + this.cachePutKeyGenerator = cachePutKeyGenerator; + this.cachePutAfter = cachePutAfter; + this.cachePut = cachePut; + this.cacheRemoveCacheName = cacheRemoveCacheName; + this.cacheRemoveResolverFactory = cacheRemoveResolverFactory; + this.cacheRemoveKeyGenerator = cacheRemoveKeyGenerator; + this.cacheRemoveAfter = cacheRemoveAfter; + this.cacheRemove = cacheRemove; + this.cacheRemoveAllCacheName = cacheRemoveAllCacheName; + this.cacheRemoveAllResolverFactory = cacheRemoveAllResolverFactory; + this.cacheRemoveAll = cacheRemoveAll; + this.completionStage = completionStage; + } + + public boolean isCompletionStage() { + return completionStage; + } + + public boolean isCacheRemoveAfter() { + return cacheRemoveAfter; + } + + public boolean isCachePutAfter() { + return cachePutAfter; + } + + public Class[] getParameterTypes() { + return parameterTypes; + } + + public List> getParameterAnnotations() { + return parameterAnnotations; + } + + public String getCacheResultCacheName() { + return cacheResultCacheName; + } + + public CacheResolverFactory getCacheResultResolverFactory() { + return cacheResultResolverFactory; + } + + public CacheKeyGenerator getCacheResultKeyGenerator() { + return cacheResultKeyGenerator; + } + + public CacheResult getCacheResult() { + return cacheResult; + } + + public Set getAnnotations() { + return annotations; + } + + public Integer[] getKeysIndices() { + return keysIndices; + } + + public Integer getValueIndex() { + return valueIndex; + } + + public String getCachePutCacheName() { + return cachePutCacheName; + } + + public CacheResolverFactory getCachePutResolverFactory() { + return cachePutResolverFactory; + } + + public CacheKeyGenerator getCachePutKeyGenerator() { + return cachePutKeyGenerator; + } + + public CachePut getCachePut() { + return cachePut; + } + + public String getCacheRemoveCacheName() { + return cacheRemoveCacheName; + } + + public CacheResolverFactory getCacheRemoveResolverFactory() { + return cacheRemoveResolverFactory; + } + + public CacheKeyGenerator getCacheRemoveKeyGenerator() { + return cacheRemoveKeyGenerator; + } + + public CacheRemove getCacheRemove() { + return cacheRemove; + } + + public String getCacheRemoveAllCacheName() { + return cacheRemoveAllCacheName; + } + + public CacheResolverFactory getCacheRemoveAllResolverFactory() { + return cacheRemoveAllResolverFactory; + } + + public CacheRemoveAll getCacheRemoveAll() { + return cacheRemoveAll; + } + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_126/metadata.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_126/metadata.json new file mode 100644 index 000000000..55623e6cb --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_126/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CDIJCacheHelper_126", + "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/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 125, + "npe_method": "createMeta", + "deref_field": "cacheResult", + "npe_class": "CDIJCacheHelper", + "repo": "geronimo-jcache-simple", + "bug_id": "CDIJCacheHelper_126" + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_126/npe.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_126/npe.json new file mode 100644 index 000000000..0e0503617 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_126/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 125, + "npe_method": "createMeta", + "deref_field": "cacheResult", + "npe_class": "CDIJCacheHelper" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_128/Dockerfile b/Java/geronimo-jcache-simple-CDIJCacheHelper_128/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_128/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CDIJCacheHelper_128/buggy.java b/Java/geronimo-jcache-simple-CDIJCacheHelper_128/buggy.java new file mode 100644 index 000000000..50d3462cc --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_128/buggy.java @@ -0,0 +1,535 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; + +import javax.annotation.PreDestroy; +import javax.cache.annotation.CacheDefaults; +import javax.cache.annotation.CacheKey; +import javax.cache.annotation.CacheKeyGenerator; +import javax.cache.annotation.CachePut; +import javax.cache.annotation.CacheRemove; +import javax.cache.annotation.CacheRemoveAll; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.CacheValue; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; + +@ApplicationScoped +public class CDIJCacheHelper { + + private static final Logger LOGGER = Logger.getLogger(CDIJCacheHelper.class.getName()); + + private static final boolean CLOSE_CACHE = !Boolean.getBoolean("org.apache.geronimo.jcache.simple.cdi.skip-close"); + + private final CacheKeyGeneratorImpl defaultCacheKeyGenerator = new CacheKeyGeneratorImpl(); + + private final Collection> toRelease = new ArrayList>(); + + private final ConcurrentMap methods = new ConcurrentHashMap(); + + private volatile CacheResolverFactoryImpl defaultCacheResolverFactory = null; // lazy to not create any cache if not needed + + @Inject + private BeanManager beanManager; + + @PreDestroy + private void release() { + if (CLOSE_CACHE && defaultCacheResolverFactory != null) { + defaultCacheResolverFactory.release(); + } + for (final CreationalContext cc : toRelease) { + try { + cc.release(); + } catch (final RuntimeException re) { + LOGGER.warning(re.getMessage()); + } + } + } + + public MethodMeta findMeta(final InvocationContext ic) { + final Method mtd = ic.getMethod(); + final Class refType = findKeyType(ic.getTarget()); + final MethodKey key = new MethodKey(refType, mtd); + MethodMeta methodMeta = methods.get(key); + if (methodMeta == null) { + synchronized (this) { + methodMeta = methods.get(key); + if (methodMeta == null) { + methodMeta = createMeta(ic); + methods.put(key, methodMeta); + } + } + } + return methodMeta; + } + + private Class findKeyType(final Object target) { + if (null == target) { + return null; + } + return target.getClass(); + } + + // it is unlikely we have all annotations but for now we have a single meta model +// it is unlikely we have all annotations but for now we have a single meta model +private org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta createMeta(final javax.interceptor.InvocationContext ic) { + final javax.cache.annotation.CacheDefaults defaults = findDefaults(ic.getTarget() == null ? null : ic.getTarget().getClass(), ic.getMethod()); + final java.lang.Class[] parameterTypes = ic.getMethod().getParameterTypes(); + final java.lang.annotation.Annotation[][] parameterAnnotations = ic.getMethod().getParameterAnnotations(); + final java.util.List> annotations = new java.util.ArrayList>(); + for (final java.lang.annotation.Annotation[] parameterAnnotation : parameterAnnotations) { + final java.util.Set set = new java.util.HashSet(parameterAnnotation.length); + set.addAll(java.util.Arrays.asList(parameterAnnotation)); + annotations.add(set); + } + final java.util.Set mtdAnnotations = new java.util.HashSet(); + mtdAnnotations.addAll(java.util.Arrays.asList(ic.getMethod().getAnnotations())); + final javax.cache.annotation.CacheResult cacheResult = ic.getMethod().getAnnotation(javax.cache.annotation.CacheResult.class); + final java.lang.String cacheResultCacheResultName = (/* NPEX_NULL_EXP */ + cacheResult == null) ? null : defaultName(ic.getMethod(), defaults, cacheResult.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheResultCacheResolverFactory = cacheResolverFactoryFor(defaults, cacheResult.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheResultCacheKeyGenerator = (cacheResult == null) ? null : cacheKeyGeneratorFor(defaults, cacheResult.cacheKeyGenerator()); + final javax.cache.annotation.CachePut cachePut = ic.getMethod().getAnnotation(javax.cache.annotation.CachePut.class); + final java.lang.String cachePutCachePutName = (cachePut == null) ? null : defaultName(ic.getMethod(), defaults, cachePut.cacheName()); + final javax.cache.annotation.CacheResolverFactory cachePutCacheResolverFactory = (cachePut == null) ? null : cacheResolverFactoryFor(defaults, cachePut.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cachePutCacheKeyGenerator = (cachePut == null) ? null : cacheKeyGeneratorFor(defaults, cachePut.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemove cacheRemove = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemove.class); + final java.lang.String cacheRemoveCacheRemoveName = (cacheRemove == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemove.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveCacheResolverFactory = (cacheRemove == null) ? null : cacheResolverFactoryFor(defaults, cacheRemove.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheRemoveCacheKeyGenerator = (cacheRemove == null) ? null : cacheKeyGeneratorFor(defaults, cacheRemove.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemoveAll cacheRemoveAll = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemoveAll.class); + final java.lang.String cacheRemoveAllCacheRemoveAllName = (cacheRemoveAll == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemoveAll.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveAllCacheResolverFactory = (cacheRemoveAll == null) ? null : cacheResolverFactoryFor(defaults, cacheRemoveAll.cacheResolverFactory()); + return new org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta(parameterTypes, annotations, mtdAnnotations, keyParameterIndexes(ic.getMethod()), getValueParameter(annotations), cacheResultCacheResultName, cacheResultCacheResolverFactory, cacheResultCacheKeyGenerator, cacheResult, cachePutCachePutName, cachePutCacheResolverFactory, cachePutCacheKeyGenerator, (cachePut != null) && cachePut.afterInvocation(), cachePut, cacheRemoveCacheRemoveName, cacheRemoveCacheResolverFactory, cacheRemoveCacheKeyGenerator, (cacheRemove != null) && cacheRemove.afterInvocation(), cacheRemove, cacheRemoveAllCacheRemoveAllName, cacheRemoveAllCacheResolverFactory, cacheRemoveAll, java.util.concurrent.CompletionStage.class.isAssignableFrom(ic.getMethod().getReturnType())); +} + + private Integer getValueParameter(final List> annotations) { + int idx = 0; + for (final Set set : annotations) { + for (final Annotation a : set) { + if (a.annotationType() == CacheValue.class) { + return idx; + } + } + } + return -1; + } + + private String defaultName(final Method method, final CacheDefaults defaults, final String cacheName) { + if (!cacheName.isEmpty()) { + return cacheName; + } + if (defaults != null) { + final String name = defaults.cacheName(); + if (!name.isEmpty()) { + return name; + } + } + + final StringBuilder name = new StringBuilder(method.getDeclaringClass().getName()); + name.append("."); + name.append(method.getName()); + name.append("("); + final Class[] parameterTypes = method.getParameterTypes(); + for (int pIdx = 0; pIdx < parameterTypes.length; pIdx++) { + name.append(parameterTypes[pIdx].getName()); + if ((pIdx + 1) < parameterTypes.length) { + name.append(","); + } + } + name.append(")"); + return name.toString(); + } + + private CacheDefaults findDefaults(final Class targetType, final Method method) { + if (Proxy.isProxyClass(targetType)) // target doesnt hold annotations + { + final Class api = method.getDeclaringClass(); + for (final Class type : targetType.getInterfaces()) { + if (!api.isAssignableFrom(type)) { + continue; + } + return extractDefaults(type); + } + } + return extractDefaults(targetType); + } + + private CacheDefaults extractDefaults(final Class type) { + CacheDefaults annotation = null; + Class clazz = type; + while (clazz != null && clazz != Object.class) { + annotation = clazz.getAnnotation(CacheDefaults.class); + if (annotation != null) { + break; + } + clazz = clazz.getSuperclass(); + } + return annotation; + } + + public boolean isIncluded(final Class aClass, final Class[] in, final Class[] out) { + if (in.length == 0 && out.length == 0) { + return false; + } + for (final Class potentialIn : in) { + if (potentialIn.isAssignableFrom(aClass)) { + for (final Class potentialOut : out) { + if (potentialOut.isAssignableFrom(aClass)) { + return false; + } + } + return true; + } + } + return false; + } + + private CacheKeyGenerator cacheKeyGeneratorFor(final CacheDefaults defaults, + final Class cacheKeyGenerator) { + if (!CacheKeyGenerator.class.equals(cacheKeyGenerator)) { + return instance(cacheKeyGenerator); + } + if (defaults != null) { + final Class defaultCacheKeyGenerator = defaults.cacheKeyGenerator(); + if (!CacheKeyGenerator.class.equals(defaultCacheKeyGenerator)) { + return instance(defaultCacheKeyGenerator); + } + } + return defaultCacheKeyGenerator; + } + + private CacheResolverFactory cacheResolverFactoryFor(final CacheDefaults defaults, + final Class cacheResolverFactory) { + if (!CacheResolverFactory.class.equals(cacheResolverFactory)) { + return instance(cacheResolverFactory); + } + if (defaults != null) { + final Class defaultCacheResolverFactory = defaults.cacheResolverFactory(); + if (!CacheResolverFactory.class.equals(defaultCacheResolverFactory)) { + return instance(defaultCacheResolverFactory); + } + } + return defaultCacheResolverFactory(); + } + + private T instance(final Class type) { + final Set> beans = beanManager.getBeans(type); + if (beans.isEmpty()) { + if (CacheKeyGenerator.class == type) { + return (T) defaultCacheKeyGenerator; + } + if (CacheResolverFactory.class == type) { + return (T) defaultCacheResolverFactory(); + } + return null; + } + final Bean bean = beanManager.resolve(beans); + final CreationalContext context = beanManager.createCreationalContext(bean); + final Class scope = bean.getScope(); + final boolean normalScope = beanManager.isNormalScope(scope); + try { + final Object reference = beanManager.getReference(bean, bean.getBeanClass(), context); + if (!normalScope) { + toRelease.add(context); + } + return (T) reference; + } finally { + if (normalScope) { // TODO: release at the right moment, @PreDestroy? question is: do we assume it is thread safe? + context.release(); + } + } + } + + private CacheResolverFactoryImpl defaultCacheResolverFactory() { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + synchronized (this) { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + defaultCacheResolverFactory = new CacheResolverFactoryImpl(); + } + return defaultCacheResolverFactory; + } + + private Integer[] keyParameterIndexes(final Method method) { + final List keys = new LinkedList(); + final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + + // first check if keys are specified explicitely + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheKey.class)) { + keys.add(i); + break; + } + } + } + + // if not then use all parameters but value ones + if (keys.isEmpty()) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + boolean value = false; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheValue.class)) { + value = true; + break; + } + } + if (!value) { + keys.add(i); + } + } + } + return keys.toArray(new Integer[keys.size()]); + } + + private static final class MethodKey { + + private final Class base; + + private final Method delegate; + + private final int hash; + + private MethodKey(final Class base, final Method delegate) { + this.base = base; // we need a class to ensure inheritance don't fall in the same key + this.delegate = delegate; + this.hash = 31 * delegate.hashCode() + (base == null ? 0 : base.hashCode()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MethodKey classKey = MethodKey.class.cast(o); + return delegate.equals(classKey.delegate) + && ((base == null && classKey.base == null) || (base != null && base.equals(classKey.base))); + } + + @Override + public int hashCode() { + return hash; + } + } + + // TODO: split it in 5? + public static class MethodMeta { + + private final Class[] parameterTypes; + + private final List> parameterAnnotations; + + private final Set annotations; + + private final Integer[] keysIndices; + + private final Integer valueIndex; + + private final String cacheResultCacheName; + + private final CacheResolverFactory cacheResultResolverFactory; + + private final CacheKeyGenerator cacheResultKeyGenerator; + + private final CacheResult cacheResult; + + private final String cachePutCacheName; + + private final CacheResolverFactory cachePutResolverFactory; + + private final CacheKeyGenerator cachePutKeyGenerator; + + private final boolean cachePutAfter; + + private final CachePut cachePut; + + private final String cacheRemoveCacheName; + + private final CacheResolverFactory cacheRemoveResolverFactory; + + private final CacheKeyGenerator cacheRemoveKeyGenerator; + + private final boolean cacheRemoveAfter; + + private final CacheRemove cacheRemove; + + private final String cacheRemoveAllCacheName; + + private final CacheResolverFactory cacheRemoveAllResolverFactory; + + private final CacheRemoveAll cacheRemoveAll; + + private final boolean completionStage; + + public MethodMeta(Class[] parameterTypes, List> parameterAnnotations, Set annotations, + Integer[] keysIndices, Integer valueIndex, String cacheResultCacheName, + CacheResolverFactory cacheResultResolverFactory, CacheKeyGenerator cacheResultKeyGenerator, + CacheResult cacheResult, String cachePutCacheName, CacheResolverFactory cachePutResolverFactory, + CacheKeyGenerator cachePutKeyGenerator, boolean cachePutAfter, CachePut cachePut, String cacheRemoveCacheName, + CacheResolverFactory cacheRemoveResolverFactory, CacheKeyGenerator cacheRemoveKeyGenerator, + boolean cacheRemoveAfter, CacheRemove cacheRemove, String cacheRemoveAllCacheName, + CacheResolverFactory cacheRemoveAllResolverFactory, CacheRemoveAll cacheRemoveAll, + boolean completionStage) { + this.parameterTypes = parameterTypes; + this.parameterAnnotations = parameterAnnotations; + this.annotations = annotations; + this.keysIndices = keysIndices; + this.valueIndex = valueIndex; + this.cacheResultCacheName = cacheResultCacheName; + this.cacheResultResolverFactory = cacheResultResolverFactory; + this.cacheResultKeyGenerator = cacheResultKeyGenerator; + this.cacheResult = cacheResult; + this.cachePutCacheName = cachePutCacheName; + this.cachePutResolverFactory = cachePutResolverFactory; + this.cachePutKeyGenerator = cachePutKeyGenerator; + this.cachePutAfter = cachePutAfter; + this.cachePut = cachePut; + this.cacheRemoveCacheName = cacheRemoveCacheName; + this.cacheRemoveResolverFactory = cacheRemoveResolverFactory; + this.cacheRemoveKeyGenerator = cacheRemoveKeyGenerator; + this.cacheRemoveAfter = cacheRemoveAfter; + this.cacheRemove = cacheRemove; + this.cacheRemoveAllCacheName = cacheRemoveAllCacheName; + this.cacheRemoveAllResolverFactory = cacheRemoveAllResolverFactory; + this.cacheRemoveAll = cacheRemoveAll; + this.completionStage = completionStage; + } + + public boolean isCompletionStage() { + return completionStage; + } + + public boolean isCacheRemoveAfter() { + return cacheRemoveAfter; + } + + public boolean isCachePutAfter() { + return cachePutAfter; + } + + public Class[] getParameterTypes() { + return parameterTypes; + } + + public List> getParameterAnnotations() { + return parameterAnnotations; + } + + public String getCacheResultCacheName() { + return cacheResultCacheName; + } + + public CacheResolverFactory getCacheResultResolverFactory() { + return cacheResultResolverFactory; + } + + public CacheKeyGenerator getCacheResultKeyGenerator() { + return cacheResultKeyGenerator; + } + + public CacheResult getCacheResult() { + return cacheResult; + } + + public Set getAnnotations() { + return annotations; + } + + public Integer[] getKeysIndices() { + return keysIndices; + } + + public Integer getValueIndex() { + return valueIndex; + } + + public String getCachePutCacheName() { + return cachePutCacheName; + } + + public CacheResolverFactory getCachePutResolverFactory() { + return cachePutResolverFactory; + } + + public CacheKeyGenerator getCachePutKeyGenerator() { + return cachePutKeyGenerator; + } + + public CachePut getCachePut() { + return cachePut; + } + + public String getCacheRemoveCacheName() { + return cacheRemoveCacheName; + } + + public CacheResolverFactory getCacheRemoveResolverFactory() { + return cacheRemoveResolverFactory; + } + + public CacheKeyGenerator getCacheRemoveKeyGenerator() { + return cacheRemoveKeyGenerator; + } + + public CacheRemove getCacheRemove() { + return cacheRemove; + } + + public String getCacheRemoveAllCacheName() { + return cacheRemoveAllCacheName; + } + + public CacheResolverFactory getCacheRemoveAllResolverFactory() { + return cacheRemoveAllResolverFactory; + } + + public CacheRemoveAll getCacheRemoveAll() { + return cacheRemoveAll; + } + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_128/metadata.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_128/metadata.json new file mode 100644 index 000000000..0f925ee9b --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_128/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CDIJCacheHelper_128", + "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/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 125, + "npe_method": "createMeta", + "deref_field": "cacheResult", + "npe_class": "CDIJCacheHelper", + "repo": "geronimo-jcache-simple", + "bug_id": "CDIJCacheHelper_128" + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_128/npe.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_128/npe.json new file mode 100644 index 000000000..0e0503617 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_128/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 125, + "npe_method": "createMeta", + "deref_field": "cacheResult", + "npe_class": "CDIJCacheHelper" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_130/Dockerfile b/Java/geronimo-jcache-simple-CDIJCacheHelper_130/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_130/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CDIJCacheHelper_130/buggy.java b/Java/geronimo-jcache-simple-CDIJCacheHelper_130/buggy.java new file mode 100644 index 000000000..4930d1d0c --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_130/buggy.java @@ -0,0 +1,535 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; + +import javax.annotation.PreDestroy; +import javax.cache.annotation.CacheDefaults; +import javax.cache.annotation.CacheKey; +import javax.cache.annotation.CacheKeyGenerator; +import javax.cache.annotation.CachePut; +import javax.cache.annotation.CacheRemove; +import javax.cache.annotation.CacheRemoveAll; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.CacheValue; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; + +@ApplicationScoped +public class CDIJCacheHelper { + + private static final Logger LOGGER = Logger.getLogger(CDIJCacheHelper.class.getName()); + + private static final boolean CLOSE_CACHE = !Boolean.getBoolean("org.apache.geronimo.jcache.simple.cdi.skip-close"); + + private final CacheKeyGeneratorImpl defaultCacheKeyGenerator = new CacheKeyGeneratorImpl(); + + private final Collection> toRelease = new ArrayList>(); + + private final ConcurrentMap methods = new ConcurrentHashMap(); + + private volatile CacheResolverFactoryImpl defaultCacheResolverFactory = null; // lazy to not create any cache if not needed + + @Inject + private BeanManager beanManager; + + @PreDestroy + private void release() { + if (CLOSE_CACHE && defaultCacheResolverFactory != null) { + defaultCacheResolverFactory.release(); + } + for (final CreationalContext cc : toRelease) { + try { + cc.release(); + } catch (final RuntimeException re) { + LOGGER.warning(re.getMessage()); + } + } + } + + public MethodMeta findMeta(final InvocationContext ic) { + final Method mtd = ic.getMethod(); + final Class refType = findKeyType(ic.getTarget()); + final MethodKey key = new MethodKey(refType, mtd); + MethodMeta methodMeta = methods.get(key); + if (methodMeta == null) { + synchronized (this) { + methodMeta = methods.get(key); + if (methodMeta == null) { + methodMeta = createMeta(ic); + methods.put(key, methodMeta); + } + } + } + return methodMeta; + } + + private Class findKeyType(final Object target) { + if (null == target) { + return null; + } + return target.getClass(); + } + + // it is unlikely we have all annotations but for now we have a single meta model +// it is unlikely we have all annotations but for now we have a single meta model +private org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta createMeta(final javax.interceptor.InvocationContext ic) { + final javax.cache.annotation.CacheDefaults defaults = findDefaults(ic.getTarget() == null ? null : ic.getTarget().getClass(), ic.getMethod()); + final java.lang.Class[] parameterTypes = ic.getMethod().getParameterTypes(); + final java.lang.annotation.Annotation[][] parameterAnnotations = ic.getMethod().getParameterAnnotations(); + final java.util.List> annotations = new java.util.ArrayList>(); + for (final java.lang.annotation.Annotation[] parameterAnnotation : parameterAnnotations) { + final java.util.Set set = new java.util.HashSet(parameterAnnotation.length); + set.addAll(java.util.Arrays.asList(parameterAnnotation)); + annotations.add(set); + } + final java.util.Set mtdAnnotations = new java.util.HashSet(); + mtdAnnotations.addAll(java.util.Arrays.asList(ic.getMethod().getAnnotations())); + final javax.cache.annotation.CacheResult cacheResult = ic.getMethod().getAnnotation(javax.cache.annotation.CacheResult.class); + final java.lang.String cacheResultCacheResultName = (/* NPEX_NULL_EXP */ + cacheResult == null) ? null : defaultName(ic.getMethod(), defaults, cacheResult.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheResultCacheResolverFactory = (cacheResult == null) ? null : cacheResolverFactoryFor(defaults, cacheResult.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheResultCacheKeyGenerator = cacheKeyGeneratorFor(defaults, cacheResult.cacheKeyGenerator()); + final javax.cache.annotation.CachePut cachePut = ic.getMethod().getAnnotation(javax.cache.annotation.CachePut.class); + final java.lang.String cachePutCachePutName = (cachePut == null) ? null : defaultName(ic.getMethod(), defaults, cachePut.cacheName()); + final javax.cache.annotation.CacheResolverFactory cachePutCacheResolverFactory = (cachePut == null) ? null : cacheResolverFactoryFor(defaults, cachePut.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cachePutCacheKeyGenerator = (cachePut == null) ? null : cacheKeyGeneratorFor(defaults, cachePut.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemove cacheRemove = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemove.class); + final java.lang.String cacheRemoveCacheRemoveName = (cacheRemove == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemove.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveCacheResolverFactory = (cacheRemove == null) ? null : cacheResolverFactoryFor(defaults, cacheRemove.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheRemoveCacheKeyGenerator = (cacheRemove == null) ? null : cacheKeyGeneratorFor(defaults, cacheRemove.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemoveAll cacheRemoveAll = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemoveAll.class); + final java.lang.String cacheRemoveAllCacheRemoveAllName = (cacheRemoveAll == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemoveAll.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveAllCacheResolverFactory = (cacheRemoveAll == null) ? null : cacheResolverFactoryFor(defaults, cacheRemoveAll.cacheResolverFactory()); + return new org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta(parameterTypes, annotations, mtdAnnotations, keyParameterIndexes(ic.getMethod()), getValueParameter(annotations), cacheResultCacheResultName, cacheResultCacheResolverFactory, cacheResultCacheKeyGenerator, cacheResult, cachePutCachePutName, cachePutCacheResolverFactory, cachePutCacheKeyGenerator, (cachePut != null) && cachePut.afterInvocation(), cachePut, cacheRemoveCacheRemoveName, cacheRemoveCacheResolverFactory, cacheRemoveCacheKeyGenerator, (cacheRemove != null) && cacheRemove.afterInvocation(), cacheRemove, cacheRemoveAllCacheRemoveAllName, cacheRemoveAllCacheResolverFactory, cacheRemoveAll, java.util.concurrent.CompletionStage.class.isAssignableFrom(ic.getMethod().getReturnType())); +} + + private Integer getValueParameter(final List> annotations) { + int idx = 0; + for (final Set set : annotations) { + for (final Annotation a : set) { + if (a.annotationType() == CacheValue.class) { + return idx; + } + } + } + return -1; + } + + private String defaultName(final Method method, final CacheDefaults defaults, final String cacheName) { + if (!cacheName.isEmpty()) { + return cacheName; + } + if (defaults != null) { + final String name = defaults.cacheName(); + if (!name.isEmpty()) { + return name; + } + } + + final StringBuilder name = new StringBuilder(method.getDeclaringClass().getName()); + name.append("."); + name.append(method.getName()); + name.append("("); + final Class[] parameterTypes = method.getParameterTypes(); + for (int pIdx = 0; pIdx < parameterTypes.length; pIdx++) { + name.append(parameterTypes[pIdx].getName()); + if ((pIdx + 1) < parameterTypes.length) { + name.append(","); + } + } + name.append(")"); + return name.toString(); + } + + private CacheDefaults findDefaults(final Class targetType, final Method method) { + if (Proxy.isProxyClass(targetType)) // target doesnt hold annotations + { + final Class api = method.getDeclaringClass(); + for (final Class type : targetType.getInterfaces()) { + if (!api.isAssignableFrom(type)) { + continue; + } + return extractDefaults(type); + } + } + return extractDefaults(targetType); + } + + private CacheDefaults extractDefaults(final Class type) { + CacheDefaults annotation = null; + Class clazz = type; + while (clazz != null && clazz != Object.class) { + annotation = clazz.getAnnotation(CacheDefaults.class); + if (annotation != null) { + break; + } + clazz = clazz.getSuperclass(); + } + return annotation; + } + + public boolean isIncluded(final Class aClass, final Class[] in, final Class[] out) { + if (in.length == 0 && out.length == 0) { + return false; + } + for (final Class potentialIn : in) { + if (potentialIn.isAssignableFrom(aClass)) { + for (final Class potentialOut : out) { + if (potentialOut.isAssignableFrom(aClass)) { + return false; + } + } + return true; + } + } + return false; + } + + private CacheKeyGenerator cacheKeyGeneratorFor(final CacheDefaults defaults, + final Class cacheKeyGenerator) { + if (!CacheKeyGenerator.class.equals(cacheKeyGenerator)) { + return instance(cacheKeyGenerator); + } + if (defaults != null) { + final Class defaultCacheKeyGenerator = defaults.cacheKeyGenerator(); + if (!CacheKeyGenerator.class.equals(defaultCacheKeyGenerator)) { + return instance(defaultCacheKeyGenerator); + } + } + return defaultCacheKeyGenerator; + } + + private CacheResolverFactory cacheResolverFactoryFor(final CacheDefaults defaults, + final Class cacheResolverFactory) { + if (!CacheResolverFactory.class.equals(cacheResolverFactory)) { + return instance(cacheResolverFactory); + } + if (defaults != null) { + final Class defaultCacheResolverFactory = defaults.cacheResolverFactory(); + if (!CacheResolverFactory.class.equals(defaultCacheResolverFactory)) { + return instance(defaultCacheResolverFactory); + } + } + return defaultCacheResolverFactory(); + } + + private T instance(final Class type) { + final Set> beans = beanManager.getBeans(type); + if (beans.isEmpty()) { + if (CacheKeyGenerator.class == type) { + return (T) defaultCacheKeyGenerator; + } + if (CacheResolverFactory.class == type) { + return (T) defaultCacheResolverFactory(); + } + return null; + } + final Bean bean = beanManager.resolve(beans); + final CreationalContext context = beanManager.createCreationalContext(bean); + final Class scope = bean.getScope(); + final boolean normalScope = beanManager.isNormalScope(scope); + try { + final Object reference = beanManager.getReference(bean, bean.getBeanClass(), context); + if (!normalScope) { + toRelease.add(context); + } + return (T) reference; + } finally { + if (normalScope) { // TODO: release at the right moment, @PreDestroy? question is: do we assume it is thread safe? + context.release(); + } + } + } + + private CacheResolverFactoryImpl defaultCacheResolverFactory() { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + synchronized (this) { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + defaultCacheResolverFactory = new CacheResolverFactoryImpl(); + } + return defaultCacheResolverFactory; + } + + private Integer[] keyParameterIndexes(final Method method) { + final List keys = new LinkedList(); + final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + + // first check if keys are specified explicitely + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheKey.class)) { + keys.add(i); + break; + } + } + } + + // if not then use all parameters but value ones + if (keys.isEmpty()) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + boolean value = false; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheValue.class)) { + value = true; + break; + } + } + if (!value) { + keys.add(i); + } + } + } + return keys.toArray(new Integer[keys.size()]); + } + + private static final class MethodKey { + + private final Class base; + + private final Method delegate; + + private final int hash; + + private MethodKey(final Class base, final Method delegate) { + this.base = base; // we need a class to ensure inheritance don't fall in the same key + this.delegate = delegate; + this.hash = 31 * delegate.hashCode() + (base == null ? 0 : base.hashCode()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MethodKey classKey = MethodKey.class.cast(o); + return delegate.equals(classKey.delegate) + && ((base == null && classKey.base == null) || (base != null && base.equals(classKey.base))); + } + + @Override + public int hashCode() { + return hash; + } + } + + // TODO: split it in 5? + public static class MethodMeta { + + private final Class[] parameterTypes; + + private final List> parameterAnnotations; + + private final Set annotations; + + private final Integer[] keysIndices; + + private final Integer valueIndex; + + private final String cacheResultCacheName; + + private final CacheResolverFactory cacheResultResolverFactory; + + private final CacheKeyGenerator cacheResultKeyGenerator; + + private final CacheResult cacheResult; + + private final String cachePutCacheName; + + private final CacheResolverFactory cachePutResolverFactory; + + private final CacheKeyGenerator cachePutKeyGenerator; + + private final boolean cachePutAfter; + + private final CachePut cachePut; + + private final String cacheRemoveCacheName; + + private final CacheResolverFactory cacheRemoveResolverFactory; + + private final CacheKeyGenerator cacheRemoveKeyGenerator; + + private final boolean cacheRemoveAfter; + + private final CacheRemove cacheRemove; + + private final String cacheRemoveAllCacheName; + + private final CacheResolverFactory cacheRemoveAllResolverFactory; + + private final CacheRemoveAll cacheRemoveAll; + + private final boolean completionStage; + + public MethodMeta(Class[] parameterTypes, List> parameterAnnotations, Set annotations, + Integer[] keysIndices, Integer valueIndex, String cacheResultCacheName, + CacheResolverFactory cacheResultResolverFactory, CacheKeyGenerator cacheResultKeyGenerator, + CacheResult cacheResult, String cachePutCacheName, CacheResolverFactory cachePutResolverFactory, + CacheKeyGenerator cachePutKeyGenerator, boolean cachePutAfter, CachePut cachePut, String cacheRemoveCacheName, + CacheResolverFactory cacheRemoveResolverFactory, CacheKeyGenerator cacheRemoveKeyGenerator, + boolean cacheRemoveAfter, CacheRemove cacheRemove, String cacheRemoveAllCacheName, + CacheResolverFactory cacheRemoveAllResolverFactory, CacheRemoveAll cacheRemoveAll, + boolean completionStage) { + this.parameterTypes = parameterTypes; + this.parameterAnnotations = parameterAnnotations; + this.annotations = annotations; + this.keysIndices = keysIndices; + this.valueIndex = valueIndex; + this.cacheResultCacheName = cacheResultCacheName; + this.cacheResultResolverFactory = cacheResultResolverFactory; + this.cacheResultKeyGenerator = cacheResultKeyGenerator; + this.cacheResult = cacheResult; + this.cachePutCacheName = cachePutCacheName; + this.cachePutResolverFactory = cachePutResolverFactory; + this.cachePutKeyGenerator = cachePutKeyGenerator; + this.cachePutAfter = cachePutAfter; + this.cachePut = cachePut; + this.cacheRemoveCacheName = cacheRemoveCacheName; + this.cacheRemoveResolverFactory = cacheRemoveResolverFactory; + this.cacheRemoveKeyGenerator = cacheRemoveKeyGenerator; + this.cacheRemoveAfter = cacheRemoveAfter; + this.cacheRemove = cacheRemove; + this.cacheRemoveAllCacheName = cacheRemoveAllCacheName; + this.cacheRemoveAllResolverFactory = cacheRemoveAllResolverFactory; + this.cacheRemoveAll = cacheRemoveAll; + this.completionStage = completionStage; + } + + public boolean isCompletionStage() { + return completionStage; + } + + public boolean isCacheRemoveAfter() { + return cacheRemoveAfter; + } + + public boolean isCachePutAfter() { + return cachePutAfter; + } + + public Class[] getParameterTypes() { + return parameterTypes; + } + + public List> getParameterAnnotations() { + return parameterAnnotations; + } + + public String getCacheResultCacheName() { + return cacheResultCacheName; + } + + public CacheResolverFactory getCacheResultResolverFactory() { + return cacheResultResolverFactory; + } + + public CacheKeyGenerator getCacheResultKeyGenerator() { + return cacheResultKeyGenerator; + } + + public CacheResult getCacheResult() { + return cacheResult; + } + + public Set getAnnotations() { + return annotations; + } + + public Integer[] getKeysIndices() { + return keysIndices; + } + + public Integer getValueIndex() { + return valueIndex; + } + + public String getCachePutCacheName() { + return cachePutCacheName; + } + + public CacheResolverFactory getCachePutResolverFactory() { + return cachePutResolverFactory; + } + + public CacheKeyGenerator getCachePutKeyGenerator() { + return cachePutKeyGenerator; + } + + public CachePut getCachePut() { + return cachePut; + } + + public String getCacheRemoveCacheName() { + return cacheRemoveCacheName; + } + + public CacheResolverFactory getCacheRemoveResolverFactory() { + return cacheRemoveResolverFactory; + } + + public CacheKeyGenerator getCacheRemoveKeyGenerator() { + return cacheRemoveKeyGenerator; + } + + public CacheRemove getCacheRemove() { + return cacheRemove; + } + + public String getCacheRemoveAllCacheName() { + return cacheRemoveAllCacheName; + } + + public CacheResolverFactory getCacheRemoveAllResolverFactory() { + return cacheRemoveAllResolverFactory; + } + + public CacheRemoveAll getCacheRemoveAll() { + return cacheRemoveAll; + } + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_130/metadata.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_130/metadata.json new file mode 100644 index 000000000..6892d5310 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_130/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CDIJCacheHelper_130", + "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/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 125, + "npe_method": "createMeta", + "deref_field": "cacheResult", + "npe_class": "CDIJCacheHelper", + "repo": "geronimo-jcache-simple", + "bug_id": "CDIJCacheHelper_130" + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_130/npe.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_130/npe.json new file mode 100644 index 000000000..0e0503617 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_130/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 125, + "npe_method": "createMeta", + "deref_field": "cacheResult", + "npe_class": "CDIJCacheHelper" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_134/Dockerfile b/Java/geronimo-jcache-simple-CDIJCacheHelper_134/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_134/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CDIJCacheHelper_134/buggy.java b/Java/geronimo-jcache-simple-CDIJCacheHelper_134/buggy.java new file mode 100644 index 000000000..3b04a6bb4 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_134/buggy.java @@ -0,0 +1,535 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; + +import javax.annotation.PreDestroy; +import javax.cache.annotation.CacheDefaults; +import javax.cache.annotation.CacheKey; +import javax.cache.annotation.CacheKeyGenerator; +import javax.cache.annotation.CachePut; +import javax.cache.annotation.CacheRemove; +import javax.cache.annotation.CacheRemoveAll; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.CacheValue; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; + +@ApplicationScoped +public class CDIJCacheHelper { + + private static final Logger LOGGER = Logger.getLogger(CDIJCacheHelper.class.getName()); + + private static final boolean CLOSE_CACHE = !Boolean.getBoolean("org.apache.geronimo.jcache.simple.cdi.skip-close"); + + private final CacheKeyGeneratorImpl defaultCacheKeyGenerator = new CacheKeyGeneratorImpl(); + + private final Collection> toRelease = new ArrayList>(); + + private final ConcurrentMap methods = new ConcurrentHashMap(); + + private volatile CacheResolverFactoryImpl defaultCacheResolverFactory = null; // lazy to not create any cache if not needed + + @Inject + private BeanManager beanManager; + + @PreDestroy + private void release() { + if (CLOSE_CACHE && defaultCacheResolverFactory != null) { + defaultCacheResolverFactory.release(); + } + for (final CreationalContext cc : toRelease) { + try { + cc.release(); + } catch (final RuntimeException re) { + LOGGER.warning(re.getMessage()); + } + } + } + + public MethodMeta findMeta(final InvocationContext ic) { + final Method mtd = ic.getMethod(); + final Class refType = findKeyType(ic.getTarget()); + final MethodKey key = new MethodKey(refType, mtd); + MethodMeta methodMeta = methods.get(key); + if (methodMeta == null) { + synchronized (this) { + methodMeta = methods.get(key); + if (methodMeta == null) { + methodMeta = createMeta(ic); + methods.put(key, methodMeta); + } + } + } + return methodMeta; + } + + private Class findKeyType(final Object target) { + if (null == target) { + return null; + } + return target.getClass(); + } + + // it is unlikely we have all annotations but for now we have a single meta model +// it is unlikely we have all annotations but for now we have a single meta model +private org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta createMeta(final javax.interceptor.InvocationContext ic) { + final javax.cache.annotation.CacheDefaults defaults = findDefaults(ic.getTarget() == null ? null : ic.getTarget().getClass(), ic.getMethod()); + final java.lang.Class[] parameterTypes = ic.getMethod().getParameterTypes(); + final java.lang.annotation.Annotation[][] parameterAnnotations = ic.getMethod().getParameterAnnotations(); + final java.util.List> annotations = new java.util.ArrayList>(); + for (final java.lang.annotation.Annotation[] parameterAnnotation : parameterAnnotations) { + final java.util.Set set = new java.util.HashSet(parameterAnnotation.length); + set.addAll(java.util.Arrays.asList(parameterAnnotation)); + annotations.add(set); + } + final java.util.Set mtdAnnotations = new java.util.HashSet(); + mtdAnnotations.addAll(java.util.Arrays.asList(ic.getMethod().getAnnotations())); + final javax.cache.annotation.CacheResult cacheResult = ic.getMethod().getAnnotation(javax.cache.annotation.CacheResult.class); + final java.lang.String cacheResultCacheResultName = (cacheResult == null) ? null : defaultName(ic.getMethod(), defaults, cacheResult.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheResultCacheResolverFactory = (cacheResult == null) ? null : cacheResolverFactoryFor(defaults, cacheResult.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheResultCacheKeyGenerator = (cacheResult == null) ? null : cacheKeyGeneratorFor(defaults, cacheResult.cacheKeyGenerator()); + final javax.cache.annotation.CachePut cachePut = ic.getMethod().getAnnotation(javax.cache.annotation.CachePut.class); + final java.lang.String cachePutCachePutName = defaultName(ic.getMethod(), defaults, /* NPEX_NULL_EXP */ + cachePut.cacheName()); + final javax.cache.annotation.CacheResolverFactory cachePutCacheResolverFactory = (cachePut == null) ? null : cacheResolverFactoryFor(defaults, cachePut.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cachePutCacheKeyGenerator = (cachePut == null) ? null : cacheKeyGeneratorFor(defaults, cachePut.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemove cacheRemove = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemove.class); + final java.lang.String cacheRemoveCacheRemoveName = (cacheRemove == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemove.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveCacheResolverFactory = (cacheRemove == null) ? null : cacheResolverFactoryFor(defaults, cacheRemove.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheRemoveCacheKeyGenerator = (cacheRemove == null) ? null : cacheKeyGeneratorFor(defaults, cacheRemove.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemoveAll cacheRemoveAll = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemoveAll.class); + final java.lang.String cacheRemoveAllCacheRemoveAllName = (cacheRemoveAll == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemoveAll.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveAllCacheResolverFactory = (cacheRemoveAll == null) ? null : cacheResolverFactoryFor(defaults, cacheRemoveAll.cacheResolverFactory()); + return new org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta(parameterTypes, annotations, mtdAnnotations, keyParameterIndexes(ic.getMethod()), getValueParameter(annotations), cacheResultCacheResultName, cacheResultCacheResolverFactory, cacheResultCacheKeyGenerator, cacheResult, cachePutCachePutName, cachePutCacheResolverFactory, cachePutCacheKeyGenerator, (cachePut != null) && cachePut.afterInvocation(), cachePut, cacheRemoveCacheRemoveName, cacheRemoveCacheResolverFactory, cacheRemoveCacheKeyGenerator, (cacheRemove != null) && cacheRemove.afterInvocation(), cacheRemove, cacheRemoveAllCacheRemoveAllName, cacheRemoveAllCacheResolverFactory, cacheRemoveAll, java.util.concurrent.CompletionStage.class.isAssignableFrom(ic.getMethod().getReturnType())); +} + + private Integer getValueParameter(final List> annotations) { + int idx = 0; + for (final Set set : annotations) { + for (final Annotation a : set) { + if (a.annotationType() == CacheValue.class) { + return idx; + } + } + } + return -1; + } + + private String defaultName(final Method method, final CacheDefaults defaults, final String cacheName) { + if (!cacheName.isEmpty()) { + return cacheName; + } + if (defaults != null) { + final String name = defaults.cacheName(); + if (!name.isEmpty()) { + return name; + } + } + + final StringBuilder name = new StringBuilder(method.getDeclaringClass().getName()); + name.append("."); + name.append(method.getName()); + name.append("("); + final Class[] parameterTypes = method.getParameterTypes(); + for (int pIdx = 0; pIdx < parameterTypes.length; pIdx++) { + name.append(parameterTypes[pIdx].getName()); + if ((pIdx + 1) < parameterTypes.length) { + name.append(","); + } + } + name.append(")"); + return name.toString(); + } + + private CacheDefaults findDefaults(final Class targetType, final Method method) { + if (Proxy.isProxyClass(targetType)) // target doesnt hold annotations + { + final Class api = method.getDeclaringClass(); + for (final Class type : targetType.getInterfaces()) { + if (!api.isAssignableFrom(type)) { + continue; + } + return extractDefaults(type); + } + } + return extractDefaults(targetType); + } + + private CacheDefaults extractDefaults(final Class type) { + CacheDefaults annotation = null; + Class clazz = type; + while (clazz != null && clazz != Object.class) { + annotation = clazz.getAnnotation(CacheDefaults.class); + if (annotation != null) { + break; + } + clazz = clazz.getSuperclass(); + } + return annotation; + } + + public boolean isIncluded(final Class aClass, final Class[] in, final Class[] out) { + if (in.length == 0 && out.length == 0) { + return false; + } + for (final Class potentialIn : in) { + if (potentialIn.isAssignableFrom(aClass)) { + for (final Class potentialOut : out) { + if (potentialOut.isAssignableFrom(aClass)) { + return false; + } + } + return true; + } + } + return false; + } + + private CacheKeyGenerator cacheKeyGeneratorFor(final CacheDefaults defaults, + final Class cacheKeyGenerator) { + if (!CacheKeyGenerator.class.equals(cacheKeyGenerator)) { + return instance(cacheKeyGenerator); + } + if (defaults != null) { + final Class defaultCacheKeyGenerator = defaults.cacheKeyGenerator(); + if (!CacheKeyGenerator.class.equals(defaultCacheKeyGenerator)) { + return instance(defaultCacheKeyGenerator); + } + } + return defaultCacheKeyGenerator; + } + + private CacheResolverFactory cacheResolverFactoryFor(final CacheDefaults defaults, + final Class cacheResolverFactory) { + if (!CacheResolverFactory.class.equals(cacheResolverFactory)) { + return instance(cacheResolverFactory); + } + if (defaults != null) { + final Class defaultCacheResolverFactory = defaults.cacheResolverFactory(); + if (!CacheResolverFactory.class.equals(defaultCacheResolverFactory)) { + return instance(defaultCacheResolverFactory); + } + } + return defaultCacheResolverFactory(); + } + + private T instance(final Class type) { + final Set> beans = beanManager.getBeans(type); + if (beans.isEmpty()) { + if (CacheKeyGenerator.class == type) { + return (T) defaultCacheKeyGenerator; + } + if (CacheResolverFactory.class == type) { + return (T) defaultCacheResolverFactory(); + } + return null; + } + final Bean bean = beanManager.resolve(beans); + final CreationalContext context = beanManager.createCreationalContext(bean); + final Class scope = bean.getScope(); + final boolean normalScope = beanManager.isNormalScope(scope); + try { + final Object reference = beanManager.getReference(bean, bean.getBeanClass(), context); + if (!normalScope) { + toRelease.add(context); + } + return (T) reference; + } finally { + if (normalScope) { // TODO: release at the right moment, @PreDestroy? question is: do we assume it is thread safe? + context.release(); + } + } + } + + private CacheResolverFactoryImpl defaultCacheResolverFactory() { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + synchronized (this) { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + defaultCacheResolverFactory = new CacheResolverFactoryImpl(); + } + return defaultCacheResolverFactory; + } + + private Integer[] keyParameterIndexes(final Method method) { + final List keys = new LinkedList(); + final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + + // first check if keys are specified explicitely + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheKey.class)) { + keys.add(i); + break; + } + } + } + + // if not then use all parameters but value ones + if (keys.isEmpty()) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + boolean value = false; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheValue.class)) { + value = true; + break; + } + } + if (!value) { + keys.add(i); + } + } + } + return keys.toArray(new Integer[keys.size()]); + } + + private static final class MethodKey { + + private final Class base; + + private final Method delegate; + + private final int hash; + + private MethodKey(final Class base, final Method delegate) { + this.base = base; // we need a class to ensure inheritance don't fall in the same key + this.delegate = delegate; + this.hash = 31 * delegate.hashCode() + (base == null ? 0 : base.hashCode()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MethodKey classKey = MethodKey.class.cast(o); + return delegate.equals(classKey.delegate) + && ((base == null && classKey.base == null) || (base != null && base.equals(classKey.base))); + } + + @Override + public int hashCode() { + return hash; + } + } + + // TODO: split it in 5? + public static class MethodMeta { + + private final Class[] parameterTypes; + + private final List> parameterAnnotations; + + private final Set annotations; + + private final Integer[] keysIndices; + + private final Integer valueIndex; + + private final String cacheResultCacheName; + + private final CacheResolverFactory cacheResultResolverFactory; + + private final CacheKeyGenerator cacheResultKeyGenerator; + + private final CacheResult cacheResult; + + private final String cachePutCacheName; + + private final CacheResolverFactory cachePutResolverFactory; + + private final CacheKeyGenerator cachePutKeyGenerator; + + private final boolean cachePutAfter; + + private final CachePut cachePut; + + private final String cacheRemoveCacheName; + + private final CacheResolverFactory cacheRemoveResolverFactory; + + private final CacheKeyGenerator cacheRemoveKeyGenerator; + + private final boolean cacheRemoveAfter; + + private final CacheRemove cacheRemove; + + private final String cacheRemoveAllCacheName; + + private final CacheResolverFactory cacheRemoveAllResolverFactory; + + private final CacheRemoveAll cacheRemoveAll; + + private final boolean completionStage; + + public MethodMeta(Class[] parameterTypes, List> parameterAnnotations, Set annotations, + Integer[] keysIndices, Integer valueIndex, String cacheResultCacheName, + CacheResolverFactory cacheResultResolverFactory, CacheKeyGenerator cacheResultKeyGenerator, + CacheResult cacheResult, String cachePutCacheName, CacheResolverFactory cachePutResolverFactory, + CacheKeyGenerator cachePutKeyGenerator, boolean cachePutAfter, CachePut cachePut, String cacheRemoveCacheName, + CacheResolverFactory cacheRemoveResolverFactory, CacheKeyGenerator cacheRemoveKeyGenerator, + boolean cacheRemoveAfter, CacheRemove cacheRemove, String cacheRemoveAllCacheName, + CacheResolverFactory cacheRemoveAllResolverFactory, CacheRemoveAll cacheRemoveAll, + boolean completionStage) { + this.parameterTypes = parameterTypes; + this.parameterAnnotations = parameterAnnotations; + this.annotations = annotations; + this.keysIndices = keysIndices; + this.valueIndex = valueIndex; + this.cacheResultCacheName = cacheResultCacheName; + this.cacheResultResolverFactory = cacheResultResolverFactory; + this.cacheResultKeyGenerator = cacheResultKeyGenerator; + this.cacheResult = cacheResult; + this.cachePutCacheName = cachePutCacheName; + this.cachePutResolverFactory = cachePutResolverFactory; + this.cachePutKeyGenerator = cachePutKeyGenerator; + this.cachePutAfter = cachePutAfter; + this.cachePut = cachePut; + this.cacheRemoveCacheName = cacheRemoveCacheName; + this.cacheRemoveResolverFactory = cacheRemoveResolverFactory; + this.cacheRemoveKeyGenerator = cacheRemoveKeyGenerator; + this.cacheRemoveAfter = cacheRemoveAfter; + this.cacheRemove = cacheRemove; + this.cacheRemoveAllCacheName = cacheRemoveAllCacheName; + this.cacheRemoveAllResolverFactory = cacheRemoveAllResolverFactory; + this.cacheRemoveAll = cacheRemoveAll; + this.completionStage = completionStage; + } + + public boolean isCompletionStage() { + return completionStage; + } + + public boolean isCacheRemoveAfter() { + return cacheRemoveAfter; + } + + public boolean isCachePutAfter() { + return cachePutAfter; + } + + public Class[] getParameterTypes() { + return parameterTypes; + } + + public List> getParameterAnnotations() { + return parameterAnnotations; + } + + public String getCacheResultCacheName() { + return cacheResultCacheName; + } + + public CacheResolverFactory getCacheResultResolverFactory() { + return cacheResultResolverFactory; + } + + public CacheKeyGenerator getCacheResultKeyGenerator() { + return cacheResultKeyGenerator; + } + + public CacheResult getCacheResult() { + return cacheResult; + } + + public Set getAnnotations() { + return annotations; + } + + public Integer[] getKeysIndices() { + return keysIndices; + } + + public Integer getValueIndex() { + return valueIndex; + } + + public String getCachePutCacheName() { + return cachePutCacheName; + } + + public CacheResolverFactory getCachePutResolverFactory() { + return cachePutResolverFactory; + } + + public CacheKeyGenerator getCachePutKeyGenerator() { + return cachePutKeyGenerator; + } + + public CachePut getCachePut() { + return cachePut; + } + + public String getCacheRemoveCacheName() { + return cacheRemoveCacheName; + } + + public CacheResolverFactory getCacheRemoveResolverFactory() { + return cacheRemoveResolverFactory; + } + + public CacheKeyGenerator getCacheRemoveKeyGenerator() { + return cacheRemoveKeyGenerator; + } + + public CacheRemove getCacheRemove() { + return cacheRemove; + } + + public String getCacheRemoveAllCacheName() { + return cacheRemoveAllCacheName; + } + + public CacheResolverFactory getCacheRemoveAllResolverFactory() { + return cacheRemoveAllResolverFactory; + } + + public CacheRemoveAll getCacheRemoveAll() { + return cacheRemoveAll; + } + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_134/metadata.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_134/metadata.json new file mode 100644 index 000000000..9295c5935 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_134/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CDIJCacheHelper_134", + "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/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 129, + "npe_method": "createMeta", + "deref_field": "cachePut", + "npe_class": "CDIJCacheHelper", + "repo": "geronimo-jcache-simple", + "bug_id": "CDIJCacheHelper_134" + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_134/npe.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_134/npe.json new file mode 100644 index 000000000..4c07ca40a --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_134/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 129, + "npe_method": "createMeta", + "deref_field": "cachePut", + "npe_class": "CDIJCacheHelper" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_135/Dockerfile b/Java/geronimo-jcache-simple-CDIJCacheHelper_135/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_135/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CDIJCacheHelper_135/buggy.java b/Java/geronimo-jcache-simple-CDIJCacheHelper_135/buggy.java new file mode 100644 index 000000000..4a8c89258 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_135/buggy.java @@ -0,0 +1,535 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; + +import javax.annotation.PreDestroy; +import javax.cache.annotation.CacheDefaults; +import javax.cache.annotation.CacheKey; +import javax.cache.annotation.CacheKeyGenerator; +import javax.cache.annotation.CachePut; +import javax.cache.annotation.CacheRemove; +import javax.cache.annotation.CacheRemoveAll; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.CacheValue; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; + +@ApplicationScoped +public class CDIJCacheHelper { + + private static final Logger LOGGER = Logger.getLogger(CDIJCacheHelper.class.getName()); + + private static final boolean CLOSE_CACHE = !Boolean.getBoolean("org.apache.geronimo.jcache.simple.cdi.skip-close"); + + private final CacheKeyGeneratorImpl defaultCacheKeyGenerator = new CacheKeyGeneratorImpl(); + + private final Collection> toRelease = new ArrayList>(); + + private final ConcurrentMap methods = new ConcurrentHashMap(); + + private volatile CacheResolverFactoryImpl defaultCacheResolverFactory = null; // lazy to not create any cache if not needed + + @Inject + private BeanManager beanManager; + + @PreDestroy + private void release() { + if (CLOSE_CACHE && defaultCacheResolverFactory != null) { + defaultCacheResolverFactory.release(); + } + for (final CreationalContext cc : toRelease) { + try { + cc.release(); + } catch (final RuntimeException re) { + LOGGER.warning(re.getMessage()); + } + } + } + + public MethodMeta findMeta(final InvocationContext ic) { + final Method mtd = ic.getMethod(); + final Class refType = findKeyType(ic.getTarget()); + final MethodKey key = new MethodKey(refType, mtd); + MethodMeta methodMeta = methods.get(key); + if (methodMeta == null) { + synchronized (this) { + methodMeta = methods.get(key); + if (methodMeta == null) { + methodMeta = createMeta(ic); + methods.put(key, methodMeta); + } + } + } + return methodMeta; + } + + private Class findKeyType(final Object target) { + if (null == target) { + return null; + } + return target.getClass(); + } + + // it is unlikely we have all annotations but for now we have a single meta model +// it is unlikely we have all annotations but for now we have a single meta model +private org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta createMeta(final javax.interceptor.InvocationContext ic) { + final javax.cache.annotation.CacheDefaults defaults = findDefaults(ic.getTarget() == null ? null : ic.getTarget().getClass(), ic.getMethod()); + final java.lang.Class[] parameterTypes = ic.getMethod().getParameterTypes(); + final java.lang.annotation.Annotation[][] parameterAnnotations = ic.getMethod().getParameterAnnotations(); + final java.util.List> annotations = new java.util.ArrayList>(); + for (final java.lang.annotation.Annotation[] parameterAnnotation : parameterAnnotations) { + final java.util.Set set = new java.util.HashSet(parameterAnnotation.length); + set.addAll(java.util.Arrays.asList(parameterAnnotation)); + annotations.add(set); + } + final java.util.Set mtdAnnotations = new java.util.HashSet(); + mtdAnnotations.addAll(java.util.Arrays.asList(ic.getMethod().getAnnotations())); + final javax.cache.annotation.CacheResult cacheResult = ic.getMethod().getAnnotation(javax.cache.annotation.CacheResult.class); + final java.lang.String cacheResultCacheResultName = (cacheResult == null) ? null : defaultName(ic.getMethod(), defaults, cacheResult.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheResultCacheResolverFactory = (cacheResult == null) ? null : cacheResolverFactoryFor(defaults, cacheResult.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheResultCacheKeyGenerator = (cacheResult == null) ? null : cacheKeyGeneratorFor(defaults, cacheResult.cacheKeyGenerator()); + final javax.cache.annotation.CachePut cachePut = ic.getMethod().getAnnotation(javax.cache.annotation.CachePut.class); + final java.lang.String cachePutCachePutName = (/* NPEX_NULL_EXP */ + cachePut == null) ? null : defaultName(ic.getMethod(), defaults, cachePut.cacheName()); + final javax.cache.annotation.CacheResolverFactory cachePutCacheResolverFactory = cacheResolverFactoryFor(defaults, cachePut.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cachePutCacheKeyGenerator = (cachePut == null) ? null : cacheKeyGeneratorFor(defaults, cachePut.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemove cacheRemove = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemove.class); + final java.lang.String cacheRemoveCacheRemoveName = (cacheRemove == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemove.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveCacheResolverFactory = (cacheRemove == null) ? null : cacheResolverFactoryFor(defaults, cacheRemove.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheRemoveCacheKeyGenerator = (cacheRemove == null) ? null : cacheKeyGeneratorFor(defaults, cacheRemove.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemoveAll cacheRemoveAll = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemoveAll.class); + final java.lang.String cacheRemoveAllCacheRemoveAllName = (cacheRemoveAll == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemoveAll.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveAllCacheResolverFactory = (cacheRemoveAll == null) ? null : cacheResolverFactoryFor(defaults, cacheRemoveAll.cacheResolverFactory()); + return new org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta(parameterTypes, annotations, mtdAnnotations, keyParameterIndexes(ic.getMethod()), getValueParameter(annotations), cacheResultCacheResultName, cacheResultCacheResolverFactory, cacheResultCacheKeyGenerator, cacheResult, cachePutCachePutName, cachePutCacheResolverFactory, cachePutCacheKeyGenerator, (cachePut != null) && cachePut.afterInvocation(), cachePut, cacheRemoveCacheRemoveName, cacheRemoveCacheResolverFactory, cacheRemoveCacheKeyGenerator, (cacheRemove != null) && cacheRemove.afterInvocation(), cacheRemove, cacheRemoveAllCacheRemoveAllName, cacheRemoveAllCacheResolverFactory, cacheRemoveAll, java.util.concurrent.CompletionStage.class.isAssignableFrom(ic.getMethod().getReturnType())); +} + + private Integer getValueParameter(final List> annotations) { + int idx = 0; + for (final Set set : annotations) { + for (final Annotation a : set) { + if (a.annotationType() == CacheValue.class) { + return idx; + } + } + } + return -1; + } + + private String defaultName(final Method method, final CacheDefaults defaults, final String cacheName) { + if (!cacheName.isEmpty()) { + return cacheName; + } + if (defaults != null) { + final String name = defaults.cacheName(); + if (!name.isEmpty()) { + return name; + } + } + + final StringBuilder name = new StringBuilder(method.getDeclaringClass().getName()); + name.append("."); + name.append(method.getName()); + name.append("("); + final Class[] parameterTypes = method.getParameterTypes(); + for (int pIdx = 0; pIdx < parameterTypes.length; pIdx++) { + name.append(parameterTypes[pIdx].getName()); + if ((pIdx + 1) < parameterTypes.length) { + name.append(","); + } + } + name.append(")"); + return name.toString(); + } + + private CacheDefaults findDefaults(final Class targetType, final Method method) { + if (Proxy.isProxyClass(targetType)) // target doesnt hold annotations + { + final Class api = method.getDeclaringClass(); + for (final Class type : targetType.getInterfaces()) { + if (!api.isAssignableFrom(type)) { + continue; + } + return extractDefaults(type); + } + } + return extractDefaults(targetType); + } + + private CacheDefaults extractDefaults(final Class type) { + CacheDefaults annotation = null; + Class clazz = type; + while (clazz != null && clazz != Object.class) { + annotation = clazz.getAnnotation(CacheDefaults.class); + if (annotation != null) { + break; + } + clazz = clazz.getSuperclass(); + } + return annotation; + } + + public boolean isIncluded(final Class aClass, final Class[] in, final Class[] out) { + if (in.length == 0 && out.length == 0) { + return false; + } + for (final Class potentialIn : in) { + if (potentialIn.isAssignableFrom(aClass)) { + for (final Class potentialOut : out) { + if (potentialOut.isAssignableFrom(aClass)) { + return false; + } + } + return true; + } + } + return false; + } + + private CacheKeyGenerator cacheKeyGeneratorFor(final CacheDefaults defaults, + final Class cacheKeyGenerator) { + if (!CacheKeyGenerator.class.equals(cacheKeyGenerator)) { + return instance(cacheKeyGenerator); + } + if (defaults != null) { + final Class defaultCacheKeyGenerator = defaults.cacheKeyGenerator(); + if (!CacheKeyGenerator.class.equals(defaultCacheKeyGenerator)) { + return instance(defaultCacheKeyGenerator); + } + } + return defaultCacheKeyGenerator; + } + + private CacheResolverFactory cacheResolverFactoryFor(final CacheDefaults defaults, + final Class cacheResolverFactory) { + if (!CacheResolverFactory.class.equals(cacheResolverFactory)) { + return instance(cacheResolverFactory); + } + if (defaults != null) { + final Class defaultCacheResolverFactory = defaults.cacheResolverFactory(); + if (!CacheResolverFactory.class.equals(defaultCacheResolverFactory)) { + return instance(defaultCacheResolverFactory); + } + } + return defaultCacheResolverFactory(); + } + + private T instance(final Class type) { + final Set> beans = beanManager.getBeans(type); + if (beans.isEmpty()) { + if (CacheKeyGenerator.class == type) { + return (T) defaultCacheKeyGenerator; + } + if (CacheResolverFactory.class == type) { + return (T) defaultCacheResolverFactory(); + } + return null; + } + final Bean bean = beanManager.resolve(beans); + final CreationalContext context = beanManager.createCreationalContext(bean); + final Class scope = bean.getScope(); + final boolean normalScope = beanManager.isNormalScope(scope); + try { + final Object reference = beanManager.getReference(bean, bean.getBeanClass(), context); + if (!normalScope) { + toRelease.add(context); + } + return (T) reference; + } finally { + if (normalScope) { // TODO: release at the right moment, @PreDestroy? question is: do we assume it is thread safe? + context.release(); + } + } + } + + private CacheResolverFactoryImpl defaultCacheResolverFactory() { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + synchronized (this) { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + defaultCacheResolverFactory = new CacheResolverFactoryImpl(); + } + return defaultCacheResolverFactory; + } + + private Integer[] keyParameterIndexes(final Method method) { + final List keys = new LinkedList(); + final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + + // first check if keys are specified explicitely + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheKey.class)) { + keys.add(i); + break; + } + } + } + + // if not then use all parameters but value ones + if (keys.isEmpty()) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + boolean value = false; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheValue.class)) { + value = true; + break; + } + } + if (!value) { + keys.add(i); + } + } + } + return keys.toArray(new Integer[keys.size()]); + } + + private static final class MethodKey { + + private final Class base; + + private final Method delegate; + + private final int hash; + + private MethodKey(final Class base, final Method delegate) { + this.base = base; // we need a class to ensure inheritance don't fall in the same key + this.delegate = delegate; + this.hash = 31 * delegate.hashCode() + (base == null ? 0 : base.hashCode()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MethodKey classKey = MethodKey.class.cast(o); + return delegate.equals(classKey.delegate) + && ((base == null && classKey.base == null) || (base != null && base.equals(classKey.base))); + } + + @Override + public int hashCode() { + return hash; + } + } + + // TODO: split it in 5? + public static class MethodMeta { + + private final Class[] parameterTypes; + + private final List> parameterAnnotations; + + private final Set annotations; + + private final Integer[] keysIndices; + + private final Integer valueIndex; + + private final String cacheResultCacheName; + + private final CacheResolverFactory cacheResultResolverFactory; + + private final CacheKeyGenerator cacheResultKeyGenerator; + + private final CacheResult cacheResult; + + private final String cachePutCacheName; + + private final CacheResolverFactory cachePutResolverFactory; + + private final CacheKeyGenerator cachePutKeyGenerator; + + private final boolean cachePutAfter; + + private final CachePut cachePut; + + private final String cacheRemoveCacheName; + + private final CacheResolverFactory cacheRemoveResolverFactory; + + private final CacheKeyGenerator cacheRemoveKeyGenerator; + + private final boolean cacheRemoveAfter; + + private final CacheRemove cacheRemove; + + private final String cacheRemoveAllCacheName; + + private final CacheResolverFactory cacheRemoveAllResolverFactory; + + private final CacheRemoveAll cacheRemoveAll; + + private final boolean completionStage; + + public MethodMeta(Class[] parameterTypes, List> parameterAnnotations, Set annotations, + Integer[] keysIndices, Integer valueIndex, String cacheResultCacheName, + CacheResolverFactory cacheResultResolverFactory, CacheKeyGenerator cacheResultKeyGenerator, + CacheResult cacheResult, String cachePutCacheName, CacheResolverFactory cachePutResolverFactory, + CacheKeyGenerator cachePutKeyGenerator, boolean cachePutAfter, CachePut cachePut, String cacheRemoveCacheName, + CacheResolverFactory cacheRemoveResolverFactory, CacheKeyGenerator cacheRemoveKeyGenerator, + boolean cacheRemoveAfter, CacheRemove cacheRemove, String cacheRemoveAllCacheName, + CacheResolverFactory cacheRemoveAllResolverFactory, CacheRemoveAll cacheRemoveAll, + boolean completionStage) { + this.parameterTypes = parameterTypes; + this.parameterAnnotations = parameterAnnotations; + this.annotations = annotations; + this.keysIndices = keysIndices; + this.valueIndex = valueIndex; + this.cacheResultCacheName = cacheResultCacheName; + this.cacheResultResolverFactory = cacheResultResolverFactory; + this.cacheResultKeyGenerator = cacheResultKeyGenerator; + this.cacheResult = cacheResult; + this.cachePutCacheName = cachePutCacheName; + this.cachePutResolverFactory = cachePutResolverFactory; + this.cachePutKeyGenerator = cachePutKeyGenerator; + this.cachePutAfter = cachePutAfter; + this.cachePut = cachePut; + this.cacheRemoveCacheName = cacheRemoveCacheName; + this.cacheRemoveResolverFactory = cacheRemoveResolverFactory; + this.cacheRemoveKeyGenerator = cacheRemoveKeyGenerator; + this.cacheRemoveAfter = cacheRemoveAfter; + this.cacheRemove = cacheRemove; + this.cacheRemoveAllCacheName = cacheRemoveAllCacheName; + this.cacheRemoveAllResolverFactory = cacheRemoveAllResolverFactory; + this.cacheRemoveAll = cacheRemoveAll; + this.completionStage = completionStage; + } + + public boolean isCompletionStage() { + return completionStage; + } + + public boolean isCacheRemoveAfter() { + return cacheRemoveAfter; + } + + public boolean isCachePutAfter() { + return cachePutAfter; + } + + public Class[] getParameterTypes() { + return parameterTypes; + } + + public List> getParameterAnnotations() { + return parameterAnnotations; + } + + public String getCacheResultCacheName() { + return cacheResultCacheName; + } + + public CacheResolverFactory getCacheResultResolverFactory() { + return cacheResultResolverFactory; + } + + public CacheKeyGenerator getCacheResultKeyGenerator() { + return cacheResultKeyGenerator; + } + + public CacheResult getCacheResult() { + return cacheResult; + } + + public Set getAnnotations() { + return annotations; + } + + public Integer[] getKeysIndices() { + return keysIndices; + } + + public Integer getValueIndex() { + return valueIndex; + } + + public String getCachePutCacheName() { + return cachePutCacheName; + } + + public CacheResolverFactory getCachePutResolverFactory() { + return cachePutResolverFactory; + } + + public CacheKeyGenerator getCachePutKeyGenerator() { + return cachePutKeyGenerator; + } + + public CachePut getCachePut() { + return cachePut; + } + + public String getCacheRemoveCacheName() { + return cacheRemoveCacheName; + } + + public CacheResolverFactory getCacheRemoveResolverFactory() { + return cacheRemoveResolverFactory; + } + + public CacheKeyGenerator getCacheRemoveKeyGenerator() { + return cacheRemoveKeyGenerator; + } + + public CacheRemove getCacheRemove() { + return cacheRemove; + } + + public String getCacheRemoveAllCacheName() { + return cacheRemoveAllCacheName; + } + + public CacheResolverFactory getCacheRemoveAllResolverFactory() { + return cacheRemoveAllResolverFactory; + } + + public CacheRemoveAll getCacheRemoveAll() { + return cacheRemoveAll; + } + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_135/metadata.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_135/metadata.json new file mode 100644 index 000000000..a20aed522 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_135/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CDIJCacheHelper_135", + "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/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 129, + "npe_method": "createMeta", + "deref_field": "cachePut", + "npe_class": "CDIJCacheHelper", + "repo": "geronimo-jcache-simple", + "bug_id": "CDIJCacheHelper_135" + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_135/npe.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_135/npe.json new file mode 100644 index 000000000..4c07ca40a --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_135/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 129, + "npe_method": "createMeta", + "deref_field": "cachePut", + "npe_class": "CDIJCacheHelper" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_137/Dockerfile b/Java/geronimo-jcache-simple-CDIJCacheHelper_137/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_137/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CDIJCacheHelper_137/buggy.java b/Java/geronimo-jcache-simple-CDIJCacheHelper_137/buggy.java new file mode 100644 index 000000000..4f7360e8b --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_137/buggy.java @@ -0,0 +1,535 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; + +import javax.annotation.PreDestroy; +import javax.cache.annotation.CacheDefaults; +import javax.cache.annotation.CacheKey; +import javax.cache.annotation.CacheKeyGenerator; +import javax.cache.annotation.CachePut; +import javax.cache.annotation.CacheRemove; +import javax.cache.annotation.CacheRemoveAll; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.CacheValue; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; + +@ApplicationScoped +public class CDIJCacheHelper { + + private static final Logger LOGGER = Logger.getLogger(CDIJCacheHelper.class.getName()); + + private static final boolean CLOSE_CACHE = !Boolean.getBoolean("org.apache.geronimo.jcache.simple.cdi.skip-close"); + + private final CacheKeyGeneratorImpl defaultCacheKeyGenerator = new CacheKeyGeneratorImpl(); + + private final Collection> toRelease = new ArrayList>(); + + private final ConcurrentMap methods = new ConcurrentHashMap(); + + private volatile CacheResolverFactoryImpl defaultCacheResolverFactory = null; // lazy to not create any cache if not needed + + @Inject + private BeanManager beanManager; + + @PreDestroy + private void release() { + if (CLOSE_CACHE && defaultCacheResolverFactory != null) { + defaultCacheResolverFactory.release(); + } + for (final CreationalContext cc : toRelease) { + try { + cc.release(); + } catch (final RuntimeException re) { + LOGGER.warning(re.getMessage()); + } + } + } + + public MethodMeta findMeta(final InvocationContext ic) { + final Method mtd = ic.getMethod(); + final Class refType = findKeyType(ic.getTarget()); + final MethodKey key = new MethodKey(refType, mtd); + MethodMeta methodMeta = methods.get(key); + if (methodMeta == null) { + synchronized (this) { + methodMeta = methods.get(key); + if (methodMeta == null) { + methodMeta = createMeta(ic); + methods.put(key, methodMeta); + } + } + } + return methodMeta; + } + + private Class findKeyType(final Object target) { + if (null == target) { + return null; + } + return target.getClass(); + } + + // it is unlikely we have all annotations but for now we have a single meta model +// it is unlikely we have all annotations but for now we have a single meta model +private org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta createMeta(final javax.interceptor.InvocationContext ic) { + final javax.cache.annotation.CacheDefaults defaults = findDefaults(ic.getTarget() == null ? null : ic.getTarget().getClass(), ic.getMethod()); + final java.lang.Class[] parameterTypes = ic.getMethod().getParameterTypes(); + final java.lang.annotation.Annotation[][] parameterAnnotations = ic.getMethod().getParameterAnnotations(); + final java.util.List> annotations = new java.util.ArrayList>(); + for (final java.lang.annotation.Annotation[] parameterAnnotation : parameterAnnotations) { + final java.util.Set set = new java.util.HashSet(parameterAnnotation.length); + set.addAll(java.util.Arrays.asList(parameterAnnotation)); + annotations.add(set); + } + final java.util.Set mtdAnnotations = new java.util.HashSet(); + mtdAnnotations.addAll(java.util.Arrays.asList(ic.getMethod().getAnnotations())); + final javax.cache.annotation.CacheResult cacheResult = ic.getMethod().getAnnotation(javax.cache.annotation.CacheResult.class); + final java.lang.String cacheResultCacheResultName = (cacheResult == null) ? null : defaultName(ic.getMethod(), defaults, cacheResult.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheResultCacheResolverFactory = (cacheResult == null) ? null : cacheResolverFactoryFor(defaults, cacheResult.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheResultCacheKeyGenerator = (cacheResult == null) ? null : cacheKeyGeneratorFor(defaults, cacheResult.cacheKeyGenerator()); + final javax.cache.annotation.CachePut cachePut = ic.getMethod().getAnnotation(javax.cache.annotation.CachePut.class); + final java.lang.String cachePutCachePutName = (/* NPEX_NULL_EXP */ + cachePut == null) ? null : defaultName(ic.getMethod(), defaults, cachePut.cacheName()); + final javax.cache.annotation.CacheResolverFactory cachePutCacheResolverFactory = (cachePut == null) ? null : cacheResolverFactoryFor(defaults, cachePut.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cachePutCacheKeyGenerator = cacheKeyGeneratorFor(defaults, cachePut.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemove cacheRemove = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemove.class); + final java.lang.String cacheRemoveCacheRemoveName = (cacheRemove == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemove.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveCacheResolverFactory = (cacheRemove == null) ? null : cacheResolverFactoryFor(defaults, cacheRemove.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheRemoveCacheKeyGenerator = (cacheRemove == null) ? null : cacheKeyGeneratorFor(defaults, cacheRemove.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemoveAll cacheRemoveAll = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemoveAll.class); + final java.lang.String cacheRemoveAllCacheRemoveAllName = (cacheRemoveAll == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemoveAll.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveAllCacheResolverFactory = (cacheRemoveAll == null) ? null : cacheResolverFactoryFor(defaults, cacheRemoveAll.cacheResolverFactory()); + return new org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta(parameterTypes, annotations, mtdAnnotations, keyParameterIndexes(ic.getMethod()), getValueParameter(annotations), cacheResultCacheResultName, cacheResultCacheResolverFactory, cacheResultCacheKeyGenerator, cacheResult, cachePutCachePutName, cachePutCacheResolverFactory, cachePutCacheKeyGenerator, (cachePut != null) && cachePut.afterInvocation(), cachePut, cacheRemoveCacheRemoveName, cacheRemoveCacheResolverFactory, cacheRemoveCacheKeyGenerator, (cacheRemove != null) && cacheRemove.afterInvocation(), cacheRemove, cacheRemoveAllCacheRemoveAllName, cacheRemoveAllCacheResolverFactory, cacheRemoveAll, java.util.concurrent.CompletionStage.class.isAssignableFrom(ic.getMethod().getReturnType())); +} + + private Integer getValueParameter(final List> annotations) { + int idx = 0; + for (final Set set : annotations) { + for (final Annotation a : set) { + if (a.annotationType() == CacheValue.class) { + return idx; + } + } + } + return -1; + } + + private String defaultName(final Method method, final CacheDefaults defaults, final String cacheName) { + if (!cacheName.isEmpty()) { + return cacheName; + } + if (defaults != null) { + final String name = defaults.cacheName(); + if (!name.isEmpty()) { + return name; + } + } + + final StringBuilder name = new StringBuilder(method.getDeclaringClass().getName()); + name.append("."); + name.append(method.getName()); + name.append("("); + final Class[] parameterTypes = method.getParameterTypes(); + for (int pIdx = 0; pIdx < parameterTypes.length; pIdx++) { + name.append(parameterTypes[pIdx].getName()); + if ((pIdx + 1) < parameterTypes.length) { + name.append(","); + } + } + name.append(")"); + return name.toString(); + } + + private CacheDefaults findDefaults(final Class targetType, final Method method) { + if (Proxy.isProxyClass(targetType)) // target doesnt hold annotations + { + final Class api = method.getDeclaringClass(); + for (final Class type : targetType.getInterfaces()) { + if (!api.isAssignableFrom(type)) { + continue; + } + return extractDefaults(type); + } + } + return extractDefaults(targetType); + } + + private CacheDefaults extractDefaults(final Class type) { + CacheDefaults annotation = null; + Class clazz = type; + while (clazz != null && clazz != Object.class) { + annotation = clazz.getAnnotation(CacheDefaults.class); + if (annotation != null) { + break; + } + clazz = clazz.getSuperclass(); + } + return annotation; + } + + public boolean isIncluded(final Class aClass, final Class[] in, final Class[] out) { + if (in.length == 0 && out.length == 0) { + return false; + } + for (final Class potentialIn : in) { + if (potentialIn.isAssignableFrom(aClass)) { + for (final Class potentialOut : out) { + if (potentialOut.isAssignableFrom(aClass)) { + return false; + } + } + return true; + } + } + return false; + } + + private CacheKeyGenerator cacheKeyGeneratorFor(final CacheDefaults defaults, + final Class cacheKeyGenerator) { + if (!CacheKeyGenerator.class.equals(cacheKeyGenerator)) { + return instance(cacheKeyGenerator); + } + if (defaults != null) { + final Class defaultCacheKeyGenerator = defaults.cacheKeyGenerator(); + if (!CacheKeyGenerator.class.equals(defaultCacheKeyGenerator)) { + return instance(defaultCacheKeyGenerator); + } + } + return defaultCacheKeyGenerator; + } + + private CacheResolverFactory cacheResolverFactoryFor(final CacheDefaults defaults, + final Class cacheResolverFactory) { + if (!CacheResolverFactory.class.equals(cacheResolverFactory)) { + return instance(cacheResolverFactory); + } + if (defaults != null) { + final Class defaultCacheResolverFactory = defaults.cacheResolverFactory(); + if (!CacheResolverFactory.class.equals(defaultCacheResolverFactory)) { + return instance(defaultCacheResolverFactory); + } + } + return defaultCacheResolverFactory(); + } + + private T instance(final Class type) { + final Set> beans = beanManager.getBeans(type); + if (beans.isEmpty()) { + if (CacheKeyGenerator.class == type) { + return (T) defaultCacheKeyGenerator; + } + if (CacheResolverFactory.class == type) { + return (T) defaultCacheResolverFactory(); + } + return null; + } + final Bean bean = beanManager.resolve(beans); + final CreationalContext context = beanManager.createCreationalContext(bean); + final Class scope = bean.getScope(); + final boolean normalScope = beanManager.isNormalScope(scope); + try { + final Object reference = beanManager.getReference(bean, bean.getBeanClass(), context); + if (!normalScope) { + toRelease.add(context); + } + return (T) reference; + } finally { + if (normalScope) { // TODO: release at the right moment, @PreDestroy? question is: do we assume it is thread safe? + context.release(); + } + } + } + + private CacheResolverFactoryImpl defaultCacheResolverFactory() { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + synchronized (this) { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + defaultCacheResolverFactory = new CacheResolverFactoryImpl(); + } + return defaultCacheResolverFactory; + } + + private Integer[] keyParameterIndexes(final Method method) { + final List keys = new LinkedList(); + final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + + // first check if keys are specified explicitely + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheKey.class)) { + keys.add(i); + break; + } + } + } + + // if not then use all parameters but value ones + if (keys.isEmpty()) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + boolean value = false; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheValue.class)) { + value = true; + break; + } + } + if (!value) { + keys.add(i); + } + } + } + return keys.toArray(new Integer[keys.size()]); + } + + private static final class MethodKey { + + private final Class base; + + private final Method delegate; + + private final int hash; + + private MethodKey(final Class base, final Method delegate) { + this.base = base; // we need a class to ensure inheritance don't fall in the same key + this.delegate = delegate; + this.hash = 31 * delegate.hashCode() + (base == null ? 0 : base.hashCode()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MethodKey classKey = MethodKey.class.cast(o); + return delegate.equals(classKey.delegate) + && ((base == null && classKey.base == null) || (base != null && base.equals(classKey.base))); + } + + @Override + public int hashCode() { + return hash; + } + } + + // TODO: split it in 5? + public static class MethodMeta { + + private final Class[] parameterTypes; + + private final List> parameterAnnotations; + + private final Set annotations; + + private final Integer[] keysIndices; + + private final Integer valueIndex; + + private final String cacheResultCacheName; + + private final CacheResolverFactory cacheResultResolverFactory; + + private final CacheKeyGenerator cacheResultKeyGenerator; + + private final CacheResult cacheResult; + + private final String cachePutCacheName; + + private final CacheResolverFactory cachePutResolverFactory; + + private final CacheKeyGenerator cachePutKeyGenerator; + + private final boolean cachePutAfter; + + private final CachePut cachePut; + + private final String cacheRemoveCacheName; + + private final CacheResolverFactory cacheRemoveResolverFactory; + + private final CacheKeyGenerator cacheRemoveKeyGenerator; + + private final boolean cacheRemoveAfter; + + private final CacheRemove cacheRemove; + + private final String cacheRemoveAllCacheName; + + private final CacheResolverFactory cacheRemoveAllResolverFactory; + + private final CacheRemoveAll cacheRemoveAll; + + private final boolean completionStage; + + public MethodMeta(Class[] parameterTypes, List> parameterAnnotations, Set annotations, + Integer[] keysIndices, Integer valueIndex, String cacheResultCacheName, + CacheResolverFactory cacheResultResolverFactory, CacheKeyGenerator cacheResultKeyGenerator, + CacheResult cacheResult, String cachePutCacheName, CacheResolverFactory cachePutResolverFactory, + CacheKeyGenerator cachePutKeyGenerator, boolean cachePutAfter, CachePut cachePut, String cacheRemoveCacheName, + CacheResolverFactory cacheRemoveResolverFactory, CacheKeyGenerator cacheRemoveKeyGenerator, + boolean cacheRemoveAfter, CacheRemove cacheRemove, String cacheRemoveAllCacheName, + CacheResolverFactory cacheRemoveAllResolverFactory, CacheRemoveAll cacheRemoveAll, + boolean completionStage) { + this.parameterTypes = parameterTypes; + this.parameterAnnotations = parameterAnnotations; + this.annotations = annotations; + this.keysIndices = keysIndices; + this.valueIndex = valueIndex; + this.cacheResultCacheName = cacheResultCacheName; + this.cacheResultResolverFactory = cacheResultResolverFactory; + this.cacheResultKeyGenerator = cacheResultKeyGenerator; + this.cacheResult = cacheResult; + this.cachePutCacheName = cachePutCacheName; + this.cachePutResolverFactory = cachePutResolverFactory; + this.cachePutKeyGenerator = cachePutKeyGenerator; + this.cachePutAfter = cachePutAfter; + this.cachePut = cachePut; + this.cacheRemoveCacheName = cacheRemoveCacheName; + this.cacheRemoveResolverFactory = cacheRemoveResolverFactory; + this.cacheRemoveKeyGenerator = cacheRemoveKeyGenerator; + this.cacheRemoveAfter = cacheRemoveAfter; + this.cacheRemove = cacheRemove; + this.cacheRemoveAllCacheName = cacheRemoveAllCacheName; + this.cacheRemoveAllResolverFactory = cacheRemoveAllResolverFactory; + this.cacheRemoveAll = cacheRemoveAll; + this.completionStage = completionStage; + } + + public boolean isCompletionStage() { + return completionStage; + } + + public boolean isCacheRemoveAfter() { + return cacheRemoveAfter; + } + + public boolean isCachePutAfter() { + return cachePutAfter; + } + + public Class[] getParameterTypes() { + return parameterTypes; + } + + public List> getParameterAnnotations() { + return parameterAnnotations; + } + + public String getCacheResultCacheName() { + return cacheResultCacheName; + } + + public CacheResolverFactory getCacheResultResolverFactory() { + return cacheResultResolverFactory; + } + + public CacheKeyGenerator getCacheResultKeyGenerator() { + return cacheResultKeyGenerator; + } + + public CacheResult getCacheResult() { + return cacheResult; + } + + public Set getAnnotations() { + return annotations; + } + + public Integer[] getKeysIndices() { + return keysIndices; + } + + public Integer getValueIndex() { + return valueIndex; + } + + public String getCachePutCacheName() { + return cachePutCacheName; + } + + public CacheResolverFactory getCachePutResolverFactory() { + return cachePutResolverFactory; + } + + public CacheKeyGenerator getCachePutKeyGenerator() { + return cachePutKeyGenerator; + } + + public CachePut getCachePut() { + return cachePut; + } + + public String getCacheRemoveCacheName() { + return cacheRemoveCacheName; + } + + public CacheResolverFactory getCacheRemoveResolverFactory() { + return cacheRemoveResolverFactory; + } + + public CacheKeyGenerator getCacheRemoveKeyGenerator() { + return cacheRemoveKeyGenerator; + } + + public CacheRemove getCacheRemove() { + return cacheRemove; + } + + public String getCacheRemoveAllCacheName() { + return cacheRemoveAllCacheName; + } + + public CacheResolverFactory getCacheRemoveAllResolverFactory() { + return cacheRemoveAllResolverFactory; + } + + public CacheRemoveAll getCacheRemoveAll() { + return cacheRemoveAll; + } + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_137/metadata.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_137/metadata.json new file mode 100644 index 000000000..ee077d332 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_137/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CDIJCacheHelper_137", + "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/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 129, + "npe_method": "createMeta", + "deref_field": "cachePut", + "npe_class": "CDIJCacheHelper", + "repo": "geronimo-jcache-simple", + "bug_id": "CDIJCacheHelper_137" + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_137/npe.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_137/npe.json new file mode 100644 index 000000000..4c07ca40a --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_137/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 129, + "npe_method": "createMeta", + "deref_field": "cachePut", + "npe_class": "CDIJCacheHelper" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_141/Dockerfile b/Java/geronimo-jcache-simple-CDIJCacheHelper_141/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_141/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CDIJCacheHelper_141/buggy.java b/Java/geronimo-jcache-simple-CDIJCacheHelper_141/buggy.java new file mode 100644 index 000000000..1150da825 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_141/buggy.java @@ -0,0 +1,535 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; + +import javax.annotation.PreDestroy; +import javax.cache.annotation.CacheDefaults; +import javax.cache.annotation.CacheKey; +import javax.cache.annotation.CacheKeyGenerator; +import javax.cache.annotation.CachePut; +import javax.cache.annotation.CacheRemove; +import javax.cache.annotation.CacheRemoveAll; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.CacheValue; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; + +@ApplicationScoped +public class CDIJCacheHelper { + + private static final Logger LOGGER = Logger.getLogger(CDIJCacheHelper.class.getName()); + + private static final boolean CLOSE_CACHE = !Boolean.getBoolean("org.apache.geronimo.jcache.simple.cdi.skip-close"); + + private final CacheKeyGeneratorImpl defaultCacheKeyGenerator = new CacheKeyGeneratorImpl(); + + private final Collection> toRelease = new ArrayList>(); + + private final ConcurrentMap methods = new ConcurrentHashMap(); + + private volatile CacheResolverFactoryImpl defaultCacheResolverFactory = null; // lazy to not create any cache if not needed + + @Inject + private BeanManager beanManager; + + @PreDestroy + private void release() { + if (CLOSE_CACHE && defaultCacheResolverFactory != null) { + defaultCacheResolverFactory.release(); + } + for (final CreationalContext cc : toRelease) { + try { + cc.release(); + } catch (final RuntimeException re) { + LOGGER.warning(re.getMessage()); + } + } + } + + public MethodMeta findMeta(final InvocationContext ic) { + final Method mtd = ic.getMethod(); + final Class refType = findKeyType(ic.getTarget()); + final MethodKey key = new MethodKey(refType, mtd); + MethodMeta methodMeta = methods.get(key); + if (methodMeta == null) { + synchronized (this) { + methodMeta = methods.get(key); + if (methodMeta == null) { + methodMeta = createMeta(ic); + methods.put(key, methodMeta); + } + } + } + return methodMeta; + } + + private Class findKeyType(final Object target) { + if (null == target) { + return null; + } + return target.getClass(); + } + + // it is unlikely we have all annotations but for now we have a single meta model +// it is unlikely we have all annotations but for now we have a single meta model +private org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta createMeta(final javax.interceptor.InvocationContext ic) { + final javax.cache.annotation.CacheDefaults defaults = findDefaults(ic.getTarget() == null ? null : ic.getTarget().getClass(), ic.getMethod()); + final java.lang.Class[] parameterTypes = ic.getMethod().getParameterTypes(); + final java.lang.annotation.Annotation[][] parameterAnnotations = ic.getMethod().getParameterAnnotations(); + final java.util.List> annotations = new java.util.ArrayList>(); + for (final java.lang.annotation.Annotation[] parameterAnnotation : parameterAnnotations) { + final java.util.Set set = new java.util.HashSet(parameterAnnotation.length); + set.addAll(java.util.Arrays.asList(parameterAnnotation)); + annotations.add(set); + } + final java.util.Set mtdAnnotations = new java.util.HashSet(); + mtdAnnotations.addAll(java.util.Arrays.asList(ic.getMethod().getAnnotations())); + final javax.cache.annotation.CacheResult cacheResult = ic.getMethod().getAnnotation(javax.cache.annotation.CacheResult.class); + final java.lang.String cacheResultCacheResultName = (cacheResult == null) ? null : defaultName(ic.getMethod(), defaults, cacheResult.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheResultCacheResolverFactory = (cacheResult == null) ? null : cacheResolverFactoryFor(defaults, cacheResult.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheResultCacheKeyGenerator = (cacheResult == null) ? null : cacheKeyGeneratorFor(defaults, cacheResult.cacheKeyGenerator()); + final javax.cache.annotation.CachePut cachePut = ic.getMethod().getAnnotation(javax.cache.annotation.CachePut.class); + final java.lang.String cachePutCachePutName = (cachePut == null) ? null : defaultName(ic.getMethod(), defaults, cachePut.cacheName()); + final javax.cache.annotation.CacheResolverFactory cachePutCacheResolverFactory = (cachePut == null) ? null : cacheResolverFactoryFor(defaults, cachePut.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cachePutCacheKeyGenerator = (cachePut == null) ? null : cacheKeyGeneratorFor(defaults, cachePut.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemove cacheRemove = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemove.class); + final java.lang.String cacheRemoveCacheRemoveName = defaultName(ic.getMethod(), defaults, /* NPEX_NULL_EXP */ + cacheRemove.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveCacheResolverFactory = (cacheRemove == null) ? null : cacheResolverFactoryFor(defaults, cacheRemove.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheRemoveCacheKeyGenerator = (cacheRemove == null) ? null : cacheKeyGeneratorFor(defaults, cacheRemove.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemoveAll cacheRemoveAll = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemoveAll.class); + final java.lang.String cacheRemoveAllCacheRemoveAllName = (cacheRemoveAll == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemoveAll.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveAllCacheResolverFactory = (cacheRemoveAll == null) ? null : cacheResolverFactoryFor(defaults, cacheRemoveAll.cacheResolverFactory()); + return new org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta(parameterTypes, annotations, mtdAnnotations, keyParameterIndexes(ic.getMethod()), getValueParameter(annotations), cacheResultCacheResultName, cacheResultCacheResolverFactory, cacheResultCacheKeyGenerator, cacheResult, cachePutCachePutName, cachePutCacheResolverFactory, cachePutCacheKeyGenerator, (cachePut != null) && cachePut.afterInvocation(), cachePut, cacheRemoveCacheRemoveName, cacheRemoveCacheResolverFactory, cacheRemoveCacheKeyGenerator, (cacheRemove != null) && cacheRemove.afterInvocation(), cacheRemove, cacheRemoveAllCacheRemoveAllName, cacheRemoveAllCacheResolverFactory, cacheRemoveAll, java.util.concurrent.CompletionStage.class.isAssignableFrom(ic.getMethod().getReturnType())); +} + + private Integer getValueParameter(final List> annotations) { + int idx = 0; + for (final Set set : annotations) { + for (final Annotation a : set) { + if (a.annotationType() == CacheValue.class) { + return idx; + } + } + } + return -1; + } + + private String defaultName(final Method method, final CacheDefaults defaults, final String cacheName) { + if (!cacheName.isEmpty()) { + return cacheName; + } + if (defaults != null) { + final String name = defaults.cacheName(); + if (!name.isEmpty()) { + return name; + } + } + + final StringBuilder name = new StringBuilder(method.getDeclaringClass().getName()); + name.append("."); + name.append(method.getName()); + name.append("("); + final Class[] parameterTypes = method.getParameterTypes(); + for (int pIdx = 0; pIdx < parameterTypes.length; pIdx++) { + name.append(parameterTypes[pIdx].getName()); + if ((pIdx + 1) < parameterTypes.length) { + name.append(","); + } + } + name.append(")"); + return name.toString(); + } + + private CacheDefaults findDefaults(final Class targetType, final Method method) { + if (Proxy.isProxyClass(targetType)) // target doesnt hold annotations + { + final Class api = method.getDeclaringClass(); + for (final Class type : targetType.getInterfaces()) { + if (!api.isAssignableFrom(type)) { + continue; + } + return extractDefaults(type); + } + } + return extractDefaults(targetType); + } + + private CacheDefaults extractDefaults(final Class type) { + CacheDefaults annotation = null; + Class clazz = type; + while (clazz != null && clazz != Object.class) { + annotation = clazz.getAnnotation(CacheDefaults.class); + if (annotation != null) { + break; + } + clazz = clazz.getSuperclass(); + } + return annotation; + } + + public boolean isIncluded(final Class aClass, final Class[] in, final Class[] out) { + if (in.length == 0 && out.length == 0) { + return false; + } + for (final Class potentialIn : in) { + if (potentialIn.isAssignableFrom(aClass)) { + for (final Class potentialOut : out) { + if (potentialOut.isAssignableFrom(aClass)) { + return false; + } + } + return true; + } + } + return false; + } + + private CacheKeyGenerator cacheKeyGeneratorFor(final CacheDefaults defaults, + final Class cacheKeyGenerator) { + if (!CacheKeyGenerator.class.equals(cacheKeyGenerator)) { + return instance(cacheKeyGenerator); + } + if (defaults != null) { + final Class defaultCacheKeyGenerator = defaults.cacheKeyGenerator(); + if (!CacheKeyGenerator.class.equals(defaultCacheKeyGenerator)) { + return instance(defaultCacheKeyGenerator); + } + } + return defaultCacheKeyGenerator; + } + + private CacheResolverFactory cacheResolverFactoryFor(final CacheDefaults defaults, + final Class cacheResolverFactory) { + if (!CacheResolverFactory.class.equals(cacheResolverFactory)) { + return instance(cacheResolverFactory); + } + if (defaults != null) { + final Class defaultCacheResolverFactory = defaults.cacheResolverFactory(); + if (!CacheResolverFactory.class.equals(defaultCacheResolverFactory)) { + return instance(defaultCacheResolverFactory); + } + } + return defaultCacheResolverFactory(); + } + + private T instance(final Class type) { + final Set> beans = beanManager.getBeans(type); + if (beans.isEmpty()) { + if (CacheKeyGenerator.class == type) { + return (T) defaultCacheKeyGenerator; + } + if (CacheResolverFactory.class == type) { + return (T) defaultCacheResolverFactory(); + } + return null; + } + final Bean bean = beanManager.resolve(beans); + final CreationalContext context = beanManager.createCreationalContext(bean); + final Class scope = bean.getScope(); + final boolean normalScope = beanManager.isNormalScope(scope); + try { + final Object reference = beanManager.getReference(bean, bean.getBeanClass(), context); + if (!normalScope) { + toRelease.add(context); + } + return (T) reference; + } finally { + if (normalScope) { // TODO: release at the right moment, @PreDestroy? question is: do we assume it is thread safe? + context.release(); + } + } + } + + private CacheResolverFactoryImpl defaultCacheResolverFactory() { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + synchronized (this) { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + defaultCacheResolverFactory = new CacheResolverFactoryImpl(); + } + return defaultCacheResolverFactory; + } + + private Integer[] keyParameterIndexes(final Method method) { + final List keys = new LinkedList(); + final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + + // first check if keys are specified explicitely + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheKey.class)) { + keys.add(i); + break; + } + } + } + + // if not then use all parameters but value ones + if (keys.isEmpty()) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + boolean value = false; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheValue.class)) { + value = true; + break; + } + } + if (!value) { + keys.add(i); + } + } + } + return keys.toArray(new Integer[keys.size()]); + } + + private static final class MethodKey { + + private final Class base; + + private final Method delegate; + + private final int hash; + + private MethodKey(final Class base, final Method delegate) { + this.base = base; // we need a class to ensure inheritance don't fall in the same key + this.delegate = delegate; + this.hash = 31 * delegate.hashCode() + (base == null ? 0 : base.hashCode()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MethodKey classKey = MethodKey.class.cast(o); + return delegate.equals(classKey.delegate) + && ((base == null && classKey.base == null) || (base != null && base.equals(classKey.base))); + } + + @Override + public int hashCode() { + return hash; + } + } + + // TODO: split it in 5? + public static class MethodMeta { + + private final Class[] parameterTypes; + + private final List> parameterAnnotations; + + private final Set annotations; + + private final Integer[] keysIndices; + + private final Integer valueIndex; + + private final String cacheResultCacheName; + + private final CacheResolverFactory cacheResultResolverFactory; + + private final CacheKeyGenerator cacheResultKeyGenerator; + + private final CacheResult cacheResult; + + private final String cachePutCacheName; + + private final CacheResolverFactory cachePutResolverFactory; + + private final CacheKeyGenerator cachePutKeyGenerator; + + private final boolean cachePutAfter; + + private final CachePut cachePut; + + private final String cacheRemoveCacheName; + + private final CacheResolverFactory cacheRemoveResolverFactory; + + private final CacheKeyGenerator cacheRemoveKeyGenerator; + + private final boolean cacheRemoveAfter; + + private final CacheRemove cacheRemove; + + private final String cacheRemoveAllCacheName; + + private final CacheResolverFactory cacheRemoveAllResolverFactory; + + private final CacheRemoveAll cacheRemoveAll; + + private final boolean completionStage; + + public MethodMeta(Class[] parameterTypes, List> parameterAnnotations, Set annotations, + Integer[] keysIndices, Integer valueIndex, String cacheResultCacheName, + CacheResolverFactory cacheResultResolverFactory, CacheKeyGenerator cacheResultKeyGenerator, + CacheResult cacheResult, String cachePutCacheName, CacheResolverFactory cachePutResolverFactory, + CacheKeyGenerator cachePutKeyGenerator, boolean cachePutAfter, CachePut cachePut, String cacheRemoveCacheName, + CacheResolverFactory cacheRemoveResolverFactory, CacheKeyGenerator cacheRemoveKeyGenerator, + boolean cacheRemoveAfter, CacheRemove cacheRemove, String cacheRemoveAllCacheName, + CacheResolverFactory cacheRemoveAllResolverFactory, CacheRemoveAll cacheRemoveAll, + boolean completionStage) { + this.parameterTypes = parameterTypes; + this.parameterAnnotations = parameterAnnotations; + this.annotations = annotations; + this.keysIndices = keysIndices; + this.valueIndex = valueIndex; + this.cacheResultCacheName = cacheResultCacheName; + this.cacheResultResolverFactory = cacheResultResolverFactory; + this.cacheResultKeyGenerator = cacheResultKeyGenerator; + this.cacheResult = cacheResult; + this.cachePutCacheName = cachePutCacheName; + this.cachePutResolverFactory = cachePutResolverFactory; + this.cachePutKeyGenerator = cachePutKeyGenerator; + this.cachePutAfter = cachePutAfter; + this.cachePut = cachePut; + this.cacheRemoveCacheName = cacheRemoveCacheName; + this.cacheRemoveResolverFactory = cacheRemoveResolverFactory; + this.cacheRemoveKeyGenerator = cacheRemoveKeyGenerator; + this.cacheRemoveAfter = cacheRemoveAfter; + this.cacheRemove = cacheRemove; + this.cacheRemoveAllCacheName = cacheRemoveAllCacheName; + this.cacheRemoveAllResolverFactory = cacheRemoveAllResolverFactory; + this.cacheRemoveAll = cacheRemoveAll; + this.completionStage = completionStage; + } + + public boolean isCompletionStage() { + return completionStage; + } + + public boolean isCacheRemoveAfter() { + return cacheRemoveAfter; + } + + public boolean isCachePutAfter() { + return cachePutAfter; + } + + public Class[] getParameterTypes() { + return parameterTypes; + } + + public List> getParameterAnnotations() { + return parameterAnnotations; + } + + public String getCacheResultCacheName() { + return cacheResultCacheName; + } + + public CacheResolverFactory getCacheResultResolverFactory() { + return cacheResultResolverFactory; + } + + public CacheKeyGenerator getCacheResultKeyGenerator() { + return cacheResultKeyGenerator; + } + + public CacheResult getCacheResult() { + return cacheResult; + } + + public Set getAnnotations() { + return annotations; + } + + public Integer[] getKeysIndices() { + return keysIndices; + } + + public Integer getValueIndex() { + return valueIndex; + } + + public String getCachePutCacheName() { + return cachePutCacheName; + } + + public CacheResolverFactory getCachePutResolverFactory() { + return cachePutResolverFactory; + } + + public CacheKeyGenerator getCachePutKeyGenerator() { + return cachePutKeyGenerator; + } + + public CachePut getCachePut() { + return cachePut; + } + + public String getCacheRemoveCacheName() { + return cacheRemoveCacheName; + } + + public CacheResolverFactory getCacheRemoveResolverFactory() { + return cacheRemoveResolverFactory; + } + + public CacheKeyGenerator getCacheRemoveKeyGenerator() { + return cacheRemoveKeyGenerator; + } + + public CacheRemove getCacheRemove() { + return cacheRemove; + } + + public String getCacheRemoveAllCacheName() { + return cacheRemoveAllCacheName; + } + + public CacheResolverFactory getCacheRemoveAllResolverFactory() { + return cacheRemoveAllResolverFactory; + } + + public CacheRemoveAll getCacheRemoveAll() { + return cacheRemoveAll; + } + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_141/metadata.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_141/metadata.json new file mode 100644 index 000000000..4d36dbd42 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_141/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CDIJCacheHelper_141", + "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/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 133, + "npe_method": "createMeta", + "deref_field": "cacheRemove", + "npe_class": "CDIJCacheHelper", + "repo": "geronimo-jcache-simple", + "bug_id": "CDIJCacheHelper_141" + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_141/npe.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_141/npe.json new file mode 100644 index 000000000..ccaffb175 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_141/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 133, + "npe_method": "createMeta", + "deref_field": "cacheRemove", + "npe_class": "CDIJCacheHelper" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_143/Dockerfile b/Java/geronimo-jcache-simple-CDIJCacheHelper_143/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_143/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CDIJCacheHelper_143/buggy.java b/Java/geronimo-jcache-simple-CDIJCacheHelper_143/buggy.java new file mode 100644 index 000000000..e76d9afa1 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_143/buggy.java @@ -0,0 +1,535 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; + +import javax.annotation.PreDestroy; +import javax.cache.annotation.CacheDefaults; +import javax.cache.annotation.CacheKey; +import javax.cache.annotation.CacheKeyGenerator; +import javax.cache.annotation.CachePut; +import javax.cache.annotation.CacheRemove; +import javax.cache.annotation.CacheRemoveAll; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.CacheValue; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; + +@ApplicationScoped +public class CDIJCacheHelper { + + private static final Logger LOGGER = Logger.getLogger(CDIJCacheHelper.class.getName()); + + private static final boolean CLOSE_CACHE = !Boolean.getBoolean("org.apache.geronimo.jcache.simple.cdi.skip-close"); + + private final CacheKeyGeneratorImpl defaultCacheKeyGenerator = new CacheKeyGeneratorImpl(); + + private final Collection> toRelease = new ArrayList>(); + + private final ConcurrentMap methods = new ConcurrentHashMap(); + + private volatile CacheResolverFactoryImpl defaultCacheResolverFactory = null; // lazy to not create any cache if not needed + + @Inject + private BeanManager beanManager; + + @PreDestroy + private void release() { + if (CLOSE_CACHE && defaultCacheResolverFactory != null) { + defaultCacheResolverFactory.release(); + } + for (final CreationalContext cc : toRelease) { + try { + cc.release(); + } catch (final RuntimeException re) { + LOGGER.warning(re.getMessage()); + } + } + } + + public MethodMeta findMeta(final InvocationContext ic) { + final Method mtd = ic.getMethod(); + final Class refType = findKeyType(ic.getTarget()); + final MethodKey key = new MethodKey(refType, mtd); + MethodMeta methodMeta = methods.get(key); + if (methodMeta == null) { + synchronized (this) { + methodMeta = methods.get(key); + if (methodMeta == null) { + methodMeta = createMeta(ic); + methods.put(key, methodMeta); + } + } + } + return methodMeta; + } + + private Class findKeyType(final Object target) { + if (null == target) { + return null; + } + return target.getClass(); + } + + // it is unlikely we have all annotations but for now we have a single meta model +// it is unlikely we have all annotations but for now we have a single meta model +private org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta createMeta(final javax.interceptor.InvocationContext ic) { + final javax.cache.annotation.CacheDefaults defaults = findDefaults(ic.getTarget() == null ? null : ic.getTarget().getClass(), ic.getMethod()); + final java.lang.Class[] parameterTypes = ic.getMethod().getParameterTypes(); + final java.lang.annotation.Annotation[][] parameterAnnotations = ic.getMethod().getParameterAnnotations(); + final java.util.List> annotations = new java.util.ArrayList>(); + for (final java.lang.annotation.Annotation[] parameterAnnotation : parameterAnnotations) { + final java.util.Set set = new java.util.HashSet(parameterAnnotation.length); + set.addAll(java.util.Arrays.asList(parameterAnnotation)); + annotations.add(set); + } + final java.util.Set mtdAnnotations = new java.util.HashSet(); + mtdAnnotations.addAll(java.util.Arrays.asList(ic.getMethod().getAnnotations())); + final javax.cache.annotation.CacheResult cacheResult = ic.getMethod().getAnnotation(javax.cache.annotation.CacheResult.class); + final java.lang.String cacheResultCacheResultName = (cacheResult == null) ? null : defaultName(ic.getMethod(), defaults, cacheResult.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheResultCacheResolverFactory = (cacheResult == null) ? null : cacheResolverFactoryFor(defaults, cacheResult.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheResultCacheKeyGenerator = (cacheResult == null) ? null : cacheKeyGeneratorFor(defaults, cacheResult.cacheKeyGenerator()); + final javax.cache.annotation.CachePut cachePut = ic.getMethod().getAnnotation(javax.cache.annotation.CachePut.class); + final java.lang.String cachePutCachePutName = (cachePut == null) ? null : defaultName(ic.getMethod(), defaults, cachePut.cacheName()); + final javax.cache.annotation.CacheResolverFactory cachePutCacheResolverFactory = (cachePut == null) ? null : cacheResolverFactoryFor(defaults, cachePut.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cachePutCacheKeyGenerator = (cachePut == null) ? null : cacheKeyGeneratorFor(defaults, cachePut.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemove cacheRemove = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemove.class); + final java.lang.String cacheRemoveCacheRemoveName = (/* NPEX_NULL_EXP */ + cacheRemove == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemove.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveCacheResolverFactory = cacheResolverFactoryFor(defaults, cacheRemove.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheRemoveCacheKeyGenerator = (cacheRemove == null) ? null : cacheKeyGeneratorFor(defaults, cacheRemove.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemoveAll cacheRemoveAll = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemoveAll.class); + final java.lang.String cacheRemoveAllCacheRemoveAllName = (cacheRemoveAll == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemoveAll.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveAllCacheResolverFactory = (cacheRemoveAll == null) ? null : cacheResolverFactoryFor(defaults, cacheRemoveAll.cacheResolverFactory()); + return new org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta(parameterTypes, annotations, mtdAnnotations, keyParameterIndexes(ic.getMethod()), getValueParameter(annotations), cacheResultCacheResultName, cacheResultCacheResolverFactory, cacheResultCacheKeyGenerator, cacheResult, cachePutCachePutName, cachePutCacheResolverFactory, cachePutCacheKeyGenerator, (cachePut != null) && cachePut.afterInvocation(), cachePut, cacheRemoveCacheRemoveName, cacheRemoveCacheResolverFactory, cacheRemoveCacheKeyGenerator, (cacheRemove != null) && cacheRemove.afterInvocation(), cacheRemove, cacheRemoveAllCacheRemoveAllName, cacheRemoveAllCacheResolverFactory, cacheRemoveAll, java.util.concurrent.CompletionStage.class.isAssignableFrom(ic.getMethod().getReturnType())); +} + + private Integer getValueParameter(final List> annotations) { + int idx = 0; + for (final Set set : annotations) { + for (final Annotation a : set) { + if (a.annotationType() == CacheValue.class) { + return idx; + } + } + } + return -1; + } + + private String defaultName(final Method method, final CacheDefaults defaults, final String cacheName) { + if (!cacheName.isEmpty()) { + return cacheName; + } + if (defaults != null) { + final String name = defaults.cacheName(); + if (!name.isEmpty()) { + return name; + } + } + + final StringBuilder name = new StringBuilder(method.getDeclaringClass().getName()); + name.append("."); + name.append(method.getName()); + name.append("("); + final Class[] parameterTypes = method.getParameterTypes(); + for (int pIdx = 0; pIdx < parameterTypes.length; pIdx++) { + name.append(parameterTypes[pIdx].getName()); + if ((pIdx + 1) < parameterTypes.length) { + name.append(","); + } + } + name.append(")"); + return name.toString(); + } + + private CacheDefaults findDefaults(final Class targetType, final Method method) { + if (Proxy.isProxyClass(targetType)) // target doesnt hold annotations + { + final Class api = method.getDeclaringClass(); + for (final Class type : targetType.getInterfaces()) { + if (!api.isAssignableFrom(type)) { + continue; + } + return extractDefaults(type); + } + } + return extractDefaults(targetType); + } + + private CacheDefaults extractDefaults(final Class type) { + CacheDefaults annotation = null; + Class clazz = type; + while (clazz != null && clazz != Object.class) { + annotation = clazz.getAnnotation(CacheDefaults.class); + if (annotation != null) { + break; + } + clazz = clazz.getSuperclass(); + } + return annotation; + } + + public boolean isIncluded(final Class aClass, final Class[] in, final Class[] out) { + if (in.length == 0 && out.length == 0) { + return false; + } + for (final Class potentialIn : in) { + if (potentialIn.isAssignableFrom(aClass)) { + for (final Class potentialOut : out) { + if (potentialOut.isAssignableFrom(aClass)) { + return false; + } + } + return true; + } + } + return false; + } + + private CacheKeyGenerator cacheKeyGeneratorFor(final CacheDefaults defaults, + final Class cacheKeyGenerator) { + if (!CacheKeyGenerator.class.equals(cacheKeyGenerator)) { + return instance(cacheKeyGenerator); + } + if (defaults != null) { + final Class defaultCacheKeyGenerator = defaults.cacheKeyGenerator(); + if (!CacheKeyGenerator.class.equals(defaultCacheKeyGenerator)) { + return instance(defaultCacheKeyGenerator); + } + } + return defaultCacheKeyGenerator; + } + + private CacheResolverFactory cacheResolverFactoryFor(final CacheDefaults defaults, + final Class cacheResolverFactory) { + if (!CacheResolverFactory.class.equals(cacheResolverFactory)) { + return instance(cacheResolverFactory); + } + if (defaults != null) { + final Class defaultCacheResolverFactory = defaults.cacheResolverFactory(); + if (!CacheResolverFactory.class.equals(defaultCacheResolverFactory)) { + return instance(defaultCacheResolverFactory); + } + } + return defaultCacheResolverFactory(); + } + + private T instance(final Class type) { + final Set> beans = beanManager.getBeans(type); + if (beans.isEmpty()) { + if (CacheKeyGenerator.class == type) { + return (T) defaultCacheKeyGenerator; + } + if (CacheResolverFactory.class == type) { + return (T) defaultCacheResolverFactory(); + } + return null; + } + final Bean bean = beanManager.resolve(beans); + final CreationalContext context = beanManager.createCreationalContext(bean); + final Class scope = bean.getScope(); + final boolean normalScope = beanManager.isNormalScope(scope); + try { + final Object reference = beanManager.getReference(bean, bean.getBeanClass(), context); + if (!normalScope) { + toRelease.add(context); + } + return (T) reference; + } finally { + if (normalScope) { // TODO: release at the right moment, @PreDestroy? question is: do we assume it is thread safe? + context.release(); + } + } + } + + private CacheResolverFactoryImpl defaultCacheResolverFactory() { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + synchronized (this) { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + defaultCacheResolverFactory = new CacheResolverFactoryImpl(); + } + return defaultCacheResolverFactory; + } + + private Integer[] keyParameterIndexes(final Method method) { + final List keys = new LinkedList(); + final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + + // first check if keys are specified explicitely + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheKey.class)) { + keys.add(i); + break; + } + } + } + + // if not then use all parameters but value ones + if (keys.isEmpty()) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + boolean value = false; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheValue.class)) { + value = true; + break; + } + } + if (!value) { + keys.add(i); + } + } + } + return keys.toArray(new Integer[keys.size()]); + } + + private static final class MethodKey { + + private final Class base; + + private final Method delegate; + + private final int hash; + + private MethodKey(final Class base, final Method delegate) { + this.base = base; // we need a class to ensure inheritance don't fall in the same key + this.delegate = delegate; + this.hash = 31 * delegate.hashCode() + (base == null ? 0 : base.hashCode()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MethodKey classKey = MethodKey.class.cast(o); + return delegate.equals(classKey.delegate) + && ((base == null && classKey.base == null) || (base != null && base.equals(classKey.base))); + } + + @Override + public int hashCode() { + return hash; + } + } + + // TODO: split it in 5? + public static class MethodMeta { + + private final Class[] parameterTypes; + + private final List> parameterAnnotations; + + private final Set annotations; + + private final Integer[] keysIndices; + + private final Integer valueIndex; + + private final String cacheResultCacheName; + + private final CacheResolverFactory cacheResultResolverFactory; + + private final CacheKeyGenerator cacheResultKeyGenerator; + + private final CacheResult cacheResult; + + private final String cachePutCacheName; + + private final CacheResolverFactory cachePutResolverFactory; + + private final CacheKeyGenerator cachePutKeyGenerator; + + private final boolean cachePutAfter; + + private final CachePut cachePut; + + private final String cacheRemoveCacheName; + + private final CacheResolverFactory cacheRemoveResolverFactory; + + private final CacheKeyGenerator cacheRemoveKeyGenerator; + + private final boolean cacheRemoveAfter; + + private final CacheRemove cacheRemove; + + private final String cacheRemoveAllCacheName; + + private final CacheResolverFactory cacheRemoveAllResolverFactory; + + private final CacheRemoveAll cacheRemoveAll; + + private final boolean completionStage; + + public MethodMeta(Class[] parameterTypes, List> parameterAnnotations, Set annotations, + Integer[] keysIndices, Integer valueIndex, String cacheResultCacheName, + CacheResolverFactory cacheResultResolverFactory, CacheKeyGenerator cacheResultKeyGenerator, + CacheResult cacheResult, String cachePutCacheName, CacheResolverFactory cachePutResolverFactory, + CacheKeyGenerator cachePutKeyGenerator, boolean cachePutAfter, CachePut cachePut, String cacheRemoveCacheName, + CacheResolverFactory cacheRemoveResolverFactory, CacheKeyGenerator cacheRemoveKeyGenerator, + boolean cacheRemoveAfter, CacheRemove cacheRemove, String cacheRemoveAllCacheName, + CacheResolverFactory cacheRemoveAllResolverFactory, CacheRemoveAll cacheRemoveAll, + boolean completionStage) { + this.parameterTypes = parameterTypes; + this.parameterAnnotations = parameterAnnotations; + this.annotations = annotations; + this.keysIndices = keysIndices; + this.valueIndex = valueIndex; + this.cacheResultCacheName = cacheResultCacheName; + this.cacheResultResolverFactory = cacheResultResolverFactory; + this.cacheResultKeyGenerator = cacheResultKeyGenerator; + this.cacheResult = cacheResult; + this.cachePutCacheName = cachePutCacheName; + this.cachePutResolverFactory = cachePutResolverFactory; + this.cachePutKeyGenerator = cachePutKeyGenerator; + this.cachePutAfter = cachePutAfter; + this.cachePut = cachePut; + this.cacheRemoveCacheName = cacheRemoveCacheName; + this.cacheRemoveResolverFactory = cacheRemoveResolverFactory; + this.cacheRemoveKeyGenerator = cacheRemoveKeyGenerator; + this.cacheRemoveAfter = cacheRemoveAfter; + this.cacheRemove = cacheRemove; + this.cacheRemoveAllCacheName = cacheRemoveAllCacheName; + this.cacheRemoveAllResolverFactory = cacheRemoveAllResolverFactory; + this.cacheRemoveAll = cacheRemoveAll; + this.completionStage = completionStage; + } + + public boolean isCompletionStage() { + return completionStage; + } + + public boolean isCacheRemoveAfter() { + return cacheRemoveAfter; + } + + public boolean isCachePutAfter() { + return cachePutAfter; + } + + public Class[] getParameterTypes() { + return parameterTypes; + } + + public List> getParameterAnnotations() { + return parameterAnnotations; + } + + public String getCacheResultCacheName() { + return cacheResultCacheName; + } + + public CacheResolverFactory getCacheResultResolverFactory() { + return cacheResultResolverFactory; + } + + public CacheKeyGenerator getCacheResultKeyGenerator() { + return cacheResultKeyGenerator; + } + + public CacheResult getCacheResult() { + return cacheResult; + } + + public Set getAnnotations() { + return annotations; + } + + public Integer[] getKeysIndices() { + return keysIndices; + } + + public Integer getValueIndex() { + return valueIndex; + } + + public String getCachePutCacheName() { + return cachePutCacheName; + } + + public CacheResolverFactory getCachePutResolverFactory() { + return cachePutResolverFactory; + } + + public CacheKeyGenerator getCachePutKeyGenerator() { + return cachePutKeyGenerator; + } + + public CachePut getCachePut() { + return cachePut; + } + + public String getCacheRemoveCacheName() { + return cacheRemoveCacheName; + } + + public CacheResolverFactory getCacheRemoveResolverFactory() { + return cacheRemoveResolverFactory; + } + + public CacheKeyGenerator getCacheRemoveKeyGenerator() { + return cacheRemoveKeyGenerator; + } + + public CacheRemove getCacheRemove() { + return cacheRemove; + } + + public String getCacheRemoveAllCacheName() { + return cacheRemoveAllCacheName; + } + + public CacheResolverFactory getCacheRemoveAllResolverFactory() { + return cacheRemoveAllResolverFactory; + } + + public CacheRemoveAll getCacheRemoveAll() { + return cacheRemoveAll; + } + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_143/metadata.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_143/metadata.json new file mode 100644 index 000000000..d953a50ab --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_143/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CDIJCacheHelper_143", + "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/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 133, + "npe_method": "createMeta", + "deref_field": "cacheRemove", + "npe_class": "CDIJCacheHelper", + "repo": "geronimo-jcache-simple", + "bug_id": "CDIJCacheHelper_143" + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_143/npe.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_143/npe.json new file mode 100644 index 000000000..ccaffb175 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_143/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 133, + "npe_method": "createMeta", + "deref_field": "cacheRemove", + "npe_class": "CDIJCacheHelper" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_145/Dockerfile b/Java/geronimo-jcache-simple-CDIJCacheHelper_145/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_145/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CDIJCacheHelper_145/buggy.java b/Java/geronimo-jcache-simple-CDIJCacheHelper_145/buggy.java new file mode 100644 index 000000000..82b67190c --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_145/buggy.java @@ -0,0 +1,535 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; + +import javax.annotation.PreDestroy; +import javax.cache.annotation.CacheDefaults; +import javax.cache.annotation.CacheKey; +import javax.cache.annotation.CacheKeyGenerator; +import javax.cache.annotation.CachePut; +import javax.cache.annotation.CacheRemove; +import javax.cache.annotation.CacheRemoveAll; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.CacheValue; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; + +@ApplicationScoped +public class CDIJCacheHelper { + + private static final Logger LOGGER = Logger.getLogger(CDIJCacheHelper.class.getName()); + + private static final boolean CLOSE_CACHE = !Boolean.getBoolean("org.apache.geronimo.jcache.simple.cdi.skip-close"); + + private final CacheKeyGeneratorImpl defaultCacheKeyGenerator = new CacheKeyGeneratorImpl(); + + private final Collection> toRelease = new ArrayList>(); + + private final ConcurrentMap methods = new ConcurrentHashMap(); + + private volatile CacheResolverFactoryImpl defaultCacheResolverFactory = null; // lazy to not create any cache if not needed + + @Inject + private BeanManager beanManager; + + @PreDestroy + private void release() { + if (CLOSE_CACHE && defaultCacheResolverFactory != null) { + defaultCacheResolverFactory.release(); + } + for (final CreationalContext cc : toRelease) { + try { + cc.release(); + } catch (final RuntimeException re) { + LOGGER.warning(re.getMessage()); + } + } + } + + public MethodMeta findMeta(final InvocationContext ic) { + final Method mtd = ic.getMethod(); + final Class refType = findKeyType(ic.getTarget()); + final MethodKey key = new MethodKey(refType, mtd); + MethodMeta methodMeta = methods.get(key); + if (methodMeta == null) { + synchronized (this) { + methodMeta = methods.get(key); + if (methodMeta == null) { + methodMeta = createMeta(ic); + methods.put(key, methodMeta); + } + } + } + return methodMeta; + } + + private Class findKeyType(final Object target) { + if (null == target) { + return null; + } + return target.getClass(); + } + + // it is unlikely we have all annotations but for now we have a single meta model +// it is unlikely we have all annotations but for now we have a single meta model +private org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta createMeta(final javax.interceptor.InvocationContext ic) { + final javax.cache.annotation.CacheDefaults defaults = findDefaults(ic.getTarget() == null ? null : ic.getTarget().getClass(), ic.getMethod()); + final java.lang.Class[] parameterTypes = ic.getMethod().getParameterTypes(); + final java.lang.annotation.Annotation[][] parameterAnnotations = ic.getMethod().getParameterAnnotations(); + final java.util.List> annotations = new java.util.ArrayList>(); + for (final java.lang.annotation.Annotation[] parameterAnnotation : parameterAnnotations) { + final java.util.Set set = new java.util.HashSet(parameterAnnotation.length); + set.addAll(java.util.Arrays.asList(parameterAnnotation)); + annotations.add(set); + } + final java.util.Set mtdAnnotations = new java.util.HashSet(); + mtdAnnotations.addAll(java.util.Arrays.asList(ic.getMethod().getAnnotations())); + final javax.cache.annotation.CacheResult cacheResult = ic.getMethod().getAnnotation(javax.cache.annotation.CacheResult.class); + final java.lang.String cacheResultCacheResultName = (cacheResult == null) ? null : defaultName(ic.getMethod(), defaults, cacheResult.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheResultCacheResolverFactory = (cacheResult == null) ? null : cacheResolverFactoryFor(defaults, cacheResult.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheResultCacheKeyGenerator = (cacheResult == null) ? null : cacheKeyGeneratorFor(defaults, cacheResult.cacheKeyGenerator()); + final javax.cache.annotation.CachePut cachePut = ic.getMethod().getAnnotation(javax.cache.annotation.CachePut.class); + final java.lang.String cachePutCachePutName = (cachePut == null) ? null : defaultName(ic.getMethod(), defaults, cachePut.cacheName()); + final javax.cache.annotation.CacheResolverFactory cachePutCacheResolverFactory = (cachePut == null) ? null : cacheResolverFactoryFor(defaults, cachePut.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cachePutCacheKeyGenerator = (cachePut == null) ? null : cacheKeyGeneratorFor(defaults, cachePut.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemove cacheRemove = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemove.class); + final java.lang.String cacheRemoveCacheRemoveName = (/* NPEX_NULL_EXP */ + cacheRemove == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemove.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveCacheResolverFactory = (cacheRemove == null) ? null : cacheResolverFactoryFor(defaults, cacheRemove.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheRemoveCacheKeyGenerator = cacheKeyGeneratorFor(defaults, cacheRemove.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemoveAll cacheRemoveAll = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemoveAll.class); + final java.lang.String cacheRemoveAllCacheRemoveAllName = (cacheRemoveAll == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemoveAll.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveAllCacheResolverFactory = (cacheRemoveAll == null) ? null : cacheResolverFactoryFor(defaults, cacheRemoveAll.cacheResolverFactory()); + return new org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta(parameterTypes, annotations, mtdAnnotations, keyParameterIndexes(ic.getMethod()), getValueParameter(annotations), cacheResultCacheResultName, cacheResultCacheResolverFactory, cacheResultCacheKeyGenerator, cacheResult, cachePutCachePutName, cachePutCacheResolverFactory, cachePutCacheKeyGenerator, (cachePut != null) && cachePut.afterInvocation(), cachePut, cacheRemoveCacheRemoveName, cacheRemoveCacheResolverFactory, cacheRemoveCacheKeyGenerator, (cacheRemove != null) && cacheRemove.afterInvocation(), cacheRemove, cacheRemoveAllCacheRemoveAllName, cacheRemoveAllCacheResolverFactory, cacheRemoveAll, java.util.concurrent.CompletionStage.class.isAssignableFrom(ic.getMethod().getReturnType())); +} + + private Integer getValueParameter(final List> annotations) { + int idx = 0; + for (final Set set : annotations) { + for (final Annotation a : set) { + if (a.annotationType() == CacheValue.class) { + return idx; + } + } + } + return -1; + } + + private String defaultName(final Method method, final CacheDefaults defaults, final String cacheName) { + if (!cacheName.isEmpty()) { + return cacheName; + } + if (defaults != null) { + final String name = defaults.cacheName(); + if (!name.isEmpty()) { + return name; + } + } + + final StringBuilder name = new StringBuilder(method.getDeclaringClass().getName()); + name.append("."); + name.append(method.getName()); + name.append("("); + final Class[] parameterTypes = method.getParameterTypes(); + for (int pIdx = 0; pIdx < parameterTypes.length; pIdx++) { + name.append(parameterTypes[pIdx].getName()); + if ((pIdx + 1) < parameterTypes.length) { + name.append(","); + } + } + name.append(")"); + return name.toString(); + } + + private CacheDefaults findDefaults(final Class targetType, final Method method) { + if (Proxy.isProxyClass(targetType)) // target doesnt hold annotations + { + final Class api = method.getDeclaringClass(); + for (final Class type : targetType.getInterfaces()) { + if (!api.isAssignableFrom(type)) { + continue; + } + return extractDefaults(type); + } + } + return extractDefaults(targetType); + } + + private CacheDefaults extractDefaults(final Class type) { + CacheDefaults annotation = null; + Class clazz = type; + while (clazz != null && clazz != Object.class) { + annotation = clazz.getAnnotation(CacheDefaults.class); + if (annotation != null) { + break; + } + clazz = clazz.getSuperclass(); + } + return annotation; + } + + public boolean isIncluded(final Class aClass, final Class[] in, final Class[] out) { + if (in.length == 0 && out.length == 0) { + return false; + } + for (final Class potentialIn : in) { + if (potentialIn.isAssignableFrom(aClass)) { + for (final Class potentialOut : out) { + if (potentialOut.isAssignableFrom(aClass)) { + return false; + } + } + return true; + } + } + return false; + } + + private CacheKeyGenerator cacheKeyGeneratorFor(final CacheDefaults defaults, + final Class cacheKeyGenerator) { + if (!CacheKeyGenerator.class.equals(cacheKeyGenerator)) { + return instance(cacheKeyGenerator); + } + if (defaults != null) { + final Class defaultCacheKeyGenerator = defaults.cacheKeyGenerator(); + if (!CacheKeyGenerator.class.equals(defaultCacheKeyGenerator)) { + return instance(defaultCacheKeyGenerator); + } + } + return defaultCacheKeyGenerator; + } + + private CacheResolverFactory cacheResolverFactoryFor(final CacheDefaults defaults, + final Class cacheResolverFactory) { + if (!CacheResolverFactory.class.equals(cacheResolverFactory)) { + return instance(cacheResolverFactory); + } + if (defaults != null) { + final Class defaultCacheResolverFactory = defaults.cacheResolverFactory(); + if (!CacheResolverFactory.class.equals(defaultCacheResolverFactory)) { + return instance(defaultCacheResolverFactory); + } + } + return defaultCacheResolverFactory(); + } + + private T instance(final Class type) { + final Set> beans = beanManager.getBeans(type); + if (beans.isEmpty()) { + if (CacheKeyGenerator.class == type) { + return (T) defaultCacheKeyGenerator; + } + if (CacheResolverFactory.class == type) { + return (T) defaultCacheResolverFactory(); + } + return null; + } + final Bean bean = beanManager.resolve(beans); + final CreationalContext context = beanManager.createCreationalContext(bean); + final Class scope = bean.getScope(); + final boolean normalScope = beanManager.isNormalScope(scope); + try { + final Object reference = beanManager.getReference(bean, bean.getBeanClass(), context); + if (!normalScope) { + toRelease.add(context); + } + return (T) reference; + } finally { + if (normalScope) { // TODO: release at the right moment, @PreDestroy? question is: do we assume it is thread safe? + context.release(); + } + } + } + + private CacheResolverFactoryImpl defaultCacheResolverFactory() { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + synchronized (this) { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + defaultCacheResolverFactory = new CacheResolverFactoryImpl(); + } + return defaultCacheResolverFactory; + } + + private Integer[] keyParameterIndexes(final Method method) { + final List keys = new LinkedList(); + final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + + // first check if keys are specified explicitely + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheKey.class)) { + keys.add(i); + break; + } + } + } + + // if not then use all parameters but value ones + if (keys.isEmpty()) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + boolean value = false; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheValue.class)) { + value = true; + break; + } + } + if (!value) { + keys.add(i); + } + } + } + return keys.toArray(new Integer[keys.size()]); + } + + private static final class MethodKey { + + private final Class base; + + private final Method delegate; + + private final int hash; + + private MethodKey(final Class base, final Method delegate) { + this.base = base; // we need a class to ensure inheritance don't fall in the same key + this.delegate = delegate; + this.hash = 31 * delegate.hashCode() + (base == null ? 0 : base.hashCode()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MethodKey classKey = MethodKey.class.cast(o); + return delegate.equals(classKey.delegate) + && ((base == null && classKey.base == null) || (base != null && base.equals(classKey.base))); + } + + @Override + public int hashCode() { + return hash; + } + } + + // TODO: split it in 5? + public static class MethodMeta { + + private final Class[] parameterTypes; + + private final List> parameterAnnotations; + + private final Set annotations; + + private final Integer[] keysIndices; + + private final Integer valueIndex; + + private final String cacheResultCacheName; + + private final CacheResolverFactory cacheResultResolverFactory; + + private final CacheKeyGenerator cacheResultKeyGenerator; + + private final CacheResult cacheResult; + + private final String cachePutCacheName; + + private final CacheResolverFactory cachePutResolverFactory; + + private final CacheKeyGenerator cachePutKeyGenerator; + + private final boolean cachePutAfter; + + private final CachePut cachePut; + + private final String cacheRemoveCacheName; + + private final CacheResolverFactory cacheRemoveResolverFactory; + + private final CacheKeyGenerator cacheRemoveKeyGenerator; + + private final boolean cacheRemoveAfter; + + private final CacheRemove cacheRemove; + + private final String cacheRemoveAllCacheName; + + private final CacheResolverFactory cacheRemoveAllResolverFactory; + + private final CacheRemoveAll cacheRemoveAll; + + private final boolean completionStage; + + public MethodMeta(Class[] parameterTypes, List> parameterAnnotations, Set annotations, + Integer[] keysIndices, Integer valueIndex, String cacheResultCacheName, + CacheResolverFactory cacheResultResolverFactory, CacheKeyGenerator cacheResultKeyGenerator, + CacheResult cacheResult, String cachePutCacheName, CacheResolverFactory cachePutResolverFactory, + CacheKeyGenerator cachePutKeyGenerator, boolean cachePutAfter, CachePut cachePut, String cacheRemoveCacheName, + CacheResolverFactory cacheRemoveResolverFactory, CacheKeyGenerator cacheRemoveKeyGenerator, + boolean cacheRemoveAfter, CacheRemove cacheRemove, String cacheRemoveAllCacheName, + CacheResolverFactory cacheRemoveAllResolverFactory, CacheRemoveAll cacheRemoveAll, + boolean completionStage) { + this.parameterTypes = parameterTypes; + this.parameterAnnotations = parameterAnnotations; + this.annotations = annotations; + this.keysIndices = keysIndices; + this.valueIndex = valueIndex; + this.cacheResultCacheName = cacheResultCacheName; + this.cacheResultResolverFactory = cacheResultResolverFactory; + this.cacheResultKeyGenerator = cacheResultKeyGenerator; + this.cacheResult = cacheResult; + this.cachePutCacheName = cachePutCacheName; + this.cachePutResolverFactory = cachePutResolverFactory; + this.cachePutKeyGenerator = cachePutKeyGenerator; + this.cachePutAfter = cachePutAfter; + this.cachePut = cachePut; + this.cacheRemoveCacheName = cacheRemoveCacheName; + this.cacheRemoveResolverFactory = cacheRemoveResolverFactory; + this.cacheRemoveKeyGenerator = cacheRemoveKeyGenerator; + this.cacheRemoveAfter = cacheRemoveAfter; + this.cacheRemove = cacheRemove; + this.cacheRemoveAllCacheName = cacheRemoveAllCacheName; + this.cacheRemoveAllResolverFactory = cacheRemoveAllResolverFactory; + this.cacheRemoveAll = cacheRemoveAll; + this.completionStage = completionStage; + } + + public boolean isCompletionStage() { + return completionStage; + } + + public boolean isCacheRemoveAfter() { + return cacheRemoveAfter; + } + + public boolean isCachePutAfter() { + return cachePutAfter; + } + + public Class[] getParameterTypes() { + return parameterTypes; + } + + public List> getParameterAnnotations() { + return parameterAnnotations; + } + + public String getCacheResultCacheName() { + return cacheResultCacheName; + } + + public CacheResolverFactory getCacheResultResolverFactory() { + return cacheResultResolverFactory; + } + + public CacheKeyGenerator getCacheResultKeyGenerator() { + return cacheResultKeyGenerator; + } + + public CacheResult getCacheResult() { + return cacheResult; + } + + public Set getAnnotations() { + return annotations; + } + + public Integer[] getKeysIndices() { + return keysIndices; + } + + public Integer getValueIndex() { + return valueIndex; + } + + public String getCachePutCacheName() { + return cachePutCacheName; + } + + public CacheResolverFactory getCachePutResolverFactory() { + return cachePutResolverFactory; + } + + public CacheKeyGenerator getCachePutKeyGenerator() { + return cachePutKeyGenerator; + } + + public CachePut getCachePut() { + return cachePut; + } + + public String getCacheRemoveCacheName() { + return cacheRemoveCacheName; + } + + public CacheResolverFactory getCacheRemoveResolverFactory() { + return cacheRemoveResolverFactory; + } + + public CacheKeyGenerator getCacheRemoveKeyGenerator() { + return cacheRemoveKeyGenerator; + } + + public CacheRemove getCacheRemove() { + return cacheRemove; + } + + public String getCacheRemoveAllCacheName() { + return cacheRemoveAllCacheName; + } + + public CacheResolverFactory getCacheRemoveAllResolverFactory() { + return cacheRemoveAllResolverFactory; + } + + public CacheRemoveAll getCacheRemoveAll() { + return cacheRemoveAll; + } + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_145/metadata.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_145/metadata.json new file mode 100644 index 000000000..75a774b4c --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_145/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CDIJCacheHelper_145", + "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/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 133, + "npe_method": "createMeta", + "deref_field": "cacheRemove", + "npe_class": "CDIJCacheHelper", + "repo": "geronimo-jcache-simple", + "bug_id": "CDIJCacheHelper_145" + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_145/npe.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_145/npe.json new file mode 100644 index 000000000..ccaffb175 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_145/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 133, + "npe_method": "createMeta", + "deref_field": "cacheRemove", + "npe_class": "CDIJCacheHelper" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_149/Dockerfile b/Java/geronimo-jcache-simple-CDIJCacheHelper_149/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_149/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CDIJCacheHelper_149/buggy.java b/Java/geronimo-jcache-simple-CDIJCacheHelper_149/buggy.java new file mode 100644 index 000000000..5e0f8cd56 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_149/buggy.java @@ -0,0 +1,535 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; + +import javax.annotation.PreDestroy; +import javax.cache.annotation.CacheDefaults; +import javax.cache.annotation.CacheKey; +import javax.cache.annotation.CacheKeyGenerator; +import javax.cache.annotation.CachePut; +import javax.cache.annotation.CacheRemove; +import javax.cache.annotation.CacheRemoveAll; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.CacheValue; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; + +@ApplicationScoped +public class CDIJCacheHelper { + + private static final Logger LOGGER = Logger.getLogger(CDIJCacheHelper.class.getName()); + + private static final boolean CLOSE_CACHE = !Boolean.getBoolean("org.apache.geronimo.jcache.simple.cdi.skip-close"); + + private final CacheKeyGeneratorImpl defaultCacheKeyGenerator = new CacheKeyGeneratorImpl(); + + private final Collection> toRelease = new ArrayList>(); + + private final ConcurrentMap methods = new ConcurrentHashMap(); + + private volatile CacheResolverFactoryImpl defaultCacheResolverFactory = null; // lazy to not create any cache if not needed + + @Inject + private BeanManager beanManager; + + @PreDestroy + private void release() { + if (CLOSE_CACHE && defaultCacheResolverFactory != null) { + defaultCacheResolverFactory.release(); + } + for (final CreationalContext cc : toRelease) { + try { + cc.release(); + } catch (final RuntimeException re) { + LOGGER.warning(re.getMessage()); + } + } + } + + public MethodMeta findMeta(final InvocationContext ic) { + final Method mtd = ic.getMethod(); + final Class refType = findKeyType(ic.getTarget()); + final MethodKey key = new MethodKey(refType, mtd); + MethodMeta methodMeta = methods.get(key); + if (methodMeta == null) { + synchronized (this) { + methodMeta = methods.get(key); + if (methodMeta == null) { + methodMeta = createMeta(ic); + methods.put(key, methodMeta); + } + } + } + return methodMeta; + } + + private Class findKeyType(final Object target) { + if (null == target) { + return null; + } + return target.getClass(); + } + + // it is unlikely we have all annotations but for now we have a single meta model +// it is unlikely we have all annotations but for now we have a single meta model +private org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta createMeta(final javax.interceptor.InvocationContext ic) { + final javax.cache.annotation.CacheDefaults defaults = findDefaults(ic.getTarget() == null ? null : ic.getTarget().getClass(), ic.getMethod()); + final java.lang.Class[] parameterTypes = ic.getMethod().getParameterTypes(); + final java.lang.annotation.Annotation[][] parameterAnnotations = ic.getMethod().getParameterAnnotations(); + final java.util.List> annotations = new java.util.ArrayList>(); + for (final java.lang.annotation.Annotation[] parameterAnnotation : parameterAnnotations) { + final java.util.Set set = new java.util.HashSet(parameterAnnotation.length); + set.addAll(java.util.Arrays.asList(parameterAnnotation)); + annotations.add(set); + } + final java.util.Set mtdAnnotations = new java.util.HashSet(); + mtdAnnotations.addAll(java.util.Arrays.asList(ic.getMethod().getAnnotations())); + final javax.cache.annotation.CacheResult cacheResult = ic.getMethod().getAnnotation(javax.cache.annotation.CacheResult.class); + final java.lang.String cacheResultCacheResultName = (cacheResult == null) ? null : defaultName(ic.getMethod(), defaults, cacheResult.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheResultCacheResolverFactory = (cacheResult == null) ? null : cacheResolverFactoryFor(defaults, cacheResult.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheResultCacheKeyGenerator = (cacheResult == null) ? null : cacheKeyGeneratorFor(defaults, cacheResult.cacheKeyGenerator()); + final javax.cache.annotation.CachePut cachePut = ic.getMethod().getAnnotation(javax.cache.annotation.CachePut.class); + final java.lang.String cachePutCachePutName = (cachePut == null) ? null : defaultName(ic.getMethod(), defaults, cachePut.cacheName()); + final javax.cache.annotation.CacheResolverFactory cachePutCacheResolverFactory = (cachePut == null) ? null : cacheResolverFactoryFor(defaults, cachePut.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cachePutCacheKeyGenerator = (cachePut == null) ? null : cacheKeyGeneratorFor(defaults, cachePut.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemove cacheRemove = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemove.class); + final java.lang.String cacheRemoveCacheRemoveName = (cacheRemove == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemove.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveCacheResolverFactory = (cacheRemove == null) ? null : cacheResolverFactoryFor(defaults, cacheRemove.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheRemoveCacheKeyGenerator = (cacheRemove == null) ? null : cacheKeyGeneratorFor(defaults, cacheRemove.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemoveAll cacheRemoveAll = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemoveAll.class); + final java.lang.String cacheRemoveAllCacheRemoveAllName = defaultName(ic.getMethod(), defaults, /* NPEX_NULL_EXP */ + cacheRemoveAll.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveAllCacheResolverFactory = (cacheRemoveAll == null) ? null : cacheResolverFactoryFor(defaults, cacheRemoveAll.cacheResolverFactory()); + return new org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta(parameterTypes, annotations, mtdAnnotations, keyParameterIndexes(ic.getMethod()), getValueParameter(annotations), cacheResultCacheResultName, cacheResultCacheResolverFactory, cacheResultCacheKeyGenerator, cacheResult, cachePutCachePutName, cachePutCacheResolverFactory, cachePutCacheKeyGenerator, (cachePut != null) && cachePut.afterInvocation(), cachePut, cacheRemoveCacheRemoveName, cacheRemoveCacheResolverFactory, cacheRemoveCacheKeyGenerator, (cacheRemove != null) && cacheRemove.afterInvocation(), cacheRemove, cacheRemoveAllCacheRemoveAllName, cacheRemoveAllCacheResolverFactory, cacheRemoveAll, java.util.concurrent.CompletionStage.class.isAssignableFrom(ic.getMethod().getReturnType())); +} + + private Integer getValueParameter(final List> annotations) { + int idx = 0; + for (final Set set : annotations) { + for (final Annotation a : set) { + if (a.annotationType() == CacheValue.class) { + return idx; + } + } + } + return -1; + } + + private String defaultName(final Method method, final CacheDefaults defaults, final String cacheName) { + if (!cacheName.isEmpty()) { + return cacheName; + } + if (defaults != null) { + final String name = defaults.cacheName(); + if (!name.isEmpty()) { + return name; + } + } + + final StringBuilder name = new StringBuilder(method.getDeclaringClass().getName()); + name.append("."); + name.append(method.getName()); + name.append("("); + final Class[] parameterTypes = method.getParameterTypes(); + for (int pIdx = 0; pIdx < parameterTypes.length; pIdx++) { + name.append(parameterTypes[pIdx].getName()); + if ((pIdx + 1) < parameterTypes.length) { + name.append(","); + } + } + name.append(")"); + return name.toString(); + } + + private CacheDefaults findDefaults(final Class targetType, final Method method) { + if (Proxy.isProxyClass(targetType)) // target doesnt hold annotations + { + final Class api = method.getDeclaringClass(); + for (final Class type : targetType.getInterfaces()) { + if (!api.isAssignableFrom(type)) { + continue; + } + return extractDefaults(type); + } + } + return extractDefaults(targetType); + } + + private CacheDefaults extractDefaults(final Class type) { + CacheDefaults annotation = null; + Class clazz = type; + while (clazz != null && clazz != Object.class) { + annotation = clazz.getAnnotation(CacheDefaults.class); + if (annotation != null) { + break; + } + clazz = clazz.getSuperclass(); + } + return annotation; + } + + public boolean isIncluded(final Class aClass, final Class[] in, final Class[] out) { + if (in.length == 0 && out.length == 0) { + return false; + } + for (final Class potentialIn : in) { + if (potentialIn.isAssignableFrom(aClass)) { + for (final Class potentialOut : out) { + if (potentialOut.isAssignableFrom(aClass)) { + return false; + } + } + return true; + } + } + return false; + } + + private CacheKeyGenerator cacheKeyGeneratorFor(final CacheDefaults defaults, + final Class cacheKeyGenerator) { + if (!CacheKeyGenerator.class.equals(cacheKeyGenerator)) { + return instance(cacheKeyGenerator); + } + if (defaults != null) { + final Class defaultCacheKeyGenerator = defaults.cacheKeyGenerator(); + if (!CacheKeyGenerator.class.equals(defaultCacheKeyGenerator)) { + return instance(defaultCacheKeyGenerator); + } + } + return defaultCacheKeyGenerator; + } + + private CacheResolverFactory cacheResolverFactoryFor(final CacheDefaults defaults, + final Class cacheResolverFactory) { + if (!CacheResolverFactory.class.equals(cacheResolverFactory)) { + return instance(cacheResolverFactory); + } + if (defaults != null) { + final Class defaultCacheResolverFactory = defaults.cacheResolverFactory(); + if (!CacheResolverFactory.class.equals(defaultCacheResolverFactory)) { + return instance(defaultCacheResolverFactory); + } + } + return defaultCacheResolverFactory(); + } + + private T instance(final Class type) { + final Set> beans = beanManager.getBeans(type); + if (beans.isEmpty()) { + if (CacheKeyGenerator.class == type) { + return (T) defaultCacheKeyGenerator; + } + if (CacheResolverFactory.class == type) { + return (T) defaultCacheResolverFactory(); + } + return null; + } + final Bean bean = beanManager.resolve(beans); + final CreationalContext context = beanManager.createCreationalContext(bean); + final Class scope = bean.getScope(); + final boolean normalScope = beanManager.isNormalScope(scope); + try { + final Object reference = beanManager.getReference(bean, bean.getBeanClass(), context); + if (!normalScope) { + toRelease.add(context); + } + return (T) reference; + } finally { + if (normalScope) { // TODO: release at the right moment, @PreDestroy? question is: do we assume it is thread safe? + context.release(); + } + } + } + + private CacheResolverFactoryImpl defaultCacheResolverFactory() { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + synchronized (this) { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + defaultCacheResolverFactory = new CacheResolverFactoryImpl(); + } + return defaultCacheResolverFactory; + } + + private Integer[] keyParameterIndexes(final Method method) { + final List keys = new LinkedList(); + final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + + // first check if keys are specified explicitely + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheKey.class)) { + keys.add(i); + break; + } + } + } + + // if not then use all parameters but value ones + if (keys.isEmpty()) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + boolean value = false; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheValue.class)) { + value = true; + break; + } + } + if (!value) { + keys.add(i); + } + } + } + return keys.toArray(new Integer[keys.size()]); + } + + private static final class MethodKey { + + private final Class base; + + private final Method delegate; + + private final int hash; + + private MethodKey(final Class base, final Method delegate) { + this.base = base; // we need a class to ensure inheritance don't fall in the same key + this.delegate = delegate; + this.hash = 31 * delegate.hashCode() + (base == null ? 0 : base.hashCode()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MethodKey classKey = MethodKey.class.cast(o); + return delegate.equals(classKey.delegate) + && ((base == null && classKey.base == null) || (base != null && base.equals(classKey.base))); + } + + @Override + public int hashCode() { + return hash; + } + } + + // TODO: split it in 5? + public static class MethodMeta { + + private final Class[] parameterTypes; + + private final List> parameterAnnotations; + + private final Set annotations; + + private final Integer[] keysIndices; + + private final Integer valueIndex; + + private final String cacheResultCacheName; + + private final CacheResolverFactory cacheResultResolverFactory; + + private final CacheKeyGenerator cacheResultKeyGenerator; + + private final CacheResult cacheResult; + + private final String cachePutCacheName; + + private final CacheResolverFactory cachePutResolverFactory; + + private final CacheKeyGenerator cachePutKeyGenerator; + + private final boolean cachePutAfter; + + private final CachePut cachePut; + + private final String cacheRemoveCacheName; + + private final CacheResolverFactory cacheRemoveResolverFactory; + + private final CacheKeyGenerator cacheRemoveKeyGenerator; + + private final boolean cacheRemoveAfter; + + private final CacheRemove cacheRemove; + + private final String cacheRemoveAllCacheName; + + private final CacheResolverFactory cacheRemoveAllResolverFactory; + + private final CacheRemoveAll cacheRemoveAll; + + private final boolean completionStage; + + public MethodMeta(Class[] parameterTypes, List> parameterAnnotations, Set annotations, + Integer[] keysIndices, Integer valueIndex, String cacheResultCacheName, + CacheResolverFactory cacheResultResolverFactory, CacheKeyGenerator cacheResultKeyGenerator, + CacheResult cacheResult, String cachePutCacheName, CacheResolverFactory cachePutResolverFactory, + CacheKeyGenerator cachePutKeyGenerator, boolean cachePutAfter, CachePut cachePut, String cacheRemoveCacheName, + CacheResolverFactory cacheRemoveResolverFactory, CacheKeyGenerator cacheRemoveKeyGenerator, + boolean cacheRemoveAfter, CacheRemove cacheRemove, String cacheRemoveAllCacheName, + CacheResolverFactory cacheRemoveAllResolverFactory, CacheRemoveAll cacheRemoveAll, + boolean completionStage) { + this.parameterTypes = parameterTypes; + this.parameterAnnotations = parameterAnnotations; + this.annotations = annotations; + this.keysIndices = keysIndices; + this.valueIndex = valueIndex; + this.cacheResultCacheName = cacheResultCacheName; + this.cacheResultResolverFactory = cacheResultResolverFactory; + this.cacheResultKeyGenerator = cacheResultKeyGenerator; + this.cacheResult = cacheResult; + this.cachePutCacheName = cachePutCacheName; + this.cachePutResolverFactory = cachePutResolverFactory; + this.cachePutKeyGenerator = cachePutKeyGenerator; + this.cachePutAfter = cachePutAfter; + this.cachePut = cachePut; + this.cacheRemoveCacheName = cacheRemoveCacheName; + this.cacheRemoveResolverFactory = cacheRemoveResolverFactory; + this.cacheRemoveKeyGenerator = cacheRemoveKeyGenerator; + this.cacheRemoveAfter = cacheRemoveAfter; + this.cacheRemove = cacheRemove; + this.cacheRemoveAllCacheName = cacheRemoveAllCacheName; + this.cacheRemoveAllResolverFactory = cacheRemoveAllResolverFactory; + this.cacheRemoveAll = cacheRemoveAll; + this.completionStage = completionStage; + } + + public boolean isCompletionStage() { + return completionStage; + } + + public boolean isCacheRemoveAfter() { + return cacheRemoveAfter; + } + + public boolean isCachePutAfter() { + return cachePutAfter; + } + + public Class[] getParameterTypes() { + return parameterTypes; + } + + public List> getParameterAnnotations() { + return parameterAnnotations; + } + + public String getCacheResultCacheName() { + return cacheResultCacheName; + } + + public CacheResolverFactory getCacheResultResolverFactory() { + return cacheResultResolverFactory; + } + + public CacheKeyGenerator getCacheResultKeyGenerator() { + return cacheResultKeyGenerator; + } + + public CacheResult getCacheResult() { + return cacheResult; + } + + public Set getAnnotations() { + return annotations; + } + + public Integer[] getKeysIndices() { + return keysIndices; + } + + public Integer getValueIndex() { + return valueIndex; + } + + public String getCachePutCacheName() { + return cachePutCacheName; + } + + public CacheResolverFactory getCachePutResolverFactory() { + return cachePutResolverFactory; + } + + public CacheKeyGenerator getCachePutKeyGenerator() { + return cachePutKeyGenerator; + } + + public CachePut getCachePut() { + return cachePut; + } + + public String getCacheRemoveCacheName() { + return cacheRemoveCacheName; + } + + public CacheResolverFactory getCacheRemoveResolverFactory() { + return cacheRemoveResolverFactory; + } + + public CacheKeyGenerator getCacheRemoveKeyGenerator() { + return cacheRemoveKeyGenerator; + } + + public CacheRemove getCacheRemove() { + return cacheRemove; + } + + public String getCacheRemoveAllCacheName() { + return cacheRemoveAllCacheName; + } + + public CacheResolverFactory getCacheRemoveAllResolverFactory() { + return cacheRemoveAllResolverFactory; + } + + public CacheRemoveAll getCacheRemoveAll() { + return cacheRemoveAll; + } + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_149/metadata.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_149/metadata.json new file mode 100644 index 000000000..84288defc --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_149/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CDIJCacheHelper_149", + "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/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 137, + "npe_method": "createMeta", + "deref_field": "cacheRemoveAll", + "npe_class": "CDIJCacheHelper", + "repo": "geronimo-jcache-simple", + "bug_id": "CDIJCacheHelper_149" + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_149/npe.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_149/npe.json new file mode 100644 index 000000000..43b7522c5 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_149/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 137, + "npe_method": "createMeta", + "deref_field": "cacheRemoveAll", + "npe_class": "CDIJCacheHelper" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_151/Dockerfile b/Java/geronimo-jcache-simple-CDIJCacheHelper_151/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_151/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CDIJCacheHelper_151/buggy.java b/Java/geronimo-jcache-simple-CDIJCacheHelper_151/buggy.java new file mode 100644 index 000000000..1d471e3b5 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_151/buggy.java @@ -0,0 +1,535 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; + +import javax.annotation.PreDestroy; +import javax.cache.annotation.CacheDefaults; +import javax.cache.annotation.CacheKey; +import javax.cache.annotation.CacheKeyGenerator; +import javax.cache.annotation.CachePut; +import javax.cache.annotation.CacheRemove; +import javax.cache.annotation.CacheRemoveAll; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.CacheValue; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; + +@ApplicationScoped +public class CDIJCacheHelper { + + private static final Logger LOGGER = Logger.getLogger(CDIJCacheHelper.class.getName()); + + private static final boolean CLOSE_CACHE = !Boolean.getBoolean("org.apache.geronimo.jcache.simple.cdi.skip-close"); + + private final CacheKeyGeneratorImpl defaultCacheKeyGenerator = new CacheKeyGeneratorImpl(); + + private final Collection> toRelease = new ArrayList>(); + + private final ConcurrentMap methods = new ConcurrentHashMap(); + + private volatile CacheResolverFactoryImpl defaultCacheResolverFactory = null; // lazy to not create any cache if not needed + + @Inject + private BeanManager beanManager; + + @PreDestroy + private void release() { + if (CLOSE_CACHE && defaultCacheResolverFactory != null) { + defaultCacheResolverFactory.release(); + } + for (final CreationalContext cc : toRelease) { + try { + cc.release(); + } catch (final RuntimeException re) { + LOGGER.warning(re.getMessage()); + } + } + } + + public MethodMeta findMeta(final InvocationContext ic) { + final Method mtd = ic.getMethod(); + final Class refType = findKeyType(ic.getTarget()); + final MethodKey key = new MethodKey(refType, mtd); + MethodMeta methodMeta = methods.get(key); + if (methodMeta == null) { + synchronized (this) { + methodMeta = methods.get(key); + if (methodMeta == null) { + methodMeta = createMeta(ic); + methods.put(key, methodMeta); + } + } + } + return methodMeta; + } + + private Class findKeyType(final Object target) { + if (null == target) { + return null; + } + return target.getClass(); + } + + // it is unlikely we have all annotations but for now we have a single meta model +// it is unlikely we have all annotations but for now we have a single meta model +private org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta createMeta(final javax.interceptor.InvocationContext ic) { + final javax.cache.annotation.CacheDefaults defaults = findDefaults(ic.getTarget() == null ? null : ic.getTarget().getClass(), ic.getMethod()); + final java.lang.Class[] parameterTypes = ic.getMethod().getParameterTypes(); + final java.lang.annotation.Annotation[][] parameterAnnotations = ic.getMethod().getParameterAnnotations(); + final java.util.List> annotations = new java.util.ArrayList>(); + for (final java.lang.annotation.Annotation[] parameterAnnotation : parameterAnnotations) { + final java.util.Set set = new java.util.HashSet(parameterAnnotation.length); + set.addAll(java.util.Arrays.asList(parameterAnnotation)); + annotations.add(set); + } + final java.util.Set mtdAnnotations = new java.util.HashSet(); + mtdAnnotations.addAll(java.util.Arrays.asList(ic.getMethod().getAnnotations())); + final javax.cache.annotation.CacheResult cacheResult = ic.getMethod().getAnnotation(javax.cache.annotation.CacheResult.class); + final java.lang.String cacheResultCacheResultName = (cacheResult == null) ? null : defaultName(ic.getMethod(), defaults, cacheResult.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheResultCacheResolverFactory = (cacheResult == null) ? null : cacheResolverFactoryFor(defaults, cacheResult.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheResultCacheKeyGenerator = (cacheResult == null) ? null : cacheKeyGeneratorFor(defaults, cacheResult.cacheKeyGenerator()); + final javax.cache.annotation.CachePut cachePut = ic.getMethod().getAnnotation(javax.cache.annotation.CachePut.class); + final java.lang.String cachePutCachePutName = (cachePut == null) ? null : defaultName(ic.getMethod(), defaults, cachePut.cacheName()); + final javax.cache.annotation.CacheResolverFactory cachePutCacheResolverFactory = (cachePut == null) ? null : cacheResolverFactoryFor(defaults, cachePut.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cachePutCacheKeyGenerator = (cachePut == null) ? null : cacheKeyGeneratorFor(defaults, cachePut.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemove cacheRemove = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemove.class); + final java.lang.String cacheRemoveCacheRemoveName = (cacheRemove == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemove.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveCacheResolverFactory = (cacheRemove == null) ? null : cacheResolverFactoryFor(defaults, cacheRemove.cacheResolverFactory()); + final javax.cache.annotation.CacheKeyGenerator cacheRemoveCacheKeyGenerator = (cacheRemove == null) ? null : cacheKeyGeneratorFor(defaults, cacheRemove.cacheKeyGenerator()); + final javax.cache.annotation.CacheRemoveAll cacheRemoveAll = ic.getMethod().getAnnotation(javax.cache.annotation.CacheRemoveAll.class); + final java.lang.String cacheRemoveAllCacheRemoveAllName = (/* NPEX_NULL_EXP */ + cacheRemoveAll == null) ? null : defaultName(ic.getMethod(), defaults, cacheRemoveAll.cacheName()); + final javax.cache.annotation.CacheResolverFactory cacheRemoveAllCacheResolverFactory = cacheResolverFactoryFor(defaults, cacheRemoveAll.cacheResolverFactory()); + return new org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta(parameterTypes, annotations, mtdAnnotations, keyParameterIndexes(ic.getMethod()), getValueParameter(annotations), cacheResultCacheResultName, cacheResultCacheResolverFactory, cacheResultCacheKeyGenerator, cacheResult, cachePutCachePutName, cachePutCacheResolverFactory, cachePutCacheKeyGenerator, (cachePut != null) && cachePut.afterInvocation(), cachePut, cacheRemoveCacheRemoveName, cacheRemoveCacheResolverFactory, cacheRemoveCacheKeyGenerator, (cacheRemove != null) && cacheRemove.afterInvocation(), cacheRemove, cacheRemoveAllCacheRemoveAllName, cacheRemoveAllCacheResolverFactory, cacheRemoveAll, java.util.concurrent.CompletionStage.class.isAssignableFrom(ic.getMethod().getReturnType())); +} + + private Integer getValueParameter(final List> annotations) { + int idx = 0; + for (final Set set : annotations) { + for (final Annotation a : set) { + if (a.annotationType() == CacheValue.class) { + return idx; + } + } + } + return -1; + } + + private String defaultName(final Method method, final CacheDefaults defaults, final String cacheName) { + if (!cacheName.isEmpty()) { + return cacheName; + } + if (defaults != null) { + final String name = defaults.cacheName(); + if (!name.isEmpty()) { + return name; + } + } + + final StringBuilder name = new StringBuilder(method.getDeclaringClass().getName()); + name.append("."); + name.append(method.getName()); + name.append("("); + final Class[] parameterTypes = method.getParameterTypes(); + for (int pIdx = 0; pIdx < parameterTypes.length; pIdx++) { + name.append(parameterTypes[pIdx].getName()); + if ((pIdx + 1) < parameterTypes.length) { + name.append(","); + } + } + name.append(")"); + return name.toString(); + } + + private CacheDefaults findDefaults(final Class targetType, final Method method) { + if (Proxy.isProxyClass(targetType)) // target doesnt hold annotations + { + final Class api = method.getDeclaringClass(); + for (final Class type : targetType.getInterfaces()) { + if (!api.isAssignableFrom(type)) { + continue; + } + return extractDefaults(type); + } + } + return extractDefaults(targetType); + } + + private CacheDefaults extractDefaults(final Class type) { + CacheDefaults annotation = null; + Class clazz = type; + while (clazz != null && clazz != Object.class) { + annotation = clazz.getAnnotation(CacheDefaults.class); + if (annotation != null) { + break; + } + clazz = clazz.getSuperclass(); + } + return annotation; + } + + public boolean isIncluded(final Class aClass, final Class[] in, final Class[] out) { + if (in.length == 0 && out.length == 0) { + return false; + } + for (final Class potentialIn : in) { + if (potentialIn.isAssignableFrom(aClass)) { + for (final Class potentialOut : out) { + if (potentialOut.isAssignableFrom(aClass)) { + return false; + } + } + return true; + } + } + return false; + } + + private CacheKeyGenerator cacheKeyGeneratorFor(final CacheDefaults defaults, + final Class cacheKeyGenerator) { + if (!CacheKeyGenerator.class.equals(cacheKeyGenerator)) { + return instance(cacheKeyGenerator); + } + if (defaults != null) { + final Class defaultCacheKeyGenerator = defaults.cacheKeyGenerator(); + if (!CacheKeyGenerator.class.equals(defaultCacheKeyGenerator)) { + return instance(defaultCacheKeyGenerator); + } + } + return defaultCacheKeyGenerator; + } + + private CacheResolverFactory cacheResolverFactoryFor(final CacheDefaults defaults, + final Class cacheResolverFactory) { + if (!CacheResolverFactory.class.equals(cacheResolverFactory)) { + return instance(cacheResolverFactory); + } + if (defaults != null) { + final Class defaultCacheResolverFactory = defaults.cacheResolverFactory(); + if (!CacheResolverFactory.class.equals(defaultCacheResolverFactory)) { + return instance(defaultCacheResolverFactory); + } + } + return defaultCacheResolverFactory(); + } + + private T instance(final Class type) { + final Set> beans = beanManager.getBeans(type); + if (beans.isEmpty()) { + if (CacheKeyGenerator.class == type) { + return (T) defaultCacheKeyGenerator; + } + if (CacheResolverFactory.class == type) { + return (T) defaultCacheResolverFactory(); + } + return null; + } + final Bean bean = beanManager.resolve(beans); + final CreationalContext context = beanManager.createCreationalContext(bean); + final Class scope = bean.getScope(); + final boolean normalScope = beanManager.isNormalScope(scope); + try { + final Object reference = beanManager.getReference(bean, bean.getBeanClass(), context); + if (!normalScope) { + toRelease.add(context); + } + return (T) reference; + } finally { + if (normalScope) { // TODO: release at the right moment, @PreDestroy? question is: do we assume it is thread safe? + context.release(); + } + } + } + + private CacheResolverFactoryImpl defaultCacheResolverFactory() { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + synchronized (this) { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + defaultCacheResolverFactory = new CacheResolverFactoryImpl(); + } + return defaultCacheResolverFactory; + } + + private Integer[] keyParameterIndexes(final Method method) { + final List keys = new LinkedList(); + final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + + // first check if keys are specified explicitely + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheKey.class)) { + keys.add(i); + break; + } + } + } + + // if not then use all parameters but value ones + if (keys.isEmpty()) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + boolean value = false; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheValue.class)) { + value = true; + break; + } + } + if (!value) { + keys.add(i); + } + } + } + return keys.toArray(new Integer[keys.size()]); + } + + private static final class MethodKey { + + private final Class base; + + private final Method delegate; + + private final int hash; + + private MethodKey(final Class base, final Method delegate) { + this.base = base; // we need a class to ensure inheritance don't fall in the same key + this.delegate = delegate; + this.hash = 31 * delegate.hashCode() + (base == null ? 0 : base.hashCode()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MethodKey classKey = MethodKey.class.cast(o); + return delegate.equals(classKey.delegate) + && ((base == null && classKey.base == null) || (base != null && base.equals(classKey.base))); + } + + @Override + public int hashCode() { + return hash; + } + } + + // TODO: split it in 5? + public static class MethodMeta { + + private final Class[] parameterTypes; + + private final List> parameterAnnotations; + + private final Set annotations; + + private final Integer[] keysIndices; + + private final Integer valueIndex; + + private final String cacheResultCacheName; + + private final CacheResolverFactory cacheResultResolverFactory; + + private final CacheKeyGenerator cacheResultKeyGenerator; + + private final CacheResult cacheResult; + + private final String cachePutCacheName; + + private final CacheResolverFactory cachePutResolverFactory; + + private final CacheKeyGenerator cachePutKeyGenerator; + + private final boolean cachePutAfter; + + private final CachePut cachePut; + + private final String cacheRemoveCacheName; + + private final CacheResolverFactory cacheRemoveResolverFactory; + + private final CacheKeyGenerator cacheRemoveKeyGenerator; + + private final boolean cacheRemoveAfter; + + private final CacheRemove cacheRemove; + + private final String cacheRemoveAllCacheName; + + private final CacheResolverFactory cacheRemoveAllResolverFactory; + + private final CacheRemoveAll cacheRemoveAll; + + private final boolean completionStage; + + public MethodMeta(Class[] parameterTypes, List> parameterAnnotations, Set annotations, + Integer[] keysIndices, Integer valueIndex, String cacheResultCacheName, + CacheResolverFactory cacheResultResolverFactory, CacheKeyGenerator cacheResultKeyGenerator, + CacheResult cacheResult, String cachePutCacheName, CacheResolverFactory cachePutResolverFactory, + CacheKeyGenerator cachePutKeyGenerator, boolean cachePutAfter, CachePut cachePut, String cacheRemoveCacheName, + CacheResolverFactory cacheRemoveResolverFactory, CacheKeyGenerator cacheRemoveKeyGenerator, + boolean cacheRemoveAfter, CacheRemove cacheRemove, String cacheRemoveAllCacheName, + CacheResolverFactory cacheRemoveAllResolverFactory, CacheRemoveAll cacheRemoveAll, + boolean completionStage) { + this.parameterTypes = parameterTypes; + this.parameterAnnotations = parameterAnnotations; + this.annotations = annotations; + this.keysIndices = keysIndices; + this.valueIndex = valueIndex; + this.cacheResultCacheName = cacheResultCacheName; + this.cacheResultResolverFactory = cacheResultResolverFactory; + this.cacheResultKeyGenerator = cacheResultKeyGenerator; + this.cacheResult = cacheResult; + this.cachePutCacheName = cachePutCacheName; + this.cachePutResolverFactory = cachePutResolverFactory; + this.cachePutKeyGenerator = cachePutKeyGenerator; + this.cachePutAfter = cachePutAfter; + this.cachePut = cachePut; + this.cacheRemoveCacheName = cacheRemoveCacheName; + this.cacheRemoveResolverFactory = cacheRemoveResolverFactory; + this.cacheRemoveKeyGenerator = cacheRemoveKeyGenerator; + this.cacheRemoveAfter = cacheRemoveAfter; + this.cacheRemove = cacheRemove; + this.cacheRemoveAllCacheName = cacheRemoveAllCacheName; + this.cacheRemoveAllResolverFactory = cacheRemoveAllResolverFactory; + this.cacheRemoveAll = cacheRemoveAll; + this.completionStage = completionStage; + } + + public boolean isCompletionStage() { + return completionStage; + } + + public boolean isCacheRemoveAfter() { + return cacheRemoveAfter; + } + + public boolean isCachePutAfter() { + return cachePutAfter; + } + + public Class[] getParameterTypes() { + return parameterTypes; + } + + public List> getParameterAnnotations() { + return parameterAnnotations; + } + + public String getCacheResultCacheName() { + return cacheResultCacheName; + } + + public CacheResolverFactory getCacheResultResolverFactory() { + return cacheResultResolverFactory; + } + + public CacheKeyGenerator getCacheResultKeyGenerator() { + return cacheResultKeyGenerator; + } + + public CacheResult getCacheResult() { + return cacheResult; + } + + public Set getAnnotations() { + return annotations; + } + + public Integer[] getKeysIndices() { + return keysIndices; + } + + public Integer getValueIndex() { + return valueIndex; + } + + public String getCachePutCacheName() { + return cachePutCacheName; + } + + public CacheResolverFactory getCachePutResolverFactory() { + return cachePutResolverFactory; + } + + public CacheKeyGenerator getCachePutKeyGenerator() { + return cachePutKeyGenerator; + } + + public CachePut getCachePut() { + return cachePut; + } + + public String getCacheRemoveCacheName() { + return cacheRemoveCacheName; + } + + public CacheResolverFactory getCacheRemoveResolverFactory() { + return cacheRemoveResolverFactory; + } + + public CacheKeyGenerator getCacheRemoveKeyGenerator() { + return cacheRemoveKeyGenerator; + } + + public CacheRemove getCacheRemove() { + return cacheRemove; + } + + public String getCacheRemoveAllCacheName() { + return cacheRemoveAllCacheName; + } + + public CacheResolverFactory getCacheRemoveAllResolverFactory() { + return cacheRemoveAllResolverFactory; + } + + public CacheRemoveAll getCacheRemoveAll() { + return cacheRemoveAll; + } + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_151/metadata.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_151/metadata.json new file mode 100644 index 000000000..3ca4b860b --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_151/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CDIJCacheHelper_151", + "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/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 137, + "npe_method": "createMeta", + "deref_field": "cacheRemoveAll", + "npe_class": "CDIJCacheHelper", + "repo": "geronimo-jcache-simple", + "bug_id": "CDIJCacheHelper_151" + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_151/npe.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_151/npe.json new file mode 100644 index 000000000..43b7522c5 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_151/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 137, + "npe_method": "createMeta", + "deref_field": "cacheRemoveAll", + "npe_class": "CDIJCacheHelper" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_180/Dockerfile b/Java/geronimo-jcache-simple-CDIJCacheHelper_180/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_180/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CDIJCacheHelper_180/buggy.java b/Java/geronimo-jcache-simple-CDIJCacheHelper_180/buggy.java new file mode 100644 index 000000000..b04487e44 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_180/buggy.java @@ -0,0 +1,557 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; + +import javax.annotation.PreDestroy; +import javax.cache.annotation.CacheDefaults; +import javax.cache.annotation.CacheKey; +import javax.cache.annotation.CacheKeyGenerator; +import javax.cache.annotation.CachePut; +import javax.cache.annotation.CacheRemove; +import javax.cache.annotation.CacheRemoveAll; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.CacheValue; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; + +@ApplicationScoped +public class CDIJCacheHelper { + + private static final Logger LOGGER = Logger.getLogger(CDIJCacheHelper.class.getName()); + + private static final boolean CLOSE_CACHE = !Boolean.getBoolean("org.apache.geronimo.jcache.simple.cdi.skip-close"); + + private final CacheKeyGeneratorImpl defaultCacheKeyGenerator = new CacheKeyGeneratorImpl(); + + private final Collection> toRelease = new ArrayList>(); + + private final ConcurrentMap methods = new ConcurrentHashMap(); + + private volatile CacheResolverFactoryImpl defaultCacheResolverFactory = null; // lazy to not create any cache if not needed + + @Inject + private BeanManager beanManager; + + @PreDestroy + private void release() { + if (CLOSE_CACHE && defaultCacheResolverFactory != null) { + defaultCacheResolverFactory.release(); + } + for (final CreationalContext cc : toRelease) { + try { + cc.release(); + } catch (final RuntimeException re) { + LOGGER.warning(re.getMessage()); + } + } + } + + public MethodMeta findMeta(final InvocationContext ic) { + final Method mtd = ic.getMethod(); + final Class refType = findKeyType(ic.getTarget()); + final MethodKey key = new MethodKey(refType, mtd); + MethodMeta methodMeta = methods.get(key); + if (methodMeta == null) { + synchronized (this) { + methodMeta = methods.get(key); + if (methodMeta == null) { + methodMeta = createMeta(ic); + methods.put(key, methodMeta); + } + } + } + return methodMeta; + } + + private Class findKeyType(final Object target) { + if (null == target) { + return null; + } + return target.getClass(); + } + + // it is unlikely we have all annotations but for now we have a single meta model + private MethodMeta createMeta(final InvocationContext ic) { + final CacheDefaults defaults = findDefaults(ic.getTarget() == null ? null : ic.getTarget().getClass(), ic.getMethod()); + + final Class[] parameterTypes = ic.getMethod().getParameterTypes(); + final Annotation[][] parameterAnnotations = ic.getMethod().getParameterAnnotations(); + final List> annotations = new ArrayList>(); + for (final Annotation[] parameterAnnotation : parameterAnnotations) { + final Set set = new HashSet(parameterAnnotation.length); + set.addAll(Arrays.asList(parameterAnnotation)); + annotations.add(set); + } + + final Set mtdAnnotations = new HashSet(); + mtdAnnotations.addAll(Arrays.asList(ic.getMethod().getAnnotations())); + + final CacheResult cacheResult = ic.getMethod().getAnnotation(CacheResult.class); + final String cacheResultCacheResultName = cacheResult == null ? null + : defaultName(ic.getMethod(), defaults, cacheResult.cacheName()); + final CacheResolverFactory cacheResultCacheResolverFactory = cacheResult == null ? null + : cacheResolverFactoryFor(defaults, cacheResult.cacheResolverFactory()); + final CacheKeyGenerator cacheResultCacheKeyGenerator = cacheResult == null ? null + : cacheKeyGeneratorFor(defaults, cacheResult.cacheKeyGenerator()); + + final CachePut cachePut = ic.getMethod().getAnnotation(CachePut.class); + final String cachePutCachePutName = cachePut == null ? null : defaultName(ic.getMethod(), defaults, cachePut.cacheName()); + final CacheResolverFactory cachePutCacheResolverFactory = cachePut == null ? null + : cacheResolverFactoryFor(defaults, cachePut.cacheResolverFactory()); + final CacheKeyGenerator cachePutCacheKeyGenerator = cachePut == null ? null + : cacheKeyGeneratorFor(defaults, cachePut.cacheKeyGenerator()); + + final CacheRemove cacheRemove = ic.getMethod().getAnnotation(CacheRemove.class); + final String cacheRemoveCacheRemoveName = cacheRemove == null ? null + : defaultName(ic.getMethod(), defaults, cacheRemove.cacheName()); + final CacheResolverFactory cacheRemoveCacheResolverFactory = cacheRemove == null ? null + : cacheResolverFactoryFor(defaults, cacheRemove.cacheResolverFactory()); + final CacheKeyGenerator cacheRemoveCacheKeyGenerator = cacheRemove == null ? null + : cacheKeyGeneratorFor(defaults, cacheRemove.cacheKeyGenerator()); + + final CacheRemoveAll cacheRemoveAll = ic.getMethod().getAnnotation(CacheRemoveAll.class); + final String cacheRemoveAllCacheRemoveAllName = cacheRemoveAll == null ? null + : defaultName(ic.getMethod(), defaults, cacheRemoveAll.cacheName()); + final CacheResolverFactory cacheRemoveAllCacheResolverFactory = cacheRemoveAll == null ? null + : cacheResolverFactoryFor(defaults, cacheRemoveAll.cacheResolverFactory()); + + return new MethodMeta(parameterTypes, annotations, mtdAnnotations, keyParameterIndexes(ic.getMethod()), + getValueParameter(annotations), cacheResultCacheResultName, + cacheResultCacheResolverFactory, cacheResultCacheKeyGenerator, cacheResult, cachePutCachePutName, + cachePutCacheResolverFactory, cachePutCacheKeyGenerator, cachePut != null && cachePut.afterInvocation(), cachePut, + cacheRemoveCacheRemoveName, cacheRemoveCacheResolverFactory, cacheRemoveCacheKeyGenerator, + cacheRemove != null && cacheRemove.afterInvocation(), cacheRemove, cacheRemoveAllCacheRemoveAllName, + cacheRemoveAllCacheResolverFactory, cacheRemoveAll, + CompletionStage.class.isAssignableFrom(ic.getMethod().getReturnType())); + } + + private Integer getValueParameter(final List> annotations) { + int idx = 0; + for (final Set set : annotations) { + for (final Annotation a : set) { + if (a.annotationType() == CacheValue.class) { + return idx; + } + } + } + return -1; + } + +private java.lang.String defaultName(final java.lang.reflect.Method method, final javax.cache.annotation.CacheDefaults defaults, final java.lang.String cacheName) { + if (!cacheName.isEmpty()) { + return cacheName; + } + { + final java.lang.String name = /* NPEX_NULL_EXP */ + defaults.cacheName(); + if (!name.isEmpty()) { + return name; + } + } + final java.lang.StringBuilder name = new java.lang.StringBuilder(method.getDeclaringClass().getName()); + name.append("."); + name.append(method.getName()); + name.append("("); + final java.lang.Class[] parameterTypes = method.getParameterTypes(); + for (int pIdx = 0; pIdx < parameterTypes.length; pIdx++) { + name.append(parameterTypes[pIdx].getName()); + if ((pIdx + 1) < parameterTypes.length) { + name.append(","); + } + } + name.append(")"); + return name.toString(); +} + + private CacheDefaults findDefaults(final Class targetType, final Method method) { + if (Proxy.isProxyClass(targetType)) // target doesnt hold annotations + { + final Class api = method.getDeclaringClass(); + for (final Class type : targetType.getInterfaces()) { + if (!api.isAssignableFrom(type)) { + continue; + } + return extractDefaults(type); + } + } + return extractDefaults(targetType); + } + + private CacheDefaults extractDefaults(final Class type) { + CacheDefaults annotation = null; + Class clazz = type; + while (clazz != null && clazz != Object.class) { + annotation = clazz.getAnnotation(CacheDefaults.class); + if (annotation != null) { + break; + } + clazz = clazz.getSuperclass(); + } + return annotation; + } + + public boolean isIncluded(final Class aClass, final Class[] in, final Class[] out) { + if (in.length == 0 && out.length == 0) { + return false; + } + for (final Class potentialIn : in) { + if (potentialIn.isAssignableFrom(aClass)) { + for (final Class potentialOut : out) { + if (potentialOut.isAssignableFrom(aClass)) { + return false; + } + } + return true; + } + } + return false; + } + + private CacheKeyGenerator cacheKeyGeneratorFor(final CacheDefaults defaults, + final Class cacheKeyGenerator) { + if (!CacheKeyGenerator.class.equals(cacheKeyGenerator)) { + return instance(cacheKeyGenerator); + } + if (defaults != null) { + final Class defaultCacheKeyGenerator = defaults.cacheKeyGenerator(); + if (!CacheKeyGenerator.class.equals(defaultCacheKeyGenerator)) { + return instance(defaultCacheKeyGenerator); + } + } + return defaultCacheKeyGenerator; + } + + private CacheResolverFactory cacheResolverFactoryFor(final CacheDefaults defaults, + final Class cacheResolverFactory) { + if (!CacheResolverFactory.class.equals(cacheResolverFactory)) { + return instance(cacheResolverFactory); + } + if (defaults != null) { + final Class defaultCacheResolverFactory = defaults.cacheResolverFactory(); + if (!CacheResolverFactory.class.equals(defaultCacheResolverFactory)) { + return instance(defaultCacheResolverFactory); + } + } + return defaultCacheResolverFactory(); + } + + private T instance(final Class type) { + final Set> beans = beanManager.getBeans(type); + if (beans.isEmpty()) { + if (CacheKeyGenerator.class == type) { + return (T) defaultCacheKeyGenerator; + } + if (CacheResolverFactory.class == type) { + return (T) defaultCacheResolverFactory(); + } + return null; + } + final Bean bean = beanManager.resolve(beans); + final CreationalContext context = beanManager.createCreationalContext(bean); + final Class scope = bean.getScope(); + final boolean normalScope = beanManager.isNormalScope(scope); + try { + final Object reference = beanManager.getReference(bean, bean.getBeanClass(), context); + if (!normalScope) { + toRelease.add(context); + } + return (T) reference; + } finally { + if (normalScope) { // TODO: release at the right moment, @PreDestroy? question is: do we assume it is thread safe? + context.release(); + } + } + } + + private CacheResolverFactoryImpl defaultCacheResolverFactory() { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + synchronized (this) { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + defaultCacheResolverFactory = new CacheResolverFactoryImpl(); + } + return defaultCacheResolverFactory; + } + + private Integer[] keyParameterIndexes(final Method method) { + final List keys = new LinkedList(); + final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + + // first check if keys are specified explicitely + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheKey.class)) { + keys.add(i); + break; + } + } + } + + // if not then use all parameters but value ones + if (keys.isEmpty()) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + boolean value = false; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheValue.class)) { + value = true; + break; + } + } + if (!value) { + keys.add(i); + } + } + } + return keys.toArray(new Integer[keys.size()]); + } + + private static final class MethodKey { + + private final Class base; + + private final Method delegate; + + private final int hash; + + private MethodKey(final Class base, final Method delegate) { + this.base = base; // we need a class to ensure inheritance don't fall in the same key + this.delegate = delegate; + this.hash = 31 * delegate.hashCode() + (base == null ? 0 : base.hashCode()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MethodKey classKey = MethodKey.class.cast(o); + return delegate.equals(classKey.delegate) + && ((base == null && classKey.base == null) || (base != null && base.equals(classKey.base))); + } + + @Override + public int hashCode() { + return hash; + } + } + + // TODO: split it in 5? + public static class MethodMeta { + + private final Class[] parameterTypes; + + private final List> parameterAnnotations; + + private final Set annotations; + + private final Integer[] keysIndices; + + private final Integer valueIndex; + + private final String cacheResultCacheName; + + private final CacheResolverFactory cacheResultResolverFactory; + + private final CacheKeyGenerator cacheResultKeyGenerator; + + private final CacheResult cacheResult; + + private final String cachePutCacheName; + + private final CacheResolverFactory cachePutResolverFactory; + + private final CacheKeyGenerator cachePutKeyGenerator; + + private final boolean cachePutAfter; + + private final CachePut cachePut; + + private final String cacheRemoveCacheName; + + private final CacheResolverFactory cacheRemoveResolverFactory; + + private final CacheKeyGenerator cacheRemoveKeyGenerator; + + private final boolean cacheRemoveAfter; + + private final CacheRemove cacheRemove; + + private final String cacheRemoveAllCacheName; + + private final CacheResolverFactory cacheRemoveAllResolverFactory; + + private final CacheRemoveAll cacheRemoveAll; + + private final boolean completionStage; + + public MethodMeta(Class[] parameterTypes, List> parameterAnnotations, Set annotations, + Integer[] keysIndices, Integer valueIndex, String cacheResultCacheName, + CacheResolverFactory cacheResultResolverFactory, CacheKeyGenerator cacheResultKeyGenerator, + CacheResult cacheResult, String cachePutCacheName, CacheResolverFactory cachePutResolverFactory, + CacheKeyGenerator cachePutKeyGenerator, boolean cachePutAfter, CachePut cachePut, String cacheRemoveCacheName, + CacheResolverFactory cacheRemoveResolverFactory, CacheKeyGenerator cacheRemoveKeyGenerator, + boolean cacheRemoveAfter, CacheRemove cacheRemove, String cacheRemoveAllCacheName, + CacheResolverFactory cacheRemoveAllResolverFactory, CacheRemoveAll cacheRemoveAll, + boolean completionStage) { + this.parameterTypes = parameterTypes; + this.parameterAnnotations = parameterAnnotations; + this.annotations = annotations; + this.keysIndices = keysIndices; + this.valueIndex = valueIndex; + this.cacheResultCacheName = cacheResultCacheName; + this.cacheResultResolverFactory = cacheResultResolverFactory; + this.cacheResultKeyGenerator = cacheResultKeyGenerator; + this.cacheResult = cacheResult; + this.cachePutCacheName = cachePutCacheName; + this.cachePutResolverFactory = cachePutResolverFactory; + this.cachePutKeyGenerator = cachePutKeyGenerator; + this.cachePutAfter = cachePutAfter; + this.cachePut = cachePut; + this.cacheRemoveCacheName = cacheRemoveCacheName; + this.cacheRemoveResolverFactory = cacheRemoveResolverFactory; + this.cacheRemoveKeyGenerator = cacheRemoveKeyGenerator; + this.cacheRemoveAfter = cacheRemoveAfter; + this.cacheRemove = cacheRemove; + this.cacheRemoveAllCacheName = cacheRemoveAllCacheName; + this.cacheRemoveAllResolverFactory = cacheRemoveAllResolverFactory; + this.cacheRemoveAll = cacheRemoveAll; + this.completionStage = completionStage; + } + + public boolean isCompletionStage() { + return completionStage; + } + + public boolean isCacheRemoveAfter() { + return cacheRemoveAfter; + } + + public boolean isCachePutAfter() { + return cachePutAfter; + } + + public Class[] getParameterTypes() { + return parameterTypes; + } + + public List> getParameterAnnotations() { + return parameterAnnotations; + } + + public String getCacheResultCacheName() { + return cacheResultCacheName; + } + + public CacheResolverFactory getCacheResultResolverFactory() { + return cacheResultResolverFactory; + } + + public CacheKeyGenerator getCacheResultKeyGenerator() { + return cacheResultKeyGenerator; + } + + public CacheResult getCacheResult() { + return cacheResult; + } + + public Set getAnnotations() { + return annotations; + } + + public Integer[] getKeysIndices() { + return keysIndices; + } + + public Integer getValueIndex() { + return valueIndex; + } + + public String getCachePutCacheName() { + return cachePutCacheName; + } + + public CacheResolverFactory getCachePutResolverFactory() { + return cachePutResolverFactory; + } + + public CacheKeyGenerator getCachePutKeyGenerator() { + return cachePutKeyGenerator; + } + + public CachePut getCachePut() { + return cachePut; + } + + public String getCacheRemoveCacheName() { + return cacheRemoveCacheName; + } + + public CacheResolverFactory getCacheRemoveResolverFactory() { + return cacheRemoveResolverFactory; + } + + public CacheKeyGenerator getCacheRemoveKeyGenerator() { + return cacheRemoveKeyGenerator; + } + + public CacheRemove getCacheRemove() { + return cacheRemove; + } + + public String getCacheRemoveAllCacheName() { + return cacheRemoveAllCacheName; + } + + public CacheResolverFactory getCacheRemoveAllResolverFactory() { + return cacheRemoveAllResolverFactory; + } + + public CacheRemoveAll getCacheRemoveAll() { + return cacheRemoveAll; + } + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_180/metadata.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_180/metadata.json new file mode 100644 index 000000000..992e41998 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_180/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CDIJCacheHelper_180", + "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/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 182, + "npe_method": "defaultName", + "deref_field": "defaults", + "npe_class": "CDIJCacheHelper", + "repo": "geronimo-jcache-simple", + "bug_id": "CDIJCacheHelper_180" + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_180/npe.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_180/npe.json new file mode 100644 index 000000000..bbe00d390 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_180/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 182, + "npe_method": "defaultName", + "deref_field": "defaults", + "npe_class": "CDIJCacheHelper" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_251/Dockerfile b/Java/geronimo-jcache-simple-CDIJCacheHelper_251/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_251/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CDIJCacheHelper_251/buggy.java b/Java/geronimo-jcache-simple-CDIJCacheHelper_251/buggy.java new file mode 100644 index 000000000..59f9452a3 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_251/buggy.java @@ -0,0 +1,557 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; + +import javax.annotation.PreDestroy; +import javax.cache.annotation.CacheDefaults; +import javax.cache.annotation.CacheKey; +import javax.cache.annotation.CacheKeyGenerator; +import javax.cache.annotation.CachePut; +import javax.cache.annotation.CacheRemove; +import javax.cache.annotation.CacheRemoveAll; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.CacheValue; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; + +@ApplicationScoped +public class CDIJCacheHelper { + + private static final Logger LOGGER = Logger.getLogger(CDIJCacheHelper.class.getName()); + + private static final boolean CLOSE_CACHE = !Boolean.getBoolean("org.apache.geronimo.jcache.simple.cdi.skip-close"); + + private final CacheKeyGeneratorImpl defaultCacheKeyGenerator = new CacheKeyGeneratorImpl(); + + private final Collection> toRelease = new ArrayList>(); + + private final ConcurrentMap methods = new ConcurrentHashMap(); + + private volatile CacheResolverFactoryImpl defaultCacheResolverFactory = null; // lazy to not create any cache if not needed + + @Inject + private BeanManager beanManager; + + @PreDestroy + private void release() { + if (CLOSE_CACHE && defaultCacheResolverFactory != null) { + defaultCacheResolverFactory.release(); + } + for (final CreationalContext cc : toRelease) { + try { + cc.release(); + } catch (final RuntimeException re) { + LOGGER.warning(re.getMessage()); + } + } + } + + public MethodMeta findMeta(final InvocationContext ic) { + final Method mtd = ic.getMethod(); + final Class refType = findKeyType(ic.getTarget()); + final MethodKey key = new MethodKey(refType, mtd); + MethodMeta methodMeta = methods.get(key); + if (methodMeta == null) { + synchronized (this) { + methodMeta = methods.get(key); + if (methodMeta == null) { + methodMeta = createMeta(ic); + methods.put(key, methodMeta); + } + } + } + return methodMeta; + } + + private Class findKeyType(final Object target) { + if (null == target) { + return null; + } + return target.getClass(); + } + + // it is unlikely we have all annotations but for now we have a single meta model + private MethodMeta createMeta(final InvocationContext ic) { + final CacheDefaults defaults = findDefaults(ic.getTarget() == null ? null : ic.getTarget().getClass(), ic.getMethod()); + + final Class[] parameterTypes = ic.getMethod().getParameterTypes(); + final Annotation[][] parameterAnnotations = ic.getMethod().getParameterAnnotations(); + final List> annotations = new ArrayList>(); + for (final Annotation[] parameterAnnotation : parameterAnnotations) { + final Set set = new HashSet(parameterAnnotation.length); + set.addAll(Arrays.asList(parameterAnnotation)); + annotations.add(set); + } + + final Set mtdAnnotations = new HashSet(); + mtdAnnotations.addAll(Arrays.asList(ic.getMethod().getAnnotations())); + + final CacheResult cacheResult = ic.getMethod().getAnnotation(CacheResult.class); + final String cacheResultCacheResultName = cacheResult == null ? null + : defaultName(ic.getMethod(), defaults, cacheResult.cacheName()); + final CacheResolverFactory cacheResultCacheResolverFactory = cacheResult == null ? null + : cacheResolverFactoryFor(defaults, cacheResult.cacheResolverFactory()); + final CacheKeyGenerator cacheResultCacheKeyGenerator = cacheResult == null ? null + : cacheKeyGeneratorFor(defaults, cacheResult.cacheKeyGenerator()); + + final CachePut cachePut = ic.getMethod().getAnnotation(CachePut.class); + final String cachePutCachePutName = cachePut == null ? null : defaultName(ic.getMethod(), defaults, cachePut.cacheName()); + final CacheResolverFactory cachePutCacheResolverFactory = cachePut == null ? null + : cacheResolverFactoryFor(defaults, cachePut.cacheResolverFactory()); + final CacheKeyGenerator cachePutCacheKeyGenerator = cachePut == null ? null + : cacheKeyGeneratorFor(defaults, cachePut.cacheKeyGenerator()); + + final CacheRemove cacheRemove = ic.getMethod().getAnnotation(CacheRemove.class); + final String cacheRemoveCacheRemoveName = cacheRemove == null ? null + : defaultName(ic.getMethod(), defaults, cacheRemove.cacheName()); + final CacheResolverFactory cacheRemoveCacheResolverFactory = cacheRemove == null ? null + : cacheResolverFactoryFor(defaults, cacheRemove.cacheResolverFactory()); + final CacheKeyGenerator cacheRemoveCacheKeyGenerator = cacheRemove == null ? null + : cacheKeyGeneratorFor(defaults, cacheRemove.cacheKeyGenerator()); + + final CacheRemoveAll cacheRemoveAll = ic.getMethod().getAnnotation(CacheRemoveAll.class); + final String cacheRemoveAllCacheRemoveAllName = cacheRemoveAll == null ? null + : defaultName(ic.getMethod(), defaults, cacheRemoveAll.cacheName()); + final CacheResolverFactory cacheRemoveAllCacheResolverFactory = cacheRemoveAll == null ? null + : cacheResolverFactoryFor(defaults, cacheRemoveAll.cacheResolverFactory()); + + return new MethodMeta(parameterTypes, annotations, mtdAnnotations, keyParameterIndexes(ic.getMethod()), + getValueParameter(annotations), cacheResultCacheResultName, + cacheResultCacheResolverFactory, cacheResultCacheKeyGenerator, cacheResult, cachePutCachePutName, + cachePutCacheResolverFactory, cachePutCacheKeyGenerator, cachePut != null && cachePut.afterInvocation(), cachePut, + cacheRemoveCacheRemoveName, cacheRemoveCacheResolverFactory, cacheRemoveCacheKeyGenerator, + cacheRemove != null && cacheRemove.afterInvocation(), cacheRemove, cacheRemoveAllCacheRemoveAllName, + cacheRemoveAllCacheResolverFactory, cacheRemoveAll, + CompletionStage.class.isAssignableFrom(ic.getMethod().getReturnType())); + } + + private Integer getValueParameter(final List> annotations) { + int idx = 0; + for (final Set set : annotations) { + for (final Annotation a : set) { + if (a.annotationType() == CacheValue.class) { + return idx; + } + } + } + return -1; + } + + private String defaultName(final Method method, final CacheDefaults defaults, final String cacheName) { + if (!cacheName.isEmpty()) { + return cacheName; + } + if (defaults != null) { + final String name = defaults.cacheName(); + if (!name.isEmpty()) { + return name; + } + } + + final StringBuilder name = new StringBuilder(method.getDeclaringClass().getName()); + name.append("."); + name.append(method.getName()); + name.append("("); + final Class[] parameterTypes = method.getParameterTypes(); + for (int pIdx = 0; pIdx < parameterTypes.length; pIdx++) { + name.append(parameterTypes[pIdx].getName()); + if ((pIdx + 1) < parameterTypes.length) { + name.append(","); + } + } + name.append(")"); + return name.toString(); + } + + private CacheDefaults findDefaults(final Class targetType, final Method method) { + if (Proxy.isProxyClass(targetType)) // target doesnt hold annotations + { + final Class api = method.getDeclaringClass(); + for (final Class type : targetType.getInterfaces()) { + if (!api.isAssignableFrom(type)) { + continue; + } + return extractDefaults(type); + } + } + return extractDefaults(targetType); + } + + private CacheDefaults extractDefaults(final Class type) { + CacheDefaults annotation = null; + Class clazz = type; + while (clazz != null && clazz != Object.class) { + annotation = clazz.getAnnotation(CacheDefaults.class); + if (annotation != null) { + break; + } + clazz = clazz.getSuperclass(); + } + return annotation; + } + + public boolean isIncluded(final Class aClass, final Class[] in, final Class[] out) { + if (in.length == 0 && out.length == 0) { + return false; + } + for (final Class potentialIn : in) { + if (potentialIn.isAssignableFrom(aClass)) { + for (final Class potentialOut : out) { + if (potentialOut.isAssignableFrom(aClass)) { + return false; + } + } + return true; + } + } + return false; + } + +private javax.cache.annotation.CacheKeyGenerator cacheKeyGeneratorFor(final javax.cache.annotation.CacheDefaults defaults, final java.lang.Class cacheKeyGenerator) { + if (!javax.cache.annotation.CacheKeyGenerator.class.equals(cacheKeyGenerator)) { + return instance(cacheKeyGenerator); + } + { + final java.lang.Class defaultCacheKeyGenerator = /* NPEX_NULL_EXP */ + defaults.cacheKeyGenerator(); + if (!javax.cache.annotation.CacheKeyGenerator.class.equals(defaultCacheKeyGenerator)) { + return instance(defaultCacheKeyGenerator); + } + } + return defaultCacheKeyGenerator; +} + + private CacheResolverFactory cacheResolverFactoryFor(final CacheDefaults defaults, + final Class cacheResolverFactory) { + if (!CacheResolverFactory.class.equals(cacheResolverFactory)) { + return instance(cacheResolverFactory); + } + if (defaults != null) { + final Class defaultCacheResolverFactory = defaults.cacheResolverFactory(); + if (!CacheResolverFactory.class.equals(defaultCacheResolverFactory)) { + return instance(defaultCacheResolverFactory); + } + } + return defaultCacheResolverFactory(); + } + + private T instance(final Class type) { + final Set> beans = beanManager.getBeans(type); + if (beans.isEmpty()) { + if (CacheKeyGenerator.class == type) { + return (T) defaultCacheKeyGenerator; + } + if (CacheResolverFactory.class == type) { + return (T) defaultCacheResolverFactory(); + } + return null; + } + final Bean bean = beanManager.resolve(beans); + final CreationalContext context = beanManager.createCreationalContext(bean); + final Class scope = bean.getScope(); + final boolean normalScope = beanManager.isNormalScope(scope); + try { + final Object reference = beanManager.getReference(bean, bean.getBeanClass(), context); + if (!normalScope) { + toRelease.add(context); + } + return (T) reference; + } finally { + if (normalScope) { // TODO: release at the right moment, @PreDestroy? question is: do we assume it is thread safe? + context.release(); + } + } + } + + private CacheResolverFactoryImpl defaultCacheResolverFactory() { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + synchronized (this) { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + defaultCacheResolverFactory = new CacheResolverFactoryImpl(); + } + return defaultCacheResolverFactory; + } + + private Integer[] keyParameterIndexes(final Method method) { + final List keys = new LinkedList(); + final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + + // first check if keys are specified explicitely + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheKey.class)) { + keys.add(i); + break; + } + } + } + + // if not then use all parameters but value ones + if (keys.isEmpty()) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + boolean value = false; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheValue.class)) { + value = true; + break; + } + } + if (!value) { + keys.add(i); + } + } + } + return keys.toArray(new Integer[keys.size()]); + } + + private static final class MethodKey { + + private final Class base; + + private final Method delegate; + + private final int hash; + + private MethodKey(final Class base, final Method delegate) { + this.base = base; // we need a class to ensure inheritance don't fall in the same key + this.delegate = delegate; + this.hash = 31 * delegate.hashCode() + (base == null ? 0 : base.hashCode()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MethodKey classKey = MethodKey.class.cast(o); + return delegate.equals(classKey.delegate) + && ((base == null && classKey.base == null) || (base != null && base.equals(classKey.base))); + } + + @Override + public int hashCode() { + return hash; + } + } + + // TODO: split it in 5? + public static class MethodMeta { + + private final Class[] parameterTypes; + + private final List> parameterAnnotations; + + private final Set annotations; + + private final Integer[] keysIndices; + + private final Integer valueIndex; + + private final String cacheResultCacheName; + + private final CacheResolverFactory cacheResultResolverFactory; + + private final CacheKeyGenerator cacheResultKeyGenerator; + + private final CacheResult cacheResult; + + private final String cachePutCacheName; + + private final CacheResolverFactory cachePutResolverFactory; + + private final CacheKeyGenerator cachePutKeyGenerator; + + private final boolean cachePutAfter; + + private final CachePut cachePut; + + private final String cacheRemoveCacheName; + + private final CacheResolverFactory cacheRemoveResolverFactory; + + private final CacheKeyGenerator cacheRemoveKeyGenerator; + + private final boolean cacheRemoveAfter; + + private final CacheRemove cacheRemove; + + private final String cacheRemoveAllCacheName; + + private final CacheResolverFactory cacheRemoveAllResolverFactory; + + private final CacheRemoveAll cacheRemoveAll; + + private final boolean completionStage; + + public MethodMeta(Class[] parameterTypes, List> parameterAnnotations, Set annotations, + Integer[] keysIndices, Integer valueIndex, String cacheResultCacheName, + CacheResolverFactory cacheResultResolverFactory, CacheKeyGenerator cacheResultKeyGenerator, + CacheResult cacheResult, String cachePutCacheName, CacheResolverFactory cachePutResolverFactory, + CacheKeyGenerator cachePutKeyGenerator, boolean cachePutAfter, CachePut cachePut, String cacheRemoveCacheName, + CacheResolverFactory cacheRemoveResolverFactory, CacheKeyGenerator cacheRemoveKeyGenerator, + boolean cacheRemoveAfter, CacheRemove cacheRemove, String cacheRemoveAllCacheName, + CacheResolverFactory cacheRemoveAllResolverFactory, CacheRemoveAll cacheRemoveAll, + boolean completionStage) { + this.parameterTypes = parameterTypes; + this.parameterAnnotations = parameterAnnotations; + this.annotations = annotations; + this.keysIndices = keysIndices; + this.valueIndex = valueIndex; + this.cacheResultCacheName = cacheResultCacheName; + this.cacheResultResolverFactory = cacheResultResolverFactory; + this.cacheResultKeyGenerator = cacheResultKeyGenerator; + this.cacheResult = cacheResult; + this.cachePutCacheName = cachePutCacheName; + this.cachePutResolverFactory = cachePutResolverFactory; + this.cachePutKeyGenerator = cachePutKeyGenerator; + this.cachePutAfter = cachePutAfter; + this.cachePut = cachePut; + this.cacheRemoveCacheName = cacheRemoveCacheName; + this.cacheRemoveResolverFactory = cacheRemoveResolverFactory; + this.cacheRemoveKeyGenerator = cacheRemoveKeyGenerator; + this.cacheRemoveAfter = cacheRemoveAfter; + this.cacheRemove = cacheRemove; + this.cacheRemoveAllCacheName = cacheRemoveAllCacheName; + this.cacheRemoveAllResolverFactory = cacheRemoveAllResolverFactory; + this.cacheRemoveAll = cacheRemoveAll; + this.completionStage = completionStage; + } + + public boolean isCompletionStage() { + return completionStage; + } + + public boolean isCacheRemoveAfter() { + return cacheRemoveAfter; + } + + public boolean isCachePutAfter() { + return cachePutAfter; + } + + public Class[] getParameterTypes() { + return parameterTypes; + } + + public List> getParameterAnnotations() { + return parameterAnnotations; + } + + public String getCacheResultCacheName() { + return cacheResultCacheName; + } + + public CacheResolverFactory getCacheResultResolverFactory() { + return cacheResultResolverFactory; + } + + public CacheKeyGenerator getCacheResultKeyGenerator() { + return cacheResultKeyGenerator; + } + + public CacheResult getCacheResult() { + return cacheResult; + } + + public Set getAnnotations() { + return annotations; + } + + public Integer[] getKeysIndices() { + return keysIndices; + } + + public Integer getValueIndex() { + return valueIndex; + } + + public String getCachePutCacheName() { + return cachePutCacheName; + } + + public CacheResolverFactory getCachePutResolverFactory() { + return cachePutResolverFactory; + } + + public CacheKeyGenerator getCachePutKeyGenerator() { + return cachePutKeyGenerator; + } + + public CachePut getCachePut() { + return cachePut; + } + + public String getCacheRemoveCacheName() { + return cacheRemoveCacheName; + } + + public CacheResolverFactory getCacheRemoveResolverFactory() { + return cacheRemoveResolverFactory; + } + + public CacheKeyGenerator getCacheRemoveKeyGenerator() { + return cacheRemoveKeyGenerator; + } + + public CacheRemove getCacheRemove() { + return cacheRemove; + } + + public String getCacheRemoveAllCacheName() { + return cacheRemoveAllCacheName; + } + + public CacheResolverFactory getCacheRemoveAllResolverFactory() { + return cacheRemoveAllResolverFactory; + } + + public CacheRemoveAll getCacheRemoveAll() { + return cacheRemoveAll; + } + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_251/metadata.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_251/metadata.json new file mode 100644 index 000000000..184c78d72 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_251/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CDIJCacheHelper_251", + "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/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 252, + "npe_method": "cacheKeyGeneratorFor", + "deref_field": "defaults", + "npe_class": "CDIJCacheHelper", + "repo": "geronimo-jcache-simple", + "bug_id": "CDIJCacheHelper_251" + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_251/npe.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_251/npe.json new file mode 100644 index 000000000..f7bdb6b11 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_251/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 252, + "npe_method": "cacheKeyGeneratorFor", + "deref_field": "defaults", + "npe_class": "CDIJCacheHelper" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_265/Dockerfile b/Java/geronimo-jcache-simple-CDIJCacheHelper_265/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_265/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CDIJCacheHelper_265/buggy.java b/Java/geronimo-jcache-simple-CDIJCacheHelper_265/buggy.java new file mode 100644 index 000000000..191e703d1 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_265/buggy.java @@ -0,0 +1,557 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Logger; + +import javax.annotation.PreDestroy; +import javax.cache.annotation.CacheDefaults; +import javax.cache.annotation.CacheKey; +import javax.cache.annotation.CacheKeyGenerator; +import javax.cache.annotation.CachePut; +import javax.cache.annotation.CacheRemove; +import javax.cache.annotation.CacheRemoveAll; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.CacheValue; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.interceptor.InvocationContext; + +@ApplicationScoped +public class CDIJCacheHelper { + + private static final Logger LOGGER = Logger.getLogger(CDIJCacheHelper.class.getName()); + + private static final boolean CLOSE_CACHE = !Boolean.getBoolean("org.apache.geronimo.jcache.simple.cdi.skip-close"); + + private final CacheKeyGeneratorImpl defaultCacheKeyGenerator = new CacheKeyGeneratorImpl(); + + private final Collection> toRelease = new ArrayList>(); + + private final ConcurrentMap methods = new ConcurrentHashMap(); + + private volatile CacheResolverFactoryImpl defaultCacheResolverFactory = null; // lazy to not create any cache if not needed + + @Inject + private BeanManager beanManager; + + @PreDestroy + private void release() { + if (CLOSE_CACHE && defaultCacheResolverFactory != null) { + defaultCacheResolverFactory.release(); + } + for (final CreationalContext cc : toRelease) { + try { + cc.release(); + } catch (final RuntimeException re) { + LOGGER.warning(re.getMessage()); + } + } + } + + public MethodMeta findMeta(final InvocationContext ic) { + final Method mtd = ic.getMethod(); + final Class refType = findKeyType(ic.getTarget()); + final MethodKey key = new MethodKey(refType, mtd); + MethodMeta methodMeta = methods.get(key); + if (methodMeta == null) { + synchronized (this) { + methodMeta = methods.get(key); + if (methodMeta == null) { + methodMeta = createMeta(ic); + methods.put(key, methodMeta); + } + } + } + return methodMeta; + } + + private Class findKeyType(final Object target) { + if (null == target) { + return null; + } + return target.getClass(); + } + + // it is unlikely we have all annotations but for now we have a single meta model + private MethodMeta createMeta(final InvocationContext ic) { + final CacheDefaults defaults = findDefaults(ic.getTarget() == null ? null : ic.getTarget().getClass(), ic.getMethod()); + + final Class[] parameterTypes = ic.getMethod().getParameterTypes(); + final Annotation[][] parameterAnnotations = ic.getMethod().getParameterAnnotations(); + final List> annotations = new ArrayList>(); + for (final Annotation[] parameterAnnotation : parameterAnnotations) { + final Set set = new HashSet(parameterAnnotation.length); + set.addAll(Arrays.asList(parameterAnnotation)); + annotations.add(set); + } + + final Set mtdAnnotations = new HashSet(); + mtdAnnotations.addAll(Arrays.asList(ic.getMethod().getAnnotations())); + + final CacheResult cacheResult = ic.getMethod().getAnnotation(CacheResult.class); + final String cacheResultCacheResultName = cacheResult == null ? null + : defaultName(ic.getMethod(), defaults, cacheResult.cacheName()); + final CacheResolverFactory cacheResultCacheResolverFactory = cacheResult == null ? null + : cacheResolverFactoryFor(defaults, cacheResult.cacheResolverFactory()); + final CacheKeyGenerator cacheResultCacheKeyGenerator = cacheResult == null ? null + : cacheKeyGeneratorFor(defaults, cacheResult.cacheKeyGenerator()); + + final CachePut cachePut = ic.getMethod().getAnnotation(CachePut.class); + final String cachePutCachePutName = cachePut == null ? null : defaultName(ic.getMethod(), defaults, cachePut.cacheName()); + final CacheResolverFactory cachePutCacheResolverFactory = cachePut == null ? null + : cacheResolverFactoryFor(defaults, cachePut.cacheResolverFactory()); + final CacheKeyGenerator cachePutCacheKeyGenerator = cachePut == null ? null + : cacheKeyGeneratorFor(defaults, cachePut.cacheKeyGenerator()); + + final CacheRemove cacheRemove = ic.getMethod().getAnnotation(CacheRemove.class); + final String cacheRemoveCacheRemoveName = cacheRemove == null ? null + : defaultName(ic.getMethod(), defaults, cacheRemove.cacheName()); + final CacheResolverFactory cacheRemoveCacheResolverFactory = cacheRemove == null ? null + : cacheResolverFactoryFor(defaults, cacheRemove.cacheResolverFactory()); + final CacheKeyGenerator cacheRemoveCacheKeyGenerator = cacheRemove == null ? null + : cacheKeyGeneratorFor(defaults, cacheRemove.cacheKeyGenerator()); + + final CacheRemoveAll cacheRemoveAll = ic.getMethod().getAnnotation(CacheRemoveAll.class); + final String cacheRemoveAllCacheRemoveAllName = cacheRemoveAll == null ? null + : defaultName(ic.getMethod(), defaults, cacheRemoveAll.cacheName()); + final CacheResolverFactory cacheRemoveAllCacheResolverFactory = cacheRemoveAll == null ? null + : cacheResolverFactoryFor(defaults, cacheRemoveAll.cacheResolverFactory()); + + return new MethodMeta(parameterTypes, annotations, mtdAnnotations, keyParameterIndexes(ic.getMethod()), + getValueParameter(annotations), cacheResultCacheResultName, + cacheResultCacheResolverFactory, cacheResultCacheKeyGenerator, cacheResult, cachePutCachePutName, + cachePutCacheResolverFactory, cachePutCacheKeyGenerator, cachePut != null && cachePut.afterInvocation(), cachePut, + cacheRemoveCacheRemoveName, cacheRemoveCacheResolverFactory, cacheRemoveCacheKeyGenerator, + cacheRemove != null && cacheRemove.afterInvocation(), cacheRemove, cacheRemoveAllCacheRemoveAllName, + cacheRemoveAllCacheResolverFactory, cacheRemoveAll, + CompletionStage.class.isAssignableFrom(ic.getMethod().getReturnType())); + } + + private Integer getValueParameter(final List> annotations) { + int idx = 0; + for (final Set set : annotations) { + for (final Annotation a : set) { + if (a.annotationType() == CacheValue.class) { + return idx; + } + } + } + return -1; + } + + private String defaultName(final Method method, final CacheDefaults defaults, final String cacheName) { + if (!cacheName.isEmpty()) { + return cacheName; + } + if (defaults != null) { + final String name = defaults.cacheName(); + if (!name.isEmpty()) { + return name; + } + } + + final StringBuilder name = new StringBuilder(method.getDeclaringClass().getName()); + name.append("."); + name.append(method.getName()); + name.append("("); + final Class[] parameterTypes = method.getParameterTypes(); + for (int pIdx = 0; pIdx < parameterTypes.length; pIdx++) { + name.append(parameterTypes[pIdx].getName()); + if ((pIdx + 1) < parameterTypes.length) { + name.append(","); + } + } + name.append(")"); + return name.toString(); + } + + private CacheDefaults findDefaults(final Class targetType, final Method method) { + if (Proxy.isProxyClass(targetType)) // target doesnt hold annotations + { + final Class api = method.getDeclaringClass(); + for (final Class type : targetType.getInterfaces()) { + if (!api.isAssignableFrom(type)) { + continue; + } + return extractDefaults(type); + } + } + return extractDefaults(targetType); + } + + private CacheDefaults extractDefaults(final Class type) { + CacheDefaults annotation = null; + Class clazz = type; + while (clazz != null && clazz != Object.class) { + annotation = clazz.getAnnotation(CacheDefaults.class); + if (annotation != null) { + break; + } + clazz = clazz.getSuperclass(); + } + return annotation; + } + + public boolean isIncluded(final Class aClass, final Class[] in, final Class[] out) { + if (in.length == 0 && out.length == 0) { + return false; + } + for (final Class potentialIn : in) { + if (potentialIn.isAssignableFrom(aClass)) { + for (final Class potentialOut : out) { + if (potentialOut.isAssignableFrom(aClass)) { + return false; + } + } + return true; + } + } + return false; + } + + private CacheKeyGenerator cacheKeyGeneratorFor(final CacheDefaults defaults, + final Class cacheKeyGenerator) { + if (!CacheKeyGenerator.class.equals(cacheKeyGenerator)) { + return instance(cacheKeyGenerator); + } + if (defaults != null) { + final Class defaultCacheKeyGenerator = defaults.cacheKeyGenerator(); + if (!CacheKeyGenerator.class.equals(defaultCacheKeyGenerator)) { + return instance(defaultCacheKeyGenerator); + } + } + return defaultCacheKeyGenerator; + } + +private javax.cache.annotation.CacheResolverFactory cacheResolverFactoryFor(final javax.cache.annotation.CacheDefaults defaults, final java.lang.Class cacheResolverFactory) { + if (!javax.cache.annotation.CacheResolverFactory.class.equals(cacheResolverFactory)) { + return instance(cacheResolverFactory); + } + { + final java.lang.Class defaultCacheResolverFactory = /* NPEX_NULL_EXP */ + defaults.cacheResolverFactory(); + if (!javax.cache.annotation.CacheResolverFactory.class.equals(defaultCacheResolverFactory)) { + return instance(defaultCacheResolverFactory); + } + } + return defaultCacheResolverFactory(); +} + + private T instance(final Class type) { + final Set> beans = beanManager.getBeans(type); + if (beans.isEmpty()) { + if (CacheKeyGenerator.class == type) { + return (T) defaultCacheKeyGenerator; + } + if (CacheResolverFactory.class == type) { + return (T) defaultCacheResolverFactory(); + } + return null; + } + final Bean bean = beanManager.resolve(beans); + final CreationalContext context = beanManager.createCreationalContext(bean); + final Class scope = bean.getScope(); + final boolean normalScope = beanManager.isNormalScope(scope); + try { + final Object reference = beanManager.getReference(bean, bean.getBeanClass(), context); + if (!normalScope) { + toRelease.add(context); + } + return (T) reference; + } finally { + if (normalScope) { // TODO: release at the right moment, @PreDestroy? question is: do we assume it is thread safe? + context.release(); + } + } + } + + private CacheResolverFactoryImpl defaultCacheResolverFactory() { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + synchronized (this) { + if (defaultCacheResolverFactory != null) { + return defaultCacheResolverFactory; + } + defaultCacheResolverFactory = new CacheResolverFactoryImpl(); + } + return defaultCacheResolverFactory; + } + + private Integer[] keyParameterIndexes(final Method method) { + final List keys = new LinkedList(); + final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + + // first check if keys are specified explicitely + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheKey.class)) { + keys.add(i); + break; + } + } + } + + // if not then use all parameters but value ones + if (keys.isEmpty()) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + final Annotation[] annotations = parameterAnnotations[i]; + boolean value = false; + for (final Annotation a : annotations) { + if (a.annotationType().equals(CacheValue.class)) { + value = true; + break; + } + } + if (!value) { + keys.add(i); + } + } + } + return keys.toArray(new Integer[keys.size()]); + } + + private static final class MethodKey { + + private final Class base; + + private final Method delegate; + + private final int hash; + + private MethodKey(final Class base, final Method delegate) { + this.base = base; // we need a class to ensure inheritance don't fall in the same key + this.delegate = delegate; + this.hash = 31 * delegate.hashCode() + (base == null ? 0 : base.hashCode()); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MethodKey classKey = MethodKey.class.cast(o); + return delegate.equals(classKey.delegate) + && ((base == null && classKey.base == null) || (base != null && base.equals(classKey.base))); + } + + @Override + public int hashCode() { + return hash; + } + } + + // TODO: split it in 5? + public static class MethodMeta { + + private final Class[] parameterTypes; + + private final List> parameterAnnotations; + + private final Set annotations; + + private final Integer[] keysIndices; + + private final Integer valueIndex; + + private final String cacheResultCacheName; + + private final CacheResolverFactory cacheResultResolverFactory; + + private final CacheKeyGenerator cacheResultKeyGenerator; + + private final CacheResult cacheResult; + + private final String cachePutCacheName; + + private final CacheResolverFactory cachePutResolverFactory; + + private final CacheKeyGenerator cachePutKeyGenerator; + + private final boolean cachePutAfter; + + private final CachePut cachePut; + + private final String cacheRemoveCacheName; + + private final CacheResolverFactory cacheRemoveResolverFactory; + + private final CacheKeyGenerator cacheRemoveKeyGenerator; + + private final boolean cacheRemoveAfter; + + private final CacheRemove cacheRemove; + + private final String cacheRemoveAllCacheName; + + private final CacheResolverFactory cacheRemoveAllResolverFactory; + + private final CacheRemoveAll cacheRemoveAll; + + private final boolean completionStage; + + public MethodMeta(Class[] parameterTypes, List> parameterAnnotations, Set annotations, + Integer[] keysIndices, Integer valueIndex, String cacheResultCacheName, + CacheResolverFactory cacheResultResolverFactory, CacheKeyGenerator cacheResultKeyGenerator, + CacheResult cacheResult, String cachePutCacheName, CacheResolverFactory cachePutResolverFactory, + CacheKeyGenerator cachePutKeyGenerator, boolean cachePutAfter, CachePut cachePut, String cacheRemoveCacheName, + CacheResolverFactory cacheRemoveResolverFactory, CacheKeyGenerator cacheRemoveKeyGenerator, + boolean cacheRemoveAfter, CacheRemove cacheRemove, String cacheRemoveAllCacheName, + CacheResolverFactory cacheRemoveAllResolverFactory, CacheRemoveAll cacheRemoveAll, + boolean completionStage) { + this.parameterTypes = parameterTypes; + this.parameterAnnotations = parameterAnnotations; + this.annotations = annotations; + this.keysIndices = keysIndices; + this.valueIndex = valueIndex; + this.cacheResultCacheName = cacheResultCacheName; + this.cacheResultResolverFactory = cacheResultResolverFactory; + this.cacheResultKeyGenerator = cacheResultKeyGenerator; + this.cacheResult = cacheResult; + this.cachePutCacheName = cachePutCacheName; + this.cachePutResolverFactory = cachePutResolverFactory; + this.cachePutKeyGenerator = cachePutKeyGenerator; + this.cachePutAfter = cachePutAfter; + this.cachePut = cachePut; + this.cacheRemoveCacheName = cacheRemoveCacheName; + this.cacheRemoveResolverFactory = cacheRemoveResolverFactory; + this.cacheRemoveKeyGenerator = cacheRemoveKeyGenerator; + this.cacheRemoveAfter = cacheRemoveAfter; + this.cacheRemove = cacheRemove; + this.cacheRemoveAllCacheName = cacheRemoveAllCacheName; + this.cacheRemoveAllResolverFactory = cacheRemoveAllResolverFactory; + this.cacheRemoveAll = cacheRemoveAll; + this.completionStage = completionStage; + } + + public boolean isCompletionStage() { + return completionStage; + } + + public boolean isCacheRemoveAfter() { + return cacheRemoveAfter; + } + + public boolean isCachePutAfter() { + return cachePutAfter; + } + + public Class[] getParameterTypes() { + return parameterTypes; + } + + public List> getParameterAnnotations() { + return parameterAnnotations; + } + + public String getCacheResultCacheName() { + return cacheResultCacheName; + } + + public CacheResolverFactory getCacheResultResolverFactory() { + return cacheResultResolverFactory; + } + + public CacheKeyGenerator getCacheResultKeyGenerator() { + return cacheResultKeyGenerator; + } + + public CacheResult getCacheResult() { + return cacheResult; + } + + public Set getAnnotations() { + return annotations; + } + + public Integer[] getKeysIndices() { + return keysIndices; + } + + public Integer getValueIndex() { + return valueIndex; + } + + public String getCachePutCacheName() { + return cachePutCacheName; + } + + public CacheResolverFactory getCachePutResolverFactory() { + return cachePutResolverFactory; + } + + public CacheKeyGenerator getCachePutKeyGenerator() { + return cachePutKeyGenerator; + } + + public CachePut getCachePut() { + return cachePut; + } + + public String getCacheRemoveCacheName() { + return cacheRemoveCacheName; + } + + public CacheResolverFactory getCacheRemoveResolverFactory() { + return cacheRemoveResolverFactory; + } + + public CacheKeyGenerator getCacheRemoveKeyGenerator() { + return cacheRemoveKeyGenerator; + } + + public CacheRemove getCacheRemove() { + return cacheRemove; + } + + public String getCacheRemoveAllCacheName() { + return cacheRemoveAllCacheName; + } + + public CacheResolverFactory getCacheRemoveAllResolverFactory() { + return cacheRemoveAllResolverFactory; + } + + public CacheRemoveAll getCacheRemoveAll() { + return cacheRemoveAll; + } + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_265/metadata.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_265/metadata.json new file mode 100644 index 000000000..355d00509 --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_265/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CDIJCacheHelper_265", + "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/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 266, + "npe_method": "cacheResolverFactoryFor", + "deref_field": "defaults", + "npe_class": "CDIJCacheHelper", + "repo": "geronimo-jcache-simple", + "bug_id": "CDIJCacheHelper_265" + } +} diff --git a/Java/geronimo-jcache-simple-CDIJCacheHelper_265/npe.json b/Java/geronimo-jcache-simple-CDIJCacheHelper_265/npe.json new file mode 100644 index 000000000..0d15af89c --- /dev/null +++ b/Java/geronimo-jcache-simple-CDIJCacheHelper_265/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CDIJCacheHelper.java", + "line": 266, + "npe_method": "cacheResolverFactoryFor", + "deref_field": "defaults", + "npe_class": "CDIJCacheHelper" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CacheResultInterceptor_72/Dockerfile b/Java/geronimo-jcache-simple-CacheResultInterceptor_72/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CacheResultInterceptor_72/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CacheResultInterceptor_72/buggy.java b/Java/geronimo-jcache-simple-CacheResultInterceptor_72/buggy.java new file mode 100644 index 000000000..08cde9ada --- /dev/null +++ b/Java/geronimo-jcache-simple-CacheResultInterceptor_72/buggy.java @@ -0,0 +1,104 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.io.Serializable; +import java.util.concurrent.CompletionStage; + +import javax.annotation.Priority; +import javax.cache.Cache; +import javax.cache.annotation.CacheKeyInvocationContext; +import javax.cache.annotation.CacheResolver; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.GeneratedCacheKey; +import javax.inject.Inject; +import javax.interceptor.AroundInvoke; +import javax.interceptor.Interceptor; +import javax.interceptor.InvocationContext; + +@CacheResult +@Interceptor +@Priority(/* LIBRARY_BEFORE */1000) +public class CacheResultInterceptor implements Serializable { + + @Inject + private CDIJCacheHelper helper; + + @AroundInvoke +public java.lang.Object cache(final javax.interceptor.InvocationContext ic) throws java.lang.Throwable { + final org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta methodMeta = helper.findMeta(ic); + final java.lang.String cacheName = methodMeta.getCacheResultCacheName(); + final javax.cache.annotation.CacheResult cacheResult = methodMeta.getCacheResult(); + final javax.cache.annotation.CacheKeyInvocationContext context = new org.apache.geronimo.jcache.simple.cdi.CacheKeyInvocationContextImpl(ic, cacheResult, cacheName, methodMeta); + final javax.cache.annotation.CacheResolverFactory cacheResolverFactory = methodMeta.getCacheResultResolverFactory(); + final javax.cache.annotation.CacheResolver cacheResolver = cacheResolverFactory.getCacheResolver(context); + final javax.cache.Cache cache = cacheResolver.resolveCache(context); + final javax.cache.annotation.GeneratedCacheKey cacheKey = methodMeta.getCacheResultKeyGenerator().generateCacheKey(context); + javax.cache.Cache exceptionCache = null;// lazily created + + java.lang.Object result; + if (!cacheResult.skipGet()) { + result = cache.get(cacheKey); + if (result != null) { + return result; + } + if (!cacheResult.exceptionCacheName().isEmpty()) { + exceptionCache = cacheResolverFactory.getExceptionCacheResolver(context).resolveCache(context); + final java.lang.Object exception = exceptionCache.get(cacheKey); + { + if (methodMeta.isCompletionStage()) { + return /* NPEX_NULL_EXP */ + exception; + } + throw java.lang.Throwable.class.cast(exception); + } + } + } + try { + result = ic.proceed(); + if (result != null) { + cache.put(cacheKey, result); + if (java.util.concurrent.CompletionStage.class.isInstance(result)) { + final java.util.concurrent.CompletionStage completionStage = java.util.concurrent.CompletionStage.class.cast(result); + completionStage.exceptionally(( t) -> { + if (helper.isIncluded(t.getClass(), cacheResult.cachedExceptions(), cacheResult.nonCachedExceptions())) { + cacheResolverFactory.getExceptionCacheResolver(context).resolveCache(context).put(cacheKey, completionStage); + } else { + cache.remove(cacheKey); + } + if (java.lang.RuntimeException.class.isInstance(t)) { + throw java.lang.RuntimeException.class.cast(t); + } + throw new java.lang.IllegalStateException(t); + }); + } + } + return result; + } catch (final java.lang.Throwable t) { + if (helper.isIncluded(t.getClass(), cacheResult.cachedExceptions(), cacheResult.nonCachedExceptions())) { + if (exceptionCache == null) { + exceptionCache = cacheResolverFactory.getExceptionCacheResolver(context).resolveCache(context); + } + exceptionCache.put(cacheKey, t); + } + throw t; + } +} +} diff --git a/Java/geronimo-jcache-simple-CacheResultInterceptor_72/metadata.json b/Java/geronimo-jcache-simple-CacheResultInterceptor_72/metadata.json new file mode 100644 index 000000000..60c2741f4 --- /dev/null +++ b/Java/geronimo-jcache-simple-CacheResultInterceptor_72/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CacheResultInterceptor_72", + "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/geronimo/jcache/simple/cdi/CacheResultInterceptor.java", + "line": 68, + "npe_method": "cache", + "deref_field": "exception", + "npe_class": "CacheResultInterceptor", + "repo": "geronimo-jcache-simple", + "bug_id": "CacheResultInterceptor_72" + } +} diff --git a/Java/geronimo-jcache-simple-CacheResultInterceptor_72/npe.json b/Java/geronimo-jcache-simple-CacheResultInterceptor_72/npe.json new file mode 100644 index 000000000..d80a8689c --- /dev/null +++ b/Java/geronimo-jcache-simple-CacheResultInterceptor_72/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CacheResultInterceptor.java", + "line": 68, + "npe_method": "cache", + "deref_field": "exception", + "npe_class": "CacheResultInterceptor" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-CacheResultInterceptor_83/Dockerfile b/Java/geronimo-jcache-simple-CacheResultInterceptor_83/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-CacheResultInterceptor_83/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-CacheResultInterceptor_83/buggy.java b/Java/geronimo-jcache-simple-CacheResultInterceptor_83/buggy.java new file mode 100644 index 000000000..18972a70d --- /dev/null +++ b/Java/geronimo-jcache-simple-CacheResultInterceptor_83/buggy.java @@ -0,0 +1,104 @@ +/* + * 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.geronimo.jcache.simple.cdi; + +import java.io.Serializable; +import java.util.concurrent.CompletionStage; + +import javax.annotation.Priority; +import javax.cache.Cache; +import javax.cache.annotation.CacheKeyInvocationContext; +import javax.cache.annotation.CacheResolver; +import javax.cache.annotation.CacheResolverFactory; +import javax.cache.annotation.CacheResult; +import javax.cache.annotation.GeneratedCacheKey; +import javax.inject.Inject; +import javax.interceptor.AroundInvoke; +import javax.interceptor.Interceptor; +import javax.interceptor.InvocationContext; + +@CacheResult +@Interceptor +@Priority(/* LIBRARY_BEFORE */1000) +public class CacheResultInterceptor implements Serializable { + + @Inject + private CDIJCacheHelper helper; + + @AroundInvoke +public java.lang.Object cache(final javax.interceptor.InvocationContext ic) throws java.lang.Throwable { + final org.apache.geronimo.jcache.simple.cdi.CDIJCacheHelper.MethodMeta methodMeta = helper.findMeta(ic); + final java.lang.String cacheName = methodMeta.getCacheResultCacheName(); + final javax.cache.annotation.CacheResult cacheResult = methodMeta.getCacheResult(); + final javax.cache.annotation.CacheKeyInvocationContext context = new org.apache.geronimo.jcache.simple.cdi.CacheKeyInvocationContextImpl(ic, cacheResult, cacheName, methodMeta); + final javax.cache.annotation.CacheResolverFactory cacheResolverFactory = methodMeta.getCacheResultResolverFactory(); + final javax.cache.annotation.CacheResolver cacheResolver = cacheResolverFactory.getCacheResolver(context); + final javax.cache.Cache cache = cacheResolver.resolveCache(context); + final javax.cache.annotation.GeneratedCacheKey cacheKey = methodMeta.getCacheResultKeyGenerator().generateCacheKey(context); + javax.cache.Cache exceptionCache = null;// lazily created + + java.lang.Object result; + if (!cacheResult.skipGet()) { + result = cache.get(cacheKey); + if (result != null) { + return result; + } + if (!cacheResult.exceptionCacheName().isEmpty()) { + exceptionCache = cacheResolverFactory.getExceptionCacheResolver(context).resolveCache(context); + final java.lang.Object exception = exceptionCache.get(cacheKey); + if (exception != null) { + if (methodMeta.isCompletionStage()) { + return exception; + } + throw java.lang.Throwable.class.cast(exception); + } + } + } + try { + result = ic.proceed(); + { + cache.put(cacheKey, /* NPEX_NULL_EXP */ + result); + if (java.util.concurrent.CompletionStage.class.isInstance(result)) { + final java.util.concurrent.CompletionStage completionStage = java.util.concurrent.CompletionStage.class.cast(result); + completionStage.exceptionally(( t) -> { + if (helper.isIncluded(t.getClass(), cacheResult.cachedExceptions(), cacheResult.nonCachedExceptions())) { + cacheResolverFactory.getExceptionCacheResolver(context).resolveCache(context).put(cacheKey, completionStage); + } else { + cache.remove(cacheKey); + } + if (java.lang.RuntimeException.class.isInstance(t)) { + throw java.lang.RuntimeException.class.cast(t); + } + throw new java.lang.IllegalStateException(t); + }); + } + } + return result; + } catch (final java.lang.Throwable t) { + if (helper.isIncluded(t.getClass(), cacheResult.cachedExceptions(), cacheResult.nonCachedExceptions())) { + if (exceptionCache == null) { + exceptionCache = cacheResolverFactory.getExceptionCacheResolver(context).resolveCache(context); + } + exceptionCache.put(cacheKey, t); + } + throw t; + } +} +} diff --git a/Java/geronimo-jcache-simple-CacheResultInterceptor_83/metadata.json b/Java/geronimo-jcache-simple-CacheResultInterceptor_83/metadata.json new file mode 100644 index 000000000..2b5515f8b --- /dev/null +++ b/Java/geronimo-jcache-simple-CacheResultInterceptor_83/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-CacheResultInterceptor_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/geronimo/jcache/simple/cdi/CacheResultInterceptor.java", + "line": 77, + "npe_method": "cache", + "deref_field": "result", + "npe_class": "CacheResultInterceptor", + "repo": "geronimo-jcache-simple", + "bug_id": "CacheResultInterceptor_83" + } +} diff --git a/Java/geronimo-jcache-simple-CacheResultInterceptor_83/npe.json b/Java/geronimo-jcache-simple-CacheResultInterceptor_83/npe.json new file mode 100644 index 000000000..60e1bd230 --- /dev/null +++ b/Java/geronimo-jcache-simple-CacheResultInterceptor_83/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/cdi/CacheResultInterceptor.java", + "line": 77, + "npe_method": "cache", + "deref_field": "result", + "npe_class": "CacheResultInterceptor" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/Dockerfile b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/buggy.java b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/buggy.java new file mode 100644 index 000000000..196e6823d --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/buggy.java @@ -0,0 +1,154 @@ +/* + * 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.geronimo.jcache.simple; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.management.ListenerNotFoundException; +import javax.management.MBeanNotificationInfo; +import javax.management.MBeanServer; +import javax.management.MBeanServerBuilder; +import javax.management.MBeanServerDelegate; +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; + +public class ConfigurableMBeanServerIdBuilder extends MBeanServerBuilder { + + private static ConcurrentMap JVM_SINGLETONS = new ConcurrentHashMap<>(); + + @Override +public javax.management.MBeanServer newMBeanServer(final java.lang.String defaultDomain, final javax.management.MBeanServer outer, final javax.management.MBeanServerDelegate delegate) { + final org.apache.geronimo.jcache.simple.ConfigurableMBeanServerIdBuilder.Key key = new org.apache.geronimo.jcache.simple.ConfigurableMBeanServerIdBuilder.Key(defaultDomain, outer); + javax.management.MBeanServer server = org.apache.geronimo.jcache.simple.ConfigurableMBeanServerIdBuilder.JVM_SINGLETONS.get(key); + if (server == null) { + server = super.newMBeanServer(defaultDomain, outer, new org.apache.geronimo.jcache.simple.ConfigurableMBeanServerIdBuilder.ForceIdMBeanServerDelegate(delegate)); + final javax.management.MBeanServer existing = org.apache.geronimo.jcache.simple.ConfigurableMBeanServerIdBuilder.JVM_SINGLETONS.putIfAbsent(key, server); + { + server = /* NPEX_NULL_EXP */ + existing; + } + } + return server; +} + + private static class Key { + + private final String domain; + + private final MBeanServer outer; + + private Key(final String domain, final MBeanServer outer) { + this.domain = domain; + this.outer = outer; + } + + @Override + public boolean equals(final Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + final Key key = Key.class.cast(o); + return !(domain != null ? !domain.equals(key.domain) : key.domain != null) + && !(outer != null ? !outer.equals(key.outer) : key.outer != null); + + } + + @Override + public int hashCode() { + int result = domain != null ? domain.hashCode() : 0; + result = 31 * result + (outer != null ? outer.hashCode() : 0); + return result; + } + } + + private class ForceIdMBeanServerDelegate extends MBeanServerDelegate { + + private final MBeanServerDelegate delegate; + + public ForceIdMBeanServerDelegate(final MBeanServerDelegate delegate) { + this.delegate = delegate; + } + + @Override + public String getMBeanServerId() { + return System.getProperty("org.jsr107.tck.management.agentId", delegate.getMBeanServerId()); + } + + @Override + public String getSpecificationName() { + return delegate.getSpecificationName(); + } + + @Override + public String getSpecificationVersion() { + return delegate.getSpecificationVersion(); + } + + @Override + public String getSpecificationVendor() { + return delegate.getSpecificationVendor(); + } + + @Override + public String getImplementationName() { + return delegate.getImplementationName(); + } + + @Override + public String getImplementationVersion() { + return delegate.getImplementationVersion(); + } + + @Override + public String getImplementationVendor() { + return delegate.getImplementationVendor(); + } + + @Override + public MBeanNotificationInfo[] getNotificationInfo() { + return delegate.getNotificationInfo(); + } + + @Override + public void addNotificationListener(final NotificationListener listener, final NotificationFilter filter, + final Object handback) throws IllegalArgumentException { + delegate.addNotificationListener(listener, filter, handback); + } + + @Override + public void removeNotificationListener(final NotificationListener listener, final NotificationFilter filter, + final Object handback) throws ListenerNotFoundException { + delegate.removeNotificationListener(listener, filter, handback); + } + + @Override + public void removeNotificationListener(final NotificationListener listener) throws ListenerNotFoundException { + delegate.removeNotificationListener(listener); + } + + @Override + public void sendNotification(final Notification notification) { + delegate.sendNotification(notification); + } + } +} diff --git a/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/metadata.json b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/metadata.json new file mode 100644 index 000000000..368d5619e --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44", + "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/geronimo/jcache/simple/ConfigurableMBeanServerIdBuilder.java", + "line": 46, + "npe_method": "newMBeanServer", + "deref_field": "existing", + "npe_class": "ConfigurableMBeanServerIdBuilder", + "repo": "geronimo-jcache-simple", + "bug_id": "ConfigurableMBeanServerIdBuilder_44" + } +} diff --git a/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/npe.json b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/npe.json new file mode 100644 index 000000000..bb525b7ee --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_44/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/ConfigurableMBeanServerIdBuilder.java", + "line": 46, + "npe_method": "newMBeanServer", + "deref_field": "existing", + "npe_class": "ConfigurableMBeanServerIdBuilder" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/Dockerfile b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/buggy.java b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/buggy.java new file mode 100644 index 000000000..f6c87ed5a --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/buggy.java @@ -0,0 +1,153 @@ +/* + * 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.geronimo.jcache.simple; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.management.ListenerNotFoundException; +import javax.management.MBeanNotificationInfo; +import javax.management.MBeanServer; +import javax.management.MBeanServerBuilder; +import javax.management.MBeanServerDelegate; +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; + +public class ConfigurableMBeanServerIdBuilder extends MBeanServerBuilder { + + private static ConcurrentMap JVM_SINGLETONS = new ConcurrentHashMap<>(); + + @Override + public MBeanServer newMBeanServer(final String defaultDomain, final MBeanServer outer, final MBeanServerDelegate delegate) { + final Key key = new Key(defaultDomain, outer); + MBeanServer server = JVM_SINGLETONS.get(key); + if (server == null) { + server = super.newMBeanServer(defaultDomain, outer, new ForceIdMBeanServerDelegate(delegate)); + final MBeanServer existing = JVM_SINGLETONS.putIfAbsent(key, server); + if (existing != null) { + server = existing; + } + } + return server; + } + + private static class Key { + + private final String domain; + + private final MBeanServer outer; + + private Key(final String domain, final MBeanServer outer) { + this.domain = domain; + this.outer = outer; + } + + @Override +public boolean equals(final java.lang.Object o) { + if (this == o) { + return true; + } + if ((o == null) || (getClass() != o.getClass())) { + return false; + } + final org.apache.geronimo.jcache.simple.ConfigurableMBeanServerIdBuilder.Key key = org.apache.geronimo.jcache.simple.ConfigurableMBeanServerIdBuilder.Key.class.cast(o); + return (!(!/* NPEX_NULL_EXP */ + domain.equals(key.domain))) && (!(outer != null ? !outer.equals(key.outer) : key.outer != null)); +} + + @Override + public int hashCode() { + int result = domain != null ? domain.hashCode() : 0; + result = 31 * result + (outer != null ? outer.hashCode() : 0); + return result; + } + } + + private class ForceIdMBeanServerDelegate extends MBeanServerDelegate { + + private final MBeanServerDelegate delegate; + + public ForceIdMBeanServerDelegate(final MBeanServerDelegate delegate) { + this.delegate = delegate; + } + + @Override + public String getMBeanServerId() { + return System.getProperty("org.jsr107.tck.management.agentId", delegate.getMBeanServerId()); + } + + @Override + public String getSpecificationName() { + return delegate.getSpecificationName(); + } + + @Override + public String getSpecificationVersion() { + return delegate.getSpecificationVersion(); + } + + @Override + public String getSpecificationVendor() { + return delegate.getSpecificationVendor(); + } + + @Override + public String getImplementationName() { + return delegate.getImplementationName(); + } + + @Override + public String getImplementationVersion() { + return delegate.getImplementationVersion(); + } + + @Override + public String getImplementationVendor() { + return delegate.getImplementationVendor(); + } + + @Override + public MBeanNotificationInfo[] getNotificationInfo() { + return delegate.getNotificationInfo(); + } + + @Override + public void addNotificationListener(final NotificationListener listener, final NotificationFilter filter, + final Object handback) throws IllegalArgumentException { + delegate.addNotificationListener(listener, filter, handback); + } + + @Override + public void removeNotificationListener(final NotificationListener listener, final NotificationFilter filter, + final Object handback) throws ListenerNotFoundException { + delegate.removeNotificationListener(listener, filter, handback); + } + + @Override + public void removeNotificationListener(final NotificationListener listener) throws ListenerNotFoundException { + delegate.removeNotificationListener(listener); + } + + @Override + public void sendNotification(final Notification notification) { + delegate.sendNotification(notification); + } + } +} diff --git a/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/metadata.json b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/metadata.json new file mode 100644 index 000000000..ad8532dac --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70", + "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/geronimo/jcache/simple/ConfigurableMBeanServerIdBuilder.java", + "line": 72, + "npe_method": "equals", + "deref_field": "domain", + "npe_class": "Key", + "repo": "geronimo-jcache-simple", + "bug_id": "ConfigurableMBeanServerIdBuilder_70" + } +} diff --git a/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/npe.json b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/npe.json new file mode 100644 index 000000000..a59b05746 --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_70/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/ConfigurableMBeanServerIdBuilder.java", + "line": 72, + "npe_method": "equals", + "deref_field": "domain", + "npe_class": "Key" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/Dockerfile b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/buggy.java b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/buggy.java new file mode 100644 index 000000000..d5a57527f --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/buggy.java @@ -0,0 +1,153 @@ +/* + * 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.geronimo.jcache.simple; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.management.ListenerNotFoundException; +import javax.management.MBeanNotificationInfo; +import javax.management.MBeanServer; +import javax.management.MBeanServerBuilder; +import javax.management.MBeanServerDelegate; +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; + +public class ConfigurableMBeanServerIdBuilder extends MBeanServerBuilder { + + private static ConcurrentMap JVM_SINGLETONS = new ConcurrentHashMap<>(); + + @Override + public MBeanServer newMBeanServer(final String defaultDomain, final MBeanServer outer, final MBeanServerDelegate delegate) { + final Key key = new Key(defaultDomain, outer); + MBeanServer server = JVM_SINGLETONS.get(key); + if (server == null) { + server = super.newMBeanServer(defaultDomain, outer, new ForceIdMBeanServerDelegate(delegate)); + final MBeanServer existing = JVM_SINGLETONS.putIfAbsent(key, server); + if (existing != null) { + server = existing; + } + } + return server; + } + + private static class Key { + + private final String domain; + + private final MBeanServer outer; + + private Key(final String domain, final MBeanServer outer) { + this.domain = domain; + this.outer = outer; + } + + @Override +public boolean equals(final java.lang.Object o) { + if (this == o) { + return true; + } + if ((o == null) || (getClass() != o.getClass())) { + return false; + } + final org.apache.geronimo.jcache.simple.ConfigurableMBeanServerIdBuilder.Key key = org.apache.geronimo.jcache.simple.ConfigurableMBeanServerIdBuilder.Key.class.cast(o); + return (!(domain != null ? !domain.equals(key.domain) : key.domain != null)) && (!(!/* NPEX_NULL_EXP */ + outer.equals(key.outer))); +} + + @Override + public int hashCode() { + int result = domain != null ? domain.hashCode() : 0; + result = 31 * result + (outer != null ? outer.hashCode() : 0); + return result; + } + } + + private class ForceIdMBeanServerDelegate extends MBeanServerDelegate { + + private final MBeanServerDelegate delegate; + + public ForceIdMBeanServerDelegate(final MBeanServerDelegate delegate) { + this.delegate = delegate; + } + + @Override + public String getMBeanServerId() { + return System.getProperty("org.jsr107.tck.management.agentId", delegate.getMBeanServerId()); + } + + @Override + public String getSpecificationName() { + return delegate.getSpecificationName(); + } + + @Override + public String getSpecificationVersion() { + return delegate.getSpecificationVersion(); + } + + @Override + public String getSpecificationVendor() { + return delegate.getSpecificationVendor(); + } + + @Override + public String getImplementationName() { + return delegate.getImplementationName(); + } + + @Override + public String getImplementationVersion() { + return delegate.getImplementationVersion(); + } + + @Override + public String getImplementationVendor() { + return delegate.getImplementationVendor(); + } + + @Override + public MBeanNotificationInfo[] getNotificationInfo() { + return delegate.getNotificationInfo(); + } + + @Override + public void addNotificationListener(final NotificationListener listener, final NotificationFilter filter, + final Object handback) throws IllegalArgumentException { + delegate.addNotificationListener(listener, filter, handback); + } + + @Override + public void removeNotificationListener(final NotificationListener listener, final NotificationFilter filter, + final Object handback) throws ListenerNotFoundException { + delegate.removeNotificationListener(listener, filter, handback); + } + + @Override + public void removeNotificationListener(final NotificationListener listener) throws ListenerNotFoundException { + delegate.removeNotificationListener(listener); + } + + @Override + public void sendNotification(final Notification notification) { + delegate.sendNotification(notification); + } + } +} diff --git a/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/metadata.json b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/metadata.json new file mode 100644 index 000000000..46c303cf3 --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71", + "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/geronimo/jcache/simple/ConfigurableMBeanServerIdBuilder.java", + "line": 72, + "npe_method": "equals", + "deref_field": "outer", + "npe_class": "Key", + "repo": "geronimo-jcache-simple", + "bug_id": "ConfigurableMBeanServerIdBuilder_71" + } +} diff --git a/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/npe.json b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/npe.json new file mode 100644 index 000000000..9f2e04ef9 --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_71/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/ConfigurableMBeanServerIdBuilder.java", + "line": 72, + "npe_method": "equals", + "deref_field": "outer", + "npe_class": "Key" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/Dockerfile b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/buggy.java b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/buggy.java new file mode 100644 index 000000000..6e3a905ee --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/buggy.java @@ -0,0 +1,154 @@ +/* + * 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.geronimo.jcache.simple; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.management.ListenerNotFoundException; +import javax.management.MBeanNotificationInfo; +import javax.management.MBeanServer; +import javax.management.MBeanServerBuilder; +import javax.management.MBeanServerDelegate; +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; + +public class ConfigurableMBeanServerIdBuilder extends MBeanServerBuilder { + + private static ConcurrentMap JVM_SINGLETONS = new ConcurrentHashMap<>(); + + @Override + public MBeanServer newMBeanServer(final String defaultDomain, final MBeanServer outer, final MBeanServerDelegate delegate) { + final Key key = new Key(defaultDomain, outer); + MBeanServer server = JVM_SINGLETONS.get(key); + if (server == null) { + server = super.newMBeanServer(defaultDomain, outer, new ForceIdMBeanServerDelegate(delegate)); + final MBeanServer existing = JVM_SINGLETONS.putIfAbsent(key, server); + if (existing != null) { + server = existing; + } + } + return server; + } + + private static class Key { + + private final String domain; + + private final MBeanServer outer; + + private Key(final String domain, final MBeanServer outer) { + this.domain = domain; + this.outer = outer; + } + + @Override + public boolean equals(final Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + final Key key = Key.class.cast(o); + return !(domain != null ? !domain.equals(key.domain) : key.domain != null) + && !(outer != null ? !outer.equals(key.outer) : key.outer != null); + + } + + @Override +public int hashCode() { + int result = /* NPEX_NULL_EXP */ + domain.hashCode(); + result = (31 * result) + (outer != null ? outer.hashCode() : 0); + return result; +} + } + + private class ForceIdMBeanServerDelegate extends MBeanServerDelegate { + + private final MBeanServerDelegate delegate; + + public ForceIdMBeanServerDelegate(final MBeanServerDelegate delegate) { + this.delegate = delegate; + } + + @Override + public String getMBeanServerId() { + return System.getProperty("org.jsr107.tck.management.agentId", delegate.getMBeanServerId()); + } + + @Override + public String getSpecificationName() { + return delegate.getSpecificationName(); + } + + @Override + public String getSpecificationVersion() { + return delegate.getSpecificationVersion(); + } + + @Override + public String getSpecificationVendor() { + return delegate.getSpecificationVendor(); + } + + @Override + public String getImplementationName() { + return delegate.getImplementationName(); + } + + @Override + public String getImplementationVersion() { + return delegate.getImplementationVersion(); + } + + @Override + public String getImplementationVendor() { + return delegate.getImplementationVendor(); + } + + @Override + public MBeanNotificationInfo[] getNotificationInfo() { + return delegate.getNotificationInfo(); + } + + @Override + public void addNotificationListener(final NotificationListener listener, final NotificationFilter filter, + final Object handback) throws IllegalArgumentException { + delegate.addNotificationListener(listener, filter, handback); + } + + @Override + public void removeNotificationListener(final NotificationListener listener, final NotificationFilter filter, + final Object handback) throws ListenerNotFoundException { + delegate.removeNotificationListener(listener, filter, handback); + } + + @Override + public void removeNotificationListener(final NotificationListener listener) throws ListenerNotFoundException { + delegate.removeNotificationListener(listener); + } + + @Override + public void sendNotification(final Notification notification) { + delegate.sendNotification(notification); + } + } +} diff --git a/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/metadata.json b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/metadata.json new file mode 100644 index 000000000..de4f011f5 --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77", + "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/geronimo/jcache/simple/ConfigurableMBeanServerIdBuilder.java", + "line": 78, + "npe_method": "hashCode", + "deref_field": "domain", + "npe_class": "Key", + "repo": "geronimo-jcache-simple", + "bug_id": "ConfigurableMBeanServerIdBuilder_77" + } +} diff --git a/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/npe.json b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/npe.json new file mode 100644 index 000000000..e9aaf71da --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_77/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/ConfigurableMBeanServerIdBuilder.java", + "line": 78, + "npe_method": "hashCode", + "deref_field": "domain", + "npe_class": "Key" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/Dockerfile b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/buggy.java b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/buggy.java new file mode 100644 index 000000000..54ed3b336 --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/buggy.java @@ -0,0 +1,154 @@ +/* + * 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.geronimo.jcache.simple; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.management.ListenerNotFoundException; +import javax.management.MBeanNotificationInfo; +import javax.management.MBeanServer; +import javax.management.MBeanServerBuilder; +import javax.management.MBeanServerDelegate; +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; + +public class ConfigurableMBeanServerIdBuilder extends MBeanServerBuilder { + + private static ConcurrentMap JVM_SINGLETONS = new ConcurrentHashMap<>(); + + @Override + public MBeanServer newMBeanServer(final String defaultDomain, final MBeanServer outer, final MBeanServerDelegate delegate) { + final Key key = new Key(defaultDomain, outer); + MBeanServer server = JVM_SINGLETONS.get(key); + if (server == null) { + server = super.newMBeanServer(defaultDomain, outer, new ForceIdMBeanServerDelegate(delegate)); + final MBeanServer existing = JVM_SINGLETONS.putIfAbsent(key, server); + if (existing != null) { + server = existing; + } + } + return server; + } + + private static class Key { + + private final String domain; + + private final MBeanServer outer; + + private Key(final String domain, final MBeanServer outer) { + this.domain = domain; + this.outer = outer; + } + + @Override + public boolean equals(final Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + final Key key = Key.class.cast(o); + return !(domain != null ? !domain.equals(key.domain) : key.domain != null) + && !(outer != null ? !outer.equals(key.outer) : key.outer != null); + + } + + @Override +public int hashCode() { + int result = (domain != null) ? domain.hashCode() : 0; + result = (31 * result) + /* NPEX_NULL_EXP */ + outer.hashCode(); + return result; +} + } + + private class ForceIdMBeanServerDelegate extends MBeanServerDelegate { + + private final MBeanServerDelegate delegate; + + public ForceIdMBeanServerDelegate(final MBeanServerDelegate delegate) { + this.delegate = delegate; + } + + @Override + public String getMBeanServerId() { + return System.getProperty("org.jsr107.tck.management.agentId", delegate.getMBeanServerId()); + } + + @Override + public String getSpecificationName() { + return delegate.getSpecificationName(); + } + + @Override + public String getSpecificationVersion() { + return delegate.getSpecificationVersion(); + } + + @Override + public String getSpecificationVendor() { + return delegate.getSpecificationVendor(); + } + + @Override + public String getImplementationName() { + return delegate.getImplementationName(); + } + + @Override + public String getImplementationVersion() { + return delegate.getImplementationVersion(); + } + + @Override + public String getImplementationVendor() { + return delegate.getImplementationVendor(); + } + + @Override + public MBeanNotificationInfo[] getNotificationInfo() { + return delegate.getNotificationInfo(); + } + + @Override + public void addNotificationListener(final NotificationListener listener, final NotificationFilter filter, + final Object handback) throws IllegalArgumentException { + delegate.addNotificationListener(listener, filter, handback); + } + + @Override + public void removeNotificationListener(final NotificationListener listener, final NotificationFilter filter, + final Object handback) throws ListenerNotFoundException { + delegate.removeNotificationListener(listener, filter, handback); + } + + @Override + public void removeNotificationListener(final NotificationListener listener) throws ListenerNotFoundException { + delegate.removeNotificationListener(listener); + } + + @Override + public void sendNotification(final Notification notification) { + delegate.sendNotification(notification); + } + } +} diff --git a/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/metadata.json b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/metadata.json new file mode 100644 index 000000000..e9e938ca7 --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78", + "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/geronimo/jcache/simple/ConfigurableMBeanServerIdBuilder.java", + "line": 79, + "npe_method": "hashCode", + "deref_field": "outer", + "npe_class": "Key", + "repo": "geronimo-jcache-simple", + "bug_id": "ConfigurableMBeanServerIdBuilder_78" + } +} diff --git a/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/npe.json b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/npe.json new file mode 100644 index 000000000..73a0a752d --- /dev/null +++ b/Java/geronimo-jcache-simple-ConfigurableMBeanServerIdBuilder_78/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/ConfigurableMBeanServerIdBuilder.java", + "line": 79, + "npe_method": "hashCode", + "deref_field": "outer", + "npe_class": "Key" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleCache_188/Dockerfile b/Java/geronimo-jcache-simple-SimpleCache_188/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_188/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleCache_188/buggy.java b/Java/geronimo-jcache-simple-SimpleCache_188/buggy.java new file mode 100644 index 000000000..0831cb218 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_188/buggy.java @@ -0,0 +1,877 @@ +/* + * 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.geronimo.jcache.simple; + +import static org.apache.geronimo.jcache.simple.Asserts.assertNotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicReference; + +import javax.cache.Cache; +import javax.cache.CacheException; +import javax.cache.CacheManager; +import javax.cache.configuration.CacheEntryListenerConfiguration; +import javax.cache.configuration.Configuration; +import javax.cache.configuration.Factory; +import javax.cache.event.CacheEntryEvent; +import javax.cache.event.EventType; +import javax.cache.expiry.Duration; +import javax.cache.expiry.EternalExpiryPolicy; +import javax.cache.expiry.ExpiryPolicy; +import javax.cache.integration.CacheLoader; +import javax.cache.integration.CacheLoaderException; +import javax.cache.integration.CacheWriter; +import javax.cache.integration.CacheWriterException; +import javax.cache.integration.CompletionListener; +import javax.cache.processor.EntryProcessor; +import javax.cache.processor.EntryProcessorException; +import javax.cache.processor.EntryProcessorResult; +import javax.management.ObjectName; + +public class SimpleCache implements Cache { + + private final SimpleManager manager; + + private final SimpleConfiguration config; + + private final CacheLoader loader; + + private final CacheWriter writer; + + private final ExpiryPolicy expiryPolicy; + + private final ObjectName cacheConfigObjectName; + + private final ObjectName cacheStatsObjectName; + + private final String name; + + private final ConcurrentHashMap, SimpleElement> delegate; + + private final Map, SimpleListener> listeners = new ConcurrentHashMap<>(); + + private final Statistics statistics = new Statistics(); + + private final ExecutorService pool; + + private final Serializations serializations; + + private final Collection> poolTasks = new CopyOnWriteArraySet<>(); + + private volatile boolean closed = false; + + public SimpleCache(final ClassLoader classLoader, final SimpleManager mgr, final String cacheName, + final SimpleConfiguration configuration, final Properties properties, + final ExecutorService executorService) { + manager = mgr; + + name = cacheName; + + final int capacity = Integer.parseInt(property(properties, cacheName, "capacity", "1000")); + final float loadFactor = Float.parseFloat(property(properties, cacheName, "loadFactor", "0.75")); + final int concurrencyLevel = Integer.parseInt(property(properties, cacheName, "concurrencyLevel", "16")); + delegate = new ConcurrentHashMap<>(capacity, loadFactor, concurrencyLevel); + config = configuration; + pool = executorService; + + final long evictionPause = Long.parseLong( + properties.getProperty(cacheName + ".evictionPause", properties.getProperty("evictionPause", "30000"))); + if (evictionPause > 0) { + final long maxDeleteByEvictionRun = Long.parseLong(property(properties, cacheName, "maxDeleteByEvictionRun", "100")); + addPoolTask(new EvictionThread(evictionPause, maxDeleteByEvictionRun)); + } + + serializations = new Serializations(property(properties, cacheName, "serialization.whitelist", null)); + + final Factory> cacheLoaderFactory = configuration.getCacheLoaderFactory(); + if (cacheLoaderFactory == null) { + loader = NoLoader.INSTANCE; + } else { + loader = ExceptionWrapperHandler.newProxy(classLoader, cacheLoaderFactory.create(), CacheLoaderException.class, + CacheLoader.class); + } + + final Factory> cacheWriterFactory = configuration.getCacheWriterFactory(); + if (cacheWriterFactory == null) { + writer = NoWriter.INSTANCE; + } else { + writer = ExceptionWrapperHandler.newProxy(classLoader, cacheWriterFactory.create(), CacheWriterException.class, + CacheWriter.class); + } + + final Factory expiryPolicyFactory = configuration.getExpiryPolicyFactory(); + if (expiryPolicyFactory == null) { + expiryPolicy = new EternalExpiryPolicy(); + } else { + expiryPolicy = expiryPolicyFactory.create(); + } + + for (final CacheEntryListenerConfiguration listener : config.getCacheEntryListenerConfigurations()) { + listeners.put(listener, new SimpleListener<>(listener)); + } + + statistics.setActive(config.isStatisticsEnabled()); + + final String mgrStr = manager.getURI().toString().replaceAll(",|:|=|\n", "."); + final String cacheStr = name.replaceAll(",|:|=|\n", "."); + try { + cacheConfigObjectName = new ObjectName( + "javax.cache:type=CacheConfiguration," + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr); + cacheStatsObjectName = new ObjectName( + "javax.cache:type=CacheStatistics," + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr); + } catch (final Exception e) { + throw new IllegalArgumentException(e); + } + if (config.isManagementEnabled()) { + JMXs.register(cacheConfigObjectName, new SimpleCacheMXBean(this)); + } + if (config.isStatisticsEnabled()) { + JMXs.register(cacheStatsObjectName, new SimpleCacheStatisticsMXBean(statistics)); + } + } + + private void assertNotClosed() { + if (isClosed()) { + throw new IllegalStateException("cache closed"); + } + } + + @Override + public V get(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + final long getStart = Times.now(false); + return doGetControllingExpiry(getStart, key, true, false, false, true, loader); + } + +private V doLoad(final K key, final boolean update, final boolean propagateLoadException, final javax.cache.integration.CacheLoader loader) { + V v = null; + try { + v = loader.load(key); + } catch (final javax.cache.integration.CacheLoaderException e) { + if (propagateLoadException) { + throw e; + } + } + { + final javax.cache.expiry.Duration duration = (update) ? expiryPolicy.getExpiryForUpdate() : expiryPolicy.getExpiryForCreation(); + if (org.apache.geronimo.jcache.simple.SimpleCache.isNotZero(duration)) { + delegate.put(new org.apache.geronimo.jcache.simple.SimpleKey<>(key), new org.apache.geronimo.jcache.simple.SimpleElement<>(/* NPEX_NULL_EXP */ + v, duration)); + } + } + return v; +} + + private void touch(final SimpleKey key, final SimpleElement element) { + if (config.isStoreByValue()) { + delegate.put(new SimpleKey<>(serializations.copy(manager.getClassLoader(), key.getKey())), element); + } + } + + @Override + public Map getAll(final Set keys) { + assertNotClosed(); + for (final K k : keys) { + assertNotNull(k, "key"); + } + + final Map result = new HashMap<>(); + for (final K key : keys) { + assertNotNull(key, "key"); + + final SimpleKey simpleKey = new SimpleKey<>(key); + final SimpleElement elt = delegate.get(simpleKey); + V val = elt != null ? elt.getElement() : null; + if (val == null && config.isReadThrough()) { + val = doLoad(key, false, false, loader); + if (val != null) { + result.put(key, val); + } + } else if (elt != null) { + final Duration expiryForAccess = expiryPolicy.getExpiryForAccess(); + if (isNotZero(expiryForAccess)) { + touch(simpleKey, elt); + result.put(key, val); + } else { + expires(simpleKey); + } + } + } + return result; + } + + @Override + public boolean containsKey(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + return delegate.get(new SimpleKey<>(key)) != null; + } + + @Override + public void put(final K key, final V rawValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(rawValue, "value"); + + final boolean storeByValue = config.isStoreByValue(); + final SimpleKey simpleKey = new SimpleKey<>(storeByValue ? serializations.copy(manager.getClassLoader(), key) : key); + final SimpleElement oldElt = delegate.get(simpleKey); + final V old = oldElt != null ? oldElt.getElement() : null; + final V value = storeByValue ? serializations.copy(manager.getClassLoader(), rawValue) : rawValue; + + final boolean created = old == null; + final Duration duration = created ? expiryPolicy.getExpiryForCreation() : expiryPolicy.getExpiryForUpdate(); + if (isNotZero(duration)) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final long start = Times.now(false); + + writer.write(new SimpleEntry<>(key, value)); + delegate.put(simpleKey, new SimpleElement<>(value, duration)); + if (!listeners.isEmpty()) { + for (final SimpleListener listener : listeners.values()) { + if (created) { + listener.onCreated(Collections.> singletonList( + new SimpleEvent<>(this, EventType.CREATED, null, key, value))); + } else + listener.onUpdated(Collections.> singletonList( + new SimpleEvent<>(this, EventType.UPDATED, old, key, value))); + } + } + + if (statisticsEnabled) { + statistics.increasePuts(1); + statistics.addPutTime(Times.now(false) - start); + } + } else { + if (!created) { + expires(simpleKey); + } + } + } + + private void expires(final SimpleKey cacheKey) { + final SimpleElement elt = delegate.get(cacheKey); + delegate.remove(cacheKey); + onExpired(cacheKey, elt); + } + + private void onExpired(final SimpleKey cacheKey, final SimpleElement elt) { + for (final SimpleListener listener : listeners.values()) { + listener.onExpired(Collections.> singletonList( + new SimpleEvent<>(this, EventType.REMOVED, null, cacheKey.getKey(), elt.getElement()))); + } + } + + @Override + public V getAndPut(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, true, false, loader); + put(key, value); + return v; + } + + @Override + public void putAll(final Map map) { + assertNotClosed(); + final TempStateCacheView view = new TempStateCacheView(this); + for (final Map.Entry e : map.entrySet()) { + view.put(e.getKey(), e.getValue()); + } + view.merge(); + } + + @Override + public boolean putIfAbsent(final K key, final V value) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + if (!containsKey(key)) { + if (statisticsEnabled) { + statistics.increaseMisses(1); + } + put(key, value); + return true; + } else { + if (statisticsEnabled) { + statistics.increaseHits(1); + } + } + return false; + } + + @Override + public boolean remove(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final long start = Times.now(!statisticsEnabled); + + writer.delete(key); + final SimpleKey cacheKey = new SimpleKey<>(key); + + final SimpleElement v = delegate.remove(cacheKey); + if (v == null || v.isExpired()) { + return false; + } + + final V value = v.getElement(); + for (final SimpleListener listener : listeners.values()) { + listener.onRemoved(Collections.> singletonList( + new SimpleEvent<>(this, EventType.REMOVED, value, key, value))); + } + if (statisticsEnabled) { + statistics.increaseRemovals(1); + statistics.addRemoveTime(Times.now(false) - start); + } + + return true; + } + + @Override + public boolean remove(final K key, final V oldValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(oldValue, "oldValue"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, false, false, loader); + if (oldValue.equals(v)) { + remove(key); + return true; + } else if (v != null) { + // weird but just for stats to be right + // (org.jsr107.tck.expiry.CacheExpiryTest.removeSpecifiedEntryShouldNotCallExpiryPolicyMethods()) + expiryPolicy.getExpiryForAccess(); + } + return false; + } + + @Override + public V getAndRemove(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, true, false, loader); + remove(key); + return v; + } + + private V doGetControllingExpiry(final long getStart, final K key, final boolean updateAcess, final boolean forceDoLoad, + final boolean skipLoad, final boolean propagateLoadException, final CacheLoader loader) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final SimpleKey simpleKey = new SimpleKey<>(key); + final SimpleElement elt = delegate.get(simpleKey); + V v = elt != null ? elt.getElement() : null; + if (v == null && (config.isReadThrough() || forceDoLoad)) { + if (!skipLoad) { + v = doLoad(key, false, propagateLoadException, loader); + } + } else if (statisticsEnabled) { + if (v != null) { + statistics.increaseHits(1); + } else { + statistics.increaseMisses(1); + } + } + + if (updateAcess && elt != null) { + final Duration expiryForAccess = expiryPolicy.getExpiryForAccess(); + if (!isNotZero(expiryForAccess)) { + expires(simpleKey); + } + } + if (statisticsEnabled && v != null) { + statistics.addGetTime(Times.now(false) - getStart); + } + return v; + } + + @Override + public boolean replace(final K key, final V oldValue, final V newValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(oldValue, "oldValue"); + assertNotNull(newValue, "newValue"); + final V value = doGetControllingExpiry(Times.now(config.isStatisticsEnabled()), key, false, config.isReadThrough(), false, + true, loader); + if (value != null && value.equals(oldValue)) { + put(key, newValue); + return true; + } else if (value != null) { + expiryPolicy.getExpiryForAccess(); + } + return false; + } + + @Override + public boolean replace(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + boolean statisticsEnabled = config.isStatisticsEnabled(); + if (containsKey(key)) { + if (statisticsEnabled) { + statistics.increaseHits(1); + } + put(key, value); + return true; + } else if (statisticsEnabled) { + statistics.increaseMisses(1); + } + return false; + } + + @Override + public V getAndReplace(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + + final boolean statisticsEnabled = config.isStatisticsEnabled(); + + final SimpleElement elt = delegate.get(new SimpleKey<>(key)); + if (elt != null) { + V oldValue = elt.getElement(); + if (oldValue == null && config.isReadThrough()) { + oldValue = doLoad(key, false, false, loader); + } else if (statisticsEnabled) { + statistics.increaseHits(1); + } + put(key, value); + return oldValue; + } else if (statisticsEnabled) { + statistics.increaseMisses(1); + } + return null; + } + + @Override + public void removeAll(final Set keys) { + assertNotClosed(); + assertNotNull(keys, "keys"); + for (final K k : keys) { + remove(k); + } + } + + @Override + public void removeAll() { + assertNotClosed(); + for (final SimpleKey k : delegate.keySet()) { + remove(k.getKey()); + } + } + + @Override + public void clear() { + assertNotClosed(); + delegate.clear(); + } + + @Override + public > C2 getConfiguration(final Class clazz) { + assertNotClosed(); + return clazz.cast(config); + } + + @Override + public void loadAll(final Set keys, final boolean replaceExistingValues, + final CompletionListener completionListener) { + assertNotClosed(); + assertNotNull(keys, "keys"); + if (loader == null) { // quick exit path + if (completionListener != null) { + completionListener.onCompletion(); + } + return; + } + for (final K k : keys) { + assertNotNull(k, "a key"); + } + addPoolTask(new Runnable() { + + @Override + public void run() { + doLoadAll(keys, replaceExistingValues, completionListener); + } + }); + } + + private void addPoolTask(final Runnable runnable) { + final AtomicReference> ref = new AtomicReference<>(); + final CountDownLatch refIsSet = new CountDownLatch(1); + ref.set(pool.submit(new Runnable() { + @Override + public void run() { + try { + runnable.run(); + } finally { + try { + refIsSet.await(); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + } + poolTasks.remove(ref.get()); + } + } + })); + refIsSet.countDown(); + poolTasks.add(ref.get()); + } + + private void doLoadAll(final Set keys, final boolean replaceExistingValues, + final CompletionListener completionListener) { + try { + final long now = Times.now(false); + final Map kvMap = loader.loadAll(keys); + if (kvMap == null) { + return; + } + final CacheLoader preloaded = new MapLoader<>(kvMap); + for (final K k : keys) { + if (replaceExistingValues) { + doLoad(k, containsKey(k), completionListener != null, preloaded); + } else if (!containsKey(k)) { + doGetControllingExpiry(now, k, true, true, false, completionListener != null, preloaded); + } + } + } catch (final RuntimeException e) { + if (completionListener != null) { + completionListener.onException(e); + return; + } + } + if (completionListener != null) { + completionListener.onCompletion(); + } + } + + @Override + public T invoke(final K key, final EntryProcessor entryProcessor, final Object... arguments) + throws EntryProcessorException { + final TempStateCacheView view = new TempStateCacheView(this); + final T t = doInvoke(view, key, entryProcessor, arguments); + view.merge(); + return t; + } + + private T doInvoke(final TempStateCacheView view, final K key, final EntryProcessor entryProcessor, + final Object... arguments) { + assertNotClosed(); + assertNotNull(entryProcessor, "entryProcessor"); + assertNotNull(key, "key"); + try { + if (config.isStatisticsEnabled()) { + if (containsKey(key)) { + statistics.increaseHits(1); + } else { + statistics.increaseMisses(1); + } + } + return entryProcessor.process(new SimpleMutableEntry<>(view, key), arguments); + } catch (final Exception ex) { + return throwEntryProcessorException(ex); + } + } + + @Override + public Map> invokeAll(final Set keys, + final EntryProcessor entryProcessor, final Object... arguments) { + assertNotClosed(); + assertNotNull(entryProcessor, "entryProcessor"); + final Map> results = new HashMap<>(); + for (final K k : keys) { + try { + final T invoke = invoke(k, entryProcessor, arguments); + if (invoke != null) { + results.put(k, new EntryProcessorResult() { + + @Override + public T get() throws EntryProcessorException { + return invoke; + } + }); + } + } catch (final Exception e) { + results.put(k, new EntryProcessorResult() { + + @Override + public T get() throws EntryProcessorException { + return throwEntryProcessorException(e); + } + }); + } + } + return results; + } + + @Override + public void registerCacheEntryListener(final CacheEntryListenerConfiguration cacheEntryListenerConfiguration) { + assertNotClosed(); + if (listeners.containsKey(cacheEntryListenerConfiguration)) { + throw new IllegalArgumentException(cacheEntryListenerConfiguration + " already registered"); + } + listeners.put(cacheEntryListenerConfiguration, new SimpleListener<>(cacheEntryListenerConfiguration)); + config.addListener(cacheEntryListenerConfiguration); + } + + @Override + public void deregisterCacheEntryListener(final CacheEntryListenerConfiguration cacheEntryListenerConfiguration) { + assertNotClosed(); + listeners.remove(cacheEntryListenerConfiguration); + config.removeListener(cacheEntryListenerConfiguration); + } + + @Override + public Iterator> iterator() { + assertNotClosed(); + final Iterator> keys = new HashSet<>(delegate.keySet()).iterator(); + return new Iterator>() { + + private K lastKey = null; + + @Override + public boolean hasNext() { + return keys.hasNext(); + } + + @Override + public Entry next() { + lastKey = keys.next().getKey(); + return new SimpleEntry<>(lastKey, get(lastKey)); + } + + @Override + public void remove() { + if (isClosed() || lastKey == null) { + throw new IllegalStateException(isClosed() ? "cache closed" : "call next() before remove()"); + } + SimpleCache.this.remove(lastKey); + } + }; + } + + @Override + public String getName() { + assertNotClosed(); + return name; + } + + @Override + public CacheManager getCacheManager() { + assertNotClosed(); + return manager; + } + + @Override + public synchronized void close() { + if (isClosed()) { + return; + } + + for (final Future task : poolTasks) { + task.cancel(true); + } + + final CacheException ce = new CacheException(); + manager.release(getName()); + closed = true; + close(loader, ce); + close(writer, ce); + close(expiryPolicy, ce); + for (final SimpleListener listener : listeners.values()) { + try { + listener.close(); + } catch (final Exception e) { + ce.addSuppressed(e); + } + } + listeners.clear(); + JMXs.unregister(cacheConfigObjectName); + JMXs.unregister(cacheStatsObjectName); + delegate.clear(); + if (ce.getSuppressed().length > 0) { + throw ce; + } + } + + @Override + public boolean isClosed() { + return closed; + } + + @Override + public T unwrap(final Class clazz) { + assertNotClosed(); + if (clazz.isInstance(this)) { + return clazz.cast(this); + } + if (clazz.isAssignableFrom(Map.class) || clazz.isAssignableFrom(ConcurrentMap.class)) { + return clazz.cast(delegate); + } + throw new IllegalArgumentException(clazz.getName() + " not supported in unwrap"); + } + + public Statistics getStatistics() { + return statistics; + } + + public void enableManagement() { + config.managementEnabled(); + JMXs.register(cacheConfigObjectName, new SimpleCacheMXBean(this)); + } + + public void disableManagement() { + config.managementDisabled(); + JMXs.unregister(cacheConfigObjectName); + } + + public void enableStatistics() { + config.statisticsEnabled(); + statistics.setActive(true); + JMXs.register(cacheStatsObjectName, new SimpleCacheStatisticsMXBean(statistics)); + } + + public void disableStatistics() { + config.statisticsDisabled(); + statistics.setActive(false); + JMXs.unregister(cacheStatsObjectName); + } + + private static String property(final Properties properties, final String cacheName, final String name, + final String defaultValue) { + return properties.getProperty(cacheName + "." + name, properties.getProperty(name, defaultValue)); + } + + private static boolean isNotZero(final Duration duration) { + return duration == null || !duration.isZero(); + } + + private static T throwEntryProcessorException(final Exception ex) { + if (EntryProcessorException.class.isInstance(ex)) { + throw EntryProcessorException.class.cast(ex); + } + throw new EntryProcessorException(ex); + } + + private static void close(final Object potentiallyCloseable, final CacheException wrapper) { + if (AutoCloseable.class.isInstance(potentiallyCloseable)) { + try { + AutoCloseable.class.cast(potentiallyCloseable).close(); + } catch (final Exception re) { + wrapper.addSuppressed(re); + } + } + } + + private class EvictionThread implements Runnable { + + private final long pause; + + private final long maxDelete; + + private EvictionThread(final long evictionPause, final long maxDelete) { + this.pause = evictionPause; + this.maxDelete = maxDelete; + } + + @Override + public void run() { + while (!isClosed()) { + try { + Thread.sleep(pause); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } + if (delegate.isEmpty()) { + continue; + } + + try { + final List> keys = new ArrayList<>(delegate.keySet()); + Collections.sort(keys, new Comparator>() { + + @Override + public int compare(final SimpleKey o1, final SimpleKey o2) { + final long l = o1.lastAccess() - o2.lastAccess(); + if (l == 0) { + return keys.indexOf(o1) - keys.indexOf(o2); + } + return (int) l; + } + }); + + int delete = 0; + for (final SimpleKey key : keys) { + final SimpleElement elt = delegate.get(key); + if (elt != null && elt.isExpired()) { + delegate.remove(key); + statistics.increaseEvictions(1); + onExpired(key, elt); + delete++; + if (delete >= maxDelete) { + break; + } + } + } + } catch (final Exception e) { + // no-op + } + } + } + } + + private static class MapLoader implements CacheLoader { + + private final Map loaded; + + private MapLoader(final Map loaded) { + this.loaded = loaded; + } + + @Override + public V load(final K key) throws CacheLoaderException { + return loaded.get(key); + } + + @Override + public Map loadAll(final Iterable keys) throws CacheLoaderException { + throw new UnsupportedOperationException(); + } + } +} diff --git a/Java/geronimo-jcache-simple-SimpleCache_188/metadata.json b/Java/geronimo-jcache-simple-SimpleCache_188/metadata.json new file mode 100644 index 000000000..c867f031a --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_188/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleCache_188", + "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/geronimo/jcache/simple/SimpleCache.java", + "line": 192, + "npe_method": "doLoad", + "deref_field": "v", + "npe_class": "SimpleCache", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleCache_188" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleCache_188/npe.json b/Java/geronimo-jcache-simple-SimpleCache_188/npe.json new file mode 100644 index 000000000..ec210728e --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_188/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleCache.java", + "line": 192, + "npe_method": "doLoad", + "deref_field": "v", + "npe_class": "SimpleCache" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleCache_216/Dockerfile b/Java/geronimo-jcache-simple-SimpleCache_216/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_216/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleCache_216/buggy.java b/Java/geronimo-jcache-simple-SimpleCache_216/buggy.java new file mode 100644 index 000000000..be1272549 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_216/buggy.java @@ -0,0 +1,875 @@ +/* + * 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.geronimo.jcache.simple; + +import static org.apache.geronimo.jcache.simple.Asserts.assertNotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicReference; + +import javax.cache.Cache; +import javax.cache.CacheException; +import javax.cache.CacheManager; +import javax.cache.configuration.CacheEntryListenerConfiguration; +import javax.cache.configuration.Configuration; +import javax.cache.configuration.Factory; +import javax.cache.event.CacheEntryEvent; +import javax.cache.event.EventType; +import javax.cache.expiry.Duration; +import javax.cache.expiry.EternalExpiryPolicy; +import javax.cache.expiry.ExpiryPolicy; +import javax.cache.integration.CacheLoader; +import javax.cache.integration.CacheLoaderException; +import javax.cache.integration.CacheWriter; +import javax.cache.integration.CacheWriterException; +import javax.cache.integration.CompletionListener; +import javax.cache.processor.EntryProcessor; +import javax.cache.processor.EntryProcessorException; +import javax.cache.processor.EntryProcessorResult; +import javax.management.ObjectName; + +public class SimpleCache implements Cache { + + private final SimpleManager manager; + + private final SimpleConfiguration config; + + private final CacheLoader loader; + + private final CacheWriter writer; + + private final ExpiryPolicy expiryPolicy; + + private final ObjectName cacheConfigObjectName; + + private final ObjectName cacheStatsObjectName; + + private final String name; + + private final ConcurrentHashMap, SimpleElement> delegate; + + private final Map, SimpleListener> listeners = new ConcurrentHashMap<>(); + + private final Statistics statistics = new Statistics(); + + private final ExecutorService pool; + + private final Serializations serializations; + + private final Collection> poolTasks = new CopyOnWriteArraySet<>(); + + private volatile boolean closed = false; + + public SimpleCache(final ClassLoader classLoader, final SimpleManager mgr, final String cacheName, + final SimpleConfiguration configuration, final Properties properties, + final ExecutorService executorService) { + manager = mgr; + + name = cacheName; + + final int capacity = Integer.parseInt(property(properties, cacheName, "capacity", "1000")); + final float loadFactor = Float.parseFloat(property(properties, cacheName, "loadFactor", "0.75")); + final int concurrencyLevel = Integer.parseInt(property(properties, cacheName, "concurrencyLevel", "16")); + delegate = new ConcurrentHashMap<>(capacity, loadFactor, concurrencyLevel); + config = configuration; + pool = executorService; + + final long evictionPause = Long.parseLong( + properties.getProperty(cacheName + ".evictionPause", properties.getProperty("evictionPause", "30000"))); + if (evictionPause > 0) { + final long maxDeleteByEvictionRun = Long.parseLong(property(properties, cacheName, "maxDeleteByEvictionRun", "100")); + addPoolTask(new EvictionThread(evictionPause, maxDeleteByEvictionRun)); + } + + serializations = new Serializations(property(properties, cacheName, "serialization.whitelist", null)); + + final Factory> cacheLoaderFactory = configuration.getCacheLoaderFactory(); + if (cacheLoaderFactory == null) { + loader = NoLoader.INSTANCE; + } else { + loader = ExceptionWrapperHandler.newProxy(classLoader, cacheLoaderFactory.create(), CacheLoaderException.class, + CacheLoader.class); + } + + final Factory> cacheWriterFactory = configuration.getCacheWriterFactory(); + if (cacheWriterFactory == null) { + writer = NoWriter.INSTANCE; + } else { + writer = ExceptionWrapperHandler.newProxy(classLoader, cacheWriterFactory.create(), CacheWriterException.class, + CacheWriter.class); + } + + final Factory expiryPolicyFactory = configuration.getExpiryPolicyFactory(); + if (expiryPolicyFactory == null) { + expiryPolicy = new EternalExpiryPolicy(); + } else { + expiryPolicy = expiryPolicyFactory.create(); + } + + for (final CacheEntryListenerConfiguration listener : config.getCacheEntryListenerConfigurations()) { + listeners.put(listener, new SimpleListener<>(listener)); + } + + statistics.setActive(config.isStatisticsEnabled()); + + final String mgrStr = manager.getURI().toString().replaceAll(",|:|=|\n", "."); + final String cacheStr = name.replaceAll(",|:|=|\n", "."); + try { + cacheConfigObjectName = new ObjectName( + "javax.cache:type=CacheConfiguration," + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr); + cacheStatsObjectName = new ObjectName( + "javax.cache:type=CacheStatistics," + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr); + } catch (final Exception e) { + throw new IllegalArgumentException(e); + } + if (config.isManagementEnabled()) { + JMXs.register(cacheConfigObjectName, new SimpleCacheMXBean(this)); + } + if (config.isStatisticsEnabled()) { + JMXs.register(cacheStatsObjectName, new SimpleCacheStatisticsMXBean(statistics)); + } + } + + private void assertNotClosed() { + if (isClosed()) { + throw new IllegalStateException("cache closed"); + } + } + + @Override + public V get(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + final long getStart = Times.now(false); + return doGetControllingExpiry(getStart, key, true, false, false, true, loader); + } + + private V doLoad(final K key, final boolean update, final boolean propagateLoadException, final CacheLoader loader) { + V v = null; + try { + v = loader.load(key); + } catch (final CacheLoaderException e) { + if (propagateLoadException) { + throw e; + } + } + if (v != null) { + final Duration duration = update ? expiryPolicy.getExpiryForUpdate() : expiryPolicy.getExpiryForCreation(); + if (isNotZero(duration)) { + delegate.put(new SimpleKey<>(key), new SimpleElement<>(v, duration)); + } + } + return v; + } + + private void touch(final SimpleKey key, final SimpleElement element) { + if (config.isStoreByValue()) { + delegate.put(new SimpleKey<>(serializations.copy(manager.getClassLoader(), key.getKey())), element); + } + } + + @Override +public java.util.Map getAll(final java.util.Set keys) { + assertNotClosed(); + for (final K k : keys) { + org.apache.geronimo.jcache.simple.Asserts.assertNotNull(k, "key"); + } + final java.util.Map result = new java.util.HashMap<>(); + for (final K key : keys) { + org.apache.geronimo.jcache.simple.Asserts.assertNotNull(key, "key"); + final org.apache.geronimo.jcache.simple.SimpleKey simpleKey = new org.apache.geronimo.jcache.simple.SimpleKey<>(key); + final org.apache.geronimo.jcache.simple.SimpleElement elt = delegate.get(simpleKey); + V val = /* NPEX_NULL_EXP */ + elt.getElement(); + if ((val == null) && config.isReadThrough()) { + val = doLoad(key, false, false, loader); + if (val != null) { + result.put(key, val); + } + } else if (elt != null) { + final javax.cache.expiry.Duration expiryForAccess = expiryPolicy.getExpiryForAccess(); + if (org.apache.geronimo.jcache.simple.SimpleCache.isNotZero(expiryForAccess)) { + touch(simpleKey, elt); + result.put(key, val); + } else { + expires(simpleKey); + } + } + } + return result; +} + + @Override + public boolean containsKey(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + return delegate.get(new SimpleKey<>(key)) != null; + } + + @Override + public void put(final K key, final V rawValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(rawValue, "value"); + + final boolean storeByValue = config.isStoreByValue(); + final SimpleKey simpleKey = new SimpleKey<>(storeByValue ? serializations.copy(manager.getClassLoader(), key) : key); + final SimpleElement oldElt = delegate.get(simpleKey); + final V old = oldElt != null ? oldElt.getElement() : null; + final V value = storeByValue ? serializations.copy(manager.getClassLoader(), rawValue) : rawValue; + + final boolean created = old == null; + final Duration duration = created ? expiryPolicy.getExpiryForCreation() : expiryPolicy.getExpiryForUpdate(); + if (isNotZero(duration)) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final long start = Times.now(false); + + writer.write(new SimpleEntry<>(key, value)); + delegate.put(simpleKey, new SimpleElement<>(value, duration)); + if (!listeners.isEmpty()) { + for (final SimpleListener listener : listeners.values()) { + if (created) { + listener.onCreated(Collections.> singletonList( + new SimpleEvent<>(this, EventType.CREATED, null, key, value))); + } else + listener.onUpdated(Collections.> singletonList( + new SimpleEvent<>(this, EventType.UPDATED, old, key, value))); + } + } + + if (statisticsEnabled) { + statistics.increasePuts(1); + statistics.addPutTime(Times.now(false) - start); + } + } else { + if (!created) { + expires(simpleKey); + } + } + } + + private void expires(final SimpleKey cacheKey) { + final SimpleElement elt = delegate.get(cacheKey); + delegate.remove(cacheKey); + onExpired(cacheKey, elt); + } + + private void onExpired(final SimpleKey cacheKey, final SimpleElement elt) { + for (final SimpleListener listener : listeners.values()) { + listener.onExpired(Collections.> singletonList( + new SimpleEvent<>(this, EventType.REMOVED, null, cacheKey.getKey(), elt.getElement()))); + } + } + + @Override + public V getAndPut(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, true, false, loader); + put(key, value); + return v; + } + + @Override + public void putAll(final Map map) { + assertNotClosed(); + final TempStateCacheView view = new TempStateCacheView(this); + for (final Map.Entry e : map.entrySet()) { + view.put(e.getKey(), e.getValue()); + } + view.merge(); + } + + @Override + public boolean putIfAbsent(final K key, final V value) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + if (!containsKey(key)) { + if (statisticsEnabled) { + statistics.increaseMisses(1); + } + put(key, value); + return true; + } else { + if (statisticsEnabled) { + statistics.increaseHits(1); + } + } + return false; + } + + @Override + public boolean remove(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final long start = Times.now(!statisticsEnabled); + + writer.delete(key); + final SimpleKey cacheKey = new SimpleKey<>(key); + + final SimpleElement v = delegate.remove(cacheKey); + if (v == null || v.isExpired()) { + return false; + } + + final V value = v.getElement(); + for (final SimpleListener listener : listeners.values()) { + listener.onRemoved(Collections.> singletonList( + new SimpleEvent<>(this, EventType.REMOVED, value, key, value))); + } + if (statisticsEnabled) { + statistics.increaseRemovals(1); + statistics.addRemoveTime(Times.now(false) - start); + } + + return true; + } + + @Override + public boolean remove(final K key, final V oldValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(oldValue, "oldValue"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, false, false, loader); + if (oldValue.equals(v)) { + remove(key); + return true; + } else if (v != null) { + // weird but just for stats to be right + // (org.jsr107.tck.expiry.CacheExpiryTest.removeSpecifiedEntryShouldNotCallExpiryPolicyMethods()) + expiryPolicy.getExpiryForAccess(); + } + return false; + } + + @Override + public V getAndRemove(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, true, false, loader); + remove(key); + return v; + } + + private V doGetControllingExpiry(final long getStart, final K key, final boolean updateAcess, final boolean forceDoLoad, + final boolean skipLoad, final boolean propagateLoadException, final CacheLoader loader) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final SimpleKey simpleKey = new SimpleKey<>(key); + final SimpleElement elt = delegate.get(simpleKey); + V v = elt != null ? elt.getElement() : null; + if (v == null && (config.isReadThrough() || forceDoLoad)) { + if (!skipLoad) { + v = doLoad(key, false, propagateLoadException, loader); + } + } else if (statisticsEnabled) { + if (v != null) { + statistics.increaseHits(1); + } else { + statistics.increaseMisses(1); + } + } + + if (updateAcess && elt != null) { + final Duration expiryForAccess = expiryPolicy.getExpiryForAccess(); + if (!isNotZero(expiryForAccess)) { + expires(simpleKey); + } + } + if (statisticsEnabled && v != null) { + statistics.addGetTime(Times.now(false) - getStart); + } + return v; + } + + @Override + public boolean replace(final K key, final V oldValue, final V newValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(oldValue, "oldValue"); + assertNotNull(newValue, "newValue"); + final V value = doGetControllingExpiry(Times.now(config.isStatisticsEnabled()), key, false, config.isReadThrough(), false, + true, loader); + if (value != null && value.equals(oldValue)) { + put(key, newValue); + return true; + } else if (value != null) { + expiryPolicy.getExpiryForAccess(); + } + return false; + } + + @Override + public boolean replace(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + boolean statisticsEnabled = config.isStatisticsEnabled(); + if (containsKey(key)) { + if (statisticsEnabled) { + statistics.increaseHits(1); + } + put(key, value); + return true; + } else if (statisticsEnabled) { + statistics.increaseMisses(1); + } + return false; + } + + @Override + public V getAndReplace(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + + final boolean statisticsEnabled = config.isStatisticsEnabled(); + + final SimpleElement elt = delegate.get(new SimpleKey<>(key)); + if (elt != null) { + V oldValue = elt.getElement(); + if (oldValue == null && config.isReadThrough()) { + oldValue = doLoad(key, false, false, loader); + } else if (statisticsEnabled) { + statistics.increaseHits(1); + } + put(key, value); + return oldValue; + } else if (statisticsEnabled) { + statistics.increaseMisses(1); + } + return null; + } + + @Override + public void removeAll(final Set keys) { + assertNotClosed(); + assertNotNull(keys, "keys"); + for (final K k : keys) { + remove(k); + } + } + + @Override + public void removeAll() { + assertNotClosed(); + for (final SimpleKey k : delegate.keySet()) { + remove(k.getKey()); + } + } + + @Override + public void clear() { + assertNotClosed(); + delegate.clear(); + } + + @Override + public > C2 getConfiguration(final Class clazz) { + assertNotClosed(); + return clazz.cast(config); + } + + @Override + public void loadAll(final Set keys, final boolean replaceExistingValues, + final CompletionListener completionListener) { + assertNotClosed(); + assertNotNull(keys, "keys"); + if (loader == null) { // quick exit path + if (completionListener != null) { + completionListener.onCompletion(); + } + return; + } + for (final K k : keys) { + assertNotNull(k, "a key"); + } + addPoolTask(new Runnable() { + + @Override + public void run() { + doLoadAll(keys, replaceExistingValues, completionListener); + } + }); + } + + private void addPoolTask(final Runnable runnable) { + final AtomicReference> ref = new AtomicReference<>(); + final CountDownLatch refIsSet = new CountDownLatch(1); + ref.set(pool.submit(new Runnable() { + @Override + public void run() { + try { + runnable.run(); + } finally { + try { + refIsSet.await(); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + } + poolTasks.remove(ref.get()); + } + } + })); + refIsSet.countDown(); + poolTasks.add(ref.get()); + } + + private void doLoadAll(final Set keys, final boolean replaceExistingValues, + final CompletionListener completionListener) { + try { + final long now = Times.now(false); + final Map kvMap = loader.loadAll(keys); + if (kvMap == null) { + return; + } + final CacheLoader preloaded = new MapLoader<>(kvMap); + for (final K k : keys) { + if (replaceExistingValues) { + doLoad(k, containsKey(k), completionListener != null, preloaded); + } else if (!containsKey(k)) { + doGetControllingExpiry(now, k, true, true, false, completionListener != null, preloaded); + } + } + } catch (final RuntimeException e) { + if (completionListener != null) { + completionListener.onException(e); + return; + } + } + if (completionListener != null) { + completionListener.onCompletion(); + } + } + + @Override + public T invoke(final K key, final EntryProcessor entryProcessor, final Object... arguments) + throws EntryProcessorException { + final TempStateCacheView view = new TempStateCacheView(this); + final T t = doInvoke(view, key, entryProcessor, arguments); + view.merge(); + return t; + } + + private T doInvoke(final TempStateCacheView view, final K key, final EntryProcessor entryProcessor, + final Object... arguments) { + assertNotClosed(); + assertNotNull(entryProcessor, "entryProcessor"); + assertNotNull(key, "key"); + try { + if (config.isStatisticsEnabled()) { + if (containsKey(key)) { + statistics.increaseHits(1); + } else { + statistics.increaseMisses(1); + } + } + return entryProcessor.process(new SimpleMutableEntry<>(view, key), arguments); + } catch (final Exception ex) { + return throwEntryProcessorException(ex); + } + } + + @Override + public Map> invokeAll(final Set keys, + final EntryProcessor entryProcessor, final Object... arguments) { + assertNotClosed(); + assertNotNull(entryProcessor, "entryProcessor"); + final Map> results = new HashMap<>(); + for (final K k : keys) { + try { + final T invoke = invoke(k, entryProcessor, arguments); + if (invoke != null) { + results.put(k, new EntryProcessorResult() { + + @Override + public T get() throws EntryProcessorException { + return invoke; + } + }); + } + } catch (final Exception e) { + results.put(k, new EntryProcessorResult() { + + @Override + public T get() throws EntryProcessorException { + return throwEntryProcessorException(e); + } + }); + } + } + return results; + } + + @Override + public void registerCacheEntryListener(final CacheEntryListenerConfiguration cacheEntryListenerConfiguration) { + assertNotClosed(); + if (listeners.containsKey(cacheEntryListenerConfiguration)) { + throw new IllegalArgumentException(cacheEntryListenerConfiguration + " already registered"); + } + listeners.put(cacheEntryListenerConfiguration, new SimpleListener<>(cacheEntryListenerConfiguration)); + config.addListener(cacheEntryListenerConfiguration); + } + + @Override + public void deregisterCacheEntryListener(final CacheEntryListenerConfiguration cacheEntryListenerConfiguration) { + assertNotClosed(); + listeners.remove(cacheEntryListenerConfiguration); + config.removeListener(cacheEntryListenerConfiguration); + } + + @Override + public Iterator> iterator() { + assertNotClosed(); + final Iterator> keys = new HashSet<>(delegate.keySet()).iterator(); + return new Iterator>() { + + private K lastKey = null; + + @Override + public boolean hasNext() { + return keys.hasNext(); + } + + @Override + public Entry next() { + lastKey = keys.next().getKey(); + return new SimpleEntry<>(lastKey, get(lastKey)); + } + + @Override + public void remove() { + if (isClosed() || lastKey == null) { + throw new IllegalStateException(isClosed() ? "cache closed" : "call next() before remove()"); + } + SimpleCache.this.remove(lastKey); + } + }; + } + + @Override + public String getName() { + assertNotClosed(); + return name; + } + + @Override + public CacheManager getCacheManager() { + assertNotClosed(); + return manager; + } + + @Override + public synchronized void close() { + if (isClosed()) { + return; + } + + for (final Future task : poolTasks) { + task.cancel(true); + } + + final CacheException ce = new CacheException(); + manager.release(getName()); + closed = true; + close(loader, ce); + close(writer, ce); + close(expiryPolicy, ce); + for (final SimpleListener listener : listeners.values()) { + try { + listener.close(); + } catch (final Exception e) { + ce.addSuppressed(e); + } + } + listeners.clear(); + JMXs.unregister(cacheConfigObjectName); + JMXs.unregister(cacheStatsObjectName); + delegate.clear(); + if (ce.getSuppressed().length > 0) { + throw ce; + } + } + + @Override + public boolean isClosed() { + return closed; + } + + @Override + public T unwrap(final Class clazz) { + assertNotClosed(); + if (clazz.isInstance(this)) { + return clazz.cast(this); + } + if (clazz.isAssignableFrom(Map.class) || clazz.isAssignableFrom(ConcurrentMap.class)) { + return clazz.cast(delegate); + } + throw new IllegalArgumentException(clazz.getName() + " not supported in unwrap"); + } + + public Statistics getStatistics() { + return statistics; + } + + public void enableManagement() { + config.managementEnabled(); + JMXs.register(cacheConfigObjectName, new SimpleCacheMXBean(this)); + } + + public void disableManagement() { + config.managementDisabled(); + JMXs.unregister(cacheConfigObjectName); + } + + public void enableStatistics() { + config.statisticsEnabled(); + statistics.setActive(true); + JMXs.register(cacheStatsObjectName, new SimpleCacheStatisticsMXBean(statistics)); + } + + public void disableStatistics() { + config.statisticsDisabled(); + statistics.setActive(false); + JMXs.unregister(cacheStatsObjectName); + } + + private static String property(final Properties properties, final String cacheName, final String name, + final String defaultValue) { + return properties.getProperty(cacheName + "." + name, properties.getProperty(name, defaultValue)); + } + + private static boolean isNotZero(final Duration duration) { + return duration == null || !duration.isZero(); + } + + private static T throwEntryProcessorException(final Exception ex) { + if (EntryProcessorException.class.isInstance(ex)) { + throw EntryProcessorException.class.cast(ex); + } + throw new EntryProcessorException(ex); + } + + private static void close(final Object potentiallyCloseable, final CacheException wrapper) { + if (AutoCloseable.class.isInstance(potentiallyCloseable)) { + try { + AutoCloseable.class.cast(potentiallyCloseable).close(); + } catch (final Exception re) { + wrapper.addSuppressed(re); + } + } + } + + private class EvictionThread implements Runnable { + + private final long pause; + + private final long maxDelete; + + private EvictionThread(final long evictionPause, final long maxDelete) { + this.pause = evictionPause; + this.maxDelete = maxDelete; + } + + @Override + public void run() { + while (!isClosed()) { + try { + Thread.sleep(pause); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } + if (delegate.isEmpty()) { + continue; + } + + try { + final List> keys = new ArrayList<>(delegate.keySet()); + Collections.sort(keys, new Comparator>() { + + @Override + public int compare(final SimpleKey o1, final SimpleKey o2) { + final long l = o1.lastAccess() - o2.lastAccess(); + if (l == 0) { + return keys.indexOf(o1) - keys.indexOf(o2); + } + return (int) l; + } + }); + + int delete = 0; + for (final SimpleKey key : keys) { + final SimpleElement elt = delegate.get(key); + if (elt != null && elt.isExpired()) { + delegate.remove(key); + statistics.increaseEvictions(1); + onExpired(key, elt); + delete++; + if (delete >= maxDelete) { + break; + } + } + } + } catch (final Exception e) { + // no-op + } + } + } + } + + private static class MapLoader implements CacheLoader { + + private final Map loaded; + + private MapLoader(final Map loaded) { + this.loaded = loaded; + } + + @Override + public V load(final K key) throws CacheLoaderException { + return loaded.get(key); + } + + @Override + public Map loadAll(final Iterable keys) throws CacheLoaderException { + throw new UnsupportedOperationException(); + } + } +} diff --git a/Java/geronimo-jcache-simple-SimpleCache_216/metadata.json b/Java/geronimo-jcache-simple-SimpleCache_216/metadata.json new file mode 100644 index 000000000..e433acef9 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_216/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleCache_216", + "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/geronimo/jcache/simple/SimpleCache.java", + "line": 215, + "npe_method": "getAll", + "deref_field": "elt", + "npe_class": "SimpleCache", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleCache_216" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleCache_216/npe.json b/Java/geronimo-jcache-simple-SimpleCache_216/npe.json new file mode 100644 index 000000000..313fb5eb5 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_216/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleCache.java", + "line": 215, + "npe_method": "getAll", + "deref_field": "elt", + "npe_class": "SimpleCache" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleCache_219/Dockerfile b/Java/geronimo-jcache-simple-SimpleCache_219/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_219/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleCache_219/buggy.java b/Java/geronimo-jcache-simple-SimpleCache_219/buggy.java new file mode 100644 index 000000000..39450c5e6 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_219/buggy.java @@ -0,0 +1,875 @@ +/* + * 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.geronimo.jcache.simple; + +import static org.apache.geronimo.jcache.simple.Asserts.assertNotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicReference; + +import javax.cache.Cache; +import javax.cache.CacheException; +import javax.cache.CacheManager; +import javax.cache.configuration.CacheEntryListenerConfiguration; +import javax.cache.configuration.Configuration; +import javax.cache.configuration.Factory; +import javax.cache.event.CacheEntryEvent; +import javax.cache.event.EventType; +import javax.cache.expiry.Duration; +import javax.cache.expiry.EternalExpiryPolicy; +import javax.cache.expiry.ExpiryPolicy; +import javax.cache.integration.CacheLoader; +import javax.cache.integration.CacheLoaderException; +import javax.cache.integration.CacheWriter; +import javax.cache.integration.CacheWriterException; +import javax.cache.integration.CompletionListener; +import javax.cache.processor.EntryProcessor; +import javax.cache.processor.EntryProcessorException; +import javax.cache.processor.EntryProcessorResult; +import javax.management.ObjectName; + +public class SimpleCache implements Cache { + + private final SimpleManager manager; + + private final SimpleConfiguration config; + + private final CacheLoader loader; + + private final CacheWriter writer; + + private final ExpiryPolicy expiryPolicy; + + private final ObjectName cacheConfigObjectName; + + private final ObjectName cacheStatsObjectName; + + private final String name; + + private final ConcurrentHashMap, SimpleElement> delegate; + + private final Map, SimpleListener> listeners = new ConcurrentHashMap<>(); + + private final Statistics statistics = new Statistics(); + + private final ExecutorService pool; + + private final Serializations serializations; + + private final Collection> poolTasks = new CopyOnWriteArraySet<>(); + + private volatile boolean closed = false; + + public SimpleCache(final ClassLoader classLoader, final SimpleManager mgr, final String cacheName, + final SimpleConfiguration configuration, final Properties properties, + final ExecutorService executorService) { + manager = mgr; + + name = cacheName; + + final int capacity = Integer.parseInt(property(properties, cacheName, "capacity", "1000")); + final float loadFactor = Float.parseFloat(property(properties, cacheName, "loadFactor", "0.75")); + final int concurrencyLevel = Integer.parseInt(property(properties, cacheName, "concurrencyLevel", "16")); + delegate = new ConcurrentHashMap<>(capacity, loadFactor, concurrencyLevel); + config = configuration; + pool = executorService; + + final long evictionPause = Long.parseLong( + properties.getProperty(cacheName + ".evictionPause", properties.getProperty("evictionPause", "30000"))); + if (evictionPause > 0) { + final long maxDeleteByEvictionRun = Long.parseLong(property(properties, cacheName, "maxDeleteByEvictionRun", "100")); + addPoolTask(new EvictionThread(evictionPause, maxDeleteByEvictionRun)); + } + + serializations = new Serializations(property(properties, cacheName, "serialization.whitelist", null)); + + final Factory> cacheLoaderFactory = configuration.getCacheLoaderFactory(); + if (cacheLoaderFactory == null) { + loader = NoLoader.INSTANCE; + } else { + loader = ExceptionWrapperHandler.newProxy(classLoader, cacheLoaderFactory.create(), CacheLoaderException.class, + CacheLoader.class); + } + + final Factory> cacheWriterFactory = configuration.getCacheWriterFactory(); + if (cacheWriterFactory == null) { + writer = NoWriter.INSTANCE; + } else { + writer = ExceptionWrapperHandler.newProxy(classLoader, cacheWriterFactory.create(), CacheWriterException.class, + CacheWriter.class); + } + + final Factory expiryPolicyFactory = configuration.getExpiryPolicyFactory(); + if (expiryPolicyFactory == null) { + expiryPolicy = new EternalExpiryPolicy(); + } else { + expiryPolicy = expiryPolicyFactory.create(); + } + + for (final CacheEntryListenerConfiguration listener : config.getCacheEntryListenerConfigurations()) { + listeners.put(listener, new SimpleListener<>(listener)); + } + + statistics.setActive(config.isStatisticsEnabled()); + + final String mgrStr = manager.getURI().toString().replaceAll(",|:|=|\n", "."); + final String cacheStr = name.replaceAll(",|:|=|\n", "."); + try { + cacheConfigObjectName = new ObjectName( + "javax.cache:type=CacheConfiguration," + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr); + cacheStatsObjectName = new ObjectName( + "javax.cache:type=CacheStatistics," + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr); + } catch (final Exception e) { + throw new IllegalArgumentException(e); + } + if (config.isManagementEnabled()) { + JMXs.register(cacheConfigObjectName, new SimpleCacheMXBean(this)); + } + if (config.isStatisticsEnabled()) { + JMXs.register(cacheStatsObjectName, new SimpleCacheStatisticsMXBean(statistics)); + } + } + + private void assertNotClosed() { + if (isClosed()) { + throw new IllegalStateException("cache closed"); + } + } + + @Override + public V get(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + final long getStart = Times.now(false); + return doGetControllingExpiry(getStart, key, true, false, false, true, loader); + } + + private V doLoad(final K key, final boolean update, final boolean propagateLoadException, final CacheLoader loader) { + V v = null; + try { + v = loader.load(key); + } catch (final CacheLoaderException e) { + if (propagateLoadException) { + throw e; + } + } + if (v != null) { + final Duration duration = update ? expiryPolicy.getExpiryForUpdate() : expiryPolicy.getExpiryForCreation(); + if (isNotZero(duration)) { + delegate.put(new SimpleKey<>(key), new SimpleElement<>(v, duration)); + } + } + return v; + } + + private void touch(final SimpleKey key, final SimpleElement element) { + if (config.isStoreByValue()) { + delegate.put(new SimpleKey<>(serializations.copy(manager.getClassLoader(), key.getKey())), element); + } + } + + @Override +public java.util.Map getAll(final java.util.Set keys) { + assertNotClosed(); + for (final K k : keys) { + org.apache.geronimo.jcache.simple.Asserts.assertNotNull(k, "key"); + } + final java.util.Map result = new java.util.HashMap<>(); + for (final K key : keys) { + org.apache.geronimo.jcache.simple.Asserts.assertNotNull(key, "key"); + final org.apache.geronimo.jcache.simple.SimpleKey simpleKey = new org.apache.geronimo.jcache.simple.SimpleKey<>(key); + final org.apache.geronimo.jcache.simple.SimpleElement elt = delegate.get(simpleKey); + V val = (elt != null) ? elt.getElement() : null; + if ((val == null) && config.isReadThrough()) { + val = doLoad(key, false, false, loader); + { + result.put(key, /* NPEX_NULL_EXP */ + val); + } + } else if (elt != null) { + final javax.cache.expiry.Duration expiryForAccess = expiryPolicy.getExpiryForAccess(); + if (org.apache.geronimo.jcache.simple.SimpleCache.isNotZero(expiryForAccess)) { + touch(simpleKey, elt); + result.put(key, val); + } else { + expires(simpleKey); + } + } + } + return result; +} + + @Override + public boolean containsKey(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + return delegate.get(new SimpleKey<>(key)) != null; + } + + @Override + public void put(final K key, final V rawValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(rawValue, "value"); + + final boolean storeByValue = config.isStoreByValue(); + final SimpleKey simpleKey = new SimpleKey<>(storeByValue ? serializations.copy(manager.getClassLoader(), key) : key); + final SimpleElement oldElt = delegate.get(simpleKey); + final V old = oldElt != null ? oldElt.getElement() : null; + final V value = storeByValue ? serializations.copy(manager.getClassLoader(), rawValue) : rawValue; + + final boolean created = old == null; + final Duration duration = created ? expiryPolicy.getExpiryForCreation() : expiryPolicy.getExpiryForUpdate(); + if (isNotZero(duration)) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final long start = Times.now(false); + + writer.write(new SimpleEntry<>(key, value)); + delegate.put(simpleKey, new SimpleElement<>(value, duration)); + if (!listeners.isEmpty()) { + for (final SimpleListener listener : listeners.values()) { + if (created) { + listener.onCreated(Collections.> singletonList( + new SimpleEvent<>(this, EventType.CREATED, null, key, value))); + } else + listener.onUpdated(Collections.> singletonList( + new SimpleEvent<>(this, EventType.UPDATED, old, key, value))); + } + } + + if (statisticsEnabled) { + statistics.increasePuts(1); + statistics.addPutTime(Times.now(false) - start); + } + } else { + if (!created) { + expires(simpleKey); + } + } + } + + private void expires(final SimpleKey cacheKey) { + final SimpleElement elt = delegate.get(cacheKey); + delegate.remove(cacheKey); + onExpired(cacheKey, elt); + } + + private void onExpired(final SimpleKey cacheKey, final SimpleElement elt) { + for (final SimpleListener listener : listeners.values()) { + listener.onExpired(Collections.> singletonList( + new SimpleEvent<>(this, EventType.REMOVED, null, cacheKey.getKey(), elt.getElement()))); + } + } + + @Override + public V getAndPut(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, true, false, loader); + put(key, value); + return v; + } + + @Override + public void putAll(final Map map) { + assertNotClosed(); + final TempStateCacheView view = new TempStateCacheView(this); + for (final Map.Entry e : map.entrySet()) { + view.put(e.getKey(), e.getValue()); + } + view.merge(); + } + + @Override + public boolean putIfAbsent(final K key, final V value) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + if (!containsKey(key)) { + if (statisticsEnabled) { + statistics.increaseMisses(1); + } + put(key, value); + return true; + } else { + if (statisticsEnabled) { + statistics.increaseHits(1); + } + } + return false; + } + + @Override + public boolean remove(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final long start = Times.now(!statisticsEnabled); + + writer.delete(key); + final SimpleKey cacheKey = new SimpleKey<>(key); + + final SimpleElement v = delegate.remove(cacheKey); + if (v == null || v.isExpired()) { + return false; + } + + final V value = v.getElement(); + for (final SimpleListener listener : listeners.values()) { + listener.onRemoved(Collections.> singletonList( + new SimpleEvent<>(this, EventType.REMOVED, value, key, value))); + } + if (statisticsEnabled) { + statistics.increaseRemovals(1); + statistics.addRemoveTime(Times.now(false) - start); + } + + return true; + } + + @Override + public boolean remove(final K key, final V oldValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(oldValue, "oldValue"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, false, false, loader); + if (oldValue.equals(v)) { + remove(key); + return true; + } else if (v != null) { + // weird but just for stats to be right + // (org.jsr107.tck.expiry.CacheExpiryTest.removeSpecifiedEntryShouldNotCallExpiryPolicyMethods()) + expiryPolicy.getExpiryForAccess(); + } + return false; + } + + @Override + public V getAndRemove(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, true, false, loader); + remove(key); + return v; + } + + private V doGetControllingExpiry(final long getStart, final K key, final boolean updateAcess, final boolean forceDoLoad, + final boolean skipLoad, final boolean propagateLoadException, final CacheLoader loader) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final SimpleKey simpleKey = new SimpleKey<>(key); + final SimpleElement elt = delegate.get(simpleKey); + V v = elt != null ? elt.getElement() : null; + if (v == null && (config.isReadThrough() || forceDoLoad)) { + if (!skipLoad) { + v = doLoad(key, false, propagateLoadException, loader); + } + } else if (statisticsEnabled) { + if (v != null) { + statistics.increaseHits(1); + } else { + statistics.increaseMisses(1); + } + } + + if (updateAcess && elt != null) { + final Duration expiryForAccess = expiryPolicy.getExpiryForAccess(); + if (!isNotZero(expiryForAccess)) { + expires(simpleKey); + } + } + if (statisticsEnabled && v != null) { + statistics.addGetTime(Times.now(false) - getStart); + } + return v; + } + + @Override + public boolean replace(final K key, final V oldValue, final V newValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(oldValue, "oldValue"); + assertNotNull(newValue, "newValue"); + final V value = doGetControllingExpiry(Times.now(config.isStatisticsEnabled()), key, false, config.isReadThrough(), false, + true, loader); + if (value != null && value.equals(oldValue)) { + put(key, newValue); + return true; + } else if (value != null) { + expiryPolicy.getExpiryForAccess(); + } + return false; + } + + @Override + public boolean replace(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + boolean statisticsEnabled = config.isStatisticsEnabled(); + if (containsKey(key)) { + if (statisticsEnabled) { + statistics.increaseHits(1); + } + put(key, value); + return true; + } else if (statisticsEnabled) { + statistics.increaseMisses(1); + } + return false; + } + + @Override + public V getAndReplace(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + + final boolean statisticsEnabled = config.isStatisticsEnabled(); + + final SimpleElement elt = delegate.get(new SimpleKey<>(key)); + if (elt != null) { + V oldValue = elt.getElement(); + if (oldValue == null && config.isReadThrough()) { + oldValue = doLoad(key, false, false, loader); + } else if (statisticsEnabled) { + statistics.increaseHits(1); + } + put(key, value); + return oldValue; + } else if (statisticsEnabled) { + statistics.increaseMisses(1); + } + return null; + } + + @Override + public void removeAll(final Set keys) { + assertNotClosed(); + assertNotNull(keys, "keys"); + for (final K k : keys) { + remove(k); + } + } + + @Override + public void removeAll() { + assertNotClosed(); + for (final SimpleKey k : delegate.keySet()) { + remove(k.getKey()); + } + } + + @Override + public void clear() { + assertNotClosed(); + delegate.clear(); + } + + @Override + public > C2 getConfiguration(final Class clazz) { + assertNotClosed(); + return clazz.cast(config); + } + + @Override + public void loadAll(final Set keys, final boolean replaceExistingValues, + final CompletionListener completionListener) { + assertNotClosed(); + assertNotNull(keys, "keys"); + if (loader == null) { // quick exit path + if (completionListener != null) { + completionListener.onCompletion(); + } + return; + } + for (final K k : keys) { + assertNotNull(k, "a key"); + } + addPoolTask(new Runnable() { + + @Override + public void run() { + doLoadAll(keys, replaceExistingValues, completionListener); + } + }); + } + + private void addPoolTask(final Runnable runnable) { + final AtomicReference> ref = new AtomicReference<>(); + final CountDownLatch refIsSet = new CountDownLatch(1); + ref.set(pool.submit(new Runnable() { + @Override + public void run() { + try { + runnable.run(); + } finally { + try { + refIsSet.await(); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + } + poolTasks.remove(ref.get()); + } + } + })); + refIsSet.countDown(); + poolTasks.add(ref.get()); + } + + private void doLoadAll(final Set keys, final boolean replaceExistingValues, + final CompletionListener completionListener) { + try { + final long now = Times.now(false); + final Map kvMap = loader.loadAll(keys); + if (kvMap == null) { + return; + } + final CacheLoader preloaded = new MapLoader<>(kvMap); + for (final K k : keys) { + if (replaceExistingValues) { + doLoad(k, containsKey(k), completionListener != null, preloaded); + } else if (!containsKey(k)) { + doGetControllingExpiry(now, k, true, true, false, completionListener != null, preloaded); + } + } + } catch (final RuntimeException e) { + if (completionListener != null) { + completionListener.onException(e); + return; + } + } + if (completionListener != null) { + completionListener.onCompletion(); + } + } + + @Override + public T invoke(final K key, final EntryProcessor entryProcessor, final Object... arguments) + throws EntryProcessorException { + final TempStateCacheView view = new TempStateCacheView(this); + final T t = doInvoke(view, key, entryProcessor, arguments); + view.merge(); + return t; + } + + private T doInvoke(final TempStateCacheView view, final K key, final EntryProcessor entryProcessor, + final Object... arguments) { + assertNotClosed(); + assertNotNull(entryProcessor, "entryProcessor"); + assertNotNull(key, "key"); + try { + if (config.isStatisticsEnabled()) { + if (containsKey(key)) { + statistics.increaseHits(1); + } else { + statistics.increaseMisses(1); + } + } + return entryProcessor.process(new SimpleMutableEntry<>(view, key), arguments); + } catch (final Exception ex) { + return throwEntryProcessorException(ex); + } + } + + @Override + public Map> invokeAll(final Set keys, + final EntryProcessor entryProcessor, final Object... arguments) { + assertNotClosed(); + assertNotNull(entryProcessor, "entryProcessor"); + final Map> results = new HashMap<>(); + for (final K k : keys) { + try { + final T invoke = invoke(k, entryProcessor, arguments); + if (invoke != null) { + results.put(k, new EntryProcessorResult() { + + @Override + public T get() throws EntryProcessorException { + return invoke; + } + }); + } + } catch (final Exception e) { + results.put(k, new EntryProcessorResult() { + + @Override + public T get() throws EntryProcessorException { + return throwEntryProcessorException(e); + } + }); + } + } + return results; + } + + @Override + public void registerCacheEntryListener(final CacheEntryListenerConfiguration cacheEntryListenerConfiguration) { + assertNotClosed(); + if (listeners.containsKey(cacheEntryListenerConfiguration)) { + throw new IllegalArgumentException(cacheEntryListenerConfiguration + " already registered"); + } + listeners.put(cacheEntryListenerConfiguration, new SimpleListener<>(cacheEntryListenerConfiguration)); + config.addListener(cacheEntryListenerConfiguration); + } + + @Override + public void deregisterCacheEntryListener(final CacheEntryListenerConfiguration cacheEntryListenerConfiguration) { + assertNotClosed(); + listeners.remove(cacheEntryListenerConfiguration); + config.removeListener(cacheEntryListenerConfiguration); + } + + @Override + public Iterator> iterator() { + assertNotClosed(); + final Iterator> keys = new HashSet<>(delegate.keySet()).iterator(); + return new Iterator>() { + + private K lastKey = null; + + @Override + public boolean hasNext() { + return keys.hasNext(); + } + + @Override + public Entry next() { + lastKey = keys.next().getKey(); + return new SimpleEntry<>(lastKey, get(lastKey)); + } + + @Override + public void remove() { + if (isClosed() || lastKey == null) { + throw new IllegalStateException(isClosed() ? "cache closed" : "call next() before remove()"); + } + SimpleCache.this.remove(lastKey); + } + }; + } + + @Override + public String getName() { + assertNotClosed(); + return name; + } + + @Override + public CacheManager getCacheManager() { + assertNotClosed(); + return manager; + } + + @Override + public synchronized void close() { + if (isClosed()) { + return; + } + + for (final Future task : poolTasks) { + task.cancel(true); + } + + final CacheException ce = new CacheException(); + manager.release(getName()); + closed = true; + close(loader, ce); + close(writer, ce); + close(expiryPolicy, ce); + for (final SimpleListener listener : listeners.values()) { + try { + listener.close(); + } catch (final Exception e) { + ce.addSuppressed(e); + } + } + listeners.clear(); + JMXs.unregister(cacheConfigObjectName); + JMXs.unregister(cacheStatsObjectName); + delegate.clear(); + if (ce.getSuppressed().length > 0) { + throw ce; + } + } + + @Override + public boolean isClosed() { + return closed; + } + + @Override + public T unwrap(final Class clazz) { + assertNotClosed(); + if (clazz.isInstance(this)) { + return clazz.cast(this); + } + if (clazz.isAssignableFrom(Map.class) || clazz.isAssignableFrom(ConcurrentMap.class)) { + return clazz.cast(delegate); + } + throw new IllegalArgumentException(clazz.getName() + " not supported in unwrap"); + } + + public Statistics getStatistics() { + return statistics; + } + + public void enableManagement() { + config.managementEnabled(); + JMXs.register(cacheConfigObjectName, new SimpleCacheMXBean(this)); + } + + public void disableManagement() { + config.managementDisabled(); + JMXs.unregister(cacheConfigObjectName); + } + + public void enableStatistics() { + config.statisticsEnabled(); + statistics.setActive(true); + JMXs.register(cacheStatsObjectName, new SimpleCacheStatisticsMXBean(statistics)); + } + + public void disableStatistics() { + config.statisticsDisabled(); + statistics.setActive(false); + JMXs.unregister(cacheStatsObjectName); + } + + private static String property(final Properties properties, final String cacheName, final String name, + final String defaultValue) { + return properties.getProperty(cacheName + "." + name, properties.getProperty(name, defaultValue)); + } + + private static boolean isNotZero(final Duration duration) { + return duration == null || !duration.isZero(); + } + + private static T throwEntryProcessorException(final Exception ex) { + if (EntryProcessorException.class.isInstance(ex)) { + throw EntryProcessorException.class.cast(ex); + } + throw new EntryProcessorException(ex); + } + + private static void close(final Object potentiallyCloseable, final CacheException wrapper) { + if (AutoCloseable.class.isInstance(potentiallyCloseable)) { + try { + AutoCloseable.class.cast(potentiallyCloseable).close(); + } catch (final Exception re) { + wrapper.addSuppressed(re); + } + } + } + + private class EvictionThread implements Runnable { + + private final long pause; + + private final long maxDelete; + + private EvictionThread(final long evictionPause, final long maxDelete) { + this.pause = evictionPause; + this.maxDelete = maxDelete; + } + + @Override + public void run() { + while (!isClosed()) { + try { + Thread.sleep(pause); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } + if (delegate.isEmpty()) { + continue; + } + + try { + final List> keys = new ArrayList<>(delegate.keySet()); + Collections.sort(keys, new Comparator>() { + + @Override + public int compare(final SimpleKey o1, final SimpleKey o2) { + final long l = o1.lastAccess() - o2.lastAccess(); + if (l == 0) { + return keys.indexOf(o1) - keys.indexOf(o2); + } + return (int) l; + } + }); + + int delete = 0; + for (final SimpleKey key : keys) { + final SimpleElement elt = delegate.get(key); + if (elt != null && elt.isExpired()) { + delegate.remove(key); + statistics.increaseEvictions(1); + onExpired(key, elt); + delete++; + if (delete >= maxDelete) { + break; + } + } + } + } catch (final Exception e) { + // no-op + } + } + } + } + + private static class MapLoader implements CacheLoader { + + private final Map loaded; + + private MapLoader(final Map loaded) { + this.loaded = loaded; + } + + @Override + public V load(final K key) throws CacheLoaderException { + return loaded.get(key); + } + + @Override + public Map loadAll(final Iterable keys) throws CacheLoaderException { + throw new UnsupportedOperationException(); + } + } +} diff --git a/Java/geronimo-jcache-simple-SimpleCache_219/metadata.json b/Java/geronimo-jcache-simple-SimpleCache_219/metadata.json new file mode 100644 index 000000000..f01573581 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_219/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleCache_219", + "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/geronimo/jcache/simple/SimpleCache.java", + "line": 219, + "npe_method": "getAll", + "deref_field": "val", + "npe_class": "SimpleCache", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleCache_219" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleCache_219/npe.json b/Java/geronimo-jcache-simple-SimpleCache_219/npe.json new file mode 100644 index 000000000..d48a53381 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_219/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleCache.java", + "line": 219, + "npe_method": "getAll", + "deref_field": "val", + "npe_class": "SimpleCache" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleCache_222/Dockerfile b/Java/geronimo-jcache-simple-SimpleCache_222/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_222/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleCache_222/buggy.java b/Java/geronimo-jcache-simple-SimpleCache_222/buggy.java new file mode 100644 index 000000000..ad9b139bb --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_222/buggy.java @@ -0,0 +1,877 @@ +/* + * 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.geronimo.jcache.simple; + +import static org.apache.geronimo.jcache.simple.Asserts.assertNotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicReference; + +import javax.cache.Cache; +import javax.cache.CacheException; +import javax.cache.CacheManager; +import javax.cache.configuration.CacheEntryListenerConfiguration; +import javax.cache.configuration.Configuration; +import javax.cache.configuration.Factory; +import javax.cache.event.CacheEntryEvent; +import javax.cache.event.EventType; +import javax.cache.expiry.Duration; +import javax.cache.expiry.EternalExpiryPolicy; +import javax.cache.expiry.ExpiryPolicy; +import javax.cache.integration.CacheLoader; +import javax.cache.integration.CacheLoaderException; +import javax.cache.integration.CacheWriter; +import javax.cache.integration.CacheWriterException; +import javax.cache.integration.CompletionListener; +import javax.cache.processor.EntryProcessor; +import javax.cache.processor.EntryProcessorException; +import javax.cache.processor.EntryProcessorResult; +import javax.management.ObjectName; + +public class SimpleCache implements Cache { + + private final SimpleManager manager; + + private final SimpleConfiguration config; + + private final CacheLoader loader; + + private final CacheWriter writer; + + private final ExpiryPolicy expiryPolicy; + + private final ObjectName cacheConfigObjectName; + + private final ObjectName cacheStatsObjectName; + + private final String name; + + private final ConcurrentHashMap, SimpleElement> delegate; + + private final Map, SimpleListener> listeners = new ConcurrentHashMap<>(); + + private final Statistics statistics = new Statistics(); + + private final ExecutorService pool; + + private final Serializations serializations; + + private final Collection> poolTasks = new CopyOnWriteArraySet<>(); + + private volatile boolean closed = false; + + public SimpleCache(final ClassLoader classLoader, final SimpleManager mgr, final String cacheName, + final SimpleConfiguration configuration, final Properties properties, + final ExecutorService executorService) { + manager = mgr; + + name = cacheName; + + final int capacity = Integer.parseInt(property(properties, cacheName, "capacity", "1000")); + final float loadFactor = Float.parseFloat(property(properties, cacheName, "loadFactor", "0.75")); + final int concurrencyLevel = Integer.parseInt(property(properties, cacheName, "concurrencyLevel", "16")); + delegate = new ConcurrentHashMap<>(capacity, loadFactor, concurrencyLevel); + config = configuration; + pool = executorService; + + final long evictionPause = Long.parseLong( + properties.getProperty(cacheName + ".evictionPause", properties.getProperty("evictionPause", "30000"))); + if (evictionPause > 0) { + final long maxDeleteByEvictionRun = Long.parseLong(property(properties, cacheName, "maxDeleteByEvictionRun", "100")); + addPoolTask(new EvictionThread(evictionPause, maxDeleteByEvictionRun)); + } + + serializations = new Serializations(property(properties, cacheName, "serialization.whitelist", null)); + + final Factory> cacheLoaderFactory = configuration.getCacheLoaderFactory(); + if (cacheLoaderFactory == null) { + loader = NoLoader.INSTANCE; + } else { + loader = ExceptionWrapperHandler.newProxy(classLoader, cacheLoaderFactory.create(), CacheLoaderException.class, + CacheLoader.class); + } + + final Factory> cacheWriterFactory = configuration.getCacheWriterFactory(); + if (cacheWriterFactory == null) { + writer = NoWriter.INSTANCE; + } else { + writer = ExceptionWrapperHandler.newProxy(classLoader, cacheWriterFactory.create(), CacheWriterException.class, + CacheWriter.class); + } + + final Factory expiryPolicyFactory = configuration.getExpiryPolicyFactory(); + if (expiryPolicyFactory == null) { + expiryPolicy = new EternalExpiryPolicy(); + } else { + expiryPolicy = expiryPolicyFactory.create(); + } + + for (final CacheEntryListenerConfiguration listener : config.getCacheEntryListenerConfigurations()) { + listeners.put(listener, new SimpleListener<>(listener)); + } + + statistics.setActive(config.isStatisticsEnabled()); + + final String mgrStr = manager.getURI().toString().replaceAll(",|:|=|\n", "."); + final String cacheStr = name.replaceAll(",|:|=|\n", "."); + try { + cacheConfigObjectName = new ObjectName( + "javax.cache:type=CacheConfiguration," + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr); + cacheStatsObjectName = new ObjectName( + "javax.cache:type=CacheStatistics," + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr); + } catch (final Exception e) { + throw new IllegalArgumentException(e); + } + if (config.isManagementEnabled()) { + JMXs.register(cacheConfigObjectName, new SimpleCacheMXBean(this)); + } + if (config.isStatisticsEnabled()) { + JMXs.register(cacheStatsObjectName, new SimpleCacheStatisticsMXBean(statistics)); + } + } + + private void assertNotClosed() { + if (isClosed()) { + throw new IllegalStateException("cache closed"); + } + } + + @Override + public V get(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + final long getStart = Times.now(false); + return doGetControllingExpiry(getStart, key, true, false, false, true, loader); + } + + private V doLoad(final K key, final boolean update, final boolean propagateLoadException, final CacheLoader loader) { + V v = null; + try { + v = loader.load(key); + } catch (final CacheLoaderException e) { + if (propagateLoadException) { + throw e; + } + } + if (v != null) { + final Duration duration = update ? expiryPolicy.getExpiryForUpdate() : expiryPolicy.getExpiryForCreation(); + if (isNotZero(duration)) { + delegate.put(new SimpleKey<>(key), new SimpleElement<>(v, duration)); + } + } + return v; + } + + private void touch(final SimpleKey key, final SimpleElement element) { + if (config.isStoreByValue()) { + delegate.put(new SimpleKey<>(serializations.copy(manager.getClassLoader(), key.getKey())), element); + } + } + + @Override +public java.util.Map getAll(final java.util.Set keys) { + assertNotClosed(); + for (final K k : keys) { + org.apache.geronimo.jcache.simple.Asserts.assertNotNull(k, "key"); + } + final java.util.Map result = new java.util.HashMap<>(); + for (final K key : keys) { + org.apache.geronimo.jcache.simple.Asserts.assertNotNull(key, "key"); + final org.apache.geronimo.jcache.simple.SimpleKey simpleKey = new org.apache.geronimo.jcache.simple.SimpleKey<>(key); + final org.apache.geronimo.jcache.simple.SimpleElement elt = delegate.get(simpleKey); + V val = (elt != null) ? elt.getElement() : null; + if ((val == null) && config.isReadThrough()) { + val = doLoad(key, false, false, loader); + if (val != null) { + result.put(key, val); + } + } else { + { + final javax.cache.expiry.Duration expiryForAccess = expiryPolicy.getExpiryForAccess(); + if (org.apache.geronimo.jcache.simple.SimpleCache.isNotZero(expiryForAccess)) { + touch(simpleKey, /* NPEX_NULL_EXP */ + elt); + result.put(key, val); + } else { + expires(simpleKey); + } + } + } + } + return result; +} + + @Override + public boolean containsKey(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + return delegate.get(new SimpleKey<>(key)) != null; + } + + @Override + public void put(final K key, final V rawValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(rawValue, "value"); + + final boolean storeByValue = config.isStoreByValue(); + final SimpleKey simpleKey = new SimpleKey<>(storeByValue ? serializations.copy(manager.getClassLoader(), key) : key); + final SimpleElement oldElt = delegate.get(simpleKey); + final V old = oldElt != null ? oldElt.getElement() : null; + final V value = storeByValue ? serializations.copy(manager.getClassLoader(), rawValue) : rawValue; + + final boolean created = old == null; + final Duration duration = created ? expiryPolicy.getExpiryForCreation() : expiryPolicy.getExpiryForUpdate(); + if (isNotZero(duration)) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final long start = Times.now(false); + + writer.write(new SimpleEntry<>(key, value)); + delegate.put(simpleKey, new SimpleElement<>(value, duration)); + if (!listeners.isEmpty()) { + for (final SimpleListener listener : listeners.values()) { + if (created) { + listener.onCreated(Collections.> singletonList( + new SimpleEvent<>(this, EventType.CREATED, null, key, value))); + } else + listener.onUpdated(Collections.> singletonList( + new SimpleEvent<>(this, EventType.UPDATED, old, key, value))); + } + } + + if (statisticsEnabled) { + statistics.increasePuts(1); + statistics.addPutTime(Times.now(false) - start); + } + } else { + if (!created) { + expires(simpleKey); + } + } + } + + private void expires(final SimpleKey cacheKey) { + final SimpleElement elt = delegate.get(cacheKey); + delegate.remove(cacheKey); + onExpired(cacheKey, elt); + } + + private void onExpired(final SimpleKey cacheKey, final SimpleElement elt) { + for (final SimpleListener listener : listeners.values()) { + listener.onExpired(Collections.> singletonList( + new SimpleEvent<>(this, EventType.REMOVED, null, cacheKey.getKey(), elt.getElement()))); + } + } + + @Override + public V getAndPut(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, true, false, loader); + put(key, value); + return v; + } + + @Override + public void putAll(final Map map) { + assertNotClosed(); + final TempStateCacheView view = new TempStateCacheView(this); + for (final Map.Entry e : map.entrySet()) { + view.put(e.getKey(), e.getValue()); + } + view.merge(); + } + + @Override + public boolean putIfAbsent(final K key, final V value) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + if (!containsKey(key)) { + if (statisticsEnabled) { + statistics.increaseMisses(1); + } + put(key, value); + return true; + } else { + if (statisticsEnabled) { + statistics.increaseHits(1); + } + } + return false; + } + + @Override + public boolean remove(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final long start = Times.now(!statisticsEnabled); + + writer.delete(key); + final SimpleKey cacheKey = new SimpleKey<>(key); + + final SimpleElement v = delegate.remove(cacheKey); + if (v == null || v.isExpired()) { + return false; + } + + final V value = v.getElement(); + for (final SimpleListener listener : listeners.values()) { + listener.onRemoved(Collections.> singletonList( + new SimpleEvent<>(this, EventType.REMOVED, value, key, value))); + } + if (statisticsEnabled) { + statistics.increaseRemovals(1); + statistics.addRemoveTime(Times.now(false) - start); + } + + return true; + } + + @Override + public boolean remove(final K key, final V oldValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(oldValue, "oldValue"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, false, false, loader); + if (oldValue.equals(v)) { + remove(key); + return true; + } else if (v != null) { + // weird but just for stats to be right + // (org.jsr107.tck.expiry.CacheExpiryTest.removeSpecifiedEntryShouldNotCallExpiryPolicyMethods()) + expiryPolicy.getExpiryForAccess(); + } + return false; + } + + @Override + public V getAndRemove(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, true, false, loader); + remove(key); + return v; + } + + private V doGetControllingExpiry(final long getStart, final K key, final boolean updateAcess, final boolean forceDoLoad, + final boolean skipLoad, final boolean propagateLoadException, final CacheLoader loader) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final SimpleKey simpleKey = new SimpleKey<>(key); + final SimpleElement elt = delegate.get(simpleKey); + V v = elt != null ? elt.getElement() : null; + if (v == null && (config.isReadThrough() || forceDoLoad)) { + if (!skipLoad) { + v = doLoad(key, false, propagateLoadException, loader); + } + } else if (statisticsEnabled) { + if (v != null) { + statistics.increaseHits(1); + } else { + statistics.increaseMisses(1); + } + } + + if (updateAcess && elt != null) { + final Duration expiryForAccess = expiryPolicy.getExpiryForAccess(); + if (!isNotZero(expiryForAccess)) { + expires(simpleKey); + } + } + if (statisticsEnabled && v != null) { + statistics.addGetTime(Times.now(false) - getStart); + } + return v; + } + + @Override + public boolean replace(final K key, final V oldValue, final V newValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(oldValue, "oldValue"); + assertNotNull(newValue, "newValue"); + final V value = doGetControllingExpiry(Times.now(config.isStatisticsEnabled()), key, false, config.isReadThrough(), false, + true, loader); + if (value != null && value.equals(oldValue)) { + put(key, newValue); + return true; + } else if (value != null) { + expiryPolicy.getExpiryForAccess(); + } + return false; + } + + @Override + public boolean replace(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + boolean statisticsEnabled = config.isStatisticsEnabled(); + if (containsKey(key)) { + if (statisticsEnabled) { + statistics.increaseHits(1); + } + put(key, value); + return true; + } else if (statisticsEnabled) { + statistics.increaseMisses(1); + } + return false; + } + + @Override + public V getAndReplace(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + + final boolean statisticsEnabled = config.isStatisticsEnabled(); + + final SimpleElement elt = delegate.get(new SimpleKey<>(key)); + if (elt != null) { + V oldValue = elt.getElement(); + if (oldValue == null && config.isReadThrough()) { + oldValue = doLoad(key, false, false, loader); + } else if (statisticsEnabled) { + statistics.increaseHits(1); + } + put(key, value); + return oldValue; + } else if (statisticsEnabled) { + statistics.increaseMisses(1); + } + return null; + } + + @Override + public void removeAll(final Set keys) { + assertNotClosed(); + assertNotNull(keys, "keys"); + for (final K k : keys) { + remove(k); + } + } + + @Override + public void removeAll() { + assertNotClosed(); + for (final SimpleKey k : delegate.keySet()) { + remove(k.getKey()); + } + } + + @Override + public void clear() { + assertNotClosed(); + delegate.clear(); + } + + @Override + public > C2 getConfiguration(final Class clazz) { + assertNotClosed(); + return clazz.cast(config); + } + + @Override + public void loadAll(final Set keys, final boolean replaceExistingValues, + final CompletionListener completionListener) { + assertNotClosed(); + assertNotNull(keys, "keys"); + if (loader == null) { // quick exit path + if (completionListener != null) { + completionListener.onCompletion(); + } + return; + } + for (final K k : keys) { + assertNotNull(k, "a key"); + } + addPoolTask(new Runnable() { + + @Override + public void run() { + doLoadAll(keys, replaceExistingValues, completionListener); + } + }); + } + + private void addPoolTask(final Runnable runnable) { + final AtomicReference> ref = new AtomicReference<>(); + final CountDownLatch refIsSet = new CountDownLatch(1); + ref.set(pool.submit(new Runnable() { + @Override + public void run() { + try { + runnable.run(); + } finally { + try { + refIsSet.await(); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + } + poolTasks.remove(ref.get()); + } + } + })); + refIsSet.countDown(); + poolTasks.add(ref.get()); + } + + private void doLoadAll(final Set keys, final boolean replaceExistingValues, + final CompletionListener completionListener) { + try { + final long now = Times.now(false); + final Map kvMap = loader.loadAll(keys); + if (kvMap == null) { + return; + } + final CacheLoader preloaded = new MapLoader<>(kvMap); + for (final K k : keys) { + if (replaceExistingValues) { + doLoad(k, containsKey(k), completionListener != null, preloaded); + } else if (!containsKey(k)) { + doGetControllingExpiry(now, k, true, true, false, completionListener != null, preloaded); + } + } + } catch (final RuntimeException e) { + if (completionListener != null) { + completionListener.onException(e); + return; + } + } + if (completionListener != null) { + completionListener.onCompletion(); + } + } + + @Override + public T invoke(final K key, final EntryProcessor entryProcessor, final Object... arguments) + throws EntryProcessorException { + final TempStateCacheView view = new TempStateCacheView(this); + final T t = doInvoke(view, key, entryProcessor, arguments); + view.merge(); + return t; + } + + private T doInvoke(final TempStateCacheView view, final K key, final EntryProcessor entryProcessor, + final Object... arguments) { + assertNotClosed(); + assertNotNull(entryProcessor, "entryProcessor"); + assertNotNull(key, "key"); + try { + if (config.isStatisticsEnabled()) { + if (containsKey(key)) { + statistics.increaseHits(1); + } else { + statistics.increaseMisses(1); + } + } + return entryProcessor.process(new SimpleMutableEntry<>(view, key), arguments); + } catch (final Exception ex) { + return throwEntryProcessorException(ex); + } + } + + @Override + public Map> invokeAll(final Set keys, + final EntryProcessor entryProcessor, final Object... arguments) { + assertNotClosed(); + assertNotNull(entryProcessor, "entryProcessor"); + final Map> results = new HashMap<>(); + for (final K k : keys) { + try { + final T invoke = invoke(k, entryProcessor, arguments); + if (invoke != null) { + results.put(k, new EntryProcessorResult() { + + @Override + public T get() throws EntryProcessorException { + return invoke; + } + }); + } + } catch (final Exception e) { + results.put(k, new EntryProcessorResult() { + + @Override + public T get() throws EntryProcessorException { + return throwEntryProcessorException(e); + } + }); + } + } + return results; + } + + @Override + public void registerCacheEntryListener(final CacheEntryListenerConfiguration cacheEntryListenerConfiguration) { + assertNotClosed(); + if (listeners.containsKey(cacheEntryListenerConfiguration)) { + throw new IllegalArgumentException(cacheEntryListenerConfiguration + " already registered"); + } + listeners.put(cacheEntryListenerConfiguration, new SimpleListener<>(cacheEntryListenerConfiguration)); + config.addListener(cacheEntryListenerConfiguration); + } + + @Override + public void deregisterCacheEntryListener(final CacheEntryListenerConfiguration cacheEntryListenerConfiguration) { + assertNotClosed(); + listeners.remove(cacheEntryListenerConfiguration); + config.removeListener(cacheEntryListenerConfiguration); + } + + @Override + public Iterator> iterator() { + assertNotClosed(); + final Iterator> keys = new HashSet<>(delegate.keySet()).iterator(); + return new Iterator>() { + + private K lastKey = null; + + @Override + public boolean hasNext() { + return keys.hasNext(); + } + + @Override + public Entry next() { + lastKey = keys.next().getKey(); + return new SimpleEntry<>(lastKey, get(lastKey)); + } + + @Override + public void remove() { + if (isClosed() || lastKey == null) { + throw new IllegalStateException(isClosed() ? "cache closed" : "call next() before remove()"); + } + SimpleCache.this.remove(lastKey); + } + }; + } + + @Override + public String getName() { + assertNotClosed(); + return name; + } + + @Override + public CacheManager getCacheManager() { + assertNotClosed(); + return manager; + } + + @Override + public synchronized void close() { + if (isClosed()) { + return; + } + + for (final Future task : poolTasks) { + task.cancel(true); + } + + final CacheException ce = new CacheException(); + manager.release(getName()); + closed = true; + close(loader, ce); + close(writer, ce); + close(expiryPolicy, ce); + for (final SimpleListener listener : listeners.values()) { + try { + listener.close(); + } catch (final Exception e) { + ce.addSuppressed(e); + } + } + listeners.clear(); + JMXs.unregister(cacheConfigObjectName); + JMXs.unregister(cacheStatsObjectName); + delegate.clear(); + if (ce.getSuppressed().length > 0) { + throw ce; + } + } + + @Override + public boolean isClosed() { + return closed; + } + + @Override + public T unwrap(final Class clazz) { + assertNotClosed(); + if (clazz.isInstance(this)) { + return clazz.cast(this); + } + if (clazz.isAssignableFrom(Map.class) || clazz.isAssignableFrom(ConcurrentMap.class)) { + return clazz.cast(delegate); + } + throw new IllegalArgumentException(clazz.getName() + " not supported in unwrap"); + } + + public Statistics getStatistics() { + return statistics; + } + + public void enableManagement() { + config.managementEnabled(); + JMXs.register(cacheConfigObjectName, new SimpleCacheMXBean(this)); + } + + public void disableManagement() { + config.managementDisabled(); + JMXs.unregister(cacheConfigObjectName); + } + + public void enableStatistics() { + config.statisticsEnabled(); + statistics.setActive(true); + JMXs.register(cacheStatsObjectName, new SimpleCacheStatisticsMXBean(statistics)); + } + + public void disableStatistics() { + config.statisticsDisabled(); + statistics.setActive(false); + JMXs.unregister(cacheStatsObjectName); + } + + private static String property(final Properties properties, final String cacheName, final String name, + final String defaultValue) { + return properties.getProperty(cacheName + "." + name, properties.getProperty(name, defaultValue)); + } + + private static boolean isNotZero(final Duration duration) { + return duration == null || !duration.isZero(); + } + + private static T throwEntryProcessorException(final Exception ex) { + if (EntryProcessorException.class.isInstance(ex)) { + throw EntryProcessorException.class.cast(ex); + } + throw new EntryProcessorException(ex); + } + + private static void close(final Object potentiallyCloseable, final CacheException wrapper) { + if (AutoCloseable.class.isInstance(potentiallyCloseable)) { + try { + AutoCloseable.class.cast(potentiallyCloseable).close(); + } catch (final Exception re) { + wrapper.addSuppressed(re); + } + } + } + + private class EvictionThread implements Runnable { + + private final long pause; + + private final long maxDelete; + + private EvictionThread(final long evictionPause, final long maxDelete) { + this.pause = evictionPause; + this.maxDelete = maxDelete; + } + + @Override + public void run() { + while (!isClosed()) { + try { + Thread.sleep(pause); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } + if (delegate.isEmpty()) { + continue; + } + + try { + final List> keys = new ArrayList<>(delegate.keySet()); + Collections.sort(keys, new Comparator>() { + + @Override + public int compare(final SimpleKey o1, final SimpleKey o2) { + final long l = o1.lastAccess() - o2.lastAccess(); + if (l == 0) { + return keys.indexOf(o1) - keys.indexOf(o2); + } + return (int) l; + } + }); + + int delete = 0; + for (final SimpleKey key : keys) { + final SimpleElement elt = delegate.get(key); + if (elt != null && elt.isExpired()) { + delegate.remove(key); + statistics.increaseEvictions(1); + onExpired(key, elt); + delete++; + if (delete >= maxDelete) { + break; + } + } + } + } catch (final Exception e) { + // no-op + } + } + } + } + + private static class MapLoader implements CacheLoader { + + private final Map loaded; + + private MapLoader(final Map loaded) { + this.loaded = loaded; + } + + @Override + public V load(final K key) throws CacheLoaderException { + return loaded.get(key); + } + + @Override + public Map loadAll(final Iterable keys) throws CacheLoaderException { + throw new UnsupportedOperationException(); + } + } +} diff --git a/Java/geronimo-jcache-simple-SimpleCache_222/metadata.json b/Java/geronimo-jcache-simple-SimpleCache_222/metadata.json new file mode 100644 index 000000000..932d562b2 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_222/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleCache_222", + "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/geronimo/jcache/simple/SimpleCache.java", + "line": 225, + "npe_method": "getAll", + "deref_field": "elt", + "npe_class": "SimpleCache", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleCache_222" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleCache_222/npe.json b/Java/geronimo-jcache-simple-SimpleCache_222/npe.json new file mode 100644 index 000000000..4de6ac795 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_222/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleCache.java", + "line": 225, + "npe_method": "getAll", + "deref_field": "elt", + "npe_class": "SimpleCache" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleCache_251/Dockerfile b/Java/geronimo-jcache-simple-SimpleCache_251/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_251/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleCache_251/buggy.java b/Java/geronimo-jcache-simple-SimpleCache_251/buggy.java new file mode 100644 index 000000000..6a0737d7d --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_251/buggy.java @@ -0,0 +1,870 @@ +/* + * 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.geronimo.jcache.simple; + +import static org.apache.geronimo.jcache.simple.Asserts.assertNotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicReference; + +import javax.cache.Cache; +import javax.cache.CacheException; +import javax.cache.CacheManager; +import javax.cache.configuration.CacheEntryListenerConfiguration; +import javax.cache.configuration.Configuration; +import javax.cache.configuration.Factory; +import javax.cache.event.CacheEntryEvent; +import javax.cache.event.EventType; +import javax.cache.expiry.Duration; +import javax.cache.expiry.EternalExpiryPolicy; +import javax.cache.expiry.ExpiryPolicy; +import javax.cache.integration.CacheLoader; +import javax.cache.integration.CacheLoaderException; +import javax.cache.integration.CacheWriter; +import javax.cache.integration.CacheWriterException; +import javax.cache.integration.CompletionListener; +import javax.cache.processor.EntryProcessor; +import javax.cache.processor.EntryProcessorException; +import javax.cache.processor.EntryProcessorResult; +import javax.management.ObjectName; + +public class SimpleCache implements Cache { + + private final SimpleManager manager; + + private final SimpleConfiguration config; + + private final CacheLoader loader; + + private final CacheWriter writer; + + private final ExpiryPolicy expiryPolicy; + + private final ObjectName cacheConfigObjectName; + + private final ObjectName cacheStatsObjectName; + + private final String name; + + private final ConcurrentHashMap, SimpleElement> delegate; + + private final Map, SimpleListener> listeners = new ConcurrentHashMap<>(); + + private final Statistics statistics = new Statistics(); + + private final ExecutorService pool; + + private final Serializations serializations; + + private final Collection> poolTasks = new CopyOnWriteArraySet<>(); + + private volatile boolean closed = false; + + public SimpleCache(final ClassLoader classLoader, final SimpleManager mgr, final String cacheName, + final SimpleConfiguration configuration, final Properties properties, + final ExecutorService executorService) { + manager = mgr; + + name = cacheName; + + final int capacity = Integer.parseInt(property(properties, cacheName, "capacity", "1000")); + final float loadFactor = Float.parseFloat(property(properties, cacheName, "loadFactor", "0.75")); + final int concurrencyLevel = Integer.parseInt(property(properties, cacheName, "concurrencyLevel", "16")); + delegate = new ConcurrentHashMap<>(capacity, loadFactor, concurrencyLevel); + config = configuration; + pool = executorService; + + final long evictionPause = Long.parseLong( + properties.getProperty(cacheName + ".evictionPause", properties.getProperty("evictionPause", "30000"))); + if (evictionPause > 0) { + final long maxDeleteByEvictionRun = Long.parseLong(property(properties, cacheName, "maxDeleteByEvictionRun", "100")); + addPoolTask(new EvictionThread(evictionPause, maxDeleteByEvictionRun)); + } + + serializations = new Serializations(property(properties, cacheName, "serialization.whitelist", null)); + + final Factory> cacheLoaderFactory = configuration.getCacheLoaderFactory(); + if (cacheLoaderFactory == null) { + loader = NoLoader.INSTANCE; + } else { + loader = ExceptionWrapperHandler.newProxy(classLoader, cacheLoaderFactory.create(), CacheLoaderException.class, + CacheLoader.class); + } + + final Factory> cacheWriterFactory = configuration.getCacheWriterFactory(); + if (cacheWriterFactory == null) { + writer = NoWriter.INSTANCE; + } else { + writer = ExceptionWrapperHandler.newProxy(classLoader, cacheWriterFactory.create(), CacheWriterException.class, + CacheWriter.class); + } + + final Factory expiryPolicyFactory = configuration.getExpiryPolicyFactory(); + if (expiryPolicyFactory == null) { + expiryPolicy = new EternalExpiryPolicy(); + } else { + expiryPolicy = expiryPolicyFactory.create(); + } + + for (final CacheEntryListenerConfiguration listener : config.getCacheEntryListenerConfigurations()) { + listeners.put(listener, new SimpleListener<>(listener)); + } + + statistics.setActive(config.isStatisticsEnabled()); + + final String mgrStr = manager.getURI().toString().replaceAll(",|:|=|\n", "."); + final String cacheStr = name.replaceAll(",|:|=|\n", "."); + try { + cacheConfigObjectName = new ObjectName( + "javax.cache:type=CacheConfiguration," + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr); + cacheStatsObjectName = new ObjectName( + "javax.cache:type=CacheStatistics," + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr); + } catch (final Exception e) { + throw new IllegalArgumentException(e); + } + if (config.isManagementEnabled()) { + JMXs.register(cacheConfigObjectName, new SimpleCacheMXBean(this)); + } + if (config.isStatisticsEnabled()) { + JMXs.register(cacheStatsObjectName, new SimpleCacheStatisticsMXBean(statistics)); + } + } + + private void assertNotClosed() { + if (isClosed()) { + throw new IllegalStateException("cache closed"); + } + } + + @Override + public V get(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + final long getStart = Times.now(false); + return doGetControllingExpiry(getStart, key, true, false, false, true, loader); + } + + private V doLoad(final K key, final boolean update, final boolean propagateLoadException, final CacheLoader loader) { + V v = null; + try { + v = loader.load(key); + } catch (final CacheLoaderException e) { + if (propagateLoadException) { + throw e; + } + } + if (v != null) { + final Duration duration = update ? expiryPolicy.getExpiryForUpdate() : expiryPolicy.getExpiryForCreation(); + if (isNotZero(duration)) { + delegate.put(new SimpleKey<>(key), new SimpleElement<>(v, duration)); + } + } + return v; + } + + private void touch(final SimpleKey key, final SimpleElement element) { + if (config.isStoreByValue()) { + delegate.put(new SimpleKey<>(serializations.copy(manager.getClassLoader(), key.getKey())), element); + } + } + + @Override + public Map getAll(final Set keys) { + assertNotClosed(); + for (final K k : keys) { + assertNotNull(k, "key"); + } + + final Map result = new HashMap<>(); + for (final K key : keys) { + assertNotNull(key, "key"); + + final SimpleKey simpleKey = new SimpleKey<>(key); + final SimpleElement elt = delegate.get(simpleKey); + V val = elt != null ? elt.getElement() : null; + if (val == null && config.isReadThrough()) { + val = doLoad(key, false, false, loader); + if (val != null) { + result.put(key, val); + } + } else if (elt != null) { + final Duration expiryForAccess = expiryPolicy.getExpiryForAccess(); + if (isNotZero(expiryForAccess)) { + touch(simpleKey, elt); + result.put(key, val); + } else { + expires(simpleKey); + } + } + } + return result; + } + + @Override + public boolean containsKey(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + return delegate.get(new SimpleKey<>(key)) != null; + } + + @Override +public void put(final K key, final V rawValue) { + assertNotClosed(); + org.apache.geronimo.jcache.simple.Asserts.assertNotNull(key, "key"); + org.apache.geronimo.jcache.simple.Asserts.assertNotNull(rawValue, "value"); + final boolean storeByValue = config.isStoreByValue(); + final org.apache.geronimo.jcache.simple.SimpleKey simpleKey = new org.apache.geronimo.jcache.simple.SimpleKey<>(storeByValue ? serializations.copy(manager.getClassLoader(), key) : key); + final org.apache.geronimo.jcache.simple.SimpleElement oldElt = delegate.get(simpleKey); + final V old = /* NPEX_NULL_EXP */ + oldElt.getElement(); + final V value = (storeByValue) ? serializations.copy(manager.getClassLoader(), rawValue) : rawValue; + final boolean created = old == null; + final javax.cache.expiry.Duration duration = (created) ? expiryPolicy.getExpiryForCreation() : expiryPolicy.getExpiryForUpdate(); + if (org.apache.geronimo.jcache.simple.SimpleCache.isNotZero(duration)) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final long start = org.apache.geronimo.jcache.simple.Times.now(false); + writer.write(new org.apache.geronimo.jcache.simple.SimpleEntry<>(key, value)); + delegate.put(simpleKey, new org.apache.geronimo.jcache.simple.SimpleElement<>(value, duration)); + if (!listeners.isEmpty()) { + for (final org.apache.geronimo.jcache.simple.SimpleListener listener : listeners.values()) { + if (created) { + listener.onCreated(java.util.Collections.>singletonList(new org.apache.geronimo.jcache.simple.SimpleEvent<>(this, javax.cache.event.EventType.CREATED, null, key, value))); + } else { + listener.onUpdated(java.util.Collections.>singletonList(new org.apache.geronimo.jcache.simple.SimpleEvent<>(this, javax.cache.event.EventType.UPDATED, old, key, value))); + } + } + } + if (statisticsEnabled) { + statistics.increasePuts(1); + statistics.addPutTime(org.apache.geronimo.jcache.simple.Times.now(false) - start); + } + } else if (!created) { + expires(simpleKey); + } +} + + private void expires(final SimpleKey cacheKey) { + final SimpleElement elt = delegate.get(cacheKey); + delegate.remove(cacheKey); + onExpired(cacheKey, elt); + } + + private void onExpired(final SimpleKey cacheKey, final SimpleElement elt) { + for (final SimpleListener listener : listeners.values()) { + listener.onExpired(Collections.> singletonList( + new SimpleEvent<>(this, EventType.REMOVED, null, cacheKey.getKey(), elt.getElement()))); + } + } + + @Override + public V getAndPut(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, true, false, loader); + put(key, value); + return v; + } + + @Override + public void putAll(final Map map) { + assertNotClosed(); + final TempStateCacheView view = new TempStateCacheView(this); + for (final Map.Entry e : map.entrySet()) { + view.put(e.getKey(), e.getValue()); + } + view.merge(); + } + + @Override + public boolean putIfAbsent(final K key, final V value) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + if (!containsKey(key)) { + if (statisticsEnabled) { + statistics.increaseMisses(1); + } + put(key, value); + return true; + } else { + if (statisticsEnabled) { + statistics.increaseHits(1); + } + } + return false; + } + + @Override + public boolean remove(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final long start = Times.now(!statisticsEnabled); + + writer.delete(key); + final SimpleKey cacheKey = new SimpleKey<>(key); + + final SimpleElement v = delegate.remove(cacheKey); + if (v == null || v.isExpired()) { + return false; + } + + final V value = v.getElement(); + for (final SimpleListener listener : listeners.values()) { + listener.onRemoved(Collections.> singletonList( + new SimpleEvent<>(this, EventType.REMOVED, value, key, value))); + } + if (statisticsEnabled) { + statistics.increaseRemovals(1); + statistics.addRemoveTime(Times.now(false) - start); + } + + return true; + } + + @Override + public boolean remove(final K key, final V oldValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(oldValue, "oldValue"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, false, false, loader); + if (oldValue.equals(v)) { + remove(key); + return true; + } else if (v != null) { + // weird but just for stats to be right + // (org.jsr107.tck.expiry.CacheExpiryTest.removeSpecifiedEntryShouldNotCallExpiryPolicyMethods()) + expiryPolicy.getExpiryForAccess(); + } + return false; + } + + @Override + public V getAndRemove(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, true, false, loader); + remove(key); + return v; + } + + private V doGetControllingExpiry(final long getStart, final K key, final boolean updateAcess, final boolean forceDoLoad, + final boolean skipLoad, final boolean propagateLoadException, final CacheLoader loader) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final SimpleKey simpleKey = new SimpleKey<>(key); + final SimpleElement elt = delegate.get(simpleKey); + V v = elt != null ? elt.getElement() : null; + if (v == null && (config.isReadThrough() || forceDoLoad)) { + if (!skipLoad) { + v = doLoad(key, false, propagateLoadException, loader); + } + } else if (statisticsEnabled) { + if (v != null) { + statistics.increaseHits(1); + } else { + statistics.increaseMisses(1); + } + } + + if (updateAcess && elt != null) { + final Duration expiryForAccess = expiryPolicy.getExpiryForAccess(); + if (!isNotZero(expiryForAccess)) { + expires(simpleKey); + } + } + if (statisticsEnabled && v != null) { + statistics.addGetTime(Times.now(false) - getStart); + } + return v; + } + + @Override + public boolean replace(final K key, final V oldValue, final V newValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(oldValue, "oldValue"); + assertNotNull(newValue, "newValue"); + final V value = doGetControllingExpiry(Times.now(config.isStatisticsEnabled()), key, false, config.isReadThrough(), false, + true, loader); + if (value != null && value.equals(oldValue)) { + put(key, newValue); + return true; + } else if (value != null) { + expiryPolicy.getExpiryForAccess(); + } + return false; + } + + @Override + public boolean replace(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + boolean statisticsEnabled = config.isStatisticsEnabled(); + if (containsKey(key)) { + if (statisticsEnabled) { + statistics.increaseHits(1); + } + put(key, value); + return true; + } else if (statisticsEnabled) { + statistics.increaseMisses(1); + } + return false; + } + + @Override + public V getAndReplace(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + + final boolean statisticsEnabled = config.isStatisticsEnabled(); + + final SimpleElement elt = delegate.get(new SimpleKey<>(key)); + if (elt != null) { + V oldValue = elt.getElement(); + if (oldValue == null && config.isReadThrough()) { + oldValue = doLoad(key, false, false, loader); + } else if (statisticsEnabled) { + statistics.increaseHits(1); + } + put(key, value); + return oldValue; + } else if (statisticsEnabled) { + statistics.increaseMisses(1); + } + return null; + } + + @Override + public void removeAll(final Set keys) { + assertNotClosed(); + assertNotNull(keys, "keys"); + for (final K k : keys) { + remove(k); + } + } + + @Override + public void removeAll() { + assertNotClosed(); + for (final SimpleKey k : delegate.keySet()) { + remove(k.getKey()); + } + } + + @Override + public void clear() { + assertNotClosed(); + delegate.clear(); + } + + @Override + public > C2 getConfiguration(final Class clazz) { + assertNotClosed(); + return clazz.cast(config); + } + + @Override + public void loadAll(final Set keys, final boolean replaceExistingValues, + final CompletionListener completionListener) { + assertNotClosed(); + assertNotNull(keys, "keys"); + if (loader == null) { // quick exit path + if (completionListener != null) { + completionListener.onCompletion(); + } + return; + } + for (final K k : keys) { + assertNotNull(k, "a key"); + } + addPoolTask(new Runnable() { + + @Override + public void run() { + doLoadAll(keys, replaceExistingValues, completionListener); + } + }); + } + + private void addPoolTask(final Runnable runnable) { + final AtomicReference> ref = new AtomicReference<>(); + final CountDownLatch refIsSet = new CountDownLatch(1); + ref.set(pool.submit(new Runnable() { + @Override + public void run() { + try { + runnable.run(); + } finally { + try { + refIsSet.await(); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + } + poolTasks.remove(ref.get()); + } + } + })); + refIsSet.countDown(); + poolTasks.add(ref.get()); + } + + private void doLoadAll(final Set keys, final boolean replaceExistingValues, + final CompletionListener completionListener) { + try { + final long now = Times.now(false); + final Map kvMap = loader.loadAll(keys); + if (kvMap == null) { + return; + } + final CacheLoader preloaded = new MapLoader<>(kvMap); + for (final K k : keys) { + if (replaceExistingValues) { + doLoad(k, containsKey(k), completionListener != null, preloaded); + } else if (!containsKey(k)) { + doGetControllingExpiry(now, k, true, true, false, completionListener != null, preloaded); + } + } + } catch (final RuntimeException e) { + if (completionListener != null) { + completionListener.onException(e); + return; + } + } + if (completionListener != null) { + completionListener.onCompletion(); + } + } + + @Override + public T invoke(final K key, final EntryProcessor entryProcessor, final Object... arguments) + throws EntryProcessorException { + final TempStateCacheView view = new TempStateCacheView(this); + final T t = doInvoke(view, key, entryProcessor, arguments); + view.merge(); + return t; + } + + private T doInvoke(final TempStateCacheView view, final K key, final EntryProcessor entryProcessor, + final Object... arguments) { + assertNotClosed(); + assertNotNull(entryProcessor, "entryProcessor"); + assertNotNull(key, "key"); + try { + if (config.isStatisticsEnabled()) { + if (containsKey(key)) { + statistics.increaseHits(1); + } else { + statistics.increaseMisses(1); + } + } + return entryProcessor.process(new SimpleMutableEntry<>(view, key), arguments); + } catch (final Exception ex) { + return throwEntryProcessorException(ex); + } + } + + @Override + public Map> invokeAll(final Set keys, + final EntryProcessor entryProcessor, final Object... arguments) { + assertNotClosed(); + assertNotNull(entryProcessor, "entryProcessor"); + final Map> results = new HashMap<>(); + for (final K k : keys) { + try { + final T invoke = invoke(k, entryProcessor, arguments); + if (invoke != null) { + results.put(k, new EntryProcessorResult() { + + @Override + public T get() throws EntryProcessorException { + return invoke; + } + }); + } + } catch (final Exception e) { + results.put(k, new EntryProcessorResult() { + + @Override + public T get() throws EntryProcessorException { + return throwEntryProcessorException(e); + } + }); + } + } + return results; + } + + @Override + public void registerCacheEntryListener(final CacheEntryListenerConfiguration cacheEntryListenerConfiguration) { + assertNotClosed(); + if (listeners.containsKey(cacheEntryListenerConfiguration)) { + throw new IllegalArgumentException(cacheEntryListenerConfiguration + " already registered"); + } + listeners.put(cacheEntryListenerConfiguration, new SimpleListener<>(cacheEntryListenerConfiguration)); + config.addListener(cacheEntryListenerConfiguration); + } + + @Override + public void deregisterCacheEntryListener(final CacheEntryListenerConfiguration cacheEntryListenerConfiguration) { + assertNotClosed(); + listeners.remove(cacheEntryListenerConfiguration); + config.removeListener(cacheEntryListenerConfiguration); + } + + @Override + public Iterator> iterator() { + assertNotClosed(); + final Iterator> keys = new HashSet<>(delegate.keySet()).iterator(); + return new Iterator>() { + + private K lastKey = null; + + @Override + public boolean hasNext() { + return keys.hasNext(); + } + + @Override + public Entry next() { + lastKey = keys.next().getKey(); + return new SimpleEntry<>(lastKey, get(lastKey)); + } + + @Override + public void remove() { + if (isClosed() || lastKey == null) { + throw new IllegalStateException(isClosed() ? "cache closed" : "call next() before remove()"); + } + SimpleCache.this.remove(lastKey); + } + }; + } + + @Override + public String getName() { + assertNotClosed(); + return name; + } + + @Override + public CacheManager getCacheManager() { + assertNotClosed(); + return manager; + } + + @Override + public synchronized void close() { + if (isClosed()) { + return; + } + + for (final Future task : poolTasks) { + task.cancel(true); + } + + final CacheException ce = new CacheException(); + manager.release(getName()); + closed = true; + close(loader, ce); + close(writer, ce); + close(expiryPolicy, ce); + for (final SimpleListener listener : listeners.values()) { + try { + listener.close(); + } catch (final Exception e) { + ce.addSuppressed(e); + } + } + listeners.clear(); + JMXs.unregister(cacheConfigObjectName); + JMXs.unregister(cacheStatsObjectName); + delegate.clear(); + if (ce.getSuppressed().length > 0) { + throw ce; + } + } + + @Override + public boolean isClosed() { + return closed; + } + + @Override + public T unwrap(final Class clazz) { + assertNotClosed(); + if (clazz.isInstance(this)) { + return clazz.cast(this); + } + if (clazz.isAssignableFrom(Map.class) || clazz.isAssignableFrom(ConcurrentMap.class)) { + return clazz.cast(delegate); + } + throw new IllegalArgumentException(clazz.getName() + " not supported in unwrap"); + } + + public Statistics getStatistics() { + return statistics; + } + + public void enableManagement() { + config.managementEnabled(); + JMXs.register(cacheConfigObjectName, new SimpleCacheMXBean(this)); + } + + public void disableManagement() { + config.managementDisabled(); + JMXs.unregister(cacheConfigObjectName); + } + + public void enableStatistics() { + config.statisticsEnabled(); + statistics.setActive(true); + JMXs.register(cacheStatsObjectName, new SimpleCacheStatisticsMXBean(statistics)); + } + + public void disableStatistics() { + config.statisticsDisabled(); + statistics.setActive(false); + JMXs.unregister(cacheStatsObjectName); + } + + private static String property(final Properties properties, final String cacheName, final String name, + final String defaultValue) { + return properties.getProperty(cacheName + "." + name, properties.getProperty(name, defaultValue)); + } + + private static boolean isNotZero(final Duration duration) { + return duration == null || !duration.isZero(); + } + + private static T throwEntryProcessorException(final Exception ex) { + if (EntryProcessorException.class.isInstance(ex)) { + throw EntryProcessorException.class.cast(ex); + } + throw new EntryProcessorException(ex); + } + + private static void close(final Object potentiallyCloseable, final CacheException wrapper) { + if (AutoCloseable.class.isInstance(potentiallyCloseable)) { + try { + AutoCloseable.class.cast(potentiallyCloseable).close(); + } catch (final Exception re) { + wrapper.addSuppressed(re); + } + } + } + + private class EvictionThread implements Runnable { + + private final long pause; + + private final long maxDelete; + + private EvictionThread(final long evictionPause, final long maxDelete) { + this.pause = evictionPause; + this.maxDelete = maxDelete; + } + + @Override + public void run() { + while (!isClosed()) { + try { + Thread.sleep(pause); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } + if (delegate.isEmpty()) { + continue; + } + + try { + final List> keys = new ArrayList<>(delegate.keySet()); + Collections.sort(keys, new Comparator>() { + + @Override + public int compare(final SimpleKey o1, final SimpleKey o2) { + final long l = o1.lastAccess() - o2.lastAccess(); + if (l == 0) { + return keys.indexOf(o1) - keys.indexOf(o2); + } + return (int) l; + } + }); + + int delete = 0; + for (final SimpleKey key : keys) { + final SimpleElement elt = delegate.get(key); + if (elt != null && elt.isExpired()) { + delegate.remove(key); + statistics.increaseEvictions(1); + onExpired(key, elt); + delete++; + if (delete >= maxDelete) { + break; + } + } + } + } catch (final Exception e) { + // no-op + } + } + } + } + + private static class MapLoader implements CacheLoader { + + private final Map loaded; + + private MapLoader(final Map loaded) { + this.loaded = loaded; + } + + @Override + public V load(final K key) throws CacheLoaderException { + return loaded.get(key); + } + + @Override + public Map loadAll(final Iterable keys) throws CacheLoaderException { + throw new UnsupportedOperationException(); + } + } +} diff --git a/Java/geronimo-jcache-simple-SimpleCache_251/metadata.json b/Java/geronimo-jcache-simple-SimpleCache_251/metadata.json new file mode 100644 index 000000000..fcf163791 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_251/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleCache_251", + "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/geronimo/jcache/simple/SimpleCache.java", + "line": 251, + "npe_method": "put", + "deref_field": "oldElt", + "npe_class": "SimpleCache", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleCache_251" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleCache_251/npe.json b/Java/geronimo-jcache-simple-SimpleCache_251/npe.json new file mode 100644 index 000000000..1d81291bf --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_251/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleCache.java", + "line": 251, + "npe_method": "put", + "deref_field": "oldElt", + "npe_class": "SimpleCache" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleCache_619/Dockerfile b/Java/geronimo-jcache-simple-SimpleCache_619/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_619/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleCache_619/buggy.java b/Java/geronimo-jcache-simple-SimpleCache_619/buggy.java new file mode 100644 index 000000000..42e63a14f --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_619/buggy.java @@ -0,0 +1,874 @@ +/* + * 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.geronimo.jcache.simple; + +import static org.apache.geronimo.jcache.simple.Asserts.assertNotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicReference; + +import javax.cache.Cache; +import javax.cache.CacheException; +import javax.cache.CacheManager; +import javax.cache.configuration.CacheEntryListenerConfiguration; +import javax.cache.configuration.Configuration; +import javax.cache.configuration.Factory; +import javax.cache.event.CacheEntryEvent; +import javax.cache.event.EventType; +import javax.cache.expiry.Duration; +import javax.cache.expiry.EternalExpiryPolicy; +import javax.cache.expiry.ExpiryPolicy; +import javax.cache.integration.CacheLoader; +import javax.cache.integration.CacheLoaderException; +import javax.cache.integration.CacheWriter; +import javax.cache.integration.CacheWriterException; +import javax.cache.integration.CompletionListener; +import javax.cache.processor.EntryProcessor; +import javax.cache.processor.EntryProcessorException; +import javax.cache.processor.EntryProcessorResult; +import javax.management.ObjectName; + +public class SimpleCache implements Cache { + + private final SimpleManager manager; + + private final SimpleConfiguration config; + + private final CacheLoader loader; + + private final CacheWriter writer; + + private final ExpiryPolicy expiryPolicy; + + private final ObjectName cacheConfigObjectName; + + private final ObjectName cacheStatsObjectName; + + private final String name; + + private final ConcurrentHashMap, SimpleElement> delegate; + + private final Map, SimpleListener> listeners = new ConcurrentHashMap<>(); + + private final Statistics statistics = new Statistics(); + + private final ExecutorService pool; + + private final Serializations serializations; + + private final Collection> poolTasks = new CopyOnWriteArraySet<>(); + + private volatile boolean closed = false; + + public SimpleCache(final ClassLoader classLoader, final SimpleManager mgr, final String cacheName, + final SimpleConfiguration configuration, final Properties properties, + final ExecutorService executorService) { + manager = mgr; + + name = cacheName; + + final int capacity = Integer.parseInt(property(properties, cacheName, "capacity", "1000")); + final float loadFactor = Float.parseFloat(property(properties, cacheName, "loadFactor", "0.75")); + final int concurrencyLevel = Integer.parseInt(property(properties, cacheName, "concurrencyLevel", "16")); + delegate = new ConcurrentHashMap<>(capacity, loadFactor, concurrencyLevel); + config = configuration; + pool = executorService; + + final long evictionPause = Long.parseLong( + properties.getProperty(cacheName + ".evictionPause", properties.getProperty("evictionPause", "30000"))); + if (evictionPause > 0) { + final long maxDeleteByEvictionRun = Long.parseLong(property(properties, cacheName, "maxDeleteByEvictionRun", "100")); + addPoolTask(new EvictionThread(evictionPause, maxDeleteByEvictionRun)); + } + + serializations = new Serializations(property(properties, cacheName, "serialization.whitelist", null)); + + final Factory> cacheLoaderFactory = configuration.getCacheLoaderFactory(); + if (cacheLoaderFactory == null) { + loader = NoLoader.INSTANCE; + } else { + loader = ExceptionWrapperHandler.newProxy(classLoader, cacheLoaderFactory.create(), CacheLoaderException.class, + CacheLoader.class); + } + + final Factory> cacheWriterFactory = configuration.getCacheWriterFactory(); + if (cacheWriterFactory == null) { + writer = NoWriter.INSTANCE; + } else { + writer = ExceptionWrapperHandler.newProxy(classLoader, cacheWriterFactory.create(), CacheWriterException.class, + CacheWriter.class); + } + + final Factory expiryPolicyFactory = configuration.getExpiryPolicyFactory(); + if (expiryPolicyFactory == null) { + expiryPolicy = new EternalExpiryPolicy(); + } else { + expiryPolicy = expiryPolicyFactory.create(); + } + + for (final CacheEntryListenerConfiguration listener : config.getCacheEntryListenerConfigurations()) { + listeners.put(listener, new SimpleListener<>(listener)); + } + + statistics.setActive(config.isStatisticsEnabled()); + + final String mgrStr = manager.getURI().toString().replaceAll(",|:|=|\n", "."); + final String cacheStr = name.replaceAll(",|:|=|\n", "."); + try { + cacheConfigObjectName = new ObjectName( + "javax.cache:type=CacheConfiguration," + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr); + cacheStatsObjectName = new ObjectName( + "javax.cache:type=CacheStatistics," + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr); + } catch (final Exception e) { + throw new IllegalArgumentException(e); + } + if (config.isManagementEnabled()) { + JMXs.register(cacheConfigObjectName, new SimpleCacheMXBean(this)); + } + if (config.isStatisticsEnabled()) { + JMXs.register(cacheStatsObjectName, new SimpleCacheStatisticsMXBean(statistics)); + } + } + + private void assertNotClosed() { + if (isClosed()) { + throw new IllegalStateException("cache closed"); + } + } + + @Override + public V get(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + final long getStart = Times.now(false); + return doGetControllingExpiry(getStart, key, true, false, false, true, loader); + } + + private V doLoad(final K key, final boolean update, final boolean propagateLoadException, final CacheLoader loader) { + V v = null; + try { + v = loader.load(key); + } catch (final CacheLoaderException e) { + if (propagateLoadException) { + throw e; + } + } + if (v != null) { + final Duration duration = update ? expiryPolicy.getExpiryForUpdate() : expiryPolicy.getExpiryForCreation(); + if (isNotZero(duration)) { + delegate.put(new SimpleKey<>(key), new SimpleElement<>(v, duration)); + } + } + return v; + } + + private void touch(final SimpleKey key, final SimpleElement element) { + if (config.isStoreByValue()) { + delegate.put(new SimpleKey<>(serializations.copy(manager.getClassLoader(), key.getKey())), element); + } + } + + @Override + public Map getAll(final Set keys) { + assertNotClosed(); + for (final K k : keys) { + assertNotNull(k, "key"); + } + + final Map result = new HashMap<>(); + for (final K key : keys) { + assertNotNull(key, "key"); + + final SimpleKey simpleKey = new SimpleKey<>(key); + final SimpleElement elt = delegate.get(simpleKey); + V val = elt != null ? elt.getElement() : null; + if (val == null && config.isReadThrough()) { + val = doLoad(key, false, false, loader); + if (val != null) { + result.put(key, val); + } + } else if (elt != null) { + final Duration expiryForAccess = expiryPolicy.getExpiryForAccess(); + if (isNotZero(expiryForAccess)) { + touch(simpleKey, elt); + result.put(key, val); + } else { + expires(simpleKey); + } + } + } + return result; + } + + @Override + public boolean containsKey(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + return delegate.get(new SimpleKey<>(key)) != null; + } + + @Override + public void put(final K key, final V rawValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(rawValue, "value"); + + final boolean storeByValue = config.isStoreByValue(); + final SimpleKey simpleKey = new SimpleKey<>(storeByValue ? serializations.copy(manager.getClassLoader(), key) : key); + final SimpleElement oldElt = delegate.get(simpleKey); + final V old = oldElt != null ? oldElt.getElement() : null; + final V value = storeByValue ? serializations.copy(manager.getClassLoader(), rawValue) : rawValue; + + final boolean created = old == null; + final Duration duration = created ? expiryPolicy.getExpiryForCreation() : expiryPolicy.getExpiryForUpdate(); + if (isNotZero(duration)) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final long start = Times.now(false); + + writer.write(new SimpleEntry<>(key, value)); + delegate.put(simpleKey, new SimpleElement<>(value, duration)); + if (!listeners.isEmpty()) { + for (final SimpleListener listener : listeners.values()) { + if (created) { + listener.onCreated(Collections.> singletonList( + new SimpleEvent<>(this, EventType.CREATED, null, key, value))); + } else + listener.onUpdated(Collections.> singletonList( + new SimpleEvent<>(this, EventType.UPDATED, old, key, value))); + } + } + + if (statisticsEnabled) { + statistics.increasePuts(1); + statistics.addPutTime(Times.now(false) - start); + } + } else { + if (!created) { + expires(simpleKey); + } + } + } + + private void expires(final SimpleKey cacheKey) { + final SimpleElement elt = delegate.get(cacheKey); + delegate.remove(cacheKey); + onExpired(cacheKey, elt); + } + + private void onExpired(final SimpleKey cacheKey, final SimpleElement elt) { + for (final SimpleListener listener : listeners.values()) { + listener.onExpired(Collections.> singletonList( + new SimpleEvent<>(this, EventType.REMOVED, null, cacheKey.getKey(), elt.getElement()))); + } + } + + @Override + public V getAndPut(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, true, false, loader); + put(key, value); + return v; + } + + @Override + public void putAll(final Map map) { + assertNotClosed(); + final TempStateCacheView view = new TempStateCacheView(this); + for (final Map.Entry e : map.entrySet()) { + view.put(e.getKey(), e.getValue()); + } + view.merge(); + } + + @Override + public boolean putIfAbsent(final K key, final V value) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + if (!containsKey(key)) { + if (statisticsEnabled) { + statistics.increaseMisses(1); + } + put(key, value); + return true; + } else { + if (statisticsEnabled) { + statistics.increaseHits(1); + } + } + return false; + } + + @Override + public boolean remove(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final long start = Times.now(!statisticsEnabled); + + writer.delete(key); + final SimpleKey cacheKey = new SimpleKey<>(key); + + final SimpleElement v = delegate.remove(cacheKey); + if (v == null || v.isExpired()) { + return false; + } + + final V value = v.getElement(); + for (final SimpleListener listener : listeners.values()) { + listener.onRemoved(Collections.> singletonList( + new SimpleEvent<>(this, EventType.REMOVED, value, key, value))); + } + if (statisticsEnabled) { + statistics.increaseRemovals(1); + statistics.addRemoveTime(Times.now(false) - start); + } + + return true; + } + + @Override + public boolean remove(final K key, final V oldValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(oldValue, "oldValue"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, false, false, loader); + if (oldValue.equals(v)) { + remove(key); + return true; + } else if (v != null) { + // weird but just for stats to be right + // (org.jsr107.tck.expiry.CacheExpiryTest.removeSpecifiedEntryShouldNotCallExpiryPolicyMethods()) + expiryPolicy.getExpiryForAccess(); + } + return false; + } + + @Override + public V getAndRemove(final K key) { + assertNotClosed(); + assertNotNull(key, "key"); + final long getStart = Times.now(false); + final V v = doGetControllingExpiry(getStart, key, false, false, true, false, loader); + remove(key); + return v; + } + + private V doGetControllingExpiry(final long getStart, final K key, final boolean updateAcess, final boolean forceDoLoad, + final boolean skipLoad, final boolean propagateLoadException, final CacheLoader loader) { + final boolean statisticsEnabled = config.isStatisticsEnabled(); + final SimpleKey simpleKey = new SimpleKey<>(key); + final SimpleElement elt = delegate.get(simpleKey); + V v = elt != null ? elt.getElement() : null; + if (v == null && (config.isReadThrough() || forceDoLoad)) { + if (!skipLoad) { + v = doLoad(key, false, propagateLoadException, loader); + } + } else if (statisticsEnabled) { + if (v != null) { + statistics.increaseHits(1); + } else { + statistics.increaseMisses(1); + } + } + + if (updateAcess && elt != null) { + final Duration expiryForAccess = expiryPolicy.getExpiryForAccess(); + if (!isNotZero(expiryForAccess)) { + expires(simpleKey); + } + } + if (statisticsEnabled && v != null) { + statistics.addGetTime(Times.now(false) - getStart); + } + return v; + } + + @Override + public boolean replace(final K key, final V oldValue, final V newValue) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(oldValue, "oldValue"); + assertNotNull(newValue, "newValue"); + final V value = doGetControllingExpiry(Times.now(config.isStatisticsEnabled()), key, false, config.isReadThrough(), false, + true, loader); + if (value != null && value.equals(oldValue)) { + put(key, newValue); + return true; + } else if (value != null) { + expiryPolicy.getExpiryForAccess(); + } + return false; + } + + @Override + public boolean replace(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + boolean statisticsEnabled = config.isStatisticsEnabled(); + if (containsKey(key)) { + if (statisticsEnabled) { + statistics.increaseHits(1); + } + put(key, value); + return true; + } else if (statisticsEnabled) { + statistics.increaseMisses(1); + } + return false; + } + + @Override + public V getAndReplace(final K key, final V value) { + assertNotClosed(); + assertNotNull(key, "key"); + assertNotNull(value, "value"); + + final boolean statisticsEnabled = config.isStatisticsEnabled(); + + final SimpleElement elt = delegate.get(new SimpleKey<>(key)); + if (elt != null) { + V oldValue = elt.getElement(); + if (oldValue == null && config.isReadThrough()) { + oldValue = doLoad(key, false, false, loader); + } else if (statisticsEnabled) { + statistics.increaseHits(1); + } + put(key, value); + return oldValue; + } else if (statisticsEnabled) { + statistics.increaseMisses(1); + } + return null; + } + + @Override + public void removeAll(final Set keys) { + assertNotClosed(); + assertNotNull(keys, "keys"); + for (final K k : keys) { + remove(k); + } + } + + @Override + public void removeAll() { + assertNotClosed(); + for (final SimpleKey k : delegate.keySet()) { + remove(k.getKey()); + } + } + + @Override + public void clear() { + assertNotClosed(); + delegate.clear(); + } + + @Override + public > C2 getConfiguration(final Class clazz) { + assertNotClosed(); + return clazz.cast(config); + } + + @Override + public void loadAll(final Set keys, final boolean replaceExistingValues, + final CompletionListener completionListener) { + assertNotClosed(); + assertNotNull(keys, "keys"); + if (loader == null) { // quick exit path + if (completionListener != null) { + completionListener.onCompletion(); + } + return; + } + for (final K k : keys) { + assertNotNull(k, "a key"); + } + addPoolTask(new Runnable() { + + @Override + public void run() { + doLoadAll(keys, replaceExistingValues, completionListener); + } + }); + } + + private void addPoolTask(final Runnable runnable) { + final AtomicReference> ref = new AtomicReference<>(); + final CountDownLatch refIsSet = new CountDownLatch(1); + ref.set(pool.submit(new Runnable() { + @Override + public void run() { + try { + runnable.run(); + } finally { + try { + refIsSet.await(); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + } + poolTasks.remove(ref.get()); + } + } + })); + refIsSet.countDown(); + poolTasks.add(ref.get()); + } + + private void doLoadAll(final Set keys, final boolean replaceExistingValues, + final CompletionListener completionListener) { + try { + final long now = Times.now(false); + final Map kvMap = loader.loadAll(keys); + if (kvMap == null) { + return; + } + final CacheLoader preloaded = new MapLoader<>(kvMap); + for (final K k : keys) { + if (replaceExistingValues) { + doLoad(k, containsKey(k), completionListener != null, preloaded); + } else if (!containsKey(k)) { + doGetControllingExpiry(now, k, true, true, false, completionListener != null, preloaded); + } + } + } catch (final RuntimeException e) { + if (completionListener != null) { + completionListener.onException(e); + return; + } + } + if (completionListener != null) { + completionListener.onCompletion(); + } + } + + @Override + public T invoke(final K key, final EntryProcessor entryProcessor, final Object... arguments) + throws EntryProcessorException { + final TempStateCacheView view = new TempStateCacheView(this); + final T t = doInvoke(view, key, entryProcessor, arguments); + view.merge(); + return t; + } + + private T doInvoke(final TempStateCacheView view, final K key, final EntryProcessor entryProcessor, + final Object... arguments) { + assertNotClosed(); + assertNotNull(entryProcessor, "entryProcessor"); + assertNotNull(key, "key"); + try { + if (config.isStatisticsEnabled()) { + if (containsKey(key)) { + statistics.increaseHits(1); + } else { + statistics.increaseMisses(1); + } + } + return entryProcessor.process(new SimpleMutableEntry<>(view, key), arguments); + } catch (final Exception ex) { + return throwEntryProcessorException(ex); + } + } + + @Override +public java.util.Map> invokeAll(final java.util.Set keys, final javax.cache.processor.EntryProcessor entryProcessor, final java.lang.Object... arguments) { + assertNotClosed(); + org.apache.geronimo.jcache.simple.Asserts.assertNotNull(entryProcessor, "entryProcessor"); + final java.util.Map> results = new java.util.HashMap<>(); + for (final K k : keys) { + try { + final T invoke = invoke(k, entryProcessor, arguments); + { + results.put(k, new javax.cache.processor.EntryProcessorResult() { + @java.lang.Override + public T get() throws javax.cache.processor.EntryProcessorException { + return /* NPEX_NULL_EXP */ + invoke; + } + }); + } + } catch (final java.lang.Exception e) { + results.put(k, new javax.cache.processor.EntryProcessorResult() { + @java.lang.Override + public T get() throws javax.cache.processor.EntryProcessorException { + return org.apache.geronimo.jcache.simple.SimpleCache.throwEntryProcessorException(e); + } + }); + } + } + return results; +} + + @Override + public void registerCacheEntryListener(final CacheEntryListenerConfiguration cacheEntryListenerConfiguration) { + assertNotClosed(); + if (listeners.containsKey(cacheEntryListenerConfiguration)) { + throw new IllegalArgumentException(cacheEntryListenerConfiguration + " already registered"); + } + listeners.put(cacheEntryListenerConfiguration, new SimpleListener<>(cacheEntryListenerConfiguration)); + config.addListener(cacheEntryListenerConfiguration); + } + + @Override + public void deregisterCacheEntryListener(final CacheEntryListenerConfiguration cacheEntryListenerConfiguration) { + assertNotClosed(); + listeners.remove(cacheEntryListenerConfiguration); + config.removeListener(cacheEntryListenerConfiguration); + } + + @Override + public Iterator> iterator() { + assertNotClosed(); + final Iterator> keys = new HashSet<>(delegate.keySet()).iterator(); + return new Iterator>() { + + private K lastKey = null; + + @Override + public boolean hasNext() { + return keys.hasNext(); + } + + @Override + public Entry next() { + lastKey = keys.next().getKey(); + return new SimpleEntry<>(lastKey, get(lastKey)); + } + + @Override + public void remove() { + if (isClosed() || lastKey == null) { + throw new IllegalStateException(isClosed() ? "cache closed" : "call next() before remove()"); + } + SimpleCache.this.remove(lastKey); + } + }; + } + + @Override + public String getName() { + assertNotClosed(); + return name; + } + + @Override + public CacheManager getCacheManager() { + assertNotClosed(); + return manager; + } + + @Override + public synchronized void close() { + if (isClosed()) { + return; + } + + for (final Future task : poolTasks) { + task.cancel(true); + } + + final CacheException ce = new CacheException(); + manager.release(getName()); + closed = true; + close(loader, ce); + close(writer, ce); + close(expiryPolicy, ce); + for (final SimpleListener listener : listeners.values()) { + try { + listener.close(); + } catch (final Exception e) { + ce.addSuppressed(e); + } + } + listeners.clear(); + JMXs.unregister(cacheConfigObjectName); + JMXs.unregister(cacheStatsObjectName); + delegate.clear(); + if (ce.getSuppressed().length > 0) { + throw ce; + } + } + + @Override + public boolean isClosed() { + return closed; + } + + @Override + public T unwrap(final Class clazz) { + assertNotClosed(); + if (clazz.isInstance(this)) { + return clazz.cast(this); + } + if (clazz.isAssignableFrom(Map.class) || clazz.isAssignableFrom(ConcurrentMap.class)) { + return clazz.cast(delegate); + } + throw new IllegalArgumentException(clazz.getName() + " not supported in unwrap"); + } + + public Statistics getStatistics() { + return statistics; + } + + public void enableManagement() { + config.managementEnabled(); + JMXs.register(cacheConfigObjectName, new SimpleCacheMXBean(this)); + } + + public void disableManagement() { + config.managementDisabled(); + JMXs.unregister(cacheConfigObjectName); + } + + public void enableStatistics() { + config.statisticsEnabled(); + statistics.setActive(true); + JMXs.register(cacheStatsObjectName, new SimpleCacheStatisticsMXBean(statistics)); + } + + public void disableStatistics() { + config.statisticsDisabled(); + statistics.setActive(false); + JMXs.unregister(cacheStatsObjectName); + } + + private static String property(final Properties properties, final String cacheName, final String name, + final String defaultValue) { + return properties.getProperty(cacheName + "." + name, properties.getProperty(name, defaultValue)); + } + + private static boolean isNotZero(final Duration duration) { + return duration == null || !duration.isZero(); + } + + private static T throwEntryProcessorException(final Exception ex) { + if (EntryProcessorException.class.isInstance(ex)) { + throw EntryProcessorException.class.cast(ex); + } + throw new EntryProcessorException(ex); + } + + private static void close(final Object potentiallyCloseable, final CacheException wrapper) { + if (AutoCloseable.class.isInstance(potentiallyCloseable)) { + try { + AutoCloseable.class.cast(potentiallyCloseable).close(); + } catch (final Exception re) { + wrapper.addSuppressed(re); + } + } + } + + private class EvictionThread implements Runnable { + + private final long pause; + + private final long maxDelete; + + private EvictionThread(final long evictionPause, final long maxDelete) { + this.pause = evictionPause; + this.maxDelete = maxDelete; + } + + @Override + public void run() { + while (!isClosed()) { + try { + Thread.sleep(pause); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } + if (delegate.isEmpty()) { + continue; + } + + try { + final List> keys = new ArrayList<>(delegate.keySet()); + Collections.sort(keys, new Comparator>() { + + @Override + public int compare(final SimpleKey o1, final SimpleKey o2) { + final long l = o1.lastAccess() - o2.lastAccess(); + if (l == 0) { + return keys.indexOf(o1) - keys.indexOf(o2); + } + return (int) l; + } + }); + + int delete = 0; + for (final SimpleKey key : keys) { + final SimpleElement elt = delegate.get(key); + if (elt != null && elt.isExpired()) { + delegate.remove(key); + statistics.increaseEvictions(1); + onExpired(key, elt); + delete++; + if (delete >= maxDelete) { + break; + } + } + } + } catch (final Exception e) { + // no-op + } + } + } + } + + private static class MapLoader implements CacheLoader { + + private final Map loaded; + + private MapLoader(final Map loaded) { + this.loaded = loaded; + } + + @Override + public V load(final K key) throws CacheLoaderException { + return loaded.get(key); + } + + @Override + public Map loadAll(final Iterable keys) throws CacheLoaderException { + throw new UnsupportedOperationException(); + } + } +} diff --git a/Java/geronimo-jcache-simple-SimpleCache_619/metadata.json b/Java/geronimo-jcache-simple-SimpleCache_619/metadata.json new file mode 100644 index 000000000..8640a3169 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_619/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleCache_619", + "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/geronimo/jcache/simple/SimpleCache.java", + "line": 623, + "npe_method": "invokeAll", + "deref_field": "invoke", + "npe_class": "SimpleCache", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleCache_619" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleCache_619/npe.json b/Java/geronimo-jcache-simple-SimpleCache_619/npe.json new file mode 100644 index 000000000..66670205c --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleCache_619/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleCache.java", + "line": 623, + "npe_method": "invokeAll", + "deref_field": "invoke", + "npe_class": "SimpleCache" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleManager_103/Dockerfile b/Java/geronimo-jcache-simple-SimpleManager_103/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleManager_103/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleManager_103/buggy.java b/Java/geronimo-jcache-simple-SimpleManager_103/buggy.java new file mode 100644 index 000000000..a24aa0bc1 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleManager_103/buggy.java @@ -0,0 +1,284 @@ +/* + * 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.geronimo.jcache.simple; + +import static java.util.Collections.unmodifiableSet; +import static org.apache.geronimo.jcache.simple.Asserts.assertNotNull; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import javax.cache.Cache; +import javax.cache.CacheException; +import javax.cache.CacheManager; +import javax.cache.configuration.Configuration; +import javax.cache.spi.CachingProvider; + +public class SimpleManager implements CacheManager { + + private final CachingProvider provider; + + private final URI uri; + + private final ClassLoader loader; + + private final Properties properties; + + private final ConcurrentMap> caches = new ConcurrentHashMap<>(); + + private final Properties configProperties; + + private final ExecutorService executorService; + + private volatile boolean closed = false; + + SimpleManager(final CachingProvider provider, final URI uri, final ClassLoader loader, final Properties properties) { + this.provider = provider; + this.uri = uri; + this.loader = loader; + this.properties = readConfig(uri, loader, properties); + this.configProperties = properties; + + ExecutorService executorService = rawProperty("geronimo.pool"); + if (executorService == null) { + final int poolSize = Integer.parseInt(this.properties.getProperty("pool.size", "16")); + final SimpleThreadFactory threadFactory = new SimpleThreadFactory("geronimo-simple-jcache-[" + uri.toASCIIString() + "]-"); + executorService = poolSize > 0 ? Executors.newFixedThreadPool(poolSize, threadFactory) + : Executors.newCachedThreadPool(threadFactory); + } + this.executorService = executorService; + } + + private T rawProperty(final String name) { + final Object value = this.properties.get(name); + if (value == null) { + return (T) this.properties.get(name); + } + return (T) value; + } + +private java.util.Properties readConfig(final java.net.URI uri, final java.lang.ClassLoader loader, final java.util.Properties properties) { + final java.util.Properties props = new java.util.Properties(); + try { + if ((org.apache.geronimo.jcache.simple.SimpleProvider.DEFAULT_URI.toString().equals(uri.toString()) || uri.getScheme().equals("geronimo")) || uri.getScheme().equals("classpath")) { + final java.util.Enumeration resources = loader.getResources(uri.toASCIIString().substring((uri.getScheme() + "://").length())); + while (resources.hasMoreElements()) { + do { + addProperties(resources.nextElement(), props); + } while (resources.hasMoreElements() ); + } + } else { + props.load(uri.toURL().openStream()); + } + } catch (final java.io.IOException e) { + throw new java.lang.IllegalStateException(e); + } + { + props.putAll(/* NPEX_NULL_EXP */ + properties); + } + return props; +} + + private void addProperties(final URL url, final Properties aggregator) { + try (final InputStream inputStream = url.openStream()) { + aggregator.load(inputStream); + } catch (final IOException e) { + throw new IllegalArgumentException(e); + } + } + + private void assertNotClosed() { + if (isClosed()) { + throw new IllegalStateException("cache manager closed"); + } + } + + @Override + public > Cache createCache(final String cacheName, final C configuration) + throws IllegalArgumentException { + assertNotClosed(); + assertNotNull(cacheName, "cacheName"); + assertNotNull(configuration, "configuration"); + final Class keyType = configuration.getKeyType(); + final Class valueType = configuration.getValueType(); + if (!caches.containsKey(cacheName)) { + final Cache cache = ClassLoaderAwareCache.wrap(loader, new SimpleCache(loader, this, cacheName, + new SimpleConfiguration<>(configuration, keyType, valueType), properties, executorService)); + caches.putIfAbsent(cacheName, cache); + } else { + throw new CacheException("cache " + cacheName + " already exists"); + } + return (Cache) getCache(cacheName, keyType, valueType); + } + + @Override + public void destroyCache(final String cacheName) { + assertNotClosed(); + assertNotNull(cacheName, "cacheName"); + final Cache cache = caches.remove(cacheName); + if (cache != null && !cache.isClosed()) { + cache.clear(); + cache.close(); + } + } + + @Override + public void enableManagement(final String cacheName, final boolean enabled) { + assertNotClosed(); + assertNotNull(cacheName, "cacheName"); + final SimpleCache cache = of(cacheName); + if (cache != null) { + if (enabled) { + cache.enableManagement(); + } else { + cache.disableManagement(); + } + } + } + + private SimpleCache of(final String cacheName) { + return SimpleCache.class.cast(ClassLoaderAwareCache.getDelegate(caches.get(cacheName))); + } + + @Override + public void enableStatistics(final String cacheName, final boolean enabled) { + assertNotClosed(); + assertNotNull(cacheName, "cacheName"); + final SimpleCache cache = of(cacheName); + if (cache != null) { + if (enabled) { + cache.enableStatistics(); + } else { + cache.disableStatistics(); + } + } + } + + @Override + public synchronized void close() { + if (isClosed()) { + return; + } + + assertNotClosed(); + for (final Cache c : caches.values()) { + c.close(); + } + caches.clear(); + for (final Runnable task : executorService.shutdownNow()) { + task.run(); + } + closed = true; + if (SimpleProvider.class.isInstance(provider)) { + SimpleProvider.class.cast(provider).remove(this); + } // else throw? + } + + @Override + public T unwrap(final Class clazz) { + if (clazz.isInstance(this)) { + return clazz.cast(this); + } + throw new IllegalArgumentException(clazz.getName() + " not supported in unwrap"); + } + + @Override + public boolean isClosed() { + return closed; + } + + @Override + public Cache getCache(final String cacheName) { + assertNotClosed(); + assertNotNull(cacheName, "cacheName"); + return (Cache) doGetCache(cacheName, null, null); + } + + @Override + public Iterable getCacheNames() { + assertNotClosed(); + return unmodifiableSet(new HashSet<>(caches.keySet())); + } + + @Override + public Cache getCache(final String cacheName, final Class keyType, final Class valueType) { + assertNotClosed(); + assertNotNull(cacheName, "cacheName"); + assertNotNull(keyType, "keyType"); + assertNotNull(valueType, "valueType"); + try { + return doGetCache(cacheName, keyType, valueType); + } catch (final IllegalArgumentException iae) { + throw new ClassCastException(iae.getMessage()); + } + } + + private Cache doGetCache(final String cacheName, final Class keyType, final Class valueType) { + final Cache cache = (Cache) caches.get(cacheName); + if (keyType == null && valueType == null) { + return cache; + } + if (cache == null) { + return null; + } + + final Configuration config = cache.getConfiguration(Configuration.class); + if ((keyType != null && !config.getKeyType().isAssignableFrom(keyType)) + || (valueType != null && !config.getValueType().isAssignableFrom(valueType))) { + throw new IllegalArgumentException( + "this cache is <" + config.getKeyType().getName() + ", " + config.getValueType().getName() + "> " + + " and not <" + keyType.getName() + ", " + valueType.getName() + ">"); + } + return cache; + } + + @Override + public CachingProvider getCachingProvider() { + return provider; + } + + @Override + public URI getURI() { + return uri; + } + + @Override + public ClassLoader getClassLoader() { + return loader; + } + + @Override + public Properties getProperties() { + return configProperties; + } + + public void release(final String name) { + caches.remove(name); + } +} diff --git a/Java/geronimo-jcache-simple-SimpleManager_103/metadata.json b/Java/geronimo-jcache-simple-SimpleManager_103/metadata.json new file mode 100644 index 000000000..86a2a7a8b --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleManager_103/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleManager_103", + "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/geronimo/jcache/simple/SimpleManager.java", + "line": 103, + "npe_method": "readConfig", + "deref_field": "properties", + "npe_class": "SimpleManager", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleManager_103" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleManager_103/npe.json b/Java/geronimo-jcache-simple-SimpleManager_103/npe.json new file mode 100644 index 000000000..3c901505f --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleManager_103/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleManager.java", + "line": 103, + "npe_method": "readConfig", + "deref_field": "properties", + "npe_class": "SimpleManager" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleManager_248/Dockerfile b/Java/geronimo-jcache-simple-SimpleManager_248/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleManager_248/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleManager_248/buggy.java b/Java/geronimo-jcache-simple-SimpleManager_248/buggy.java new file mode 100644 index 000000000..3dbfd63b0 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleManager_248/buggy.java @@ -0,0 +1,281 @@ +/* + * 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.geronimo.jcache.simple; + +import static java.util.Collections.unmodifiableSet; +import static org.apache.geronimo.jcache.simple.Asserts.assertNotNull; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import javax.cache.Cache; +import javax.cache.CacheException; +import javax.cache.CacheManager; +import javax.cache.configuration.Configuration; +import javax.cache.spi.CachingProvider; + +public class SimpleManager implements CacheManager { + + private final CachingProvider provider; + + private final URI uri; + + private final ClassLoader loader; + + private final Properties properties; + + private final ConcurrentMap> caches = new ConcurrentHashMap<>(); + + private final Properties configProperties; + + private final ExecutorService executorService; + + private volatile boolean closed = false; + + SimpleManager(final CachingProvider provider, final URI uri, final ClassLoader loader, final Properties properties) { + this.provider = provider; + this.uri = uri; + this.loader = loader; + this.properties = readConfig(uri, loader, properties); + this.configProperties = properties; + + ExecutorService executorService = rawProperty("geronimo.pool"); + if (executorService == null) { + final int poolSize = Integer.parseInt(this.properties.getProperty("pool.size", "16")); + final SimpleThreadFactory threadFactory = new SimpleThreadFactory("geronimo-simple-jcache-[" + uri.toASCIIString() + "]-"); + executorService = poolSize > 0 ? Executors.newFixedThreadPool(poolSize, threadFactory) + : Executors.newCachedThreadPool(threadFactory); + } + this.executorService = executorService; + } + + private T rawProperty(final String name) { + final Object value = this.properties.get(name); + if (value == null) { + return (T) this.properties.get(name); + } + return (T) value; + } + + private Properties readConfig(final URI uri, final ClassLoader loader, final Properties properties) { + final Properties props = new Properties(); + try { + if (SimpleProvider.DEFAULT_URI.toString().equals(uri.toString()) || uri.getScheme().equals("geronimo") + || uri.getScheme().equals("classpath")) { + + final Enumeration resources = loader.getResources(uri.toASCIIString().substring((uri.getScheme() + "://").length())); + while (resources.hasMoreElements()) { + do { + addProperties(resources.nextElement(), props); + } while (resources.hasMoreElements()); + } + } else { + props.load(uri.toURL().openStream()); + } + } catch (final IOException e) { + throw new IllegalStateException(e); + } + if (properties != null) { + props.putAll(properties); + } + return props; + } + + private void addProperties(final URL url, final Properties aggregator) { + try (final InputStream inputStream = url.openStream()) { + aggregator.load(inputStream); + } catch (final IOException e) { + throw new IllegalArgumentException(e); + } + } + + private void assertNotClosed() { + if (isClosed()) { + throw new IllegalStateException("cache manager closed"); + } + } + + @Override + public > Cache createCache(final String cacheName, final C configuration) + throws IllegalArgumentException { + assertNotClosed(); + assertNotNull(cacheName, "cacheName"); + assertNotNull(configuration, "configuration"); + final Class keyType = configuration.getKeyType(); + final Class valueType = configuration.getValueType(); + if (!caches.containsKey(cacheName)) { + final Cache cache = ClassLoaderAwareCache.wrap(loader, new SimpleCache(loader, this, cacheName, + new SimpleConfiguration<>(configuration, keyType, valueType), properties, executorService)); + caches.putIfAbsent(cacheName, cache); + } else { + throw new CacheException("cache " + cacheName + " already exists"); + } + return (Cache) getCache(cacheName, keyType, valueType); + } + + @Override + public void destroyCache(final String cacheName) { + assertNotClosed(); + assertNotNull(cacheName, "cacheName"); + final Cache cache = caches.remove(cacheName); + if (cache != null && !cache.isClosed()) { + cache.clear(); + cache.close(); + } + } + + @Override + public void enableManagement(final String cacheName, final boolean enabled) { + assertNotClosed(); + assertNotNull(cacheName, "cacheName"); + final SimpleCache cache = of(cacheName); + if (cache != null) { + if (enabled) { + cache.enableManagement(); + } else { + cache.disableManagement(); + } + } + } + + private SimpleCache of(final String cacheName) { + return SimpleCache.class.cast(ClassLoaderAwareCache.getDelegate(caches.get(cacheName))); + } + + @Override + public void enableStatistics(final String cacheName, final boolean enabled) { + assertNotClosed(); + assertNotNull(cacheName, "cacheName"); + final SimpleCache cache = of(cacheName); + if (cache != null) { + if (enabled) { + cache.enableStatistics(); + } else { + cache.disableStatistics(); + } + } + } + + @Override + public synchronized void close() { + if (isClosed()) { + return; + } + + assertNotClosed(); + for (final Cache c : caches.values()) { + c.close(); + } + caches.clear(); + for (final Runnable task : executorService.shutdownNow()) { + task.run(); + } + closed = true; + if (SimpleProvider.class.isInstance(provider)) { + SimpleProvider.class.cast(provider).remove(this); + } // else throw? + } + + @Override + public T unwrap(final Class clazz) { + if (clazz.isInstance(this)) { + return clazz.cast(this); + } + throw new IllegalArgumentException(clazz.getName() + " not supported in unwrap"); + } + + @Override + public boolean isClosed() { + return closed; + } + + @Override + public Cache getCache(final String cacheName) { + assertNotClosed(); + assertNotNull(cacheName, "cacheName"); + return (Cache) doGetCache(cacheName, null, null); + } + + @Override + public Iterable getCacheNames() { + assertNotClosed(); + return unmodifiableSet(new HashSet<>(caches.keySet())); + } + + @Override + public Cache getCache(final String cacheName, final Class keyType, final Class valueType) { + assertNotClosed(); + assertNotNull(cacheName, "cacheName"); + assertNotNull(keyType, "keyType"); + assertNotNull(valueType, "valueType"); + try { + return doGetCache(cacheName, keyType, valueType); + } catch (final IllegalArgumentException iae) { + throw new ClassCastException(iae.getMessage()); + } + } + +private javax.cache.Cache doGetCache(final java.lang.String cacheName, final java.lang.Class keyType, final java.lang.Class valueType) { + final javax.cache.Cache cache = ((javax.cache.Cache) (caches.get(cacheName))); + if ((keyType == null) && (valueType == null)) { + return cache; + } + { + final javax.cache.configuration.Configuration config = /* NPEX_NULL_EXP */ + cache.getConfiguration(javax.cache.configuration.Configuration.class); + if (((keyType != null) && (!config.getKeyType().isAssignableFrom(keyType))) || ((valueType != null) && (!config.getValueType().isAssignableFrom(valueType)))) { + throw new java.lang.IllegalArgumentException((((((((("this cache is <" + config.getKeyType().getName()) + ", ") + config.getValueType().getName()) + "> ") + " and not <") + keyType.getName()) + ", ") + valueType.getName()) + ">"); + } + return cache; + } +} + + @Override + public CachingProvider getCachingProvider() { + return provider; + } + + @Override + public URI getURI() { + return uri; + } + + @Override + public ClassLoader getClassLoader() { + return loader; + } + + @Override + public Properties getProperties() { + return configProperties; + } + + public void release(final String name) { + caches.remove(name); + } +} diff --git a/Java/geronimo-jcache-simple-SimpleManager_248/metadata.json b/Java/geronimo-jcache-simple-SimpleManager_248/metadata.json new file mode 100644 index 000000000..1e67e9686 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleManager_248/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleManager_248", + "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/geronimo/jcache/simple/SimpleManager.java", + "line": 250, + "npe_method": "doGetCache", + "deref_field": "cache", + "npe_class": "SimpleManager", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleManager_248" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleManager_248/npe.json b/Java/geronimo-jcache-simple-SimpleManager_248/npe.json new file mode 100644 index 000000000..38fb10154 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleManager_248/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleManager.java", + "line": 250, + "npe_method": "doGetCache", + "deref_field": "cache", + "npe_class": "SimpleManager" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleProvider_129/Dockerfile b/Java/geronimo-jcache-simple-SimpleProvider_129/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_129/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleProvider_129/buggy.java b/Java/geronimo-jcache-simple-SimpleProvider_129/buggy.java new file mode 100644 index 000000000..6ef331d60 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_129/buggy.java @@ -0,0 +1,137 @@ +/* + * 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.geronimo.jcache.simple; + +import java.net.URI; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.cache.CacheManager; +import javax.cache.configuration.OptionalFeature; +import javax.cache.spi.CachingProvider; + +public class SimpleProvider implements CachingProvider { + + static final URI DEFAULT_URI = URI.create("geronimo://simple-jcache.properties"); + + private final ConcurrentMap> cacheManagersByLoader = new ConcurrentHashMap<>(); + + @Override + public CacheManager getCacheManager(final URI inUri, final ClassLoader inClassLoader, final Properties properties) { + final URI uri = inUri != null ? inUri : getDefaultURI(); + final ClassLoader classLoader = inClassLoader != null ? inClassLoader : getDefaultClassLoader(); + + ConcurrentMap managers = cacheManagersByLoader.get(classLoader); + if (managers == null) { + managers = new ConcurrentHashMap<>(); + final ConcurrentMap existingManagers = cacheManagersByLoader.putIfAbsent(classLoader, managers); + if (existingManagers != null) { + managers = existingManagers; + } + } + + CacheManager mgr = managers.get(uri); + if (mgr == null) { + mgr = new SimpleManager(this, uri, classLoader, properties); + final CacheManager existing = managers.putIfAbsent(uri, mgr); + if (existing != null) { + mgr = existing; + } + } + + return mgr; + } + + @Override + public URI getDefaultURI() { + return DEFAULT_URI; + } + + @Override + public void close() { + for (final Map v : cacheManagersByLoader.values()) { + for (final CacheManager m : v.values()) { + m.close(); + } + v.clear(); + } + cacheManagersByLoader.clear(); + } + + @Override + public void close(final ClassLoader classLoader) { + final Map cacheManagers = cacheManagersByLoader.remove(classLoader); + if (cacheManagers != null) { + for (final CacheManager mgr : cacheManagers.values()) { + mgr.close(); + } + cacheManagers.clear(); + } + } + + @Override + public void close(final URI uri, final ClassLoader classLoader) { + final Map cacheManagers = cacheManagersByLoader.remove(classLoader); + if (cacheManagers != null) { + final CacheManager mgr = cacheManagers.remove(uri); + if (mgr != null) { + mgr.close(); + } + } + } + + @Override + public CacheManager getCacheManager(final URI uri, final ClassLoader classLoader) { + return getCacheManager(uri, classLoader, getDefaultProperties()); + } + + @Override + public CacheManager getCacheManager() { + return getCacheManager(getDefaultURI(), getDefaultClassLoader()); + } + + @Override + public boolean isSupported(final OptionalFeature optionalFeature) { + return optionalFeature == OptionalFeature.STORE_BY_REFERENCE; + } + + @Override + public ClassLoader getDefaultClassLoader() { + return SimpleProvider.class.getClassLoader(); + } + + @Override + public Properties getDefaultProperties() { + return new Properties(); + } + +void remove(final javax.cache.CacheManager mgr) { + final java.lang.ClassLoader classLoader = mgr.getClassLoader(); + final java.util.Map mgrs = cacheManagersByLoader.get(classLoader); + { + /* NPEX_NULL_EXP */ + mgrs.remove(mgr.getURI()); + if (mgrs.isEmpty()) { + cacheManagersByLoader.remove(classLoader); + } + } +} +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_129/metadata.json b/Java/geronimo-jcache-simple-SimpleProvider_129/metadata.json new file mode 100644 index 000000000..97aac6fb4 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_129/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleProvider_129", + "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/geronimo/jcache/simple/SimpleProvider.java", + "line": 131, + "npe_method": "remove", + "deref_field": "mgrs", + "npe_class": "SimpleProvider", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleProvider_129" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_129/npe.json b/Java/geronimo-jcache-simple-SimpleProvider_129/npe.json new file mode 100644 index 000000000..279cff0bd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_129/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleProvider.java", + "line": 131, + "npe_method": "remove", + "deref_field": "mgrs", + "npe_class": "SimpleProvider" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleProvider_39/Dockerfile b/Java/geronimo-jcache-simple-SimpleProvider_39/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_39/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleProvider_39/buggy.java b/Java/geronimo-jcache-simple-SimpleProvider_39/buggy.java new file mode 100644 index 000000000..47aa06721 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_39/buggy.java @@ -0,0 +1,134 @@ +/* + * 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.geronimo.jcache.simple; + +import java.net.URI; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.cache.CacheManager; +import javax.cache.configuration.OptionalFeature; +import javax.cache.spi.CachingProvider; + +public class SimpleProvider implements CachingProvider { + + static final URI DEFAULT_URI = URI.create("geronimo://simple-jcache.properties"); + + private final ConcurrentMap> cacheManagersByLoader = new ConcurrentHashMap<>(); + + @Override +public javax.cache.CacheManager getCacheManager(final java.net.URI inUri, final java.lang.ClassLoader inClassLoader, final java.util.Properties properties) { + final java.net.URI uri = /* NPEX_NULL_EXP */ + inUri; + final java.lang.ClassLoader classLoader = (inClassLoader != null) ? inClassLoader : getDefaultClassLoader(); + java.util.concurrent.ConcurrentMap managers = cacheManagersByLoader.get(classLoader); + if (managers == null) { + managers = new java.util.concurrent.ConcurrentHashMap<>(); + final java.util.concurrent.ConcurrentMap existingManagers = cacheManagersByLoader.putIfAbsent(classLoader, managers); + if (existingManagers != null) { + managers = existingManagers; + } + } + javax.cache.CacheManager mgr = managers.get(uri); + if (mgr == null) { + mgr = new org.apache.geronimo.jcache.simple.SimpleManager(this, uri, classLoader, properties); + final javax.cache.CacheManager existing = managers.putIfAbsent(uri, mgr); + if (existing != null) { + mgr = existing; + } + } + return mgr; +} + + @Override + public URI getDefaultURI() { + return DEFAULT_URI; + } + + @Override + public void close() { + for (final Map v : cacheManagersByLoader.values()) { + for (final CacheManager m : v.values()) { + m.close(); + } + v.clear(); + } + cacheManagersByLoader.clear(); + } + + @Override + public void close(final ClassLoader classLoader) { + final Map cacheManagers = cacheManagersByLoader.remove(classLoader); + if (cacheManagers != null) { + for (final CacheManager mgr : cacheManagers.values()) { + mgr.close(); + } + cacheManagers.clear(); + } + } + + @Override + public void close(final URI uri, final ClassLoader classLoader) { + final Map cacheManagers = cacheManagersByLoader.remove(classLoader); + if (cacheManagers != null) { + final CacheManager mgr = cacheManagers.remove(uri); + if (mgr != null) { + mgr.close(); + } + } + } + + @Override + public CacheManager getCacheManager(final URI uri, final ClassLoader classLoader) { + return getCacheManager(uri, classLoader, getDefaultProperties()); + } + + @Override + public CacheManager getCacheManager() { + return getCacheManager(getDefaultURI(), getDefaultClassLoader()); + } + + @Override + public boolean isSupported(final OptionalFeature optionalFeature) { + return optionalFeature == OptionalFeature.STORE_BY_REFERENCE; + } + + @Override + public ClassLoader getDefaultClassLoader() { + return SimpleProvider.class.getClassLoader(); + } + + @Override + public Properties getDefaultProperties() { + return new Properties(); + } + + void remove(final CacheManager mgr) { + final ClassLoader classLoader = mgr.getClassLoader(); + final Map mgrs = cacheManagersByLoader.get(classLoader); + if (mgrs != null) { + mgrs.remove(mgr.getURI()); + if (mgrs.isEmpty()) { + cacheManagersByLoader.remove(classLoader); + } + } + } +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_39/metadata.json b/Java/geronimo-jcache-simple-SimpleProvider_39/metadata.json new file mode 100644 index 000000000..44551ba95 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_39/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleProvider_39", + "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/geronimo/jcache/simple/SimpleProvider.java", + "line": 40, + "npe_method": "getCacheManager", + "deref_field": "inUri", + "npe_class": "SimpleProvider", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleProvider_39" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_39/npe.json b/Java/geronimo-jcache-simple-SimpleProvider_39/npe.json new file mode 100644 index 000000000..78461f38c --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_39/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleProvider.java", + "line": 40, + "npe_method": "getCacheManager", + "deref_field": "inUri", + "npe_class": "SimpleProvider" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleProvider_40/Dockerfile b/Java/geronimo-jcache-simple-SimpleProvider_40/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_40/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleProvider_40/buggy.java b/Java/geronimo-jcache-simple-SimpleProvider_40/buggy.java new file mode 100644 index 000000000..23db4de88 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_40/buggy.java @@ -0,0 +1,134 @@ +/* + * 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.geronimo.jcache.simple; + +import java.net.URI; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.cache.CacheManager; +import javax.cache.configuration.OptionalFeature; +import javax.cache.spi.CachingProvider; + +public class SimpleProvider implements CachingProvider { + + static final URI DEFAULT_URI = URI.create("geronimo://simple-jcache.properties"); + + private final ConcurrentMap> cacheManagersByLoader = new ConcurrentHashMap<>(); + + @Override +public javax.cache.CacheManager getCacheManager(final java.net.URI inUri, final java.lang.ClassLoader inClassLoader, final java.util.Properties properties) { + final java.net.URI uri = (inUri != null) ? inUri : getDefaultURI(); + final java.lang.ClassLoader classLoader = /* NPEX_NULL_EXP */ + inClassLoader; + java.util.concurrent.ConcurrentMap managers = cacheManagersByLoader.get(classLoader); + if (managers == null) { + managers = new java.util.concurrent.ConcurrentHashMap<>(); + final java.util.concurrent.ConcurrentMap existingManagers = cacheManagersByLoader.putIfAbsent(classLoader, managers); + if (existingManagers != null) { + managers = existingManagers; + } + } + javax.cache.CacheManager mgr = managers.get(uri); + if (mgr == null) { + mgr = new org.apache.geronimo.jcache.simple.SimpleManager(this, uri, classLoader, properties); + final javax.cache.CacheManager existing = managers.putIfAbsent(uri, mgr); + if (existing != null) { + mgr = existing; + } + } + return mgr; +} + + @Override + public URI getDefaultURI() { + return DEFAULT_URI; + } + + @Override + public void close() { + for (final Map v : cacheManagersByLoader.values()) { + for (final CacheManager m : v.values()) { + m.close(); + } + v.clear(); + } + cacheManagersByLoader.clear(); + } + + @Override + public void close(final ClassLoader classLoader) { + final Map cacheManagers = cacheManagersByLoader.remove(classLoader); + if (cacheManagers != null) { + for (final CacheManager mgr : cacheManagers.values()) { + mgr.close(); + } + cacheManagers.clear(); + } + } + + @Override + public void close(final URI uri, final ClassLoader classLoader) { + final Map cacheManagers = cacheManagersByLoader.remove(classLoader); + if (cacheManagers != null) { + final CacheManager mgr = cacheManagers.remove(uri); + if (mgr != null) { + mgr.close(); + } + } + } + + @Override + public CacheManager getCacheManager(final URI uri, final ClassLoader classLoader) { + return getCacheManager(uri, classLoader, getDefaultProperties()); + } + + @Override + public CacheManager getCacheManager() { + return getCacheManager(getDefaultURI(), getDefaultClassLoader()); + } + + @Override + public boolean isSupported(final OptionalFeature optionalFeature) { + return optionalFeature == OptionalFeature.STORE_BY_REFERENCE; + } + + @Override + public ClassLoader getDefaultClassLoader() { + return SimpleProvider.class.getClassLoader(); + } + + @Override + public Properties getDefaultProperties() { + return new Properties(); + } + + void remove(final CacheManager mgr) { + final ClassLoader classLoader = mgr.getClassLoader(); + final Map mgrs = cacheManagersByLoader.get(classLoader); + if (mgrs != null) { + mgrs.remove(mgr.getURI()); + if (mgrs.isEmpty()) { + cacheManagersByLoader.remove(classLoader); + } + } + } +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_40/metadata.json b/Java/geronimo-jcache-simple-SimpleProvider_40/metadata.json new file mode 100644 index 000000000..1def0a1df --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_40/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleProvider_40", + "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/geronimo/jcache/simple/SimpleProvider.java", + "line": 41, + "npe_method": "getCacheManager", + "deref_field": "inClassLoader", + "npe_class": "SimpleProvider", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleProvider_40" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_40/npe.json b/Java/geronimo-jcache-simple-SimpleProvider_40/npe.json new file mode 100644 index 000000000..747088e9c --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_40/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleProvider.java", + "line": 41, + "npe_method": "getCacheManager", + "deref_field": "inClassLoader", + "npe_class": "SimpleProvider" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleProvider_46/Dockerfile b/Java/geronimo-jcache-simple-SimpleProvider_46/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_46/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleProvider_46/buggy.java b/Java/geronimo-jcache-simple-SimpleProvider_46/buggy.java new file mode 100644 index 000000000..125f9a16b --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_46/buggy.java @@ -0,0 +1,134 @@ +/* + * 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.geronimo.jcache.simple; + +import java.net.URI; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.cache.CacheManager; +import javax.cache.configuration.OptionalFeature; +import javax.cache.spi.CachingProvider; + +public class SimpleProvider implements CachingProvider { + + static final URI DEFAULT_URI = URI.create("geronimo://simple-jcache.properties"); + + private final ConcurrentMap> cacheManagersByLoader = new ConcurrentHashMap<>(); + + @Override +public javax.cache.CacheManager getCacheManager(final java.net.URI inUri, final java.lang.ClassLoader inClassLoader, final java.util.Properties properties) { + final java.net.URI uri = (inUri != null) ? inUri : getDefaultURI(); + final java.lang.ClassLoader classLoader = (inClassLoader != null) ? inClassLoader : getDefaultClassLoader(); + java.util.concurrent.ConcurrentMap managers = cacheManagersByLoader.get(classLoader); + if (managers == null) { + managers = new java.util.concurrent.ConcurrentHashMap<>(); + final java.util.concurrent.ConcurrentMap existingManagers = cacheManagersByLoader.putIfAbsent(classLoader, managers); + { + managers = /* NPEX_NULL_EXP */ + existingManagers; + } + } + javax.cache.CacheManager mgr = managers.get(uri); + if (mgr == null) { + mgr = new org.apache.geronimo.jcache.simple.SimpleManager(this, uri, classLoader, properties); + final javax.cache.CacheManager existing = managers.putIfAbsent(uri, mgr); + if (existing != null) { + mgr = existing; + } + } + return mgr; +} + + @Override + public URI getDefaultURI() { + return DEFAULT_URI; + } + + @Override + public void close() { + for (final Map v : cacheManagersByLoader.values()) { + for (final CacheManager m : v.values()) { + m.close(); + } + v.clear(); + } + cacheManagersByLoader.clear(); + } + + @Override + public void close(final ClassLoader classLoader) { + final Map cacheManagers = cacheManagersByLoader.remove(classLoader); + if (cacheManagers != null) { + for (final CacheManager mgr : cacheManagers.values()) { + mgr.close(); + } + cacheManagers.clear(); + } + } + + @Override + public void close(final URI uri, final ClassLoader classLoader) { + final Map cacheManagers = cacheManagersByLoader.remove(classLoader); + if (cacheManagers != null) { + final CacheManager mgr = cacheManagers.remove(uri); + if (mgr != null) { + mgr.close(); + } + } + } + + @Override + public CacheManager getCacheManager(final URI uri, final ClassLoader classLoader) { + return getCacheManager(uri, classLoader, getDefaultProperties()); + } + + @Override + public CacheManager getCacheManager() { + return getCacheManager(getDefaultURI(), getDefaultClassLoader()); + } + + @Override + public boolean isSupported(final OptionalFeature optionalFeature) { + return optionalFeature == OptionalFeature.STORE_BY_REFERENCE; + } + + @Override + public ClassLoader getDefaultClassLoader() { + return SimpleProvider.class.getClassLoader(); + } + + @Override + public Properties getDefaultProperties() { + return new Properties(); + } + + void remove(final CacheManager mgr) { + final ClassLoader classLoader = mgr.getClassLoader(); + final Map mgrs = cacheManagersByLoader.get(classLoader); + if (mgrs != null) { + mgrs.remove(mgr.getURI()); + if (mgrs.isEmpty()) { + cacheManagersByLoader.remove(classLoader); + } + } + } +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_46/metadata.json b/Java/geronimo-jcache-simple-SimpleProvider_46/metadata.json new file mode 100644 index 000000000..c7efdeee0 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_46/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleProvider_46", + "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/geronimo/jcache/simple/SimpleProvider.java", + "line": 47, + "npe_method": "getCacheManager", + "deref_field": "existingManagers", + "npe_class": "SimpleProvider", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleProvider_46" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_46/npe.json b/Java/geronimo-jcache-simple-SimpleProvider_46/npe.json new file mode 100644 index 000000000..643af3382 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_46/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleProvider.java", + "line": 47, + "npe_method": "getCacheManager", + "deref_field": "existingManagers", + "npe_class": "SimpleProvider" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleProvider_55/Dockerfile b/Java/geronimo-jcache-simple-SimpleProvider_55/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_55/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleProvider_55/buggy.java b/Java/geronimo-jcache-simple-SimpleProvider_55/buggy.java new file mode 100644 index 000000000..456ae1717 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_55/buggy.java @@ -0,0 +1,134 @@ +/* + * 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.geronimo.jcache.simple; + +import java.net.URI; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.cache.CacheManager; +import javax.cache.configuration.OptionalFeature; +import javax.cache.spi.CachingProvider; + +public class SimpleProvider implements CachingProvider { + + static final URI DEFAULT_URI = URI.create("geronimo://simple-jcache.properties"); + + private final ConcurrentMap> cacheManagersByLoader = new ConcurrentHashMap<>(); + + @Override +public javax.cache.CacheManager getCacheManager(final java.net.URI inUri, final java.lang.ClassLoader inClassLoader, final java.util.Properties properties) { + final java.net.URI uri = (inUri != null) ? inUri : getDefaultURI(); + final java.lang.ClassLoader classLoader = (inClassLoader != null) ? inClassLoader : getDefaultClassLoader(); + java.util.concurrent.ConcurrentMap managers = cacheManagersByLoader.get(classLoader); + if (managers == null) { + managers = new java.util.concurrent.ConcurrentHashMap<>(); + final java.util.concurrent.ConcurrentMap existingManagers = cacheManagersByLoader.putIfAbsent(classLoader, managers); + if (existingManagers != null) { + managers = existingManagers; + } + } + javax.cache.CacheManager mgr = managers.get(uri); + if (mgr == null) { + mgr = new org.apache.geronimo.jcache.simple.SimpleManager(this, uri, classLoader, properties); + final javax.cache.CacheManager existing = managers.putIfAbsent(uri, mgr); + { + mgr = /* NPEX_NULL_EXP */ + existing; + } + } + return mgr; +} + + @Override + public URI getDefaultURI() { + return DEFAULT_URI; + } + + @Override + public void close() { + for (final Map v : cacheManagersByLoader.values()) { + for (final CacheManager m : v.values()) { + m.close(); + } + v.clear(); + } + cacheManagersByLoader.clear(); + } + + @Override + public void close(final ClassLoader classLoader) { + final Map cacheManagers = cacheManagersByLoader.remove(classLoader); + if (cacheManagers != null) { + for (final CacheManager mgr : cacheManagers.values()) { + mgr.close(); + } + cacheManagers.clear(); + } + } + + @Override + public void close(final URI uri, final ClassLoader classLoader) { + final Map cacheManagers = cacheManagersByLoader.remove(classLoader); + if (cacheManagers != null) { + final CacheManager mgr = cacheManagers.remove(uri); + if (mgr != null) { + mgr.close(); + } + } + } + + @Override + public CacheManager getCacheManager(final URI uri, final ClassLoader classLoader) { + return getCacheManager(uri, classLoader, getDefaultProperties()); + } + + @Override + public CacheManager getCacheManager() { + return getCacheManager(getDefaultURI(), getDefaultClassLoader()); + } + + @Override + public boolean isSupported(final OptionalFeature optionalFeature) { + return optionalFeature == OptionalFeature.STORE_BY_REFERENCE; + } + + @Override + public ClassLoader getDefaultClassLoader() { + return SimpleProvider.class.getClassLoader(); + } + + @Override + public Properties getDefaultProperties() { + return new Properties(); + } + + void remove(final CacheManager mgr) { + final ClassLoader classLoader = mgr.getClassLoader(); + final Map mgrs = cacheManagersByLoader.get(classLoader); + if (mgrs != null) { + mgrs.remove(mgr.getURI()); + if (mgrs.isEmpty()) { + cacheManagersByLoader.remove(classLoader); + } + } + } +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_55/metadata.json b/Java/geronimo-jcache-simple-SimpleProvider_55/metadata.json new file mode 100644 index 000000000..53187c15f --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_55/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleProvider_55", + "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/geronimo/jcache/simple/SimpleProvider.java", + "line": 55, + "npe_method": "getCacheManager", + "deref_field": "existing", + "npe_class": "SimpleProvider", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleProvider_55" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_55/npe.json b/Java/geronimo-jcache-simple-SimpleProvider_55/npe.json new file mode 100644 index 000000000..bb24744ef --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_55/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleProvider.java", + "line": 55, + "npe_method": "getCacheManager", + "deref_field": "existing", + "npe_class": "SimpleProvider" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleProvider_82/Dockerfile b/Java/geronimo-jcache-simple-SimpleProvider_82/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_82/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleProvider_82/buggy.java b/Java/geronimo-jcache-simple-SimpleProvider_82/buggy.java new file mode 100644 index 000000000..6ef087dc9 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_82/buggy.java @@ -0,0 +1,137 @@ +/* + * 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.geronimo.jcache.simple; + +import java.net.URI; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.cache.CacheManager; +import javax.cache.configuration.OptionalFeature; +import javax.cache.spi.CachingProvider; + +public class SimpleProvider implements CachingProvider { + + static final URI DEFAULT_URI = URI.create("geronimo://simple-jcache.properties"); + + private final ConcurrentMap> cacheManagersByLoader = new ConcurrentHashMap<>(); + + @Override + public CacheManager getCacheManager(final URI inUri, final ClassLoader inClassLoader, final Properties properties) { + final URI uri = inUri != null ? inUri : getDefaultURI(); + final ClassLoader classLoader = inClassLoader != null ? inClassLoader : getDefaultClassLoader(); + + ConcurrentMap managers = cacheManagersByLoader.get(classLoader); + if (managers == null) { + managers = new ConcurrentHashMap<>(); + final ConcurrentMap existingManagers = cacheManagersByLoader.putIfAbsent(classLoader, managers); + if (existingManagers != null) { + managers = existingManagers; + } + } + + CacheManager mgr = managers.get(uri); + if (mgr == null) { + mgr = new SimpleManager(this, uri, classLoader, properties); + final CacheManager existing = managers.putIfAbsent(uri, mgr); + if (existing != null) { + mgr = existing; + } + } + + return mgr; + } + + @Override + public URI getDefaultURI() { + return DEFAULT_URI; + } + + @Override + public void close() { + for (final Map v : cacheManagersByLoader.values()) { + for (final CacheManager m : v.values()) { + m.close(); + } + v.clear(); + } + cacheManagersByLoader.clear(); + } + + @Override +public void close(final java.lang.ClassLoader classLoader) { + final java.util.Map cacheManagers = cacheManagersByLoader.remove(classLoader); + { + for (final javax.cache.CacheManager mgr : /* NPEX_NULL_EXP */ + cacheManagers.values()) { + mgr.close(); + } + cacheManagers.clear(); + } +} + + @Override + public void close(final URI uri, final ClassLoader classLoader) { + final Map cacheManagers = cacheManagersByLoader.remove(classLoader); + if (cacheManagers != null) { + final CacheManager mgr = cacheManagers.remove(uri); + if (mgr != null) { + mgr.close(); + } + } + } + + @Override + public CacheManager getCacheManager(final URI uri, final ClassLoader classLoader) { + return getCacheManager(uri, classLoader, getDefaultProperties()); + } + + @Override + public CacheManager getCacheManager() { + return getCacheManager(getDefaultURI(), getDefaultClassLoader()); + } + + @Override + public boolean isSupported(final OptionalFeature optionalFeature) { + return optionalFeature == OptionalFeature.STORE_BY_REFERENCE; + } + + @Override + public ClassLoader getDefaultClassLoader() { + return SimpleProvider.class.getClassLoader(); + } + + @Override + public Properties getDefaultProperties() { + return new Properties(); + } + + void remove(final CacheManager mgr) { + final ClassLoader classLoader = mgr.getClassLoader(); + final Map mgrs = cacheManagersByLoader.get(classLoader); + if (mgrs != null) { + mgrs.remove(mgr.getURI()); + if (mgrs.isEmpty()) { + cacheManagersByLoader.remove(classLoader); + } + } + } +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_82/metadata.json b/Java/geronimo-jcache-simple-SimpleProvider_82/metadata.json new file mode 100644 index 000000000..a12ef415a --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_82/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleProvider_82", + "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/geronimo/jcache/simple/SimpleProvider.java", + "line": 84, + "npe_method": "close", + "deref_field": "cacheManagers", + "npe_class": "SimpleProvider", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleProvider_82" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_82/npe.json b/Java/geronimo-jcache-simple-SimpleProvider_82/npe.json new file mode 100644 index 000000000..92f15f78b --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_82/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleProvider.java", + "line": 84, + "npe_method": "close", + "deref_field": "cacheManagers", + "npe_class": "SimpleProvider" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleProvider_93/Dockerfile b/Java/geronimo-jcache-simple-SimpleProvider_93/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_93/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleProvider_93/buggy.java b/Java/geronimo-jcache-simple-SimpleProvider_93/buggy.java new file mode 100644 index 000000000..8dcbb76e6 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_93/buggy.java @@ -0,0 +1,137 @@ +/* + * 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.geronimo.jcache.simple; + +import java.net.URI; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.cache.CacheManager; +import javax.cache.configuration.OptionalFeature; +import javax.cache.spi.CachingProvider; + +public class SimpleProvider implements CachingProvider { + + static final URI DEFAULT_URI = URI.create("geronimo://simple-jcache.properties"); + + private final ConcurrentMap> cacheManagersByLoader = new ConcurrentHashMap<>(); + + @Override + public CacheManager getCacheManager(final URI inUri, final ClassLoader inClassLoader, final Properties properties) { + final URI uri = inUri != null ? inUri : getDefaultURI(); + final ClassLoader classLoader = inClassLoader != null ? inClassLoader : getDefaultClassLoader(); + + ConcurrentMap managers = cacheManagersByLoader.get(classLoader); + if (managers == null) { + managers = new ConcurrentHashMap<>(); + final ConcurrentMap existingManagers = cacheManagersByLoader.putIfAbsent(classLoader, managers); + if (existingManagers != null) { + managers = existingManagers; + } + } + + CacheManager mgr = managers.get(uri); + if (mgr == null) { + mgr = new SimpleManager(this, uri, classLoader, properties); + final CacheManager existing = managers.putIfAbsent(uri, mgr); + if (existing != null) { + mgr = existing; + } + } + + return mgr; + } + + @Override + public URI getDefaultURI() { + return DEFAULT_URI; + } + + @Override + public void close() { + for (final Map v : cacheManagersByLoader.values()) { + for (final CacheManager m : v.values()) { + m.close(); + } + v.clear(); + } + cacheManagersByLoader.clear(); + } + + @Override + public void close(final ClassLoader classLoader) { + final Map cacheManagers = cacheManagersByLoader.remove(classLoader); + if (cacheManagers != null) { + for (final CacheManager mgr : cacheManagers.values()) { + mgr.close(); + } + cacheManagers.clear(); + } + } + + @Override +public void close(final java.net.URI uri, final java.lang.ClassLoader classLoader) { + final java.util.Map cacheManagers = cacheManagersByLoader.remove(classLoader); + { + final javax.cache.CacheManager mgr = /* NPEX_NULL_EXP */ + cacheManagers.remove(uri); + if (mgr != null) { + mgr.close(); + } + } +} + + @Override + public CacheManager getCacheManager(final URI uri, final ClassLoader classLoader) { + return getCacheManager(uri, classLoader, getDefaultProperties()); + } + + @Override + public CacheManager getCacheManager() { + return getCacheManager(getDefaultURI(), getDefaultClassLoader()); + } + + @Override + public boolean isSupported(final OptionalFeature optionalFeature) { + return optionalFeature == OptionalFeature.STORE_BY_REFERENCE; + } + + @Override + public ClassLoader getDefaultClassLoader() { + return SimpleProvider.class.getClassLoader(); + } + + @Override + public Properties getDefaultProperties() { + return new Properties(); + } + + void remove(final CacheManager mgr) { + final ClassLoader classLoader = mgr.getClassLoader(); + final Map mgrs = cacheManagersByLoader.get(classLoader); + if (mgrs != null) { + mgrs.remove(mgr.getURI()); + if (mgrs.isEmpty()) { + cacheManagersByLoader.remove(classLoader); + } + } + } +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_93/metadata.json b/Java/geronimo-jcache-simple-SimpleProvider_93/metadata.json new file mode 100644 index 000000000..25f1afe74 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_93/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleProvider_93", + "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/geronimo/jcache/simple/SimpleProvider.java", + "line": 95, + "npe_method": "close", + "deref_field": "cacheManagers", + "npe_class": "SimpleProvider", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleProvider_93" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_93/npe.json b/Java/geronimo-jcache-simple-SimpleProvider_93/npe.json new file mode 100644 index 000000000..b78a11434 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_93/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleProvider.java", + "line": 95, + "npe_method": "close", + "deref_field": "cacheManagers", + "npe_class": "SimpleProvider" +} \ No newline at end of file diff --git a/Java/geronimo-jcache-simple-SimpleProvider_95/Dockerfile b/Java/geronimo-jcache-simple-SimpleProvider_95/Dockerfile new file mode 100644 index 000000000..3226b6fdd --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_95/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:geronimo-jcache-simple + +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/geronimo-jcache-simple-SimpleProvider_95/buggy.java b/Java/geronimo-jcache-simple-SimpleProvider_95/buggy.java new file mode 100644 index 000000000..704cbf606 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_95/buggy.java @@ -0,0 +1,136 @@ +/* + * 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.geronimo.jcache.simple; + +import java.net.URI; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.cache.CacheManager; +import javax.cache.configuration.OptionalFeature; +import javax.cache.spi.CachingProvider; + +public class SimpleProvider implements CachingProvider { + + static final URI DEFAULT_URI = URI.create("geronimo://simple-jcache.properties"); + + private final ConcurrentMap> cacheManagersByLoader = new ConcurrentHashMap<>(); + + @Override + public CacheManager getCacheManager(final URI inUri, final ClassLoader inClassLoader, final Properties properties) { + final URI uri = inUri != null ? inUri : getDefaultURI(); + final ClassLoader classLoader = inClassLoader != null ? inClassLoader : getDefaultClassLoader(); + + ConcurrentMap managers = cacheManagersByLoader.get(classLoader); + if (managers == null) { + managers = new ConcurrentHashMap<>(); + final ConcurrentMap existingManagers = cacheManagersByLoader.putIfAbsent(classLoader, managers); + if (existingManagers != null) { + managers = existingManagers; + } + } + + CacheManager mgr = managers.get(uri); + if (mgr == null) { + mgr = new SimpleManager(this, uri, classLoader, properties); + final CacheManager existing = managers.putIfAbsent(uri, mgr); + if (existing != null) { + mgr = existing; + } + } + + return mgr; + } + + @Override + public URI getDefaultURI() { + return DEFAULT_URI; + } + + @Override + public void close() { + for (final Map v : cacheManagersByLoader.values()) { + for (final CacheManager m : v.values()) { + m.close(); + } + v.clear(); + } + cacheManagersByLoader.clear(); + } + + @Override + public void close(final ClassLoader classLoader) { + final Map cacheManagers = cacheManagersByLoader.remove(classLoader); + if (cacheManagers != null) { + for (final CacheManager mgr : cacheManagers.values()) { + mgr.close(); + } + cacheManagers.clear(); + } + } + + @Override +public void close(final java.net.URI uri, final java.lang.ClassLoader classLoader) { + final java.util.Map cacheManagers = cacheManagersByLoader.remove(classLoader); + { + final javax.cache.CacheManager mgr = cacheManagers.remove(uri); + { + mgr.close(); + } + } +} + + @Override + public CacheManager getCacheManager(final URI uri, final ClassLoader classLoader) { + return getCacheManager(uri, classLoader, getDefaultProperties()); + } + + @Override + public CacheManager getCacheManager() { + return getCacheManager(getDefaultURI(), getDefaultClassLoader()); + } + + @Override + public boolean isSupported(final OptionalFeature optionalFeature) { + return optionalFeature == OptionalFeature.STORE_BY_REFERENCE; + } + + @Override + public ClassLoader getDefaultClassLoader() { + return SimpleProvider.class.getClassLoader(); + } + + @Override + public Properties getDefaultProperties() { + return new Properties(); + } + + void remove(final CacheManager mgr) { + final ClassLoader classLoader = mgr.getClassLoader(); + final Map mgrs = cacheManagersByLoader.get(classLoader); + if (mgrs != null) { + mgrs.remove(mgr.getURI()); + if (mgrs.isEmpty()) { + cacheManagersByLoader.remove(classLoader); + } + } + } +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_95/metadata.json b/Java/geronimo-jcache-simple-SimpleProvider_95/metadata.json new file mode 100644 index 000000000..d18ea02cf --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_95/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "geronimo-jcache-simple-SimpleProvider_95", + "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/geronimo/jcache/simple/SimpleProvider.java", + "line": 84, + "npe_method": "close", + "deref_field": "mgr", + "npe_class": "SimpleProvider", + "repo": "geronimo-jcache-simple", + "bug_id": "SimpleProvider_95" + } +} diff --git a/Java/geronimo-jcache-simple-SimpleProvider_95/npe.json b/Java/geronimo-jcache-simple-SimpleProvider_95/npe.json new file mode 100644 index 000000000..a0f5128f2 --- /dev/null +++ b/Java/geronimo-jcache-simple-SimpleProvider_95/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "src/main/java/org/apache/geronimo/jcache/simple/SimpleProvider.java", + "line": 84, + "npe_method": "close", + "deref_field": "mgr", + "npe_class": "SimpleProvider" +} \ No newline at end of file