@@ -349,43 +349,16 @@ public static String getFullName(Schema schema) {
349349 if (namespace .charAt (len -1 ) == '$' ) {
350350 return namespace + name ;
351351 }
352- return _findFullName (namespace , name );
352+ // 19-Sep-2020, tatu: Due to very expensive contortions of lookups introduced
353+ // in [dataformats-binary#195], attempts to resolve [dataformats-binary#219]
354+ // isolated into separate class
355+ return FullNameResolver .instance .resolve (namespace , name );
353356
354357 default :
355358 return type .getName ();
356359 }
357360 }
358361
359- private static String _findFullName (final String namespace , final String name ) {
360- final String cacheKey = namespace + "." + name ;
361- String schemaName = SCHEMA_NAME_CACHE .get (cacheKey );
362-
363- if (schemaName == null ) {
364- schemaName = _resolveFullName (namespace , name );
365- SCHEMA_NAME_CACHE .put (cacheKey , schemaName );
366- }
367- return schemaName ;
368- }
369-
370- private static String _resolveFullName (final String namespace , final String name ) {
371- StringBuilder sb = new StringBuilder (1 + namespace .length () + name .length ());
372-
373- // 28-Feb-2020: [dataformats-binary#195] somewhat complicated logic of trying
374- // to support differences between avro-lib 1.8 and 1.9...
375- // Check if this is a nested class
376- final String nestedClassName = sb .append (namespace ).append ('$' ).append (name ).toString ();
377- try {
378- Class .forName (nestedClassName );
379-
380- return nestedClassName ;
381- } catch (ClassNotFoundException e ) {
382- // Could not find a nested class, must be a regular class
383- sb .setLength (0 );
384-
385- return sb .append (namespace ).append ('.' ).append (name ).toString ();
386- }
387- }
388-
389362 public static JsonNode nullNode () {
390363 return DEFAULT_VALUE_MAPPER .nullNode ();
391364 }
@@ -440,5 +413,65 @@ public static JsonNode parseDefaultValue(String defaultValue) throws JsonMapping
440413 }
441414
442415 // @since 2.11.3
443- private static final LRUMap <String , String > SCHEMA_NAME_CACHE = new LRUMap <>(80 , 800 );
416+ private final static class FullNameResolver {
417+ private final LRUMap <FullNameKey , String > SCHEMA_NAME_CACHE = new LRUMap <>(80 , 800 );
418+
419+ public final static FullNameResolver instance = new FullNameResolver ();
420+
421+ public String resolve (final String namespace , final String name ) {
422+ final FullNameKey cacheKey = new FullNameKey (namespace , name );
423+ String schemaName = SCHEMA_NAME_CACHE .get (cacheKey );
424+
425+ if (schemaName == null ) {
426+ schemaName = _resolve (cacheKey );
427+ SCHEMA_NAME_CACHE .put (cacheKey , schemaName );
428+ }
429+ return schemaName ;
430+ }
431+
432+ private static String _resolve (FullNameKey key ) {
433+ // 28-Feb-2020: [dataformats-binary#195] somewhat complicated logic of trying
434+ // to support differences between avro-lib 1.8 and 1.9...
435+ // Check if this is a nested class
436+ // 19-Sep-2020, tatu: This is a horrible, horribly inefficient and all-around
437+ // wrong mechanism. To be abolished if possible.
438+ final String nestedClassName = key .nameWithSeparator ('$' );
439+ try {
440+ Class .forName (nestedClassName );
441+ return nestedClassName ;
442+ } catch (ClassNotFoundException e ) {
443+ // Could not find a nested class, must be a regular class
444+ return key .nameWithSeparator ('.' );
445+ }
446+ }
447+ }
448+
449+ // @since 2.11.3
450+ private final static class FullNameKey {
451+ private final String _namespace , _name ;
452+ private final int _hashCode ;
453+
454+ public FullNameKey (String namespace , String name ) {
455+ _namespace = namespace ;
456+ _name = name ;
457+ _hashCode = namespace .hashCode () + name .hashCode ();
458+ }
459+
460+ public String nameWithSeparator (char sep ) {
461+ final StringBuilder sb = new StringBuilder (1 + _namespace .length () + _name .length ());
462+ return sb .append (_namespace ).append (sep ).append (_name ).toString ();
463+ }
464+
465+ @ Override
466+ public int hashCode () { return _hashCode ; }
467+
468+ @ Override
469+ public boolean equals (Object o ) {
470+ if (o == this ) return true ;
471+ if (o == null ) return false ;
472+ // Only used internally don't bother with type checks
473+ final FullNameKey other = (FullNameKey ) o ;
474+ return other ._name .equals (_name ) && other ._namespace .equals (_namespace );
475+ }
476+ }
444477}
0 commit comments