001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2008 Sun Microsystems, Inc. 025 */ 026package org.forgerock.opendj.server.config.meta; 027 028 029 030import java.util.Collection; 031import org.forgerock.opendj.config.AdministratorAction; 032import org.forgerock.opendj.config.AliasDefaultBehaviorProvider; 033import org.forgerock.opendj.config.BooleanPropertyDefinition; 034import org.forgerock.opendj.config.ClassPropertyDefinition; 035import org.forgerock.opendj.config.client.ConcurrentModificationException; 036import org.forgerock.opendj.config.client.IllegalManagedObjectNameException; 037import org.forgerock.opendj.config.client.ManagedObject; 038import org.forgerock.opendj.config.client.ManagedObjectDecodingException; 039import org.forgerock.opendj.config.client.MissingMandatoryPropertiesException; 040import org.forgerock.opendj.config.client.OperationRejectedException; 041import org.forgerock.opendj.config.DefaultBehaviorProvider; 042import org.forgerock.opendj.config.DefinedDefaultBehaviorProvider; 043import org.forgerock.opendj.config.DefinitionDecodingException; 044import org.forgerock.opendj.config.DurationPropertyDefinition; 045import org.forgerock.opendj.config.InstantiableRelationDefinition; 046import org.forgerock.opendj.config.IntegerPropertyDefinition; 047import org.forgerock.opendj.config.ManagedObjectAlreadyExistsException; 048import org.forgerock.opendj.config.ManagedObjectDefinition; 049import org.forgerock.opendj.config.ManagedObjectNotFoundException; 050import org.forgerock.opendj.config.OptionalRelationDefinition; 051import org.forgerock.opendj.config.PropertyException; 052import org.forgerock.opendj.config.PropertyOption; 053import org.forgerock.opendj.config.PropertyProvider; 054import org.forgerock.opendj.config.server.ConfigException; 055import org.forgerock.opendj.config.server.ConfigurationAddListener; 056import org.forgerock.opendj.config.server.ConfigurationChangeListener; 057import org.forgerock.opendj.config.server.ConfigurationDeleteListener; 058import org.forgerock.opendj.config.server.ServerManagedObject; 059import org.forgerock.opendj.config.Tag; 060import org.forgerock.opendj.ldap.DN; 061import org.forgerock.opendj.ldap.LdapException; 062import org.forgerock.opendj.server.config.client.ReplicationDomainCfgClient; 063import org.forgerock.opendj.server.config.client.ReplicationServerCfgClient; 064import org.forgerock.opendj.server.config.client.ReplicationSynchronizationProviderCfgClient; 065import org.forgerock.opendj.server.config.server.ReplicationDomainCfg; 066import org.forgerock.opendj.server.config.server.ReplicationServerCfg; 067import org.forgerock.opendj.server.config.server.ReplicationSynchronizationProviderCfg; 068import org.forgerock.opendj.server.config.server.SynchronizationProviderCfg; 069 070 071 072/** 073 * An interface for querying the Replication Synchronization Provider 074 * managed object definition meta information. 075 * <p> 076 * The Replication Synchronization Provider provides multi-master 077 * replication of data across multiple directory server instances. 078 */ 079public final class ReplicationSynchronizationProviderCfgDefn extends ManagedObjectDefinition<ReplicationSynchronizationProviderCfgClient, ReplicationSynchronizationProviderCfg> { 080 081 /** The singleton configuration definition instance. */ 082 private static final ReplicationSynchronizationProviderCfgDefn INSTANCE = new ReplicationSynchronizationProviderCfgDefn(); 083 084 085 086 /** The "connection-timeout" property definition. */ 087 private static final DurationPropertyDefinition PD_CONNECTION_TIMEOUT; 088 089 090 091 /** The "java-class" property definition. */ 092 private static final ClassPropertyDefinition PD_JAVA_CLASS; 093 094 095 096 /** The "num-update-replay-threads" property definition. */ 097 private static final IntegerPropertyDefinition PD_NUM_UPDATE_REPLAY_THREADS; 098 099 100 101 /** The "replication-domains" relation definition. */ 102 private static final InstantiableRelationDefinition<ReplicationDomainCfgClient, ReplicationDomainCfg> RD_REPLICATION_DOMAINS; 103 104 105 106 /** The "replication-server" relation definition. */ 107 private static final OptionalRelationDefinition<ReplicationServerCfgClient, ReplicationServerCfg> RD_REPLICATION_SERVER; 108 109 110 111 /** Build the "connection-timeout" property definition. */ 112 static { 113 DurationPropertyDefinition.Builder builder = DurationPropertyDefinition.createBuilder(INSTANCE, "connection-timeout"); 114 builder.setOption(PropertyOption.ADVANCED); 115 builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.NONE, INSTANCE, "connection-timeout")); 116 DefaultBehaviorProvider<Long> provider = new DefinedDefaultBehaviorProvider<Long>("5 seconds"); 117 builder.setDefaultBehaviorProvider(provider); 118 builder.setBaseUnit("ms"); 119 builder.setLowerLimit("0"); 120 PD_CONNECTION_TIMEOUT = builder.getInstance(); 121 INSTANCE.registerPropertyDefinition(PD_CONNECTION_TIMEOUT); 122 } 123 124 125 126 /** Build the "java-class" property definition. */ 127 static { 128 ClassPropertyDefinition.Builder builder = ClassPropertyDefinition.createBuilder(INSTANCE, "java-class"); 129 builder.setOption(PropertyOption.MANDATORY); 130 builder.setOption(PropertyOption.ADVANCED); 131 builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.NONE, INSTANCE, "java-class")); 132 DefaultBehaviorProvider<String> provider = new DefinedDefaultBehaviorProvider<String>("org.opends.server.replication.plugin.MultimasterReplication"); 133 builder.setDefaultBehaviorProvider(provider); 134 builder.addInstanceOf("org.opends.server.api.SynchronizationProvider"); 135 PD_JAVA_CLASS = builder.getInstance(); 136 INSTANCE.registerPropertyDefinition(PD_JAVA_CLASS); 137 } 138 139 140 141 /** Build the "num-update-replay-threads" property definition. */ 142 static { 143 IntegerPropertyDefinition.Builder builder = IntegerPropertyDefinition.createBuilder(INSTANCE, "num-update-replay-threads"); 144 builder.setOption(PropertyOption.ADVANCED); 145 builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.NONE, INSTANCE, "num-update-replay-threads")); 146 builder.setDefaultBehaviorProvider(new AliasDefaultBehaviorProvider<Integer>(INSTANCE, "num-update-replay-threads")); 147 builder.setUpperLimit(65535); 148 builder.setLowerLimit(1); 149 PD_NUM_UPDATE_REPLAY_THREADS = builder.getInstance(); 150 INSTANCE.registerPropertyDefinition(PD_NUM_UPDATE_REPLAY_THREADS); 151 } 152 153 154 155 // Build the "replication-domains" relation definition. 156 static { 157 InstantiableRelationDefinition.Builder<ReplicationDomainCfgClient, ReplicationDomainCfg> builder = 158 new InstantiableRelationDefinition.Builder<ReplicationDomainCfgClient, ReplicationDomainCfg>(INSTANCE, "replication-domain", "replication-domains", ReplicationDomainCfgDefn.getInstance()); 159 RD_REPLICATION_DOMAINS = builder.getInstance(); 160 INSTANCE.registerRelationDefinition(RD_REPLICATION_DOMAINS); 161 } 162 163 164 165 // Build the "replication-server" relation definition. 166 static { 167 OptionalRelationDefinition.Builder<ReplicationServerCfgClient, ReplicationServerCfg> builder = 168 new OptionalRelationDefinition.Builder<ReplicationServerCfgClient, ReplicationServerCfg>(INSTANCE, "replication-server", ReplicationServerCfgDefn.getInstance()); 169 RD_REPLICATION_SERVER = builder.getInstance(); 170 INSTANCE.registerRelationDefinition(RD_REPLICATION_SERVER); 171 } 172 173 174 175 // Register the tags associated with this managed object definition. 176 static { 177 INSTANCE.registerTag(Tag.valueOf("replication")); 178 } 179 180 181 182 /** 183 * Get the Replication Synchronization Provider configuration 184 * definition singleton. 185 * 186 * @return Returns the Replication Synchronization Provider 187 * configuration definition singleton. 188 */ 189 public static ReplicationSynchronizationProviderCfgDefn getInstance() { 190 return INSTANCE; 191 } 192 193 194 195 /** 196 * Private constructor. 197 */ 198 private ReplicationSynchronizationProviderCfgDefn() { 199 super("replication-synchronization-provider", SynchronizationProviderCfgDefn.getInstance()); 200 } 201 202 203 204 /** {@inheritDoc} */ 205 public ReplicationSynchronizationProviderCfgClient createClientConfiguration( 206 ManagedObject<? extends ReplicationSynchronizationProviderCfgClient> impl) { 207 return new ReplicationSynchronizationProviderCfgClientImpl(impl); 208 } 209 210 211 212 /** {@inheritDoc} */ 213 public ReplicationSynchronizationProviderCfg createServerConfiguration( 214 ServerManagedObject<? extends ReplicationSynchronizationProviderCfg> impl) { 215 return new ReplicationSynchronizationProviderCfgServerImpl(impl); 216 } 217 218 219 220 /** {@inheritDoc} */ 221 public Class<ReplicationSynchronizationProviderCfg> getServerConfigurationClass() { 222 return ReplicationSynchronizationProviderCfg.class; 223 } 224 225 226 227 /** 228 * Get the "connection-timeout" property definition. 229 * <p> 230 * Specifies the timeout used when connecting to peers and when 231 * performing SSL negotiation. 232 * 233 * @return Returns the "connection-timeout" property definition. 234 */ 235 public DurationPropertyDefinition getConnectionTimeoutPropertyDefinition() { 236 return PD_CONNECTION_TIMEOUT; 237 } 238 239 240 241 /** 242 * Get the "enabled" property definition. 243 * <p> 244 * Indicates whether the Replication Synchronization Provider is 245 * enabled for use. 246 * 247 * @return Returns the "enabled" property definition. 248 */ 249 public BooleanPropertyDefinition getEnabledPropertyDefinition() { 250 return SynchronizationProviderCfgDefn.getInstance().getEnabledPropertyDefinition(); 251 } 252 253 254 255 /** 256 * Get the "java-class" property definition. 257 * <p> 258 * Specifies the fully-qualified name of the Java class that 259 * provides the Replication Synchronization Provider implementation. 260 * 261 * @return Returns the "java-class" property definition. 262 */ 263 public ClassPropertyDefinition getJavaClassPropertyDefinition() { 264 return PD_JAVA_CLASS; 265 } 266 267 268 269 /** 270 * Get the "num-update-replay-threads" property definition. 271 * <p> 272 * Specifies the number of update replay threads. 273 * <p> 274 * This value is the number of threads created for replaying every 275 * updates received for all the replication domains. 276 * 277 * @return Returns the "num-update-replay-threads" property definition. 278 */ 279 public IntegerPropertyDefinition getNumUpdateReplayThreadsPropertyDefinition() { 280 return PD_NUM_UPDATE_REPLAY_THREADS; 281 } 282 283 284 285 /** 286 * Get the "replication-domains" relation definition. 287 * 288 * @return Returns the "replication-domains" relation definition. 289 */ 290 public InstantiableRelationDefinition<ReplicationDomainCfgClient,ReplicationDomainCfg> getReplicationDomainsRelationDefinition() { 291 return RD_REPLICATION_DOMAINS; 292 } 293 294 295 296 /** 297 * Get the "replication-server" relation definition. 298 * 299 * @return Returns the "replication-server" relation definition. 300 */ 301 public OptionalRelationDefinition<ReplicationServerCfgClient,ReplicationServerCfg> getReplicationServerRelationDefinition() { 302 return RD_REPLICATION_SERVER; 303 } 304 305 306 307 /** 308 * Managed object client implementation. 309 */ 310 private static class ReplicationSynchronizationProviderCfgClientImpl implements 311 ReplicationSynchronizationProviderCfgClient { 312 313 /** Private implementation. */ 314 private ManagedObject<? extends ReplicationSynchronizationProviderCfgClient> impl; 315 316 317 318 /** Private constructor. */ 319 private ReplicationSynchronizationProviderCfgClientImpl( 320 ManagedObject<? extends ReplicationSynchronizationProviderCfgClient> impl) { 321 this.impl = impl; 322 } 323 324 325 326 /** {@inheritDoc} */ 327 public long getConnectionTimeout() { 328 return impl.getPropertyValue(INSTANCE.getConnectionTimeoutPropertyDefinition()); 329 } 330 331 332 333 /** {@inheritDoc} */ 334 public void setConnectionTimeout(Long value) { 335 impl.setPropertyValue(INSTANCE.getConnectionTimeoutPropertyDefinition(), value); 336 } 337 338 339 340 /** {@inheritDoc} */ 341 public Boolean isEnabled() { 342 return impl.getPropertyValue(INSTANCE.getEnabledPropertyDefinition()); 343 } 344 345 346 347 /** {@inheritDoc} */ 348 public void setEnabled(boolean value) { 349 impl.setPropertyValue(INSTANCE.getEnabledPropertyDefinition(), value); 350 } 351 352 353 354 /** {@inheritDoc} */ 355 public String getJavaClass() { 356 return impl.getPropertyValue(INSTANCE.getJavaClassPropertyDefinition()); 357 } 358 359 360 361 /** {@inheritDoc} */ 362 public void setJavaClass(String value) { 363 impl.setPropertyValue(INSTANCE.getJavaClassPropertyDefinition(), value); 364 } 365 366 367 368 /** {@inheritDoc} */ 369 public Integer getNumUpdateReplayThreads() { 370 return impl.getPropertyValue(INSTANCE.getNumUpdateReplayThreadsPropertyDefinition()); 371 } 372 373 374 375 /** {@inheritDoc} */ 376 public void setNumUpdateReplayThreads(Integer value) { 377 impl.setPropertyValue(INSTANCE.getNumUpdateReplayThreadsPropertyDefinition(), value); 378 } 379 380 381 382 /** {@inheritDoc} */ 383 public String[] listReplicationDomains() throws ConcurrentModificationException, 384 LdapException { 385 return impl.listChildren(INSTANCE.getReplicationDomainsRelationDefinition()); 386 } 387 388 389 390 /** {@inheritDoc} */ 391 public ReplicationDomainCfgClient getReplicationDomain(String name) 392 throws DefinitionDecodingException, ManagedObjectDecodingException, 393 ManagedObjectNotFoundException, ConcurrentModificationException, 394 LdapException { 395 return impl.getChild(INSTANCE.getReplicationDomainsRelationDefinition(), name).getConfiguration(); 396 } 397 398 399 400 /** {@inheritDoc} */ 401 public <M extends ReplicationDomainCfgClient> M createReplicationDomain( 402 ManagedObjectDefinition<M, ? extends ReplicationDomainCfg> d, String name, Collection<PropertyException> exceptions) throws IllegalManagedObjectNameException { 403 return impl.createChild(INSTANCE.getReplicationDomainsRelationDefinition(), d, name, exceptions).getConfiguration(); 404 } 405 406 407 408 /** {@inheritDoc} */ 409 public void removeReplicationDomain(String name) 410 throws ManagedObjectNotFoundException, ConcurrentModificationException, 411 OperationRejectedException, LdapException { 412 impl.removeChild(INSTANCE.getReplicationDomainsRelationDefinition(), name); 413 } 414 415 416 417 /** {@inheritDoc} */ 418 public boolean hasReplicationServer() throws ConcurrentModificationException, 419 LdapException { 420 return impl.hasChild(INSTANCE.getReplicationServerRelationDefinition()); 421 } 422 423 424 425 /** {@inheritDoc} */ 426 public ReplicationServerCfgClient getReplicationServer() 427 throws DefinitionDecodingException, ManagedObjectDecodingException, 428 ManagedObjectNotFoundException, ConcurrentModificationException, 429 LdapException { 430 return impl.getChild(INSTANCE.getReplicationServerRelationDefinition()).getConfiguration(); 431 } 432 433 434 435 /** {@inheritDoc} */ 436 public <M extends ReplicationServerCfgClient> M createReplicationServer( 437 ManagedObjectDefinition<M, ? extends ReplicationServerCfg> d, Collection<PropertyException> exceptions) { 438 return impl.createChild(INSTANCE.getReplicationServerRelationDefinition(), d, exceptions).getConfiguration(); 439 } 440 441 442 443 /** {@inheritDoc} */ 444 public void removeReplicationServer() 445 throws ManagedObjectNotFoundException, ConcurrentModificationException, 446 OperationRejectedException, LdapException { 447 impl.removeChild(INSTANCE.getReplicationServerRelationDefinition()); 448 } 449 450 451 452 /** {@inheritDoc} */ 453 public ManagedObjectDefinition<? extends ReplicationSynchronizationProviderCfgClient, ? extends ReplicationSynchronizationProviderCfg> definition() { 454 return INSTANCE; 455 } 456 457 458 459 /** {@inheritDoc} */ 460 public PropertyProvider properties() { 461 return impl; 462 } 463 464 465 466 /** {@inheritDoc} */ 467 public void commit() throws ManagedObjectAlreadyExistsException, 468 MissingMandatoryPropertiesException, ConcurrentModificationException, 469 OperationRejectedException, LdapException { 470 impl.commit(); 471 } 472 473 474 475 /** {@inheritDoc} */ 476 public String toString() { 477 return impl.toString(); 478 } 479 } 480 481 482 483 /** 484 * Managed object server implementation. 485 */ 486 private static class ReplicationSynchronizationProviderCfgServerImpl implements 487 ReplicationSynchronizationProviderCfg { 488 489 /** Private implementation. */ 490 private ServerManagedObject<? extends ReplicationSynchronizationProviderCfg> impl; 491 492 /** The value of the "connection-timeout" property. */ 493 private final long pConnectionTimeout; 494 495 /** The value of the "enabled" property. */ 496 private final boolean pEnabled; 497 498 /** The value of the "java-class" property. */ 499 private final String pJavaClass; 500 501 /** The value of the "num-update-replay-threads" property. */ 502 private final Integer pNumUpdateReplayThreads; 503 504 505 506 /** Private constructor. */ 507 private ReplicationSynchronizationProviderCfgServerImpl(ServerManagedObject<? extends ReplicationSynchronizationProviderCfg> impl) { 508 this.impl = impl; 509 this.pConnectionTimeout = impl.getPropertyValue(INSTANCE.getConnectionTimeoutPropertyDefinition()); 510 this.pEnabled = impl.getPropertyValue(INSTANCE.getEnabledPropertyDefinition()); 511 this.pJavaClass = impl.getPropertyValue(INSTANCE.getJavaClassPropertyDefinition()); 512 this.pNumUpdateReplayThreads = impl.getPropertyValue(INSTANCE.getNumUpdateReplayThreadsPropertyDefinition()); 513 } 514 515 516 517 /** {@inheritDoc} */ 518 public void addReplicationChangeListener( 519 ConfigurationChangeListener<ReplicationSynchronizationProviderCfg> listener) { 520 impl.registerChangeListener(listener); 521 } 522 523 524 525 /** {@inheritDoc} */ 526 public void removeReplicationChangeListener( 527 ConfigurationChangeListener<ReplicationSynchronizationProviderCfg> listener) { 528 impl.deregisterChangeListener(listener); 529 } 530 /** {@inheritDoc} */ 531 public void addChangeListener( 532 ConfigurationChangeListener<SynchronizationProviderCfg> listener) { 533 impl.registerChangeListener(listener); 534 } 535 536 537 538 /** {@inheritDoc} */ 539 public void removeChangeListener( 540 ConfigurationChangeListener<SynchronizationProviderCfg> listener) { 541 impl.deregisterChangeListener(listener); 542 } 543 544 545 546 /** {@inheritDoc} */ 547 public long getConnectionTimeout() { 548 return pConnectionTimeout; 549 } 550 551 552 553 /** {@inheritDoc} */ 554 public boolean isEnabled() { 555 return pEnabled; 556 } 557 558 559 560 /** {@inheritDoc} */ 561 public String getJavaClass() { 562 return pJavaClass; 563 } 564 565 566 567 /** {@inheritDoc} */ 568 public Integer getNumUpdateReplayThreads() { 569 return pNumUpdateReplayThreads; 570 } 571 572 573 574 /** {@inheritDoc} */ 575 public String[] listReplicationDomains() { 576 return impl.listChildren(INSTANCE.getReplicationDomainsRelationDefinition()); 577 } 578 579 580 581 /** {@inheritDoc} */ 582 public ReplicationDomainCfg getReplicationDomain(String name) throws ConfigException { 583 return impl.getChild(INSTANCE.getReplicationDomainsRelationDefinition(), name).getConfiguration(); 584 } 585 586 587 588 /** {@inheritDoc} */ 589 public void addReplicationDomainAddListener( 590 ConfigurationAddListener<ReplicationDomainCfg> listener) throws ConfigException { 591 impl.registerAddListener(INSTANCE.getReplicationDomainsRelationDefinition(), listener); 592 } 593 594 595 596 /** {@inheritDoc} */ 597 public void removeReplicationDomainAddListener( 598 ConfigurationAddListener<ReplicationDomainCfg> listener) { 599 impl.deregisterAddListener(INSTANCE.getReplicationDomainsRelationDefinition(), listener); 600 } 601 602 603 604 /** {@inheritDoc} */ 605 public void addReplicationDomainDeleteListener( 606 ConfigurationDeleteListener<ReplicationDomainCfg> listener) throws ConfigException { 607 impl.registerDeleteListener(INSTANCE.getReplicationDomainsRelationDefinition(), listener); 608 } 609 610 611 612 /** {@inheritDoc} */ 613 public void removeReplicationDomainDeleteListener( 614 ConfigurationDeleteListener<ReplicationDomainCfg> listener) { 615 impl.deregisterDeleteListener(INSTANCE.getReplicationDomainsRelationDefinition(), listener); 616 } 617 618 619 620 /** {@inheritDoc} */ 621 public boolean hasReplicationServer() { 622 return impl.hasChild(INSTANCE.getReplicationServerRelationDefinition()); 623 } 624 625 626 627 /** {@inheritDoc} */ 628 public ReplicationServerCfg getReplicationServer() throws ConfigException { 629 return impl.getChild(INSTANCE.getReplicationServerRelationDefinition()).getConfiguration(); 630 } 631 632 633 634 /** {@inheritDoc} */ 635 public void addReplicationServerAddListener( 636 ConfigurationAddListener<ReplicationServerCfg> listener) throws ConfigException { 637 impl.registerAddListener(INSTANCE.getReplicationServerRelationDefinition(), listener); 638 } 639 640 641 642 /** {@inheritDoc} */ 643 public void removeReplicationServerAddListener( 644 ConfigurationAddListener<ReplicationServerCfg> listener) { 645 impl.deregisterAddListener(INSTANCE.getReplicationServerRelationDefinition(), listener); 646 } 647 648 649 650 /** {@inheritDoc} */ 651 public void addReplicationServerDeleteListener( 652 ConfigurationDeleteListener<ReplicationServerCfg> listener) throws ConfigException { 653 impl.registerDeleteListener(INSTANCE.getReplicationServerRelationDefinition(), listener); 654 } 655 656 657 658 /** {@inheritDoc} */ 659 public void removeReplicationServerDeleteListener( 660 ConfigurationDeleteListener<ReplicationServerCfg> listener) { 661 impl.deregisterDeleteListener(INSTANCE.getReplicationServerRelationDefinition(), listener); 662 } 663 664 665 666 /** {@inheritDoc} */ 667 public Class<? extends ReplicationSynchronizationProviderCfg> configurationClass() { 668 return ReplicationSynchronizationProviderCfg.class; 669 } 670 671 672 673 /** {@inheritDoc} */ 674 public DN dn() { 675 return impl.getDN(); 676 } 677 678 679 680 /** {@inheritDoc} */ 681 public String toString() { 682 return impl.toString(); 683 } 684 } 685}