1 package com.fasterxml.jackson.databind.cfg; 2 3 import java.security.AccessController; 4 import java.security.PrivilegedAction; 5 import java.text.DateFormat; 6 import java.util.*; 7 8 import com.fasterxml.jackson.annotation.JsonAutoDetect; 9 import com.fasterxml.jackson.annotation.JsonInclude; 10 import com.fasterxml.jackson.annotation.JsonSetter; 11 import com.fasterxml.jackson.annotation.JsonTypeInfo; 12 import com.fasterxml.jackson.annotation.PropertyAccessor; 13 import com.fasterxml.jackson.core.*; 14 import com.fasterxml.jackson.databind.*; 15 import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; 16 import com.fasterxml.jackson.databind.deser.*; 17 import com.fasterxml.jackson.databind.introspect.VisibilityChecker; 18 import com.fasterxml.jackson.databind.jsontype.NamedType; 19 import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator; 20 import com.fasterxml.jackson.databind.jsontype.SubtypeResolver; 21 import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder; 22 import com.fasterxml.jackson.databind.node.JsonNodeFactory; 23 import com.fasterxml.jackson.databind.ser.*; 24 import com.fasterxml.jackson.databind.type.TypeFactory; 25 26 /** 27 * Jackson 3 will introduce fully immutable, builder-based system for constructing 28 * {@link ObjectMapper}s. Same can not be done with 2.10 for backwards-compatibility 29 * reasons; but we can offer sort of "fake" builder, which simply encapsulates 30 * configuration calls. The main (and only) point is to allow gradual upgrade. 31 * 32 * @since 2.10 33 */ 34 public abstract class MapperBuilder<M extends ObjectMapper, 35 B extends MapperBuilder<M,B>> 36 { 37 protected final M _mapper; 38 39 /* 40 /********************************************************************** 41 /* Life-cycle 42 /********************************************************************** 43 */ 44 MapperBuilder(M mapper)45 protected MapperBuilder(M mapper) 46 { 47 _mapper = mapper; 48 } 49 50 /** 51 * Method to call to create actual mapper instance. 52 *<p> 53 * Implementation detail: in 2.10 (but not 3.x) underlying mapper is eagerly 54 * constructed when builder is constructed, and method simply returns that 55 * instance. 56 */ build()57 public M build() { 58 return _mapper; 59 } 60 61 /* 62 /********************************************************************** 63 /* Accessors, features 64 /********************************************************************** 65 */ 66 isEnabled(MapperFeature f)67 public boolean isEnabled(MapperFeature f) { 68 return _mapper.isEnabled(f); 69 } isEnabled(DeserializationFeature f)70 public boolean isEnabled(DeserializationFeature f) { 71 return _mapper.isEnabled(f); 72 } isEnabled(SerializationFeature f)73 public boolean isEnabled(SerializationFeature f) { 74 return _mapper.isEnabled(f); 75 } 76 isEnabled(JsonParser.Feature f)77 public boolean isEnabled(JsonParser.Feature f) { 78 return _mapper.isEnabled(f); 79 } isEnabled(JsonGenerator.Feature f)80 public boolean isEnabled(JsonGenerator.Feature f) { 81 return _mapper.isEnabled(f); 82 } 83 84 /* 85 /********************************************************************** 86 /* Accessors, other 87 /********************************************************************** 88 */ 89 streamFactory()90 public TokenStreamFactory streamFactory() { 91 return _mapper.tokenStreamFactory(); 92 } 93 94 /* 95 /********************************************************************** 96 /* Changing features: mapper, ser, deser 97 /********************************************************************** 98 */ 99 enable(MapperFeature... features)100 public B enable(MapperFeature... features) { 101 _mapper.enable(features); 102 return _this(); 103 } 104 disable(MapperFeature... features)105 public B disable(MapperFeature... features) { 106 _mapper.disable(features); 107 return _this(); 108 } 109 configure(MapperFeature feature, boolean state)110 public B configure(MapperFeature feature, boolean state) { 111 _mapper.configure(feature, state); 112 return _this(); 113 } 114 enable(SerializationFeature... features)115 public B enable(SerializationFeature... features) { 116 for (SerializationFeature f : features) { 117 _mapper.enable(f); 118 } 119 return _this(); 120 } 121 disable(SerializationFeature... features)122 public B disable(SerializationFeature... features) { 123 for (SerializationFeature f : features) { 124 _mapper.disable(f); 125 } 126 return _this(); 127 } 128 configure(SerializationFeature feature, boolean state)129 public B configure(SerializationFeature feature, boolean state) { 130 _mapper.configure(feature, state); 131 return _this(); 132 } 133 enable(DeserializationFeature... features)134 public B enable(DeserializationFeature... features) { 135 for (DeserializationFeature f : features) { 136 _mapper.enable(f); 137 } 138 return _this(); 139 } 140 disable(DeserializationFeature... features)141 public B disable(DeserializationFeature... features) { 142 for (DeserializationFeature f : features) { 143 _mapper.disable(f); 144 } 145 return _this(); 146 } 147 configure(DeserializationFeature feature, boolean state)148 public B configure(DeserializationFeature feature, boolean state) { 149 _mapper.configure(feature, state); 150 return _this(); 151 } 152 153 /* 154 /********************************************************************** 155 /* Changing features: parser, generator, pre-2.10 156 /********************************************************************** 157 */ 158 enable(JsonParser.Feature... features)159 public B enable(JsonParser.Feature... features) { 160 _mapper.enable(features); 161 return _this(); 162 } 163 disable(JsonParser.Feature... features)164 public B disable(JsonParser.Feature... features) { 165 _mapper.disable(features); 166 return _this(); 167 } 168 configure(JsonParser.Feature feature, boolean state)169 public B configure(JsonParser.Feature feature, boolean state) { 170 _mapper.configure(feature, state); 171 return _this(); 172 } 173 enable(JsonGenerator.Feature... features)174 public B enable(JsonGenerator.Feature... features) { 175 _mapper.enable(features); 176 return _this(); 177 } 178 disable(JsonGenerator.Feature... features)179 public B disable(JsonGenerator.Feature... features) { 180 _mapper.disable(features); 181 return _this(); 182 } 183 configure(JsonGenerator.Feature feature, boolean state)184 public B configure(JsonGenerator.Feature feature, boolean state) { 185 _mapper.configure(feature, state); 186 return _this(); 187 } 188 189 /* 190 /********************************************************************** 191 /* Changing features: parser, generator, 2.10+ 192 /********************************************************************** 193 */ 194 enable(StreamReadFeature... features)195 public B enable(StreamReadFeature... features) { 196 for (StreamReadFeature f : features) { 197 _mapper.enable(f.mappedFeature()); 198 } 199 return _this(); 200 } 201 disable(StreamReadFeature... features)202 public B disable(StreamReadFeature... features) { 203 for (StreamReadFeature f : features) { 204 _mapper.disable(f.mappedFeature()); 205 } 206 return _this(); 207 } 208 configure(StreamReadFeature feature, boolean state)209 public B configure(StreamReadFeature feature, boolean state) { 210 _mapper.configure(feature.mappedFeature(), state); 211 return _this(); 212 } 213 enable(StreamWriteFeature... features)214 public B enable(StreamWriteFeature... features) { 215 for (StreamWriteFeature f : features) { 216 _mapper.enable(f.mappedFeature()); 217 } 218 return _this(); 219 } 220 disable(StreamWriteFeature... features)221 public B disable(StreamWriteFeature... features) { 222 for (StreamWriteFeature f : features) { 223 _mapper.disable(f.mappedFeature()); 224 } 225 return _this(); 226 } 227 configure(StreamWriteFeature feature, boolean state)228 public B configure(StreamWriteFeature feature, boolean state) { 229 _mapper.configure(feature.mappedFeature(), state); 230 return _this(); 231 } 232 233 /* 234 /********************************************************************** 235 /* Module registration, discovery, access 236 /********************************************************************** 237 */ 238 addModule(com.fasterxml.jackson.databind.Module module)239 public B addModule(com.fasterxml.jackson.databind.Module module) 240 { 241 _mapper.registerModule(module); 242 return _this(); 243 } 244 addModules(com.fasterxml.jackson.databind.Module... modules)245 public B addModules(com.fasterxml.jackson.databind.Module... modules) 246 { 247 for (com.fasterxml.jackson.databind.Module module : modules) { 248 addModule(module); 249 } 250 return _this(); 251 } 252 addModules(Iterable<? extends com.fasterxml.jackson.databind.Module> modules)253 public B addModules(Iterable<? extends com.fasterxml.jackson.databind.Module> modules) 254 { 255 for (com.fasterxml.jackson.databind.Module module : modules) { 256 addModule(module); 257 } 258 return _this(); 259 } 260 261 /** 262 * Method for locating available methods, using JDK {@link ServiceLoader} 263 * facility, along with module-provided SPI. 264 *<p> 265 * Note that method does not do any caching, so calls should be considered 266 * potentially expensive. 267 */ findModules()268 public static List<com.fasterxml.jackson.databind.Module> findModules() { 269 return findModules(null); 270 } 271 272 /** 273 * Method for locating available methods, using JDK {@link ServiceLoader} 274 * facility, along with module-provided SPI. 275 *<p> 276 * Note that method does not do any caching, so calls should be considered 277 * potentially expensive. 278 */ findModules(ClassLoader classLoader)279 public static List<com.fasterxml.jackson.databind.Module> findModules(ClassLoader classLoader) 280 { 281 ArrayList<com.fasterxml.jackson.databind.Module> modules = new ArrayList<>(); 282 ServiceLoader<com.fasterxml.jackson.databind.Module> loader = secureGetServiceLoader(com.fasterxml.jackson.databind.Module.class, classLoader); 283 for (com.fasterxml.jackson.databind.Module module : loader) { 284 modules.add(module); 285 } 286 return modules; 287 } 288 secureGetServiceLoader(final Class<T> clazz, final ClassLoader classLoader)289 private static <T> ServiceLoader<T> secureGetServiceLoader(final Class<T> clazz, final ClassLoader classLoader) { 290 final SecurityManager sm = System.getSecurityManager(); 291 if (sm == null) { 292 return (classLoader == null) ? 293 ServiceLoader.load(clazz) : ServiceLoader.load(clazz, classLoader); 294 } 295 return AccessController.doPrivileged(new PrivilegedAction<ServiceLoader<T>>() { 296 @Override 297 public ServiceLoader<T> run() { 298 return (classLoader == null) ? 299 ServiceLoader.load(clazz) : ServiceLoader.load(clazz, classLoader); 300 } 301 }); 302 } 303 304 /** 305 * Convenience method that is functionally equivalent to: 306 *<code> 307 * addModules(builder.findModules()); 308 *</code> 309 *<p> 310 * As with {@link #findModules()}, no caching is done for modules, so care 311 * needs to be taken to either create and share a single mapper instance; 312 * or to cache introspected set of modules. 313 */ 314 public B findAndAddModules() { 315 return addModules(findModules()); 316 } 317 318 /* 319 /********************************************************************** 320 /* Changing base settings 321 /********************************************************************** 322 */ 323 324 /** 325 * Method for replacing {@link AnnotationIntrospector} used by the 326 * mapper instance to be built. 327 * Note that doing this will replace the current introspector, which 328 * may lead to unavailability of core Jackson annotations. 329 * If you want to combine handling of multiple introspectors, 330 * have a look at {@link com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair}. 331 * 332 * @see com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair 333 */ 334 public B annotationIntrospector(AnnotationIntrospector intr) { 335 _mapper.setAnnotationIntrospector(intr); 336 return _this(); 337 } 338 339 public B nodeFactory(JsonNodeFactory f) { 340 _mapper.setNodeFactory(f); 341 return _this(); 342 } 343 344 /* 345 /********************************************************************** 346 /* Changing introspection helpers 347 /********************************************************************** 348 */ 349 350 public B typeFactory(TypeFactory f) { 351 _mapper.setTypeFactory(f); 352 return _this(); 353 } 354 355 public B subtypeResolver(SubtypeResolver r) { 356 _mapper.setSubtypeResolver(r); 357 return _this(); 358 } 359 360 public B visibility(VisibilityChecker<?> vc) { 361 _mapper.setVisibility(vc); 362 return _this(); 363 } 364 365 public B visibility(PropertyAccessor forMethod, JsonAutoDetect.Visibility visibility) { 366 _mapper.setVisibility(forMethod, visibility); 367 return _this(); 368 } 369 370 /** 371 * Method for configuring {@link HandlerInstantiator} to use for creating 372 * instances of handlers (such as serializers, deserializers, type and type 373 * id resolvers), given a class. 374 * 375 * @param hi Instantiator to use; if null, use the default implementation 376 */ 377 public B handlerInstantiator(HandlerInstantiator hi) { 378 _mapper.setHandlerInstantiator(hi); 379 return _this(); 380 } 381 382 public B propertyNamingStrategy(PropertyNamingStrategy s) { 383 _mapper.setPropertyNamingStrategy(s); 384 return _this(); 385 } 386 387 /* 388 /********************************************************************** 389 /* Changing factories, serialization 390 /********************************************************************** 391 */ 392 393 public B serializerFactory(SerializerFactory f) { 394 _mapper.setSerializerFactory(f); 395 return _this(); 396 } 397 398 /** 399 * Method for configuring this mapper to use specified {@link FilterProvider} for 400 * mapping Filter Ids to actual filter instances. 401 *<p> 402 * Note that usually it is better to use method in {@link ObjectWriter}, but sometimes 403 * this method is more convenient. For example, some frameworks only allow configuring 404 * of ObjectMapper instances and not {@link ObjectWriter}s. 405 */ 406 public B filterProvider(FilterProvider prov) { 407 _mapper.setFilterProvider(prov); 408 return _this(); 409 } 410 411 public B defaultPrettyPrinter(PrettyPrinter pp) { 412 _mapper.setDefaultPrettyPrinter(pp); 413 return _this(); 414 } 415 416 /* 417 /********************************************************************** 418 /* Changing factories, related, deserialization 419 /********************************************************************** 420 */ 421 422 public B injectableValues(InjectableValues v) { 423 _mapper.setInjectableValues(v); 424 return _this(); 425 } 426 427 /** 428 * Method used for adding a {@link DeserializationProblemHandler} for this 429 * builder, at the head of the list (meaning it has priority over handler 430 * registered earlier). 431 */ 432 public B addHandler(DeserializationProblemHandler h) { 433 _mapper.addHandler(h); 434 return _this(); 435 } 436 437 /** 438 * Method that may be used to remove all {@link DeserializationProblemHandler}s added 439 * to this builder (if any). 440 */ 441 public B clearProblemHandlers() { 442 _mapper.clearProblemHandlers(); 443 return _this(); 444 } 445 446 /* 447 /********************************************************************** 448 /* Changing global defaults 449 /********************************************************************** 450 */ 451 452 public B defaultSetterInfo(JsonSetter.Value v) { 453 _mapper.setDefaultSetterInfo(v); 454 return _this(); 455 } 456 457 /** 458 * Method for setting default Setter configuration, regarding things like 459 * merging, null-handling; used for properties for which there are 460 * no per-type or per-property overrides (via annotations or config overrides). 461 */ 462 public B defaultMergeable(Boolean b) { 463 _mapper.setDefaultMergeable(b); 464 return _this(); 465 } 466 467 /** 468 * Method for setting default Setter configuration, regarding things like 469 * merging, null-handling; used for properties for which there are 470 * no per-type or per-property overrides (via annotations or config overrides). 471 */ 472 public B defaultLeniency(Boolean b) { 473 _mapper.setDefaultLeniency(b); 474 return _this(); 475 } 476 477 /* 478 /********************************************************************** 479 /* Changing settings, date/time 480 /********************************************************************** 481 */ 482 483 /** 484 * Method for configuring the default {@link DateFormat} to use when serializing time 485 * values as Strings, and deserializing from JSON Strings. 486 * If you need per-request configuration, factory methods in 487 * {@link ObjectReader} and {@link ObjectWriter} instead. 488 */ 489 public B defaultDateFormat(DateFormat df) { 490 _mapper.setDateFormat(df); 491 return _this(); 492 } 493 494 /** 495 * Method for overriding default TimeZone to use for formatting. 496 * Default value used is UTC (NOT default TimeZone of JVM). 497 */ 498 public B defaultTimeZone(TimeZone tz) { 499 _mapper.setTimeZone(tz); 500 return _this(); 501 } 502 503 /** 504 * Method for overriding default locale to use for formatting. 505 * Default value used is {@link Locale#getDefault()}. 506 */ 507 public B defaultLocale(Locale locale) { 508 _mapper.setLocale(locale); 509 return _this(); 510 } 511 512 /* 513 /********************************************************************** 514 /* Changing settings, formatting 515 /********************************************************************** 516 */ 517 518 /** 519 * Method that will configure default {@link Base64Variant} that 520 * <code>byte[]</code> serializers and deserializers will use. 521 * 522 * @param v Base64 variant to use 523 * 524 * @return This builder instance to allow call chaining 525 */ 526 public B defaultBase64Variant(Base64Variant v) { 527 _mapper.setBase64Variant(v); 528 return _this(); 529 } 530 531 /** 532 * Method for configured default property inclusion to use for serialization. 533 * 534 * @param incl Default property inclusion to set 535 * 536 * @return This builder instance to allow call chaining 537 */ 538 public B serializationInclusion(JsonInclude.Include incl) { 539 _mapper.setSerializationInclusion(incl); 540 return _this(); 541 } 542 543 /** 544 * Method for configured default property inclusion to use for serialization. 545 * 546 * @param incl Default property inclusion to set 547 * 548 * @return This builder instance to allow call chaining 549 * 550 * @since 2.11 551 */ 552 public B defaultPropertyInclusion(JsonInclude.Value incl) { 553 _mapper.setDefaultPropertyInclusion(incl); 554 return _this(); 555 } 556 557 /* 558 /********************************************************************** 559 /* Adding Mix-ins 560 /********************************************************************** 561 */ 562 563 /** 564 * Method to use for defining mix-in annotations to use for augmenting 565 * annotations that classes have, for purpose of configuration serialization 566 * and/or deserialization processing. 567 * Mixing in is done when introspecting class annotations and properties. 568 * Annotations from "mixin" class (and its supertypes) 569 * will <b>override</b> 570 * annotations that target classes (and their super-types) have. 571 *<p> 572 * Note that standard mixin handler implementations will only allow a single mix-in 573 * source class per target, so if there was a previous mix-in defined target it will 574 * be cleared. This also means that you can remove mix-in definition by specifying 575 * {@code mixinSource} of {@code null} 576 */ 577 public B addMixIn(Class<?> target, Class<?> mixinSource) 578 { 579 _mapper.addMixIn(target, mixinSource); 580 return _this(); 581 } 582 583 /* 584 /********************************************************************** 585 /* Subtype registration, related 586 /********************************************************************** 587 */ 588 589 public B registerSubtypes(Class<?>... subtypes) { 590 _mapper.registerSubtypes(subtypes); 591 return _this(); 592 } 593 594 public B registerSubtypes(NamedType... subtypes) { 595 _mapper.registerSubtypes(subtypes); 596 return _this(); 597 } 598 599 public B registerSubtypes(Collection<Class<?>> subtypes) { 600 _mapper.registerSubtypes(subtypes); 601 return _this(); 602 } 603 604 /** 605 * Method for assigning {@link PolymorphicTypeValidator} to use for validating 606 * subtypes when using Class name - based polymorphic deserialization 607 * using annotations (validator used with "Default Typing" is specified by 608 * passing in {@link #activateDefaultTyping(PolymorphicTypeValidator)} instead). 609 *<p> 610 * Validator will be called on validating types for which no default databind 611 * deserializer, or module-provided deserializer is found: typically this 612 * includes "POJO" (aka Bean) types, but not (for example) most container 613 * types. 614 * 615 * @since 2.10 616 */ 617 public B polymorphicTypeValidator(PolymorphicTypeValidator ptv) { 618 _mapper.setPolymorphicTypeValidator(ptv); 619 return _this(); 620 } 621 622 /* 623 /********************************************************************** 624 /* Default typing 625 /********************************************************************** 626 */ 627 628 /** 629 * Convenience method that is equivalent to calling 630 *<pre> 631 * activateDefaultTyping(subtypeValidator, DefaultTyping.OBJECT_AND_NON_CONCRETE); 632 *</pre> 633 *<p> 634 * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security 635 * as allowing all subtypes can be risky for untrusted content. 636 */ 637 public B activateDefaultTyping(PolymorphicTypeValidator subtypeValidator) { 638 _mapper.activateDefaultTyping(subtypeValidator); 639 return _this(); 640 } 641 642 /** 643 * Convenience method that is equivalent to calling 644 *<pre> 645 * activateDefaultTyping(subtypeValidator, dti, JsonTypeInfo.As.WRAPPER_ARRAY); 646 *</pre> 647 *<p> 648 * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security 649 * as allowing all subtypes can be risky for untrusted content. 650 */ 651 public B activateDefaultTyping(PolymorphicTypeValidator subtypeValidator, 652 DefaultTyping dti) { 653 _mapper.activateDefaultTyping(subtypeValidator, dti); 654 return _this(); 655 } 656 657 /** 658 * Method for enabling automatic inclusion of type information, needed 659 * for proper deserialization of polymorphic types (unless types 660 * have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}). 661 *<P> 662 * NOTE: use of <code>JsonTypeInfo.As#EXTERNAL_PROPERTY</code> <b>NOT SUPPORTED</b>; 663 * and attempts of do so will throw an {@link IllegalArgumentException} to make 664 * this limitation explicit. 665 *<p> 666 * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security 667 * as allowing all subtypes can be risky for untrusted content. 668 * 669 * @param applicability Defines kinds of types for which additional type information 670 * is added; see {@link DefaultTyping} for more information. 671 */ 672 public B activateDefaultTyping(PolymorphicTypeValidator subtypeValidator, 673 DefaultTyping applicability, JsonTypeInfo.As includeAs) 674 { 675 _mapper.activateDefaultTyping(subtypeValidator, applicability, includeAs); 676 return _this(); 677 } 678 679 /** 680 * Method for enabling automatic inclusion of type information -- needed 681 * for proper deserialization of polymorphic types (unless types 682 * have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) -- 683 * using "As.PROPERTY" inclusion mechanism and specified property name 684 * to use for inclusion (default being "@class" since default type information 685 * always uses class name as type identifier) 686 *<p> 687 * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security 688 * as allowing all subtypes can be risky for untrusted content. 689 */ 690 public B activateDefaultTypingAsProperty(PolymorphicTypeValidator subtypeValidator, 691 DefaultTyping applicability, String propertyName) 692 { 693 _mapper.activateDefaultTypingAsProperty(subtypeValidator, applicability, propertyName); 694 return _this(); 695 } 696 697 /** 698 * Method for disabling automatic inclusion of type information; if so, only 699 * explicitly annotated types (ones with 700 * {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) will have 701 * additional embedded type information. 702 */ 703 public B deactivateDefaultTyping() { 704 _mapper.deactivateDefaultTyping(); 705 return _this(); 706 } 707 708 /** 709 * Method for enabling automatic inclusion of type information, using 710 * specified handler object for determining which types this affects, 711 * as well as details of how information is embedded. 712 *<p> 713 * NOTE: use of Default Typing can be a potential security risk if incoming 714 * content comes from untrusted sources, so care should be taken to use 715 * a {@link TypeResolverBuilder} that can limit allowed classes to 716 * deserialize. Note in particular that 717 * {@link com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder} 718 * DOES NOT limit applicability but creates type (de)serializers for all 719 * types. 720 * 721 * @param typer Type information inclusion handler 722 * 723 * @since 2.12 724 */ 725 public B setDefaultTyping(TypeResolverBuilder<?> typer) { 726 _mapper.setDefaultTyping(typer); 727 return _this(); 728 } 729 730 /* 731 /********************************************************************** 732 /* Other helper methods 733 /********************************************************************** 734 */ 735 736 // silly convenience cast method we need 737 @SuppressWarnings("unchecked") 738 protected final B _this() { return (B) this; } 739 } 740