23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package java.security; |
26 package java.security; |
27 |
27 |
28 import java.lang.ref.Reference; |
|
29 import java.lang.ref.ReferenceQueue; |
|
30 import java.lang.ref.SoftReference; |
|
31 import java.lang.ref.WeakReference; |
|
32 import java.util.ArrayList; |
28 import java.util.ArrayList; |
|
29 import java.util.Collections; |
33 import java.util.Enumeration; |
30 import java.util.Enumeration; |
34 import java.util.List; |
31 import java.util.List; |
|
32 import java.util.Map; |
35 import java.util.Objects; |
33 import java.util.Objects; |
36 import java.util.concurrent.ConcurrentHashMap; |
34 import java.util.WeakHashMap; |
37 import jdk.internal.misc.JavaSecurityAccess; |
35 import jdk.internal.misc.JavaSecurityAccess; |
38 import jdk.internal.misc.JavaSecurityProtectionDomainAccess; |
36 import jdk.internal.misc.JavaSecurityProtectionDomainAccess; |
39 import static jdk.internal.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache; |
37 import static jdk.internal.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache; |
40 import jdk.internal.misc.SharedSecrets; |
38 import jdk.internal.misc.SharedSecrets; |
41 import sun.security.action.GetPropertyAction; |
39 import sun.security.action.GetPropertyAction; |
113 return new AccessControlContext(stack.getContext(), acc).optimize(); |
111 return new AccessControlContext(stack.getContext(), acc).optimize(); |
114 } |
112 } |
115 } |
113 } |
116 |
114 |
117 static { |
115 static { |
118 // setup SharedSecrets to allow access to doIntersectionPrivilege |
116 // Set up JavaSecurityAccess in SharedSecrets |
119 // methods and ProtectionDomain cache |
|
120 SharedSecrets.setJavaSecurityAccess(new JavaSecurityAccessImpl()); |
117 SharedSecrets.setJavaSecurityAccess(new JavaSecurityAccessImpl()); |
121 SharedSecrets.setJavaSecurityProtectionDomainAccess( |
118 } |
122 new JavaSecurityProtectionDomainAccess() { |
|
123 @Override |
|
124 public ProtectionDomainCache getProtectionDomainCache() { |
|
125 return new PDCache(); |
|
126 } |
|
127 }); |
|
128 } |
|
129 |
|
130 /** |
|
131 * Used for storing ProtectionDomains as keys in a Map. |
|
132 */ |
|
133 static final class Key {} |
|
134 |
119 |
135 /* CodeSource */ |
120 /* CodeSource */ |
136 private CodeSource codesource ; |
121 private CodeSource codesource ; |
137 |
122 |
138 /* ClassLoader the protection domain was consed from */ |
123 /* ClassLoader the protection domain was consed from */ |
569 |
554 |
570 return mergedPerms; |
555 return mergedPerms; |
571 } |
556 } |
572 |
557 |
573 /** |
558 /** |
574 * A cache of ProtectionDomains and their Permissions. |
559 * Used for storing ProtectionDomains as keys in a Map. |
575 * |
560 */ |
576 * This class stores ProtectionDomains as weak keys in a ConcurrentHashMap |
561 final class Key {} |
577 * with additional support for checking and removing weak keys that are no |
562 |
578 * longer in use. There can be cases where the permission collection may |
563 static { |
579 * have a chain of strong references back to the ProtectionDomain, which |
564 SharedSecrets.setJavaSecurityProtectionDomainAccess( |
580 * ordinarily would prevent the entry from being removed from the map. To |
565 new JavaSecurityProtectionDomainAccess() { |
581 * address that, we wrap the permission collection in a SoftReference so |
566 public ProtectionDomainCache getProtectionDomainCache() { |
582 * that it can be reclaimed by the garbage collector due to memory demand. |
567 return new ProtectionDomainCache() { |
583 */ |
568 private final Map<Key, PermissionCollection> map = |
584 private static class PDCache implements ProtectionDomainCache { |
569 Collections.synchronizedMap |
585 private final ConcurrentHashMap<WeakProtectionDomainKey, |
570 (new WeakHashMap<Key, PermissionCollection>()); |
586 SoftReference<PermissionCollection>> |
571 public void put(ProtectionDomain pd, |
587 pdMap = new ConcurrentHashMap<>(); |
572 PermissionCollection pc) { |
588 private final ReferenceQueue<Key> queue = new ReferenceQueue<>(); |
573 map.put((pd == null ? null : pd.key), pc); |
589 |
574 } |
590 @Override |
575 public PermissionCollection get(ProtectionDomain pd) { |
591 public void put(ProtectionDomain pd, PermissionCollection pc) { |
576 return pd == null ? map.get(null) : map.get(pd.key); |
592 processQueue(queue, pdMap); |
577 } |
593 WeakProtectionDomainKey weakPd = |
578 }; |
594 new WeakProtectionDomainKey(pd, queue); |
579 } |
595 pdMap.put(weakPd, new SoftReference<>(pc)); |
580 }); |
596 } |
|
597 |
|
598 @Override |
|
599 public PermissionCollection get(ProtectionDomain pd) { |
|
600 processQueue(queue, pdMap); |
|
601 WeakProtectionDomainKey weakPd = new WeakProtectionDomainKey(pd); |
|
602 SoftReference<PermissionCollection> sr = pdMap.get(weakPd); |
|
603 return (sr == null) ? null : sr.get(); |
|
604 } |
|
605 |
|
606 /** |
|
607 * Removes weak keys from the map that have been enqueued |
|
608 * on the reference queue and are no longer in use. |
|
609 */ |
|
610 private static void processQueue(ReferenceQueue<Key> queue, |
|
611 ConcurrentHashMap<? extends |
|
612 WeakReference<Key>, ?> pdMap) { |
|
613 Reference<? extends Key> ref; |
|
614 while ((ref = queue.poll()) != null) { |
|
615 pdMap.remove(ref); |
|
616 } |
|
617 } |
|
618 } |
|
619 |
|
620 /** |
|
621 * A weak key for a ProtectionDomain. |
|
622 */ |
|
623 private static class WeakProtectionDomainKey extends WeakReference<Key> { |
|
624 /** |
|
625 * Saved value of the referent's identity hash code, to maintain |
|
626 * a consistent hash code after the referent has been cleared |
|
627 */ |
|
628 private final int hash; |
|
629 |
|
630 /** |
|
631 * A key representing a null ProtectionDomain. |
|
632 */ |
|
633 private static final Key NULL_KEY = new Key(); |
|
634 |
|
635 /** |
|
636 * Create a new WeakProtectionDomain with the specified domain and |
|
637 * registered with a queue. |
|
638 */ |
|
639 WeakProtectionDomainKey(ProtectionDomain pd, ReferenceQueue<Key> rq) { |
|
640 this((pd == null ? NULL_KEY : pd.key), rq); |
|
641 } |
|
642 |
|
643 WeakProtectionDomainKey(ProtectionDomain pd) { |
|
644 this(pd == null ? NULL_KEY : pd.key); |
|
645 } |
|
646 |
|
647 private WeakProtectionDomainKey(Key key, ReferenceQueue<Key> rq) { |
|
648 super(key, rq); |
|
649 hash = key.hashCode(); |
|
650 } |
|
651 |
|
652 private WeakProtectionDomainKey(Key key) { |
|
653 super(key); |
|
654 hash = key.hashCode(); |
|
655 } |
|
656 |
|
657 /** |
|
658 * Returns the identity hash code of the original referent. |
|
659 */ |
|
660 @Override |
|
661 public int hashCode() { |
|
662 return hash; |
|
663 } |
|
664 |
|
665 /** |
|
666 * Returns true if the given object is an identical |
|
667 * WeakProtectionDomainKey instance, or, if this object's referent |
|
668 * has not been cleared and the given object is another |
|
669 * WeakProtectionDomainKey instance with an identical non-null |
|
670 * referent as this one. |
|
671 */ |
|
672 @Override |
|
673 public boolean equals(Object obj) { |
|
674 if (obj == this) { |
|
675 return true; |
|
676 } |
|
677 |
|
678 if (obj instanceof WeakProtectionDomainKey) { |
|
679 Object referent = get(); |
|
680 return (referent != null) && |
|
681 (referent == ((WeakProtectionDomainKey)obj).get()); |
|
682 } else { |
|
683 return false; |
|
684 } |
|
685 } |
|
686 } |
581 } |
687 } |
582 } |