1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 package org.apache.river.fiddler.proxy; 19 20 import java.io.IOException; 21 import java.io.InvalidObjectException; 22 import java.io.ObjectInputStream; 23 import java.lang.reflect.Method; 24 import java.rmi.RemoteException; 25 import net.jini.core.constraint.MethodConstraints; 26 import net.jini.core.constraint.RemoteMethodControl; 27 import net.jini.core.lease.Lease; 28 import net.jini.core.lease.LeaseMap; 29 import net.jini.core.lease.UnknownLeaseException; 30 import net.jini.id.ReferentUuid; 31 import net.jini.id.ReferentUuids; 32 import net.jini.id.Uuid; 33 import net.jini.security.proxytrust.ProxyTrustIterator; 34 import net.jini.security.proxytrust.SingletonProxyTrustIterator; 35 import org.apache.river.api.io.AtomicSerial; 36 import org.apache.river.api.io.AtomicSerial.GetArg; 37 import org.apache.river.lease.AbstractLease; 38 import org.apache.river.lease.ID; 39 import org.apache.river.proxy.ConstrainableProxyUtil; 40 41 /** 42 * When the Fiddler implementation of the lookup discovery service grants 43 * a lease on a registration requested by a client, a proxy to that lease 44 * is provided to allow the client to interact with the granted lease. 45 * This class is the implementation of that proxy. 46 * <p> 47 * Clients only see instances of this class via the <code>Lease</code> 48 * interface. 49 * 50 * @author Sun Microsystems, Inc. 51 * 52 */ 53 @AtomicSerial 54 public class FiddlerLease extends AbstractLease 55 implements ReferentUuid, ID<Uuid> 56 { 57 58 private static final long serialVersionUID = 2L; 59 60 /** 61 * The reference to the back-end server of the lookup discovery service 62 * that granted this lease (the granting entity). 63 * 64 * @serial 65 */ 66 final Fiddler server; 67 /** 68 * The unique ID associated with the server referenced in this class 69 * (used to compare server references). 70 * 71 * @serial 72 */ 73 final Uuid serverID; 74 /** 75 * The unique identifier assigned by the lookup discovery service to 76 * the registration to which this lease corresponds. 77 * 78 * @serial 79 */ 80 final Uuid registrationID; 81 /** 82 * The internal identifier assigned to this lease by the granting entity. 83 * 84 * @serial 85 */ 86 final Uuid leaseID; 87 88 /** 89 * Public static factory method that creates and returns an instance of 90 * <code>FiddlerLease</code>. If the server associated with this proxy 91 * implements <code>RemoteMethodControl</code>, then the object returned by 92 * this method will also implement <code>RemoteMethodControl</code>. 93 * 94 * @param server reference to the server object through which 95 * communication occurs between the client-side and 96 * server-side of the associated service. 97 * @param serverID the service ID of the service referenced by the 98 * server parameter 99 * @param registrationID the unique identifier assigned by the service to 100 * each instance of this proxy 101 * @param leaseID identifier assigned to this lease by the 102 * granting entity 103 * @param expiration the time of expiration of the lease being granted 104 * 105 * @return an instance of <code>FiddlerLease</code> that implements 106 * <code>RemoteMethodControl</code> if the given 107 * <code>server</code> does. 108 */ 109 public static FiddlerLease createLease(Fiddler server, 110 Uuid serverID, 111 Uuid registrationID, 112 Uuid leaseID, 113 long expiration) 114 { 115 if(server instanceof RemoteMethodControl) { 116 return new ConstrainableFiddlerLease(server, 117 serverID, 118 registrationID, 119 leaseID, 120 expiration, 121 null);//method constraints 122 } else { 123 return new FiddlerLease(server, 124 serverID, 125 registrationID, 126 leaseID, 127 expiration); 128 }//endif 129 }//end createLease 130 131 /** 132 * Constructs a proxy to the lease the Fiddler implementation of the 133 * lookup discovery service places on a client's requested registration. 134 * The lease corresponding to the constructed proxy will have as its 135 * expiration time, the time input to the <code>expiration</code> 136 * parameter. 137 * 138 * @param server reference to the back-end server of the lookup 139 * discovery service that granted this lease (the 140 * granting entity) 141 * @param serverID the service ID of the service referenced by the 142 * server parameter 143 * @param registrationID unique identifier assigned to the registration 144 * to which this lease corresponds 145 * @param leaseID identifier assigned to this lease by the 146 * granting entity 147 * @param expiration the time of expiration of the lease being granted 148 */ 149 private FiddlerLease(Fiddler server, 150 Uuid serverID, 151 Uuid registrationID, 152 Uuid leaseID, 153 long expiration) 154 { 155 super(expiration); 156 this.server = server; 157 this.serverID = serverID; 158 this.registrationID = registrationID; 159 this.leaseID = leaseID; 160 }//end constructor 161 162 FiddlerLease(GetArg arg) throws IOException { 163 super(check(arg)); 164 this.server = (Fiddler) arg.get("server", null); 165 this.serverID = (Uuid) arg.get("serverID", null); 166 this.registrationID = (Uuid) arg.get("registrationID", null); 167 this.leaseID = (Uuid) arg.get("leaseID", null); 168 } 169 170 private static GetArg check(GetArg arg) throws IOException { 171 check((Fiddler) arg.get("server", null), 172 (Uuid) arg.get("serverID", null), 173 (Uuid) arg.get("registrationID", null)); 174 Object leaseID = arg.get("leaseID", null); 175 if (leaseID == null || leaseID instanceof Uuid){ 176 return arg; 177 } else { 178 throw new InvalidObjectException("leaseID not instanceof Uuid"); 179 } 180 } 181 182 /** 183 * Creates a <code>LeaseMap</code> object that can contain leases whose 184 * renewal or cancellation can be batched. Additionally, upon creating 185 * the map the current lease is placed in the map as a key, and 186 * the value of the <code>duration</code> parameter is placed in 187 * the map as the lease's corresponding mapped value of type 188 * <code>Long</code>. 189 * 190 * @param duration the amount of time (in milliseconds) during which 191 * the lease being placed in the map will remain in 192 * effect. This value will be converted to an instance 193 * of <code>Long</code> prior to being placed in the 194 * map with its associated lease. 195 * the lease in the map. 196 * 197 * @return an instance of <code>LeaseMap</code> that contains as its 198 * first mapping, the ordered pair consisting of this lease 199 * and the value of the <code>duration</code> parameter. 200 * 201 * @see net.jini.core.lease.Lease#createLeaseMap 202 */ 203 public LeaseMap<FiddlerLease,Long> createLeaseMap(long duration) { 204 return FiddlerLeaseMap.createLeaseMap(this, duration); 205 } 206 207 /** 208 * Examines the input parameter to determine if that parameter, along 209 * with the current lease (the current instance of this class), can 210 * be batched in a <code>LeaseMap</code>. 211 * <p> 212 * For this implementation of the service, two leases can be batched 213 * (placed in the same service-specific instance of <code>LeaseMap</code>) 214 * if those leases satisfy the following conditions: 215 * </p><ul> 216 * <li> the leases are the same type; that is, the leases are both 217 * instances of the same, service-specific <code>Lease</code> 218 * implementation 219 * <li> the leases were granted by the same backend server 220 * </ul> 221 * @param lease reference to the <code>Lease</code> object that this 222 * method examines for batching compatibility with the 223 * the current current instance of this class 224 * 225 * @return <code>true</code> if the input parameter is compatible for 226 * batching with the current current instance of this class, 227 * <code>false</code> otherwise 228 * 229 * @see net.jini.core.lease.Lease#canBatch 230 */ 231 public boolean canBatch(Lease lease) { 232 return ( (lease instanceof FiddlerLease) 233 && (serverID.equals(((FiddlerLease)lease).serverID)) ); 234 }//end FiddlerLease.canBatch 235 236 /** 237 * Returns a reference to the back-end server of the lookup discovery 238 * service that granted this lease. 239 * 240 * @return an instance of the Fiddler implementation of the lookup 241 * discovery service. 242 */ 243 Fiddler getServer() { 244 return server; 245 } 246 247 /** 248 * Returns the unique ID associated with the server referenced in this 249 * class. 250 * 251 * @return an instance of the <code>Uuid</code> that contains the 252 * universally unique ID associated with the server referenced 253 * in this class. 254 */ 255 Uuid getServerID() { 256 return serverID; 257 } 258 259 /** 260 * Returns the unique identifier assigned by the lookup discovery 261 * service to the registration to which the current lease corresponds. 262 * 263 * @return a <code>net.jini.id.Uuid</code> value 264 * corresponding to the unique ID assigned to the registration 265 * associated with the current lease. 266 */ 267 Uuid getRegistrationID() { 268 return registrationID; 269 } 270 271 /** 272 * Returns the identifier assigned to the current lease by the entity 273 * that granted it. 274 * 275 * @return a <code>long</code> value corresponding to the ID assigned 276 * to the current lease. 277 */ 278 Uuid getLeaseID() { 279 return leaseID; 280 } 281 282 /** 283 * This method allows the entity to which the current lease is granted 284 * (the lease holder) to indicate that it is no longer interested 285 * in the resources provided to the entity by the lookup discovery 286 * service. When an entity invokes this method, the overall effect 287 * is the same as if the lease expired, except that expiration occurs 288 * immediately instead of at the end of a pre-agreed duration. 289 * 290 * @throws net.jini.core.lease.UnknownLeaseException this exception occurs 291 * when the lease being cancelled is unknown to the lease grantor. 292 * 293 * @throws java.rmi.RemoteException typically, this exception occurs when 294 * there is a communication failure between the client and the 295 * server. When this exception does occur, the lease may or may 296 * not have been cancelled successfully. 297 * 298 * @see net.jini.core.lease.Lease#cancel 299 */ 300 public void cancel() throws UnknownLeaseException, RemoteException { 301 server.cancelLease(registrationID, leaseID); 302 } 303 304 /** 305 * This method allows the entity to which the current lease is granted 306 * (the lease holder) to indicate that it is still interested in the 307 * resources of the lookup discovery service, and to request continued 308 * access to those resources for an amount of time (in milliseconds) 309 * relative to the current time. That is, the duration is not added 310 * added to the current expiration, but is added to the current time. 311 * <p> 312 * Note that the duration of the renewed lease will be no greater than 313 * the requested duration, and may be less than that duration. 314 * 315 * @param duration the requested duration for the lease being renewed 316 * 317 * @return <code>long</code> value representing the actual duration that 318 * was granted for the renewed lease. Note that the actual 319 * duration granted and returned by this method may be less than 320 * the duration requested. 321 * 322 * @throws net.jini.core.lease.UnknownLeaseException this exception occurs 323 * when the lease being renewed does not exist, or is unknown 324 * to the lease grantor; typically because the lease has expired. 325 * 326 * @throws java.rmi.RemoteException typically, this exception occurs when 327 * there is a communication failure between the client and the 328 * server. When this exception does occur, the lease may or may 329 * not have been renewed successfully. 330 * 331 * @see net.jini.core.lease.Lease#renew 332 * @see org.apache.river.lease.AbstractLease#renew 333 * @see org.apache.river.lease.AbstractLease#doRenew 334 */ 335 protected long doRenew(long duration) 336 throws UnknownLeaseException, RemoteException 337 { 338 return server.renewLease(registrationID, leaseID, duration); 339 } 340 341 /** 342 * Returns the universally unique identifier that has been assigned to the 343 * resource this proxy represents. 344 * 345 * @return the instance of <code>Uuid</code> that is associated with the 346 * resource this proxy represents. This method will not return 347 * <code>null</code>. 348 * 349 * @see net.jini.id.ReferentUuid 350 */ 351 public Uuid getReferentUuid() { 352 return leaseID; 353 } 354 355 /** 356 * For any instance of this class, returns the hashcode value generated 357 * by the hashCode method of the lease ID associated with the current 358 * instance of this lease. 359 * 360 * @return <code>int</code> value representing the hashcode for an 361 * instance of this class. 362 */ 363 public int hashCode() { 364 return leaseID.hashCode(); 365 } 366 367 /** 368 * For any instance of this class, indicates whether the object input 369 * to this method is equal to the current instance of this class; where 370 * equality of leases granted by a lookup discovery service is defined by 371 * reference equality. That is, two leases are equal if they reference 372 * (are proxies to) the same backend lease server. 373 * 374 * @param obj reference to the object that is to be compared to the 375 * object on which this method is invoked. 376 * 377 * @return <code>true</code> if the object input is referentially 378 * equal to the object on which this method is invoked; 379 * <code>false</code> otherwise. 380 */ 381 public boolean equals(Object obj) { 382 return ReferentUuids.compare(this,obj); 383 } 384 385 /** When an instance of this class is deserialized, this method is 386 * automatically invoked. This implementation of this method validates 387 * the state of the deserialized instance. 388 * 389 * @throws InvalidObjectException if the state of the 390 * deserialized instance of this class is found to be invalid. 391 */ 392 private void readObject(ObjectInputStream s) 393 throws IOException, ClassNotFoundException 394 { 395 s.defaultReadObject(); 396 check(server, serverID, registrationID); 397 }//end readObject 398 399 private static boolean check(Fiddler server, Uuid serverID, Uuid registrationID) 400 throws InvalidObjectException 401 { 402 /* Verify server */ 403 if(server == null) { 404 throw new InvalidObjectException("FiddlerLease.readObject " 405 +"failure - server " 406 +"field is null"); 407 }//endif 408 /* Verify serverID */ 409 if(serverID == null) { 410 throw new InvalidObjectException("FiddlerLease.readObject " 411 +"failure - serverID " 412 +"field is null"); 413 }//endif 414 /* Verify registrationID */ 415 if(registrationID == null) { 416 throw new InvalidObjectException("FiddlerLease.readObject " 417 +"failure - registrationID " 418 +"field is null"); 419 }//endif 420 return true; 421 } 422 423 /** During deserialization of an instance of this class, if it is found 424 * that the stream contains no data, this method is automatically 425 * invoked. Because it is expected that the stream should always 426 * contain data, this implementation of this method simply declares 427 * that something must be wrong. 428 * 429 * @throws InvalidObjectException to indicate that there 430 * was no data in the stream during deserialization of an 431 * instance of this class; declaring that something is wrong. 432 */ 433 private void readObjectNoData() throws InvalidObjectException { 434 throw new InvalidObjectException("no data found when attempting to " 435 +"deserialize FiddlerLease instance"); 436 }//end readObjectNoData 437 438 public Uuid identity() { 439 return leaseID; 440 } 441 442 void setExpiration(long expiration) { 443 this.expiration = expiration; 444 } 445 446 /** The constrainable version of the class <code>FiddlerLease</code>. 447 * <p> 448 * When a client obtains an instance of this proxy class, the client 449 * should not attempt to use the proxy until the client is assured 450 * that the proxy can be trusted. In addition to implementing the 451 * methods and mechanisms required by <code>RemoteMethodControl</code>, 452 * this class - in conjunction with the service's 453 * <code>ProxyVerifier</code> class, helps provide a mechanism 454 * for verifying trust in the proxy on behalf of a client. 455 * <p> 456 * In order to verify that an instance of this class is trusted, 457 * trust must be verified in all subsidiary objects (contained in that 458 * instance) through which the client ultimately makes calls (local or 459 * remote). With respect to this class, the <code>server</code> field 460 * is a proxy object through which the client makes remote calls to the 461 * service's backend. Therefore, trust in that object must be 462 * verified. Additionally, this class also contains a field of type 463 * <code>Uuid</code> (<code>registrationID</code> which should be 464 * tested for trust. Consider the following diagram: 465 * <p> 466 * <pre> 467 * FiddlerLease { 468 * Fiddler server 469 * Uuid registrationID 470 * }//end FiddlerLease 471 * </pre> 472 * <p> 473 * Thus, in order to verify that an instance of this class is trusted, 474 * trust must be verified in the following objects from the diagram 475 * above: 476 * <ul><li> server 477 * <li> registrationID 478 * </ul> 479 * 480 * When a client obtains an instance of this proxy class, the 481 * deserialization process which delivers the proxy to the client 482 * invokes the <code>readObject</code> method of this class. Part of 483 * trust verification is performed in the <code>readObject</code> method, 484 * and part is performed when the client prepares the proxy. Thus, this 485 * class' participation in the trust verification process can be 486 * summarized as follows: 487 * <p> 488 * <ul> 489 * <li> server 490 * <ul> 491 * <li> readObject 492 * <ul> 493 * <li> verify server != null 494 * <li> verify server implements RemoteMethodControl 495 * <li> verify server's method constraints are the same 496 * as those placed on the corresponding public Remote 497 * methods of its outer proxy class 498 * </ul> 499 * <li> proxy preparation 500 * <ul> 501 * <li> Security.verifyObjectTrust() which calls 502 * <li> ProxyVerifier.isTrustedObject() which calls 503 * <li> canonicalServerObject.checkTrustEquivalence(server) 504 * (whose implementation is supplied by the particular 505 * RMI implementation that was used to export the server) 506 * </ul> 507 * </ul> 508 * <li> registrationID 509 * <ul><li> readObject 510 * <ul><li> verify registrationID != null</ul> 511 * </ul> 512 * </ul> 513 * 514 * @since 2.0 515 */ 516 @AtomicSerial 517 static final class ConstrainableFiddlerLease extends FiddlerLease 518 implements RemoteMethodControl, ID<Uuid> 519 { 520 static final long serialVersionUID = 2L; 521 522 /* Convenience fields containing, respectively, the renew and cancel 523 * methods defined in the Lease interface. These fields are used in 524 * the method mapping array, and when retrieving method constraints 525 * for comparison in canBatch(). 526 */ 527 private static final Method renewMethod = 528 ProxyUtil.getMethod(Lease.class, 529 "renew", 530 new Class[] {long.class} ); 531 private static final Method cancelMethod = 532 ProxyUtil.getMethod(Lease.class, 533 "cancel", 534 new Class[] {} ); 535 536 /** Array containing element pairs in which each pair of elements 537 * represents a correspondence 'mapping' between two methods having 538 * the following characteristics: 539 * - the first element in the pair is one of the public, remote 540 * method(s) that may be invoked by the client through the proxy 541 * class that this class extends 542 * - the second element in the pair is the method, implemented 543 * in the backend server class, that is ultimately executed in 544 * the server's backend when the client invokes the corresponding 545 * method in this proxy 546 */ 547 private static final Method[] methodMapArray = 548 { 549 renewMethod, ProxyUtil.getMethod(Fiddler.class, 550 "renewLease", 551 new Class[] {Uuid.class, 552 Uuid.class, 553 long.class} ), 554 555 cancelMethod, ProxyUtil.getMethod(Fiddler.class, 556 "cancelLease", 557 new Class[] {Uuid.class, 558 Uuid.class} ) 559 };//end methodMapArray 560 561 /** In order to determine if this lease can be batched with another 562 * given lease, the method <code>canBatch</code> must verify that 563 * the corresponding methods of each lease have equivalent 564 * constraints. The array defined here contains the set of methods 565 * whose constraints will be compared in <code>canBatch</code>. 566 */ 567 private static final Method[] canBatchMethodMapArray = 568 { renewMethod, renewMethod, 569 cancelMethod, cancelMethod 570 };//end canBatchMethodMapArray 571 572 /** Client constraints placed on this proxy (may be <code>null</code>). 573 * 574 * @serial 575 */ 576 private MethodConstraints methodConstraints; 577 578 /** Constructs a new <code>ConstrainableFiddlerLease</code> instance. 579 * <p> 580 * For a description of all but the <code>methodConstraints</code> 581 * argument (provided below), refer to the description for the 582 * constructor of this class' super class. 583 * 584 * @param methodConstraints the client method constraints to place on 585 * this proxy (may be <code>null</code>). 586 */ 587 private ConstrainableFiddlerLease(Fiddler server, 588 Uuid serverID, 589 Uuid registrationID, 590 Uuid leaseID, 591 long expiration, 592 MethodConstraints methodConstraints) 593 { 594 super( constrainServer(server, methodConstraints), 595 serverID, registrationID, leaseID, expiration ); 596 this.methodConstraints = methodConstraints; 597 }//end constructor 598 599 /** 600 * {@link AtomicSerial} constructor. 601 * @param arg 602 * @throws IOException 603 */ 604 ConstrainableFiddlerLease(GetArg arg) throws IOException { 605 super(check(arg)); 606 this.methodConstraints 607 = (MethodConstraints) arg.get("methodConstraints", null); 608 } 609 610 private static GetArg check(GetArg arg) throws IOException{ 611 FiddlerLease fl = new FiddlerLease(arg); 612 MethodConstraints methodConstraints 613 = (MethodConstraints) arg.get("methodConstraints", null); 614 ConstrainableProxyUtil.verifyConsistentConstraints 615 (methodConstraints, 616 fl.server, 617 methodMapArray); 618 return arg; 619 } 620 621 /** 622 * Examines the input parameter to determine if that parameter, along 623 * with the current lease (the current instance of this class), can 624 * be batched in a <code>LeaseMap</code>. 625 * <p> 626 * For this implementation of the service, two leases can be 627 * batched (placed in the same service-specific instance of 628 * <code>LeaseMap</code>) if those leases satisfy the following 629 * conditions: 630 * <p><ul> 631 * <li> the leases are the same type; that is, the leases are 632 * both instances of the same, constrainable, service-specific 633 * <code>Lease</code> implementation 634 * <li> the leases were granted by the same backend server 635 * <li> the leases have the same constraints 636 * 637 * @param lease reference to the <code>Lease</code> object that this 638 * method examines for batching compatibility with the 639 * the current instance of this class 640 * 641 * @return <code>true</code> if the input parameter is compatible for 642 * batching with the current instance of this class, 643 * <code>false</code> otherwise 644 * 645 * @see net.jini.core.lease.Lease#canBatch 646 */ 647 public boolean canBatch(Lease lease) { 648 if( !(super.canBatch(lease)) ) return false; 649 /* Non-constrainable batch criteria satisfied, now handle 650 * constrainable case. 651 */ 652 if( !(lease instanceof ConstrainableFiddlerLease) ) return false; 653 /* Compare constraints */ 654 return ConstrainableProxyUtil.equivalentConstraints 655 ( methodConstraints, 656 ((ConstrainableFiddlerLease)lease).methodConstraints, 657 canBatchMethodMapArray ); 658 }//end ConstrainableFiddlerLease.canBatch 659 660 /** Returns a copy of the given server proxy having the client method 661 * constraints that result after the specified method mapping is 662 * applied to the given client method constraints. 663 */ 664 private static Fiddler constrainServer( Fiddler server, 665 MethodConstraints constraints ) 666 { 667 MethodConstraints newConstraints 668 = ConstrainableProxyUtil.translateConstraints(constraints, 669 methodMapArray); 670 RemoteMethodControl constrainedServer = 671 ((RemoteMethodControl)server).setConstraints(newConstraints); 672 673 return ((Fiddler)constrainedServer); 674 }//end constrainServer 675 676 /** Returns a new copy of this proxy class 677 * (<code>ConstrainableFiddlerLease</code>) with its client 678 * constraints set to the specified constraints. A <code>null</code> 679 * value is interpreted as mapping all methods to empty constraints. 680 */ 681 public RemoteMethodControl setConstraints 682 (MethodConstraints constraints) 683 { 684 return (new ConstrainableFiddlerLease(server, 685 serverID, 686 registrationID, 687 leaseID, 688 expiration, 689 constraints)); 690 }//end setConstraints 691 692 /** Returns the client constraints placed on the current instance 693 * of this proxy class (<code>ConstrainableFiddlerLease</code>). 694 * The value returned by this method can be <code>null</code>, 695 * which is interpreted as mapping all methods to empty constraints. 696 */ 697 public MethodConstraints getConstraints() { 698 return methodConstraints; 699 }//end getConstraints 700 701 /** Returns a proxy trust iterator that is used in 702 * <code>ProxyTrustVerifier</code> to retrieve this object's 703 * trust verifier. 704 */ 705 private ProxyTrustIterator getProxyTrustIterator() { 706 return new SingletonProxyTrustIterator(server); 707 }//end getProxyTrustIterator 708 709 /** Performs various functions related to the trust verification 710 * process for the current instance of this proxy class, as 711 * detailed in the description for this class. 712 * 713 * @throws <code>InvalidObjectException</code> if any of the 714 * requirements for trust verification (as detailed in the 715 * class description) are not satisfied. 716 */ 717 private void readObject(ObjectInputStream s) 718 throws IOException, ClassNotFoundException 719 { 720 /* Note that basic validation of the fields of this class was 721 * already performed in the readObject() method of this class' 722 * super class. 723 */ 724 s.defaultReadObject(); 725 /* Verify the server and its constraints */ 726 ConstrainableProxyUtil.verifyConsistentConstraints 727 (methodConstraints, 728 server, 729 methodMapArray); 730 }//end readObject 731 732 public void setExpiration(long expiration) { 733 synchronized (this) { 734 this.expiration = expiration; 735 } 736 } 737 738 }//end class ConstrainableFiddlerLease 739 740 }//end class FiddlerLease