1 /* 2 * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.print.attribute; 27 28 import java.io.Serial; 29 import java.io.Serializable; 30 31 /** 32 * Class {@code AttributeSetUtilities} provides static methods for manipulating 33 * {@code AttributeSets}. 34 * <ul> 35 * <li>Methods for creating unmodifiable and synchronized views of attribute 36 * sets. 37 * <li>operations useful for building implementations of interface 38 * {@link AttributeSet AttributeSet} 39 * </ul> 40 * An <b>unmodifiable view</b> <i>U</i> of an {@code AttributeSet} <i>S</i> 41 * provides a client with "read-only" access to <i>S</i>. Query operations on 42 * <i>U</i> "read through" to <i>S</i>; thus, changes in <i>S</i> are reflected 43 * in <i>U</i>. However, any attempt to modify <i>U</i>, results in an 44 * {@code UnmodifiableSetException}. The unmodifiable view object <i>U</i> will 45 * be serializable if the attribute set object <i>S</i> is serializable. 46 * <p> 47 * A <b>synchronized view</b> <i>V</i> of an attribute set <i>S</i> provides a 48 * client with synchronized (multiple thread safe) access to <i>S</i>. Each 49 * operation of <i>V</i> is synchronized using <i>V</i> itself as the lock 50 * object and then merely invokes the corresponding operation of <i>S</i>. In 51 * order to guarantee mutually exclusive access, it is critical that all access 52 * to <i>S</i> is accomplished through <i>V</i>. The synchronized view object 53 * <i>V</i> will be serializable if the attribute set object <i>S</i> is 54 * serializable. 55 * <p> 56 * As mentioned in the package description of {@code javax.print}, a 57 * {@code null} reference parameter to methods is incorrect unless explicitly 58 * documented on the method as having a meaningful interpretation. Usage to the 59 * contrary is incorrect coding and may result in a run time exception either 60 * immediately or at some later time. {@code IllegalArgumentException} and 61 * {@code NullPointerException} are examples of typical and acceptable run time 62 * exceptions for such cases. 63 * 64 * @author Alan Kaminsky 65 */ 66 public final class AttributeSetUtilities { 67 68 /** 69 * Suppress default constructor, ensuring non-instantiability. 70 */ AttributeSetUtilities()71 private AttributeSetUtilities() { 72 } 73 74 /** 75 * Unmodifiable view of {@code AttributeSet}. 76 * 77 * @serial include 78 */ 79 private static class UnmodifiableAttributeSet 80 implements AttributeSet, Serializable { 81 82 /** 83 * Use serialVersionUID from JDK 1.4 for interoperability. 84 */ 85 @Serial 86 private static final long serialVersionUID = -6131802583863447813L; 87 88 /** 89 * The attribute set. 90 */ 91 @SuppressWarnings("serial") // Not statically typed as Serializable 92 private AttributeSet attrset; 93 94 /** 95 * Constructs unmodifiable view of the underlying attribute set. 96 * 97 * @param attributeSet the attribute set 98 */ UnmodifiableAttributeSet(AttributeSet attributeSet)99 public UnmodifiableAttributeSet(AttributeSet attributeSet) { 100 101 attrset = attributeSet; 102 } 103 get(Class<?> key)104 public Attribute get(Class<?> key) { 105 return attrset.get(key); 106 } 107 add(Attribute attribute)108 public boolean add(Attribute attribute) { 109 throw new UnmodifiableSetException(); 110 } 111 remove(Class<?> category)112 public synchronized boolean remove(Class<?> category) { 113 throw new UnmodifiableSetException(); 114 } 115 remove(Attribute attribute)116 public boolean remove(Attribute attribute) { 117 throw new UnmodifiableSetException(); 118 } 119 containsKey(Class<?> category)120 public boolean containsKey(Class<?> category) { 121 return attrset.containsKey(category); 122 } 123 containsValue(Attribute attribute)124 public boolean containsValue(Attribute attribute) { 125 return attrset.containsValue(attribute); 126 } 127 addAll(AttributeSet attributes)128 public boolean addAll(AttributeSet attributes) { 129 throw new UnmodifiableSetException(); 130 } 131 size()132 public int size() { 133 return attrset.size(); 134 } 135 toArray()136 public Attribute[] toArray() { 137 return attrset.toArray(); 138 } 139 clear()140 public void clear() { 141 throw new UnmodifiableSetException(); 142 } 143 isEmpty()144 public boolean isEmpty() { 145 return attrset.isEmpty(); 146 } 147 equals(Object o)148 public boolean equals(Object o) { 149 return attrset.equals (o); 150 } 151 hashCode()152 public int hashCode() { 153 return attrset.hashCode(); 154 } 155 } 156 157 /** 158 * Unmodifiable view of {@code DocAttributeSet}. 159 * 160 * @serial include 161 */ 162 private static class UnmodifiableDocAttributeSet 163 extends UnmodifiableAttributeSet 164 implements DocAttributeSet, Serializable { 165 166 /** 167 * Use serialVersionUID from JDK 1.4 for interoperability. 168 */ 169 @Serial 170 private static final long serialVersionUID = -6349408326066898956L; 171 172 /** 173 * Constructs a new unmodifiable doc attribute set. 174 * 175 * @param attributeSet the doc attribute set 176 */ UnmodifiableDocAttributeSet(DocAttributeSet attributeSet)177 public UnmodifiableDocAttributeSet(DocAttributeSet attributeSet) { 178 179 super (attributeSet); 180 } 181 } 182 183 /** 184 * Unmodifiable view of {@code PrintRequestAttributeSet}. 185 * 186 * @serial include 187 */ 188 private static class UnmodifiablePrintRequestAttributeSet 189 extends UnmodifiableAttributeSet 190 implements PrintRequestAttributeSet, Serializable 191 { 192 193 /** 194 * Use serialVersionUID from JDK 1.4 for interoperability. 195 */ 196 @Serial 197 private static final long serialVersionUID = 7799373532614825073L; 198 199 /** 200 * Constructs a new unmodifiable print request attribute set. 201 * 202 * @param attributeSet the print request attribute set 203 */ UnmodifiablePrintRequestAttributeSet(PrintRequestAttributeSet attributeSet)204 public UnmodifiablePrintRequestAttributeSet 205 (PrintRequestAttributeSet attributeSet) { 206 207 super (attributeSet); 208 } 209 } 210 211 /** 212 * Unmodifiable view of {@code PrintJobAttributeSet}. 213 * 214 * @serial include 215 */ 216 private static class UnmodifiablePrintJobAttributeSet 217 extends UnmodifiableAttributeSet 218 implements PrintJobAttributeSet, Serializable 219 { 220 /** 221 * Use serialVersionUID from JDK 1.4 for interoperability. 222 */ 223 @Serial 224 private static final long serialVersionUID = -8002245296274522112L; 225 226 /** 227 * Constructs a new unmodifiable print job attribute set. 228 * 229 * @param attributeSet the print job attribute set 230 */ UnmodifiablePrintJobAttributeSet(PrintJobAttributeSet attributeSet)231 public UnmodifiablePrintJobAttributeSet 232 (PrintJobAttributeSet attributeSet) { 233 234 super (attributeSet); 235 } 236 } 237 238 /** 239 * Unmodifiable view of {@code PrintServiceAttributeSet}. 240 * 241 * @serial include 242 */ 243 private static class UnmodifiablePrintServiceAttributeSet 244 extends UnmodifiableAttributeSet 245 implements PrintServiceAttributeSet, Serializable 246 { 247 /** 248 * Use serialVersionUID from JDK 1.4 for interoperability. 249 */ 250 @Serial 251 private static final long serialVersionUID = -7112165137107826819L; 252 253 /** 254 * Constructs a new unmodifiable print service attribute set. 255 * 256 * @param attributeSet the print service attribute set 257 */ UnmodifiablePrintServiceAttributeSet(PrintServiceAttributeSet attributeSet)258 public UnmodifiablePrintServiceAttributeSet 259 (PrintServiceAttributeSet attributeSet) { 260 261 super (attributeSet); 262 } 263 } 264 265 /** 266 * Creates an unmodifiable view of the given attribute set. 267 * 268 * @param attributeSet underlying attribute set 269 * @return unmodifiable view of {@code attributeSet} 270 * @throws NullPointerException if {@code attributeSet} is {@code null} 271 */ unmodifiableView(AttributeSet attributeSet)272 public static AttributeSet unmodifiableView(AttributeSet attributeSet) { 273 if (attributeSet == null) { 274 throw new NullPointerException(); 275 } 276 277 return new UnmodifiableAttributeSet(attributeSet); 278 } 279 280 /** 281 * Creates an unmodifiable view of the given doc attribute set. 282 * 283 * @param attributeSet underlying doc attribute set 284 * @return unmodifiable view of {@code attributeSet} 285 * @throws NullPointerException if {@code attributeSet} is {@code null} 286 */ unmodifiableView(DocAttributeSet attributeSet)287 public static DocAttributeSet unmodifiableView 288 (DocAttributeSet attributeSet) { 289 if (attributeSet == null) { 290 throw new NullPointerException(); 291 } 292 return new UnmodifiableDocAttributeSet(attributeSet); 293 } 294 295 /** 296 * Creates an unmodifiable view of the given print request attribute set. 297 * 298 * @param attributeSet underlying print request attribute set 299 * @return unmodifiable view of {@code attributeSet} 300 * @throws NullPointerException if {@code attributeSet} is {@code null} 301 */ 302 public static PrintRequestAttributeSet unmodifiableView(PrintRequestAttributeSet attributeSet)303 unmodifiableView(PrintRequestAttributeSet attributeSet) { 304 if (attributeSet == null) { 305 throw new NullPointerException(); 306 } 307 return new UnmodifiablePrintRequestAttributeSet(attributeSet); 308 } 309 310 /** 311 * Creates an unmodifiable view of the given print job attribute set. 312 * 313 * @param attributeSet underlying print job attribute set 314 * @return unmodifiable view of {@code attributeSet} 315 * @throws NullPointerException if {@code attributeSet} is {@code null} 316 */ 317 public static PrintJobAttributeSet unmodifiableView(PrintJobAttributeSet attributeSet)318 unmodifiableView(PrintJobAttributeSet attributeSet) { 319 if (attributeSet == null) { 320 throw new NullPointerException(); 321 } 322 return new UnmodifiablePrintJobAttributeSet(attributeSet); 323 } 324 325 /** 326 * Creates an unmodifiable view of the given print service attribute set. 327 * 328 * @param attributeSet underlying print service attribute set 329 * @return unmodifiable view of {@code attributeSet} 330 * @throws NullPointerException if {@code attributeSet} is {@code null} 331 */ 332 public static PrintServiceAttributeSet unmodifiableView(PrintServiceAttributeSet attributeSet)333 unmodifiableView(PrintServiceAttributeSet attributeSet) { 334 if (attributeSet == null) { 335 throw new NullPointerException(); 336 } 337 return new UnmodifiablePrintServiceAttributeSet (attributeSet); 338 } 339 340 /** 341 * Synchronized view of {@code AttributeSet}. 342 * 343 * @serial include 344 */ 345 private static class SynchronizedAttributeSet 346 implements AttributeSet, Serializable { 347 348 /** 349 * Use serialVersionUID from JDK 1.4 for interoperability. 350 */ 351 @Serial 352 private static final long serialVersionUID = 8365731020128564925L; 353 354 /** 355 * The attribute set. 356 */ 357 @SuppressWarnings("serial") // Not statically typed as Serializable 358 private AttributeSet attrset; 359 360 /** 361 * Constructs a new synchronized attribute set. 362 * 363 * @param attributeSet the attribute set 364 */ SynchronizedAttributeSet(AttributeSet attributeSet)365 public SynchronizedAttributeSet(AttributeSet attributeSet) { 366 attrset = attributeSet; 367 } 368 get(Class<?> category)369 public synchronized Attribute get(Class<?> category) { 370 return attrset.get(category); 371 } 372 add(Attribute attribute)373 public synchronized boolean add(Attribute attribute) { 374 return attrset.add(attribute); 375 } 376 remove(Class<?> category)377 public synchronized boolean remove(Class<?> category) { 378 return attrset.remove(category); 379 } 380 remove(Attribute attribute)381 public synchronized boolean remove(Attribute attribute) { 382 return attrset.remove(attribute); 383 } 384 containsKey(Class<?> category)385 public synchronized boolean containsKey(Class<?> category) { 386 return attrset.containsKey(category); 387 } 388 containsValue(Attribute attribute)389 public synchronized boolean containsValue(Attribute attribute) { 390 return attrset.containsValue(attribute); 391 } 392 addAll(AttributeSet attributes)393 public synchronized boolean addAll(AttributeSet attributes) { 394 return attrset.addAll(attributes); 395 } 396 size()397 public synchronized int size() { 398 return attrset.size(); 399 } 400 toArray()401 public synchronized Attribute[] toArray() { 402 return attrset.toArray(); 403 } 404 clear()405 public synchronized void clear() { 406 attrset.clear(); 407 } 408 isEmpty()409 public synchronized boolean isEmpty() { 410 return attrset.isEmpty(); 411 } 412 equals(Object o)413 public synchronized boolean equals(Object o) { 414 return attrset.equals (o); 415 } 416 hashCode()417 public synchronized int hashCode() { 418 return attrset.hashCode(); 419 } 420 } 421 422 /** 423 * Synchronized view of {@code DocAttributeSet}. 424 * 425 * @serial include 426 */ 427 private static class SynchronizedDocAttributeSet 428 extends SynchronizedAttributeSet 429 implements DocAttributeSet, Serializable { 430 431 /** 432 * Use serialVersionUID from JDK 1.4 for interoperability. 433 */ 434 @Serial 435 private static final long serialVersionUID = 6455869095246629354L; 436 437 /** 438 * Constructs a new synchronized doc attribute set. 439 * 440 * @param attributeSet the doc attribute set 441 */ SynchronizedDocAttributeSet(DocAttributeSet attributeSet)442 public SynchronizedDocAttributeSet(DocAttributeSet attributeSet) { 443 super(attributeSet); 444 } 445 } 446 447 /** 448 * Synchronized view of {@code PrintRequestAttributeSet}. 449 * 450 * @serial include 451 */ 452 private static class SynchronizedPrintRequestAttributeSet 453 extends SynchronizedAttributeSet 454 implements PrintRequestAttributeSet, Serializable { 455 456 /** 457 * Use serialVersionUID from JDK 1.4 for interoperability. 458 */ 459 @Serial 460 private static final long serialVersionUID = 5671237023971169027L; 461 462 /** 463 * Constructs a new synchronized print request attribute set. 464 * 465 * @param attributeSet the print request attribute set 466 */ SynchronizedPrintRequestAttributeSet(PrintRequestAttributeSet attributeSet)467 public SynchronizedPrintRequestAttributeSet 468 (PrintRequestAttributeSet attributeSet) { 469 super(attributeSet); 470 } 471 } 472 473 /** 474 * Synchronized view of {@code PrintJobAttributeSet}. 475 * 476 * @serial include 477 */ 478 private static class SynchronizedPrintJobAttributeSet 479 extends SynchronizedAttributeSet 480 implements PrintJobAttributeSet, Serializable { 481 482 /** 483 * Use serialVersionUID from JDK 1.4 for interoperability. 484 */ 485 @Serial 486 private static final long serialVersionUID = 2117188707856965749L; 487 488 /** 489 * Constructs a new synchronized print job attribute set. 490 * 491 * @param attributeSet the print job attribute set 492 */ SynchronizedPrintJobAttributeSet(PrintJobAttributeSet attributeSet)493 public SynchronizedPrintJobAttributeSet 494 (PrintJobAttributeSet attributeSet) { 495 super(attributeSet); 496 } 497 } 498 499 /** 500 * Synchronized view of {@code PrintServiceAttributeSet}. 501 * 502 * @serial include 503 */ 504 private static class SynchronizedPrintServiceAttributeSet 505 extends SynchronizedAttributeSet 506 implements PrintServiceAttributeSet, Serializable { 507 508 /** 509 * Use serialVersionUID from JDK 1.4 for interoperability. 510 */ 511 @Serial 512 private static final long serialVersionUID = -2830705374001675073L; 513 514 /** 515 * Constructs a new synchronized print service attribute set. 516 * 517 * @param attributeSet the print service attribute set 518 */ SynchronizedPrintServiceAttributeSet(PrintServiceAttributeSet attributeSet)519 public SynchronizedPrintServiceAttributeSet 520 (PrintServiceAttributeSet attributeSet) { 521 super(attributeSet); 522 } 523 } 524 525 /** 526 * Creates a synchronized view of the given attribute set. 527 * 528 * @param attributeSet underlying attribute set 529 * @return synchronized view of {@code attributeSet} 530 * @throws NullPointerException if {@code attributeSet} is {@code null} 531 */ synchronizedView(AttributeSet attributeSet)532 public static AttributeSet synchronizedView 533 (AttributeSet attributeSet) { 534 if (attributeSet == null) { 535 throw new NullPointerException(); 536 } 537 return new SynchronizedAttributeSet(attributeSet); 538 } 539 540 /** 541 * Creates a synchronized view of the given doc attribute set. 542 * 543 * @param attributeSet underlying doc attribute set 544 * @return synchronized view of {@code attributeSet} 545 * @throws NullPointerException if {@code attributeSet} is {@code null} 546 */ 547 public static DocAttributeSet synchronizedView(DocAttributeSet attributeSet)548 synchronizedView(DocAttributeSet attributeSet) { 549 if (attributeSet == null) { 550 throw new NullPointerException(); 551 } 552 return new SynchronizedDocAttributeSet(attributeSet); 553 } 554 555 /** 556 * Creates a synchronized view of the given print request attribute set. 557 * 558 * @param attributeSet underlying print request attribute set 559 * @return synchronized view of {@code attributeSet} 560 * @throws NullPointerException if {@code attributeSet} is {@code null} 561 */ 562 public static PrintRequestAttributeSet synchronizedView(PrintRequestAttributeSet attributeSet)563 synchronizedView(PrintRequestAttributeSet attributeSet) { 564 if (attributeSet == null) { 565 throw new NullPointerException(); 566 } 567 return new SynchronizedPrintRequestAttributeSet(attributeSet); 568 } 569 570 /** 571 * Creates a synchronized view of the given print job attribute set. 572 * 573 * @param attributeSet underlying print job attribute set 574 * @return synchronized view of {@code attributeSet} 575 * @throws NullPointerException if {@code attributeSet} is {@code null} 576 */ 577 public static PrintJobAttributeSet synchronizedView(PrintJobAttributeSet attributeSet)578 synchronizedView(PrintJobAttributeSet attributeSet) { 579 if (attributeSet == null) { 580 throw new NullPointerException(); 581 } 582 return new SynchronizedPrintJobAttributeSet(attributeSet); 583 } 584 585 /** 586 * Creates a synchronized view of the given print service attribute set. 587 * 588 * @param attributeSet underlying print service attribute set 589 * @return synchronized view of {@code attributeSet} 590 * @throws NullPointerException if {@code attributeSet} is {@code null} 591 */ 592 public static PrintServiceAttributeSet synchronizedView(PrintServiceAttributeSet attributeSet)593 synchronizedView(PrintServiceAttributeSet attributeSet) { 594 if (attributeSet == null) { 595 throw new NullPointerException(); 596 } 597 return new SynchronizedPrintServiceAttributeSet(attributeSet); 598 } 599 600 /** 601 * Verify that the given object is a {@link Class Class} that implements the 602 * given interface, which is assumed to be interface 603 * {@link Attribute Attribute} or a subinterface thereof. 604 * 605 * @param object {@code Object} to test 606 * @param interfaceName interface the object must implement 607 * @return if {@code object} is a {@link Class Class} that implements 608 * {@code interfaceName}, {@code object} is returned downcast to 609 * type {@link Class Class}; otherwise an exception is thrown 610 * @throws NullPointerException if {@code object} is {@code null} 611 * @throws ClassCastException if {@code object} is not a 612 * {@link Class Class} that implements {@code interfaceName} 613 */ 614 public static Class<?> verifyAttributeCategory(Object object, Class<?> interfaceName)615 verifyAttributeCategory(Object object, Class<?> interfaceName) { 616 617 Class<?> result = (Class<?>) object; 618 if (interfaceName.isAssignableFrom (result)) { 619 return result; 620 } 621 else { 622 throw new ClassCastException(); 623 } 624 } 625 626 /** 627 * Verify that the given object is an instance of the given interface, which 628 * is assumed to be interface {@link Attribute Attribute} or a subinterface 629 * thereof. 630 * 631 * @param object {@code Object} to test 632 * @param interfaceName interface of which the object must be an instance 633 * @return if {@code object} is an instance of {@code interfaceName}, 634 * {@code object} is returned downcast to type 635 * {@link Attribute Attribute}; otherwise an exception is thrown 636 * @throws NullPointerException if {@code object} is {@code null} 637 * @throws ClassCastException if {@code object} is not an instance of 638 * {@code interfaceName} 639 */ 640 public static Attribute verifyAttributeValue(Object object, Class<?> interfaceName)641 verifyAttributeValue(Object object, Class<?> interfaceName) { 642 643 if (object == null) { 644 throw new NullPointerException(); 645 } 646 else if (interfaceName.isInstance (object)) { 647 return (Attribute) object; 648 } else { 649 throw new ClassCastException(); 650 } 651 } 652 653 /** 654 * Verify that the given attribute category object is equal to the category 655 * of the given attribute value object. If so, this method returns doing 656 * nothing. If not, this method throws an exception. 657 * 658 * @param category attribute category to test 659 * @param attribute attribute value to test 660 * @throws NullPointerException if the {@code category} or {@code attribute} 661 * are {@code null} 662 * @throws IllegalArgumentException if the {@code category} is not equal to 663 * the category of the {@code attribute} 664 */ 665 public static void verifyCategoryForValue(Class<?> category, Attribute attribute)666 verifyCategoryForValue(Class<?> category, Attribute attribute) { 667 668 if (!category.equals (attribute.getCategory())) { 669 throw new IllegalArgumentException(); 670 } 671 } 672 } 673