1 7 8 package java.net; 9 10 import java.util.Enumeration ; 11 import java.util.Vector ; 12 import java.util.List ; 13 import java.util.ArrayList ; 14 import java.util.Collections ; 15 import java.util.StringTokenizer ; 16 import java.net.InetAddress ; 17 import java.security.Permission ; 18 import java.security.PermissionCollection ; 19 import java.security.Policy ; 20 import java.io.Serializable ; 21 import java.io.ObjectStreamField ; 22 import java.io.ObjectOutputStream ; 23 import java.io.ObjectInputStream ; 24 import java.io.IOException ; 25 import sun.net.util.IPAddressUtil; 26 import sun.security.util.SecurityConstants; 27 import sun.security.util.Debug; 28 29 30 122 123 public final class SocketPermission extends Permission 124 implements java.io.Serializable 125 { 126 private static final long serialVersionUID = -7204263841984476862L; 127 128 131 private final static int CONNECT = 0x1; 132 133 136 private final static int LISTEN = 0x2; 137 138 141 private final static int ACCEPT = 0x4; 142 143 146 private final static int RESOLVE = 0x8; 147 148 151 private final static int NONE = 0x0; 152 153 156 private final static int ALL = CONNECT|LISTEN|ACCEPT|RESOLVE; 157 158 private static final int PORT_MIN = 0; 160 private static final int PORT_MAX = 65535; 161 private static final int PRIV_PORT_MAX = 1023; 162 163 private transient int mask; 165 166 171 172 private String actions; 175 private transient String hostname; 177 178 181 private transient String cname; 182 183 private transient InetAddress [] addresses; 185 186 private transient boolean wildcard; 188 189 private transient boolean init_with_ip; 191 192 private transient boolean invalid; 195 196 private transient int[] portrange; 198 199 private transient boolean defaultDeny = false; 200 201 private transient boolean untrusted; 204 205 private static boolean trustProxy; 207 208 private static boolean trustNameService; 210 211 private static Debug debug = null; 212 private static boolean debugInit = false; 213 214 static { 215 Boolean tmp = (Boolean ) java.security.AccessController.doPrivileged( 216 new sun.security.action.GetBooleanAction("trustProxy")); 217 trustProxy = tmp.booleanValue(); 218 tmp = (Boolean ) java.security.AccessController.doPrivileged( 219 new sun.security.action.GetBooleanAction("sun.net.trustNameService")); 220 trustNameService = tmp.booleanValue(); 221 } 222 223 private static synchronized Debug getDebug() 224 { 225 if (!debugInit) { 226 debug = Debug.getInstance("access"); 227 debugInit = true; 228 } 229 return debug; 230 } 231 232 262 public SocketPermission(String host, String action) { 263 super(getHost(host)); 264 init(getName(), getMask(action)); 266 } 267 268 269 SocketPermission(String host, int mask) { 270 super(getHost(host)); 271 init(getName(), mask); 273 } 274 275 private void setDeny() { 276 defaultDeny = true; 277 } 278 279 private static String getHost(String host) 280 { 281 if (host.equals("")) { 282 return "localhost"; 283 } else { 284 288 int ind; 289 if (host.charAt(0) != '[') { 290 if ((ind = host.indexOf(':')) != host.lastIndexOf(':')) { 291 295 StringTokenizer st = new StringTokenizer (host, ":"); 296 int tokens = st.countTokens(); 297 if (tokens == 9) { 298 ind = host.lastIndexOf(':'); 300 host = "[" + host.substring(0, ind) + "]" + 301 host.substring(ind); 302 } else if (tokens == 8 && host.indexOf("::") == -1) { 303 host = "[" + host + "]"; 305 } else { 306 throw new IllegalArgumentException ("Ambiguous"+ 308 " hostport part"); 309 } 310 } 311 } 312 return host; 313 } 314 } 315 316 private int[] parsePort(String port) 317 throws Exception 318 { 319 320 if (port == null || port.equals("") || port.equals("*")) { 321 return new int[] {PORT_MIN, PORT_MAX}; 322 } 323 324 int dash = port.indexOf('-'); 325 326 if (dash == -1) { 327 int p = Integer.parseInt(port); 328 return new int[] {p, p}; 329 } else { 330 String low = port.substring(0, dash); 331 String high = port.substring(dash+1); 332 int l,h; 333 334 if (low.equals("")) { 335 l = PORT_MIN; 336 } else { 337 l = Integer.parseInt(low); 338 } 339 340 if (high.equals("")) { 341 h = PORT_MAX; 342 } else { 343 h = Integer.parseInt(high); 344 } 345 if (l < 0 || h < 0 || h<l) 346 throw new IllegalArgumentException ("invalid port range"); 347 348 return new int[] {l, h}; 349 } 350 } 351 352 357 private void init(String host, int mask) { 358 360 if ((mask & ALL) != mask) 361 throw new IllegalArgumentException ("invalid actions mask"); 362 363 this.mask = mask | RESOLVE; 365 366 370 375 int rb = 0 ; 376 int start = 0, end = 0; 377 int sep = -1; 378 String hostport = host; 379 if (host.charAt(0) == '[') { 380 start = 1; 381 rb = host.indexOf(']'); 382 if (rb != -1) { 383 host = host.substring(start, rb); 384 } else { 385 throw new 386 IllegalArgumentException ("invalid host/port: "+host); 387 } 388 sep = hostport.indexOf(':', rb+1); 389 } else { 390 start = 0; 391 sep = host.indexOf(':', rb); 392 end = sep; 393 if (sep != -1) { 394 host = host.substring(start, end); 395 } 396 } 397 398 if (sep != -1) { 399 String port = hostport.substring(sep+1); 400 try { 401 portrange = parsePort(port); 402 } catch (Exception e) { 403 throw new 404 IllegalArgumentException ("invalid port range: "+port); 405 } 406 } else { 407 portrange = new int[] { PORT_MIN, PORT_MAX }; 408 } 409 410 hostname = host; 411 412 if (host.lastIndexOf('*') > 0) { 414 throw new 415 IllegalArgumentException ("invalid host wildcard specification"); 416 } else if (host.startsWith("*")) { 417 wildcard = true; 418 if (host.equals("*")) { 419 cname = ""; 420 } else if (host.startsWith("*.")) { 421 cname = host.substring(1).toLowerCase(); 422 } else { 423 throw new 424 IllegalArgumentException ("invalid host wildcard specification"); 425 } 426 return; 427 } else { 428 if (host.length() > 0) { 429 char ch = host.charAt(0); 431 if (ch == ':' || Character.digit(ch, 16) != -1) { 432 byte ip[] = IPAddressUtil.textToNumericFormatV4(host); 433 if (ip == null) { 434 ip = IPAddressUtil.textToNumericFormatV6(host); 435 } 436 if (ip != null) { 437 try { 438 addresses = 439 new InetAddress [] 440 {InetAddress.getByAddress(ip) }; 441 init_with_ip = true; 442 } catch (UnknownHostException uhe) { 443 invalid = true; 445 } 446 } 447 } 448 } 449 } 450 } 451 452 458 private static int getMask(String action) { 459 460 if (action == null) { 461 throw new NullPointerException ("action can't be null"); 462 } 463 464 if (action.equals("")) { 465 throw new IllegalArgumentException ("action can't be empty"); 466 } 467 468 int mask = NONE; 469 470 if (action == SecurityConstants.SOCKET_RESOLVE_ACTION) { 472 return RESOLVE; 473 } else if (action == SecurityConstants.SOCKET_CONNECT_ACTION) { 474 return CONNECT; 475 } else if (action == SecurityConstants.SOCKET_LISTEN_ACTION) { 476 return LISTEN; 477 } else if (action == SecurityConstants.SOCKET_ACCEPT_ACTION) { 478 return ACCEPT; 479 } else if (action == SecurityConstants.SOCKET_CONNECT_ACCEPT_ACTION) { 480 return CONNECT|ACCEPT; 481 } 482 483 char[] a = action.toCharArray(); 484 485 int i = a.length - 1; 486 if (i < 0) 487 return mask; 488 489 while (i != -1) { 490 char c; 491 492 while ((i!=-1) && ((c = a[i]) == ' ' || 494 c == '\r' || 495 c == '\n' || 496 c == '\f' || 497 c == '\t')) 498 i--; 499 500 int matchlen; 502 503 if (i >= 6 && (a[i-6] == 'c' || a[i-6] == 'C') && 504 (a[i-5] == 'o' || a[i-5] == 'O') && 505 (a[i-4] == 'n' || a[i-4] == 'N') && 506 (a[i-3] == 'n' || a[i-3] == 'N') && 507 (a[i-2] == 'e' || a[i-2] == 'E') && 508 (a[i-1] == 'c' || a[i-1] == 'C') && 509 (a[i] == 't' || a[i] == 'T')) 510 { 511 matchlen = 7; 512 mask |= CONNECT; 513 514 } else if (i >= 6 && (a[i-6] == 'r' || a[i-6] == 'R') && 515 (a[i-5] == 'e' || a[i-5] == 'E') && 516 (a[i-4] == 's' || a[i-4] == 'S') && 517 (a[i-3] == 'o' || a[i-3] == 'O') && 518 (a[i-2] == 'l' || a[i-2] == 'L') && 519 (a[i-1] == 'v' || a[i-1] == 'V') && 520 (a[i] == 'e' || a[i] == 'E')) 521 { 522 matchlen = 7; 523 mask |= RESOLVE; 524 525 } else if (i >= 5 && (a[i-5] == 'l' || a[i-5] == 'L') && 526 (a[i-4] == 'i' || a[i-4] == 'I') && 527 (a[i-3] == 's' || a[i-3] == 'S') && 528 (a[i-2] == 't' || a[i-2] == 'T') && 529 (a[i-1] == 'e' || a[i-1] == 'E') && 530 (a[i] == 'n' || a[i] == 'N')) 531 { 532 matchlen = 6; 533 mask |= LISTEN; 534 535 } else if (i >= 5 && (a[i-5] == 'a' || a[i-5] == 'A') && 536 (a[i-4] == 'c' || a[i-4] == 'C') && 537 (a[i-3] == 'c' || a[i-3] == 'C') && 538 (a[i-2] == 'e' || a[i-2] == 'E') && 539 (a[i-1] == 'p' || a[i-1] == 'P') && 540 (a[i] == 't' || a[i] == 'T')) 541 { 542 matchlen = 6; 543 mask |= ACCEPT; 544 545 } else { 546 throw new IllegalArgumentException ( 548 "invalid permission: " + action); 549 } 550 551 boolean seencomma = false; 554 while (i >= matchlen && !seencomma) { 555 switch(a[i-matchlen]) { 556 case ',': 557 seencomma = true; 558 559 case ' ': case '\r': case '\n': 560 case '\f': case '\t': 561 break; 562 default: 563 throw new IllegalArgumentException ( 564 "invalid permission: " + action); 565 } 566 i--; 567 } 568 569 i -= matchlen; 571 } 572 573 return mask; 574 } 575 576 580 void getCanonName() 581 throws UnknownHostException 582 { 583 if (cname != null || invalid || untrusted) return; 584 585 587 try { 588 if (addresses == null) { 592 getIP(); 593 } 594 595 if (init_with_ip) { 598 cname = addresses[0].getHostName(false).toLowerCase(); 599 } else { 600 cname = InetAddress.getByName(addresses[0].getHostAddress()). 601 getHostName(false).toLowerCase(); 602 if (!trustNameService && sun.net.www.URLConnection.isProxiedHost(hostname)) { 603 if (!match(cname, hostname) && 604 (defaultDeny || !cname.equals(addresses[0].getHostAddress()))) { 605 if (!authorized(hostname, addresses[0].getAddress())) { 607 untrusted = true; 608 Debug debug = getDebug(); 609 if (debug != null && Debug.isOn("failure")) { 610 debug.println("socket access restriction: proxied host " + "(" + addresses[0] + ")" + " does not match " + cname + " from reverse lookup"); 611 } 612 } 613 } 614 } 615 } 616 } catch (UnknownHostException uhe) { 617 invalid = true; 618 throw uhe; 619 } 620 } 621 622 private boolean match(String cname, String hname) { 623 String a = cname.toLowerCase(); 624 String b = hname.toLowerCase(); 625 if (a.startsWith(b) && 626 ((a.length() == b.length()) || (a.charAt(b.length()) == '.'))) 627 return true; 628 if (b.endsWith(".akamai.net") || b.endsWith(".akamai.com")) 629 return true; 630 String af = fragment(a); 631 String bf = fragment(b); 632 return af.length() != 0 && bf.length() != 0 && fragment(a).equals(fragment(b)); 633 } 634 635 636 private String fragment(String cname) { 640 int dot; 641 dot = cname.lastIndexOf('.'); 642 if (dot == -1) 643 return cname; 644 if (dot == 0) 645 return ""; 646 if (dot == cname.length() - 1) { 647 cname = cname.substring(0, cname.length() -1); 648 dot = cname.lastIndexOf('.'); 649 } 650 if (dot < 1) 651 return ""; 652 int second = cname.lastIndexOf('.', dot - 1); 653 if (second == -1) 654 return cname; 655 if (((cname.length() - dot) <= 3) && ((dot - second) <= 4) && second > 0) { 656 if (dot - second == 4) { 657 String s = cname.substring(second + 1, dot); 658 if (!(s.equals("com") || s.equals("org") || s.equals("edu"))) { 659 return cname.substring(second + 1); 660 } 661 } 662 int third = cname.lastIndexOf('.', second - 1); 663 if (third == -1) 664 return cname.substring(second + 1); 665 else 666 return cname.substring(third + 1); 667 } 668 return cname.substring(second + 1); 669 } 670 671 672 private boolean authorized(String cname, byte[] addr) { 673 if (addr.length == 4) 674 return authorizedIPv4(cname, addr); 675 else if (addr.length == 16) 676 return authorizedIPv6(cname, addr); 677 else 678 return false; 679 } 680 681 private boolean authorizedIPv4(String cname, byte[] addr) { 682 String authHost = ""; 683 InetAddress auth; 684 685 try { 686 authHost = "auth." + 687 (addr[3] & 0xff) + "." + (addr[2] & 0xff) + "." + 688 (addr[1] & 0xff) + "." + (addr[0] & 0xff) + 689 ".in-addr.arpa"; 690 authHost = hostname + '.' + authHost; 692 auth = InetAddress.getAllByName0(authHost, false)[0]; 693 if (auth.equals(InetAddress.getByAddress(addr))) 694 return true; 695 Debug debug = getDebug(); 696 if (debug != null && Debug.isOn("failure")) { 697 debug.println("socket access restriction: IP address of " + auth + " != " + InetAddress.getByAddress(addr)); 698 } 699 } catch (UnknownHostException uhe) { 700 Debug debug = getDebug(); 701 if (debug != null && Debug.isOn("failure")) { 702 debug.println("socket access restriction: forward lookup failed for " + authHost); 703 } 704 } catch (IOException x) { 705 } 706 return false; 707 } 708 709 private boolean authorizedIPv6(String cname, byte[] addr) { 710 String authHost = ""; 711 InetAddress auth; 712 713 try { 714 StringBuffer sb = new StringBuffer (39); 715 716 for (int i = 15; i >= 0; i--) { 717 sb.append(Integer.toHexString(((addr[i]) & 0x0f))); 718 sb.append('.'); 719 sb.append(Integer.toHexString(((addr[i] >> 4) & 0x0f))); 720 sb.append('.'); 721 } 722 authHost = "auth." + sb.toString() + "IP6.ARPA"; 723 authHost = hostname + '.' + authHost; 725 auth = InetAddress.getAllByName0(authHost, false)[0]; 726 if (auth.equals(InetAddress.getByAddress(addr))) 727 return true; 728 Debug debug = getDebug(); 729 if (debug != null && Debug.isOn("failure")) { 730 debug.println("socket access restriction: IP address of " + auth + " != " + InetAddress.getByAddress(addr)); 731 } 732 } catch (UnknownHostException uhe) { 733 Debug debug = getDebug(); 734 if (debug != null && Debug.isOn("failure")) { 735 debug.println("socket access restriction: forward lookup failed for " + authHost); 736 } 737 } catch (IOException x) { 738 } 739 return false; 740 } 741 742 743 747 void getIP() 748 throws UnknownHostException 749 { 750 if (addresses != null || wildcard || invalid) return; 751 752 try { 753 String host; 755 if (getName().charAt(0) == '[') { 756 host = getName().substring(1, getName().indexOf(']')); 758 } else { 759 int i = getName().indexOf(":"); 760 if (i == -1) 761 host = getName(); 762 else { 763 host = getName().substring(0,i); 764 } 765 } 766 767 addresses = 768 new InetAddress [] {InetAddress.getAllByName0(host, false)[0]}; 769 770 } catch (UnknownHostException uhe) { 771 invalid = true; 772 throw uhe; 773 } catch (IndexOutOfBoundsException iobe) { 774 invalid = true; 775 throw new UnknownHostException (getName()); 776 } 777 } 778 779 813 814 public boolean implies(Permission p) { 815 int i,j; 816 817 if (!(p instanceof SocketPermission )) 818 return false; 819 820 SocketPermission that = (SocketPermission ) p; 821 822 return ((this.mask & that.mask) == that.mask) && 823 impliesIgnoreMask(that); 824 } 825 826 849 850 boolean impliesIgnoreMask(SocketPermission that) { 851 int i,j; 852 853 if ((that.mask & RESOLVE) != that.mask) { 854 if ((that.portrange[0] < this.portrange[0]) || 856 (that.portrange[1] > this.portrange[1])) { 857 return false; 858 } 859 } 860 861 if (this.wildcard && "".equals(this.cname)) 863 return true; 864 865 if (this.invalid || that.invalid) { 867 return (trustProxy ? inProxyWeTrust(that) : false); 868 } 869 870 871 try { 872 if (this.init_with_ip) { if (that.wildcard) 874 return false; 875 876 if (that.init_with_ip) { 877 return (this.addresses[0].equals(that.addresses[0])); 878 } else { 879 if (that.addresses == null) { 880 that.getIP(); 881 } 882 for (i=0; i < that.addresses.length; i++) { 883 if (this.addresses[0].equals(that.addresses[i])) 884 return true; 885 } 886 } 887 return false; 890 } 891 892 if (this.wildcard || that.wildcard) { 894 if (this.wildcard && that.wildcard) 898 return (that.cname.endsWith(this.cname)); 899 900 if (that.wildcard) 902 return false; 903 904 if (that.cname == null) { 907 that.getCanonName(); 908 } 909 return (that.cname.endsWith(this.cname)); 910 } 911 912 if (this.cname == null) { 913 this.getCanonName(); 914 } 915 916 if (this.addresses == null) { 918 this.getIP(); 919 } 920 921 if (that.addresses == null) { 922 that.getIP(); 923 } 924 925 if (!(that.init_with_ip && this.untrusted)) { 926 for (j = 0; j < this.addresses.length; j++) { 927 for (i=0; i < that.addresses.length; i++) { 928 if (this.addresses[j].equals(that.addresses[i])) 929 return true; 930 } 931 } 932 933 if (that.cname == null) { 936 that.getCanonName(); 937 } 938 939 return (this.cname.equalsIgnoreCase(that.cname)); 940 } 941 942 } catch (UnknownHostException uhe) { 943 if (trustProxy) 944 return inProxyWeTrust(that); 945 } 946 947 950 return false; 951 } 952 953 private boolean inProxyWeTrust(SocketPermission that) { 954 957 String thisHost = hostname; 958 String thatHost = that.hostname; 959 960 if (thisHost == null) 961 return false; 962 else 963 return thisHost.equalsIgnoreCase(thatHost); 964 965 } 966 976 public boolean equals(Object obj) { 977 if (obj == this) 978 return true; 979 980 if (! (obj instanceof SocketPermission )) 981 return false; 982 983 SocketPermission that = (SocketPermission ) obj; 984 985 987 if (this.mask != that.mask) return false; 989 990 if ((that.mask & RESOLVE) != that.mask) { 991 if ((this.portrange[0] != that.portrange[0]) || 993 (this.portrange[1] != that.portrange[1])) { 994 return false; 995 } 996 } 997 998 1005 if (this.getName().equalsIgnoreCase(that.getName())) { 1006 return true; 1007 } 1008 1009 1013 try { 1014 this.getCanonName(); 1015 that.getCanonName(); 1016 } catch (UnknownHostException uhe) { 1017 return false; 1018 } 1019 1020 if (this.invalid || that.invalid) 1021 return false; 1022 1023 if (this.cname != null) { 1024 return this.cname.equalsIgnoreCase(that.cname); 1025 } 1026 1027 return false; 1028 } 1029 1030 1035 1036 public int hashCode() { 1037 1043 1044 if (init_with_ip || wildcard) { 1045 return this.getName().hashCode(); 1046 } 1047 1048 try { 1049 getCanonName(); 1050 } catch (UnknownHostException uhe) { 1051 1052 } 1053 1054 if (invalid || cname == null) 1055 return this.getName().hashCode(); 1056 else 1057 return this.cname.hashCode(); 1058 } 1059 1060 1065 1066 int getMask() { 1067 return mask; 1068 } 1069 1070 1079 private static String getActions(int mask) 1080 { 1081 StringBuilder sb = new StringBuilder (); 1082 boolean comma = false; 1083 1084 if ((mask & CONNECT) == CONNECT) { 1085 comma = true; 1086 sb.append("connect"); 1087 } 1088 1089 if ((mask & LISTEN) == LISTEN) { 1090 if (comma) sb.append(','); 1091 else comma = true; 1092 sb.append("listen"); 1093 } 1094 1095 if ((mask & ACCEPT) == ACCEPT) { 1096 if (comma) sb.append(','); 1097 else comma = true; 1098 sb.append("accept"); 1099 } 1100 1101 1102 if ((mask & RESOLVE) == RESOLVE) { 1103 if (comma) sb.append(','); 1104 else comma = true; 1105 sb.append("resolve"); 1106 } 1107 1108 return sb.toString(); 1109 } 1110 1111 1118 public String getActions() 1119 { 1120 if (actions == null) 1121 actions = getActions(this.mask); 1122 1123 return actions; 1124 } 1125 1126 1137 1138 public PermissionCollection newPermissionCollection() { 1139 return new SocketPermissionCollection(); 1140 } 1141 1142 1147 private synchronized void writeObject(java.io.ObjectOutputStream s) 1148 throws IOException 1149 { 1150 if (actions == null) 1153 getActions(); 1154 s.defaultWriteObject(); 1155 } 1156 1157 1161 private synchronized void readObject(java.io.ObjectInputStream s) 1162 throws IOException , ClassNotFoundException 1163 { 1164 s.defaultReadObject(); 1166 init(getName(),getMask(actions)); 1167 } 1168 1169 1206} 1207 1208 1225 1226final class SocketPermissionCollection extends PermissionCollection 1227implements Serializable 1228{ 1229 private transient List perms; 1231 1232 1236 1237 public SocketPermissionCollection() { 1238 perms = new ArrayList (); 1239 } 1240 1241 1253 1254 public void add(Permission permission) 1255 { 1256 if (! (permission instanceof SocketPermission )) 1257 throw new IllegalArgumentException ("invalid permission: "+ 1258 permission); 1259 if (isReadOnly()) 1260 throw new SecurityException ( 1261 "attempt to add a Permission to a readonly PermissionCollection"); 1262 1263 synchronized (this) { 1266 perms.add(0, permission); 1267 } 1268 } 1269 1270 1279 1280 public boolean implies(Permission permission) 1281 { 1282 if (! (permission instanceof SocketPermission )) 1283 return false; 1284 1285 SocketPermission np = (SocketPermission ) permission; 1286 1287 int desired = np.getMask(); 1288 int effective = 0; 1289 int needed = desired; 1290 1291 synchronized (this) { 1292 int len = perms.size(); 1293 for (int i = 0; i < len; i++) { 1295 SocketPermission x = (SocketPermission ) perms.get(i); 1296 if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(np)) { 1298 effective |= x.getMask(); 1299 if ((effective & desired) == desired) 1300 return true; 1301 needed = (desired ^ effective); 1302 } 1303 } 1304 } 1305 return false; 1306 } 1307 1308 1314 1315 public Enumeration elements() { 1316 synchronized (this) { 1318 return Collections.enumeration(perms); 1319 } 1320 } 1321 1322 private static final long serialVersionUID = 2787186408602843674L; 1323 1324 1327 1333 1337 private static final ObjectStreamField [] serialPersistentFields = { 1338 new ObjectStreamField ("permissions", Vector .class), 1339 }; 1340 1341 1344 1348 private void writeObject(ObjectOutputStream out) throws IOException { 1349 1351 Vector permissions = new Vector (perms.size()); 1353 1354 synchronized (this) { 1355 permissions.addAll(perms); 1356 } 1357 1358 ObjectOutputStream.PutField pfields = out.putFields(); 1359 pfields.put("permissions", permissions); 1360 out.writeFields(); 1361 } 1362 1363 1366 private void readObject(ObjectInputStream in) throws IOException , 1367 ClassNotFoundException { 1368 1370 ObjectInputStream.GetField gfields = in.readFields(); 1372 1373 Vector permissions = (Vector )gfields.get("permissions", null); 1375 perms = new ArrayList (permissions.size()); 1376 perms.addAll(permissions); 1377 } 1378} 1379 | Popular Tags |