Showing the changes to java/pkg/sun/security/x509/GeneralSubtrees.java (1 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,525 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1997, 2003, 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 sun.security.x509; | ||
| 27 | |||
| 28 | import java.io.*; | ||
| 29 | import java.util.*; | ||
| 30 | |||
| 31 | import sun.security.util.*; | ||
| 32 | |||
| 33 | /** | ||
| 34 | * Represent the GeneralSubtrees ASN.1 object. | ||
| 35 | * <p> | ||
| 36 | * The ASN.1 for this is | ||
| 37 | * <pre> | ||
| 38 | * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree | ||
| 39 | * </pre> | ||
| 40 | * </p> | ||
| 41 | * | ||
| 42 | * | ||
| 43 | * @author Amit Kapoor | ||
| 44 | * @author Hemma Prafullchandra | ||
| 45 | * @author Andreas Sterbenz | ||
| 46 | */ | ||
| 47 | public class GeneralSubtrees implements Cloneable { | ||
| 48 | |||
| 49 | private final List<GeneralSubtree> trees; | ||
| 50 | |||
| 51 | // Private variables | ||
| 52 | private static final int NAME_DIFF_TYPE = GeneralNameInterface.NAME_DIFF_TYPE; | ||
| 53 | private static final int NAME_MATCH = GeneralNameInterface.NAME_MATCH; | ||
| 54 | private static final int NAME_NARROWS = GeneralNameInterface.NAME_NARROWS; | ||
| 55 | private static final int NAME_WIDENS = GeneralNameInterface.NAME_WIDENS; | ||
| 56 | private static final int NAME_SAME_TYPE = GeneralNameInterface.NAME_SAME_TYPE; | ||
| 57 | |||
| 58 | /** | ||
| 59 | * The default constructor for the class. | ||
| 60 | */ | ||
| 61 | public GeneralSubtrees() { | ||
| 62 | trees = new ArrayList<GeneralSubtree>(); | ||
| 63 | } | ||
| 64 | |||
| 65 | private GeneralSubtrees(GeneralSubtrees source) { | ||
| 66 | trees = new ArrayList<GeneralSubtree>(source.trees); | ||
| 67 | } | ||
| 68 | |||
| 69 | /** | ||
| 70 | * Create the object from the passed DER encoded form. | ||
| 71 | * | ||
| 72 | * @param val the DER encoded form of the same. | ||
| 73 | */ | ||
| 74 | public GeneralSubtrees(DerValue val) throws IOException { | ||
| 75 | this(); | ||
| 76 | if (val.tag != DerValue.tag_Sequence) { | ||
| 77 | throw new IOException("Invalid encoding of GeneralSubtrees."); | ||
| 78 | } | ||
| 79 | while (val.data.available() != 0) { | ||
| 80 | DerValue opt = val.data.getDerValue(); | ||
| 81 | GeneralSubtree tree = new GeneralSubtree(opt); | ||
| 82 | add(tree); | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | public GeneralSubtree get(int index) { | ||
| 87 | return trees.get(index); | ||
| 88 | } | ||
| 89 | |||
| 90 | public void remove(int index) { | ||
| 91 | trees.remove(index); | ||
| 92 | } | ||
| 93 | |||
| 94 | public void add(GeneralSubtree tree) { | ||
| 95 | if (tree == null) { | ||
| 96 | throw new NullPointerException(); | ||
| 97 | } | ||
| 98 | trees.add(tree); | ||
| 99 | } | ||
| 100 | |||
| 101 | public boolean contains(GeneralSubtree tree) { | ||
| 102 | if (tree == null) { | ||
| 103 | throw new NullPointerException(); | ||
| 104 | } | ||
| 105 | return trees.contains(tree); | ||
| 106 | } | ||
| 107 | |||
| 108 | public int size() { | ||
| 109 | return trees.size(); | ||
| 110 | } | ||
| 111 | |||
| 112 | public Iterator<GeneralSubtree> iterator() { | ||
| 113 | return trees.iterator(); | ||
| 114 | } | ||
| 115 | |||
| 116 | public List<GeneralSubtree> trees() { | ||
| 117 | return trees; | ||
| 118 | } | ||
| 119 | |||
| 120 | public Object clone() { | ||
| 121 | return new GeneralSubtrees(this); | ||
| 122 | } | ||
| 123 | |||
| 124 | /** | ||
| 125 | * Return a printable string of the GeneralSubtree. | ||
| 126 | */ | ||
| 127 | public String toString() { | ||
| 128 | String s = " GeneralSubtrees:\n" + trees.toString() + "\n"; | ||
| 129 | return s; | ||
| 130 | } | ||
| 131 | |||
| 132 | /** | ||
| 133 | * Encode the GeneralSubtrees. | ||
| 134 | * | ||
| 135 | * @params out the DerOutputStrean to encode this object to. | ||
| 136 | */ | ||
| 137 | public void encode(DerOutputStream out) throws IOException { | ||
| 138 | DerOutputStream seq = new DerOutputStream(); | ||
| 139 | |||
| 140 | for (int i = 0, n = size(); i < n; i++) { | ||
| 141 | get(i).encode(seq); | ||
| 142 | } | ||
| 143 | out.write(DerValue.tag_Sequence, seq); | ||
| 144 | } | ||
| 145 | |||
| 146 | /** | ||
| 147 | * Compare two general subtrees by comparing the subtrees | ||
| 148 | * of each. | ||
| 149 | * | ||
| 150 | * @param other GeneralSubtrees to compare to this | ||
| 151 | * @returns true if match | ||
| 152 | */ | ||
| 153 | public boolean equals(Object obj) { | ||
| 154 | if (this == obj) { | ||
| 155 | return true; | ||
| 156 | } | ||
| 157 | if (obj instanceof GeneralSubtrees == false) { | ||
| 158 | return false; | ||
| 159 | } | ||
| 160 | GeneralSubtrees other = (GeneralSubtrees)obj; | ||
| 161 | return this.trees.equals(other.trees); | ||
| 162 | } | ||
| 163 | |||
| 164 | public int hashCode() { | ||
| 165 | return trees.hashCode(); | ||
| 166 | } | ||
| 167 | |||
| 168 | /** | ||
| 169 | * Return the GeneralNameInterface form of the GeneralName in one of | ||
| 170 | * the GeneralSubtrees. | ||
| 171 | * | ||
| 172 | * @param ndx index of the GeneralSubtree from which to obtain the name | ||
| 173 | */ | ||
| 174 | private GeneralNameInterface getGeneralNameInterface(int ndx) { | ||
| 175 | return getGeneralNameInterface(get(ndx)); | ||
| 176 | } | ||
| 177 | |||
| 178 | private static GeneralNameInterface getGeneralNameInterface(GeneralSubtree gs) { | ||
| 179 | GeneralName gn = gs.getName(); | ||
| 180 | GeneralNameInterface gni = gn.getName(); | ||
| 181 | return gni; | ||
| 182 | } | ||
| 183 | |||
| 184 | /** | ||
| 185 | * minimize this GeneralSubtrees by removing all redundant entries. | ||
| 186 | * Internal method used by intersect and reduce. | ||
| 187 | */ | ||
| 188 | private void minimize() { | ||
| 189 | |||
| 190 | // Algorithm: compare each entry n to all subsequent entries in | ||
| 191 | // the list: if any subsequent entry matches or widens entry n, | ||
| 192 | // remove entry n. If any subsequent entries narrow entry n, remove | ||
| 193 | // the subsequent entries. | ||
| 194 | for (int i = 0; i < size(); i++) { | ||
| 195 | GeneralNameInterface current = getGeneralNameInterface(i); | ||
| 196 | boolean remove1 = false; | ||
| 197 | |||
| 198 | /* compare current to subsequent elements */ | ||
| 199 | for (int j = i + 1; j < size(); j++) { | ||
| 200 | GeneralNameInterface subsequent = getGeneralNameInterface(j); | ||
| 201 | switch (current.constrains(subsequent)) { | ||
| 202 | case GeneralNameInterface.NAME_DIFF_TYPE: | ||
| 203 | /* not comparable; different name types; keep checking */ | ||
| 204 | continue; | ||
| 205 | case GeneralNameInterface.NAME_MATCH: | ||
| 206 | /* delete one of the duplicates */ | ||
| 207 | remove1 = true; | ||
| 208 | break; | ||
| 209 | case GeneralNameInterface.NAME_NARROWS: | ||
| 210 | /* subsequent narrows current */ | ||
| 211 | /* remove narrower name (subsequent) */ | ||
| 212 | remove(j); | ||
| 213 | j--; /* continue check with new subsequent */ | ||
| 214 | continue; | ||
| 215 | case GeneralNameInterface.NAME_WIDENS: | ||
| 216 | /* subsequent widens current */ | ||
| 217 | /* remove narrower name current */ | ||
| 218 | remove1 = true; | ||
| 219 | break; | ||
| 220 | case GeneralNameInterface.NAME_SAME_TYPE: | ||
| 221 | /* keep both for now; keep checking */ | ||
| 222 | continue; | ||
| 223 | } | ||
| 224 | break; | ||
| 225 | } /* end of this pass of subsequent elements */ | ||
| 226 | |||
| 227 | if (remove1) { | ||
| 228 | remove(i); | ||
| 229 | i--; /* check the new i value */ | ||
| 230 | } | ||
| 231 | |||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | /** | ||
| 236 | * create a subtree containing an instance of the input | ||
| 237 | * name type that widens all other names of that type. | ||
| 238 | * | ||
| 239 | * @params name GeneralNameInterface name | ||
| 240 | * @returns GeneralSubtree containing widest name of that type | ||
| 241 | * @throws RuntimeException on error (should not occur) | ||
| 242 | */ | ||
| 243 | private GeneralSubtree createWidestSubtree(GeneralNameInterface name) { | ||
| 244 | try { | ||
| 245 | GeneralName newName; | ||
| 246 | switch (name.getType()) { | ||
| 247 | case GeneralNameInterface.NAME_ANY: | ||
| 248 | // Create new OtherName with same OID as baseName, but | ||
| 249 | // empty value | ||
| 250 | ObjectIdentifier otherOID = ((OtherName)name).getOID(); | ||
| 251 | newName = new GeneralName(new OtherName(otherOID, null)); | ||
| 252 | break; | ||
| 253 | case GeneralNameInterface.NAME_RFC822: | ||
| 254 | newName = new GeneralName(new RFC822Name("")); | ||
| 255 | break; | ||
| 256 | case GeneralNameInterface.NAME_DNS: | ||
| 257 | newName = new GeneralName(new DNSName("")); | ||
| 258 | break; | ||
| 259 | case GeneralNameInterface.NAME_X400: | ||
| 260 | newName = new GeneralName(new X400Address((byte[])null)); | ||
| 261 | break; | ||
| 262 | case GeneralNameInterface.NAME_DIRECTORY: | ||
| 263 | newName = new GeneralName(new X500Name("")); | ||
| 264 | break; | ||
| 265 | case GeneralNameInterface.NAME_EDI: | ||
| 266 | newName = new GeneralName(new EDIPartyName("")); | ||
| 267 | break; | ||
| 268 | case GeneralNameInterface.NAME_URI: | ||
| 269 | newName = new GeneralName(new URIName("")); | ||
| 270 | break; | ||
| 271 | case GeneralNameInterface.NAME_IP: | ||
| 272 | newName = new GeneralName(new IPAddressName((byte[])null)); | ||
| 273 | break; | ||
| 274 | case GeneralNameInterface.NAME_OID: | ||
| 275 | newName = new GeneralName | ||
| 276 | (new OIDName(new ObjectIdentifier((int[])null))); | ||
| 277 | break; | ||
| 278 | default: | ||
| 279 | throw new IOException | ||
| 280 | ("Unsupported GeneralNameInterface type: " + name.getType()); | ||
| 281 | } | ||
| 282 | return new GeneralSubtree(newName, 0, -1); | ||
| 283 | } catch (IOException e) { | ||
| 284 | throw new RuntimeException("Unexpected error: " + e, e); | ||
| 285 | } | ||
| 286 | } | ||
| 287 | |||
| 288 | /** | ||
| 289 | * intersect this GeneralSubtrees with other. This function | ||
| 290 | * is used in merging permitted NameConstraints. The operation | ||
| 291 | * is performed as follows: | ||
| 292 | * <ul> | ||
| 293 | * <li>If a name in other narrows all names of the same type in this, | ||
| 294 | * the result will contain the narrower name and none of the | ||
| 295 | * names it narrows. | ||
| 296 | * <li>If a name in other widens all names of the same type in this, | ||
| 297 | * the result will not contain the wider name. | ||
| 298 | * <li>If a name in other does not share the same subtree with any name | ||
| 299 | * of the same type in this, then the name is added to the list | ||
| 300 | * of GeneralSubtrees returned. These names should be added to | ||
| 301 | * the list of names that are specifically excluded. The reason | ||
| 302 | * is that, if the intersection is empty, then no names of that | ||
| 303 | * type are permitted, and the only way to express this in | ||
| 304 | * NameConstraints is to include the name in excludedNames. | ||
| 305 | * <li>If a name in this has no name of the same type in other, then | ||
| 306 | * the result contains the name in this. No name of a given type | ||
| 307 | * means the name type is completely permitted. | ||
| 308 | * <li>If a name in other has no name of the same type in this, then | ||
| 309 | * the result contains the name in other. This means that | ||
| 310 | * the name is now constrained in some way, whereas before it was | ||
| 311 | * completely permitted. | ||
| 312 | * <ul> | ||
| 313 | * | ||
| 314 | * @param other GeneralSubtrees to be intersected with this | ||
| 315 | * @returns GeneralSubtrees to be merged with excluded; these are | ||
| 316 | * empty-valued name types corresponding to entries that were | ||
| 317 | * of the same type but did not share the same subtree between | ||
| 318 | * this and other. Returns null if no such. | ||
| 319 | */ | ||
| 320 | public GeneralSubtrees intersect(GeneralSubtrees other) { | ||
| 321 | |||
| 322 | if (other == null) { | ||
| 323 | throw new NullPointerException("other GeneralSubtrees must not be null"); | ||
| 324 | } | ||
| 325 | |||
| 326 | GeneralSubtrees newThis = new GeneralSubtrees(); | ||
| 327 | GeneralSubtrees newExcluded = null; | ||
| 328 | |||
| 329 | // Step 1: If this is empty, just add everything in other to this and | ||
| 330 | // return no new excluded entries | ||
| 331 | if (size() == 0) { | ||
| 332 | union(other); | ||
| 333 | return null; | ||
| 334 | } | ||
| 335 | |||
| 336 | // Step 2: For ease of checking the subtrees, minimize them by | ||
| 337 | // constructing versions that contain only the widest instance of | ||
| 338 | // each type | ||
| 339 | this.minimize(); | ||
| 340 | other.minimize(); | ||
| 341 | |||
| 342 | // Step 3: Check each entry in this to see whether we keep it or | ||
| 343 | // remove it, and whether we add anything to newExcluded or newThis. | ||
| 344 | // We keep an entry in this unless it is narrowed by all entries in | ||
| 345 | // other. We add an entry to newExcluded if there is at least one | ||
| 346 | // entry of the same nameType in other, but this entry does | ||
| 347 | // not share the same subtree with any of the entries in other. | ||
| 348 | // We add an entry from other to newThis if there is no name of the | ||
| 349 | // same type in this. | ||
| 350 | for (int i = 0; i < size(); i++) { | ||
| 351 | GeneralNameInterface thisEntry = getGeneralNameInterface(i); | ||
| 352 | boolean removeThisEntry = false; | ||
| 353 | |||
| 354 | // Step 3a: If the widest name of this type in other narrows | ||
| 355 | // thisEntry, remove thisEntry and add widest other to newThis. | ||
| 356 | // Simultaneously, check for situation where there is a name of | ||
| 357 | // this type in other, but no name in other matches, narrows, | ||
| 358 | // or widens thisEntry. | ||
| 359 | boolean sameType = false; | ||
| 360 | for (int j = 0; j < other.size(); j++) { | ||
| 361 | GeneralSubtree otherEntryGS = other.get(j); | ||
| 362 | GeneralNameInterface otherEntry = | ||
| 363 | getGeneralNameInterface(otherEntryGS); | ||
| 364 | switch (thisEntry.constrains(otherEntry)) { | ||
| 365 | case NAME_NARROWS: | ||
| 366 | remove(i); | ||
| 367 | i--; | ||
| 368 | newThis.add(otherEntryGS); | ||
| 369 | sameType = false; | ||
| 370 | break; | ||
| 371 | case NAME_SAME_TYPE: | ||
| 372 | sameType = true; | ||
| 373 | continue; | ||
| 374 | case NAME_MATCH: | ||
| 375 | case NAME_WIDENS: | ||
| 376 | sameType = false; | ||
| 377 | break; | ||
| 378 | case NAME_DIFF_TYPE: | ||
| 379 | default: | ||
| 380 | continue; | ||
| 381 | } | ||
| 382 | break; | ||
| 383 | } | ||
| 384 | |||
| 385 | // Step 3b: If sameType is still true, we have the situation | ||
| 386 | // where there was a name of the same type as thisEntry in | ||
| 387 | // other, but no name in other widened, matched, or narrowed | ||
| 388 | // thisEntry. | ||
| 389 | if (sameType) { | ||
| 390 | |||
| 391 | // Step 3b.1: See if there are any entries in this and other | ||
| 392 | // with this type that match, widen, or narrow each other. | ||
| 393 | // If not, then we need to add a "widest subtree" of this | ||
| 394 | // type to excluded. | ||
| 395 | boolean intersection = false; | ||
| 396 | for (int j = 0; j < size(); j++) { | ||
| 397 | GeneralNameInterface thisAltEntry = getGeneralNameInterface(j); | ||
| 398 | |||
| 399 | if (thisAltEntry.getType() == thisEntry.getType()) { | ||
| 400 | for (int k = 0; k < other.size(); k++) { | ||
| 401 | GeneralNameInterface othAltEntry = | ||
| 402 | other.getGeneralNameInterface(k); | ||
| 403 | |||
| 404 | int constraintType = | ||
| 405 | thisAltEntry.constrains(othAltEntry); | ||
| 406 | if (constraintType == NAME_MATCH || | ||
| 407 | constraintType == NAME_WIDENS || | ||
| 408 | constraintType == NAME_NARROWS) { | ||
| 409 | intersection = true; | ||
| 410 | break; | ||
| 411 | } | ||
| 412 | } | ||
| 413 | } | ||
| 414 | } | ||
| 415 | if (intersection == false) { | ||
| 416 | if (newExcluded == null) { | ||
| 417 | newExcluded = new GeneralSubtrees(); | ||
| 418 | } | ||
| 419 | GeneralSubtree widestSubtree = | ||
| 420 | createWidestSubtree(thisEntry); | ||
| 421 | if (!newExcluded.contains(widestSubtree)) { | ||
| 422 | newExcluded.add(widestSubtree); | ||
| 423 | } | ||
| 424 | } | ||
| 425 | |||
| 426 | // Step 3b.2: Remove thisEntry from this | ||
| 427 | remove(i); | ||
| 428 | i--; | ||
| 429 | } | ||
| 430 | } | ||
| 431 | |||
| 432 | // Step 4: Add all entries in newThis to this | ||
| 433 | if (newThis.size() > 0) { | ||
| 434 | union(newThis); | ||
| 435 | } | ||
| 436 | |||
| 437 | // Step 5: Add all entries in other that do not have any entry of the | ||
| 438 | // same type in this to this | ||
| 439 | for (int i = 0; i < other.size(); i++) { | ||
| 440 | GeneralSubtree otherEntryGS = other.get(i); | ||
| 441 | GeneralNameInterface otherEntry = getGeneralNameInterface(otherEntryGS); | ||
| 442 | boolean diffType = false; | ||
| 443 | for (int j = 0; j < size(); j++) { | ||
| 444 | GeneralNameInterface thisEntry = getGeneralNameInterface(j); | ||
| 445 | switch (thisEntry.constrains(otherEntry)) { | ||
| 446 | case NAME_DIFF_TYPE: | ||
| 447 | diffType = true; | ||
| 448 | // continue to see if we find something later of the | ||
| 449 | // same type | ||
| 450 | continue; | ||
| 451 | case NAME_NARROWS: | ||
| 452 | case NAME_SAME_TYPE: | ||
| 453 | case NAME_MATCH: | ||
| 454 | case NAME_WIDENS: | ||
| 455 | diffType = false; // we found an entry of the same type | ||
| 456 | // break because we know we won't be adding it to | ||
| 457 | // this now | ||
| 458 | break; | ||
| 459 | default: | ||
| 460 | continue; | ||
| 461 | } | ||
| 462 | break; | ||
| 463 | } | ||
| 464 | if (diffType) { | ||
| 465 | add(otherEntryGS); | ||
| 466 | } | ||
| 467 | } | ||
| 468 | |||
| 469 | // Step 6: Return the newExcluded GeneralSubtrees | ||
| 470 | return newExcluded; | ||
| 471 | } | ||
| 472 | |||
| 473 | /** | ||
| 474 | * construct union of this GeneralSubtrees with other. | ||
| 475 | * | ||
| 476 | * @param other GeneralSubtrees to be united with this | ||
| 477 | */ | ||
| 478 | public void union(GeneralSubtrees other) { | ||
| 479 | if (other != null) { | ||
| 480 | for (int i = 0, n = other.size(); i < n; i++) { | ||
| 481 | add(other.get(i)); | ||
| 482 | } | ||
| 483 | // Minimize this | ||
| 484 | minimize(); | ||
| 485 | } | ||
| 486 | } | ||
| 487 | |||
| 488 | /** | ||
| 489 | * reduce this GeneralSubtrees by contents of another. This function | ||
| 490 | * is used in merging excluded NameConstraints with permitted NameConstraints | ||
| 491 | * to obtain a minimal form of permitted NameConstraints. It is an | ||
| 492 | * optimization, and does not affect correctness of the results. | ||
| 493 | * | ||
| 494 | * @param excluded GeneralSubtrees | ||
| 495 | */ | ||
| 496 | public void reduce(GeneralSubtrees excluded) { | ||
| 497 | if (excluded == null) { | ||
| 498 | return; | ||
| 499 | } | ||
| 500 | for (int i = 0, n = excluded.size(); i < n; i++) { | ||
| 501 | GeneralNameInterface excludedName = excluded.getGeneralNameInterface(i); | ||
| 502 | for (int j = 0; j < size(); j++) { | ||
| 503 | GeneralNameInterface permitted = getGeneralNameInterface(j); | ||
| 504 | switch (excludedName.constrains(permitted)) { | ||
| 505 | case GeneralNameInterface.NAME_DIFF_TYPE: | ||
| 506 | break; | ||
| 507 | case GeneralNameInterface.NAME_MATCH: | ||
| 508 | remove(j); | ||
| 509 | j--; | ||
| 510 | break; | ||
| 511 | case GeneralNameInterface.NAME_NARROWS: | ||
| 512 | /* permitted narrows excluded */ | ||
| 513 | remove(j); | ||
| 514 | j--; | ||
| 515 | break; | ||
| 516 | case GeneralNameInterface.NAME_WIDENS: | ||
| 517 | /* permitted widens excluded */ | ||
| 518 | break; | ||
| 519 | case GeneralNameInterface.NAME_SAME_TYPE: | ||
| 520 | break; | ||
| 521 | } | ||
| 522 | } /* end of this pass of permitted */ | ||
| 523 | } /* end of pass of excluded */ | ||
| 524 | } | ||
| 525 | } | ||