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