1 19 20 package org.openide.modules; 21 22 import java.util.Collections ; 23 import java.util.HashMap ; 24 import java.util.HashSet ; 25 import java.util.Map ; 26 import java.util.Set ; 27 import java.util.StringTokenizer ; 28 import org.openide.util.Utilities; 29 30 34 public final class Dependency { 35 36 public final static int TYPE_MODULE = 1; 37 38 39 public final static int TYPE_PACKAGE = 2; 40 41 42 public final static int TYPE_JAVA = 3; 43 44 48 @Deprecated 49 public final static int TYPE_IDE = 4; 50 51 55 public final static int TYPE_REQUIRES = 5; 56 57 61 public final static int TYPE_NEEDS = 6; 62 63 70 public final static int TYPE_RECOMMENDS = 7; 71 72 73 public final static int COMPARE_SPEC = 1; 74 75 76 public final static int COMPARE_IMPL = 2; 77 78 79 public final static int COMPARE_ANY = 3; 80 81 82 @Deprecated 83 public static final String IDE_NAME = System.getProperty("org.openide.major.version", "IDE"); 85 86 @Deprecated 87 public static final SpecificationVersion IDE_SPEC = makeSpec( 88 System.getProperty("org.openide.specification.version") 89 ); 91 92 @Deprecated 93 public static final String IDE_IMPL = System.getProperty("org.openide.version"); 95 96 public static final String JAVA_NAME = "Java"; 98 99 public static final SpecificationVersion JAVA_SPEC = makeSpec(System.getProperty("java.specification.version")); 101 102 public static final String JAVA_IMPL = System.getProperty("java.version"); 104 105 public static final String VM_NAME = "VM"; 107 108 public static final SpecificationVersion VM_SPEC = makeSpec(System.getProperty("java.vm.specification.version")); 110 111 public static final String VM_IMPL = System.getProperty("java.vm.version"); private final int type; 113 private final int comparison; 114 private final String name; 115 private final String version; 116 117 private Dependency(int type, String name, int comparison, String version) { 118 this.type = type; 119 this.name = name.intern(); 120 this.comparison = comparison; 121 this.version = (version != null) ? version.intern() : null; 122 } 123 124 127 private static void checkCodeName(String codeName, boolean slashOK) 128 throws IllegalArgumentException { 129 String base; 130 int slash = codeName.indexOf('/'); 132 if (slash == -1) { 133 base = codeName; 134 } else { 135 if (!slashOK) { 136 throw new IllegalArgumentException ("No slash permitted in: " + codeName); } 138 139 base = codeName.substring(0, slash); 140 141 String rest = codeName.substring(slash + 1); 142 int dash = rest.indexOf('-'); 144 try { 145 if (dash == -1) { 146 int release = Integer.parseInt(rest); 147 148 if (release < 0) { 149 throw new IllegalArgumentException ("Negative release number: " + codeName); } 151 } else { 152 int release = Integer.parseInt(rest.substring(0, dash)); 153 int releaseMax = Integer.parseInt(rest.substring(dash + 1)); 154 155 if (release < 0) { 156 throw new IllegalArgumentException ("Negative release number: " + codeName); } 158 159 if (releaseMax <= release) { 160 throw new IllegalArgumentException ("Release number range must be increasing: " + codeName); } 162 } 163 } catch (NumberFormatException e) { 164 throw new IllegalArgumentException (e.toString()); 165 } 166 } 167 168 StringTokenizer tok = new StringTokenizer (base, ".", true); 171 if ((tok.countTokens() % 2) == 0) { 172 throw new NumberFormatException ("Even number of pieces: " + base); } 174 175 boolean expectingPath = true; 176 177 while (tok.hasMoreTokens()) { 178 if (expectingPath) { 179 expectingPath = false; 180 181 String nt = tok.nextToken(); 182 if (!Utilities.isJavaIdentifier(nt) && !"enum".equals (nt)) { throw new IllegalArgumentException ("Bad package component in " + base); } 185 } else { 186 if (!".".equals(tok.nextToken())) { throw new NumberFormatException ("Expected dot in code name: " + base); } 189 190 expectingPath = true; 191 } 192 } 193 } 194 195 201 public static Set <Dependency> create(int type, String body) throws IllegalArgumentException { 202 if (body == null) { 203 return Collections.emptySet(); 204 } 205 206 Set <Dependency> deps = new HashSet <Dependency>(5); 207 208 StringTokenizer tok = new StringTokenizer (body, ","); 211 if (!tok.hasMoreTokens()) { 212 throw new IllegalArgumentException ("No deps given: \"" + body + "\""); } 214 215 Map <DependencyKey, Dependency> depsByKey = new HashMap <DependencyKey, Dependency>(11); 216 217 while (tok.hasMoreTokens()) { 218 String onedep = tok.nextToken(); 219 StringTokenizer tok2 = new StringTokenizer (onedep, " \t\n\r"); 221 if (!tok2.hasMoreTokens()) { 222 throw new IllegalArgumentException ("No name in dependency: " + onedep); } 224 225 String name = tok2.nextToken(); 226 int comparison; 227 String version; 228 229 if (tok2.hasMoreTokens()) { 230 String compthing = tok2.nextToken(); 231 232 if (compthing.equals(">")) { comparison = Dependency.COMPARE_SPEC; 234 } else if (compthing.equals("=")) { comparison = Dependency.COMPARE_IMPL; 236 } else { 237 throw new IllegalArgumentException ("Strange comparison string: " + compthing); } 239 240 if (!tok2.hasMoreTokens()) { 241 throw new IllegalArgumentException ("Comparison string without version: " + onedep); } 243 244 version = tok2.nextToken(); 245 246 if (tok2.hasMoreTokens()) { 247 throw new IllegalArgumentException ("Trailing garbage in dependency: " + onedep); } 249 250 if (comparison == Dependency.COMPARE_SPEC) { 251 try { 252 new SpecificationVersion(version); 253 } catch (NumberFormatException nfe) { 254 throw new IllegalArgumentException (nfe.toString()); 255 } 256 } 257 } else { 258 comparison = Dependency.COMPARE_ANY; 259 version = null; 260 } 261 262 if (type == Dependency.TYPE_MODULE) { 263 checkCodeName(name, true); 264 265 if ((name.indexOf('-') != -1) && (comparison == Dependency.COMPARE_IMPL)) { 266 throw new IllegalArgumentException ( 267 "Cannot have an implementation dependency on a ranged release version: " + onedep 268 ); } 270 } else if (type == Dependency.TYPE_PACKAGE) { 271 int idx = name.indexOf('['); 272 273 if (idx != -1) { 274 if (idx > 0) { 275 checkCodeName(name.substring(0, idx), false); 276 } 277 278 if (name.charAt(name.length() - 1) != ']') { 279 throw new IllegalArgumentException ("No close bracket on package dep: " + name); } 281 282 checkCodeName(name.substring(idx + 1, name.length() - 1), false); 283 } else { 284 checkCodeName(name, false); 285 } 286 287 if ((idx == 0) && (comparison != Dependency.COMPARE_ANY)) { 288 throw new IllegalArgumentException ( 289 "Cannot use a version comparison on a package dependency when only a sample class is given" 290 ); } 292 293 if ((idx > 0) && (name.substring(idx + 1, name.length() - 1).indexOf('.') != -1)) { 294 throw new IllegalArgumentException ( 295 "Cannot have a sample class with dots when package is specified" 296 ); } 298 } else if (type == Dependency.TYPE_JAVA) { 299 if (!(name.equals(JAVA_NAME) || name.equals(VM_NAME))) { throw new IllegalArgumentException ("Java dependency must be on \"Java\" or \"VM\": " + name); } 302 303 if (comparison == Dependency.COMPARE_ANY) { 304 throw new IllegalArgumentException ("Must give a comparison for a Java dep: " + body); } 306 } else if (type == Dependency.TYPE_IDE) { 307 if (!(name.equals("IDE"))) { 309 int slash = name.indexOf("/"); boolean ok; 311 312 if (slash == -1) { 313 ok = false; 314 } else { 315 if (!name.substring(0, slash).equals("IDE")) { ok = false; 317 } 318 319 try { 320 int v = Integer.parseInt(name.substring(slash + 1)); 321 ok = (v >= 0); 322 } catch (NumberFormatException e) { 323 ok = false; 324 } 325 } 326 327 if (!ok) { 328 throw new IllegalArgumentException ("Invalid IDE dependency: " + name); } 330 } 331 332 if (comparison == Dependency.COMPARE_ANY) { 333 throw new IllegalArgumentException ("Must give a comparison for an IDE dep: " + body); } 335 } else if (type == Dependency.TYPE_REQUIRES) { 336 if (comparison != Dependency.COMPARE_ANY) { 337 throw new IllegalArgumentException ("Cannot give a comparison for a token requires dep: " + body); } 339 340 checkCodeName(name, false); 341 } else if (type == Dependency.TYPE_NEEDS) { 342 if (comparison != Dependency.COMPARE_ANY) { 343 throw new IllegalArgumentException ("Cannot give a comparison for a token needs dep: " + body); } 345 346 checkCodeName(name, false); 347 } else if (type == Dependency.TYPE_RECOMMENDS) { 348 if (comparison != Dependency.COMPARE_ANY) { 349 throw new IllegalArgumentException ("Cannot give a comparison for a token needs dep: " + body); } 351 352 checkCodeName(name, false); 353 } else { 354 throw new IllegalArgumentException ("unknown type"); } 356 357 Dependency nue = new Dependency(type, name, comparison, version); 358 DependencyKey key = new DependencyKey(nue); 359 360 if (depsByKey.containsKey(key)) { 361 throw new IllegalArgumentException ( 362 "Dependency " + nue + " duplicates the similar dependency " + depsByKey.get(key) 363 ); } else { 365 deps.add(nue); 366 depsByKey.put(key, nue); 367 } 368 } 369 370 return deps; 371 } 372 373 374 public final int getType() { 375 return type; 376 } 377 378 379 public final String getName() { 380 return name; 381 } 382 383 384 public final int getComparison() { 385 return comparison; 386 } 387 388 389 public final String getVersion() { 390 return version; 391 } 392 393 394 public boolean equals(Object o) { 395 if (o.getClass() != Dependency.class) { 396 return false; 397 } 398 399 Dependency d = (Dependency) o; 400 401 return (type == d.type) && (comparison == d.comparison) && name.equals(d.name) && 402 Utilities.compareObjects(version, d.version); 403 } 404 405 406 public int hashCode() { 407 return 772067 ^ type ^ name.hashCode(); 408 } 409 410 411 public String toString() { 412 StringBuffer buf = new StringBuffer (100); 413 414 if (type == TYPE_MODULE) { 415 buf.append("module "); } else if (type == TYPE_PACKAGE) { 417 buf.append("package "); } else if (type == TYPE_REQUIRES) { 419 buf.append("requires "); } else if (type == TYPE_NEEDS) { 421 buf.append("needs "); } else if (type == TYPE_RECOMMENDS) { 423 buf.append("recommends "); } 425 426 buf.append(name); 427 428 if (comparison == COMPARE_IMPL) { 429 buf.append(" = "); buf.append(version); 431 } else if (comparison == COMPARE_SPEC) { 432 buf.append(" > "); buf.append(version); 434 } 435 436 return buf.toString(); 437 } 438 439 443 private static SpecificationVersion makeSpec(String vers) { 444 if (vers != null) { 445 try { 446 return new SpecificationVersion(vers); 447 } catch (NumberFormatException nfe) { 448 System.err.println("WARNING: invalid specification version: " + vers); } 450 451 do { 452 vers = vers.substring(0, vers.length() - 1); 453 454 try { 455 return new SpecificationVersion(vers); 456 } catch (NumberFormatException nfe) { 457 } 459 } while (vers.length() > 0); 460 } 461 462 return new SpecificationVersion("0"); } 465 466 477 private static final class DependencyKey { 478 private final int type; 479 private final String name; 480 481 public DependencyKey(Dependency d) { 482 type = d.getType(); 483 484 switch (type) { 485 case TYPE_MODULE: 486 case TYPE_IDE: 487 488 String codeName = d.getName(); 489 int idx = codeName.lastIndexOf('/'); 490 491 if (idx == -1) { 492 name = codeName; 493 } else { 494 name = codeName.substring(0, idx); 495 } 496 497 break; 498 499 case TYPE_PACKAGE: 500 501 String pkgName = d.getName(); 502 idx = pkgName.indexOf('['); 503 504 if (idx != -1) { 505 if (idx == 0) { 506 name = pkgName; 509 } else { 510 name = pkgName.substring(0, idx); 512 } 513 } else { 514 name = pkgName; 516 } 517 518 break; 519 520 default: 521 522 name = d.getName(); 524 525 break; 526 } 527 528 } 530 531 public int hashCode() { 532 return name.hashCode(); 533 } 534 535 public boolean equals(Object o) { 536 return (o instanceof DependencyKey) && ((DependencyKey) o).name.equals(name) && 537 (((DependencyKey) o).type == type); 538 } 539 540 public String toString() { 541 return "DependencyKey[" + name + "," + type + "]"; } 543 } 544 } 545 | Popular Tags |