1 19 20 package org.netbeans.modules.apisupport.project; 21 22 import java.io.BufferedReader ; 23 import java.io.IOException ; 24 import java.io.InputStream ; 25 import java.io.InputStreamReader ; 26 import java.io.OutputStream ; 27 import java.io.OutputStreamWriter ; 28 import java.io.Writer ; 29 import java.util.ArrayList ; 30 import java.util.Collections ; 31 import java.util.HashSet ; 32 import java.util.Iterator ; 33 import java.util.LinkedList ; 34 import java.util.List ; 35 import java.util.Locale ; 36 import java.util.Set ; 37 import java.util.regex.Matcher ; 38 import java.util.regex.Pattern ; 39 40 52 public final class EditableManifest { 53 54 private static final String MANIFEST_VERSION = "Manifest-Version"; private static final String MANIFEST_VERSION_VALUE = "1.0"; 57 private final Section mainSection; 58 private final List <Section> sections; 59 60 64 public EditableManifest() { 65 try { 66 mainSection = new Section(Collections.singletonList(new Line(MANIFEST_VERSION, MANIFEST_VERSION_VALUE)), true, 1); 67 } catch (IOException e) { 68 throw new AssertionError (e); 69 } 70 sections = new ArrayList (); 71 } 72 73 78 public EditableManifest(InputStream is) throws IOException { 79 BufferedReader r = new BufferedReader (new InputStreamReader (is, "UTF-8")); sections = new LinkedList (); 81 String text; 82 int blankLines = 0; 83 List <Line> lines = new ArrayList (); 84 Section _mainSection = null; 85 while (true) { 86 text = r.readLine(); 87 if (text == null || (text.length() > 0 && blankLines > 0)) { 88 Section s = new Section(lines, _mainSection == null, blankLines); 89 if (_mainSection == null) { 90 _mainSection = s; 91 } else { 92 sections.add(s); 93 } 94 lines.clear(); 95 blankLines = 0; 96 } 97 if (text != null) { 98 if (text.length() > 0) { 99 Line line; 100 if (text.charAt(0) == ' ') { 101 if (lines.isEmpty()) { 102 throw new IOException ("Continuation lines only allowed for attributes"); } 104 Line prev = (Line) lines.remove(lines.size() - 1); 105 line = new Line(prev.name, prev.value + text.substring(1), prev.text + System.getProperty("line.separator") + text); 106 } else { 107 line = new Line(text); 108 } 109 lines.add(line); 110 } else { 111 blankLines++; 112 } 113 } else { 114 break; 115 } 116 } 117 mainSection = _mainSection; 118 Set <String > names = new HashSet (); 119 Iterator it = sections.iterator(); 120 while (it.hasNext()) { 121 Section s = (Section) it.next(); 122 if (!names.add(s.name)) { 123 throw new IOException ("Duplicated section names: " + s.name); } 125 } 126 } 127 128 133 public void write(OutputStream os) throws IOException { 134 Writer w = new OutputStreamWriter (os, "UTF-8"); mainSection.write(w, !sections.isEmpty()); 136 Iterator it = sections.iterator(); 137 while (it.hasNext()) { 138 ((Section) it.next()).write(w, it.hasNext()); 139 } 140 w.flush(); 141 } 142 143 150 public void addSection(String name) throws IllegalArgumentException { 151 if (name == null) { 152 throw new IllegalArgumentException (); 153 } 154 if (findSection(name) != null) { 155 throw new IllegalArgumentException (name); 156 } 157 int i; 158 for (i = 0; i < sections.size(); i++) { 159 Section s = (Section) sections.get(i); 160 if (s.name.compareTo(name) > 0) { 161 break; 162 } 163 } 164 sections.add(i, new Section(name)); 165 } 166 167 172 public void removeSection(String name) throws IllegalArgumentException { 173 if (name == null) { 174 throw new IllegalArgumentException (); 175 } 176 Iterator it = sections.iterator(); 177 while (it.hasNext()) { 178 Section s = (Section) it.next(); 179 if (s.name.equals(name)) { 180 it.remove(); 181 return; 182 } 183 } 184 throw new IllegalArgumentException (name); 185 } 186 187 191 public Set <String > getSectionNames() { 192 Set <String > names = new HashSet (); 193 Iterator it = sections.iterator(); 194 while (it.hasNext()) { 195 Section s = (Section) it.next(); 196 names.add(s.name); 197 } 198 return names; 199 } 200 201 private Section findSection(String section) { 202 if (section == null) { 203 return mainSection; 204 } else { 205 Iterator it = sections.iterator(); 206 while (it.hasNext()) { 207 Section s = (Section) it.next(); 208 if (s.name.equals(section)) { 209 return s; 210 } 211 } 212 return null; 213 } 214 } 215 216 223 public String getAttribute(String name, String section) throws IllegalArgumentException { 224 Section s = findSection(section); 225 if (s == null) { 226 throw new IllegalArgumentException (section); 227 } 228 return s.getAttribute(name); 229 } 230 231 240 public void setAttribute(String name, String value, String section) throws IllegalArgumentException { 241 Section s = findSection(section); 242 if (s == null) { 243 throw new IllegalArgumentException (section); 244 } 245 s.setAttribute(name, value); 246 } 247 248 254 public void removeAttribute(String name, String section) throws IllegalArgumentException { 255 Section s = findSection(section); 256 if (s == null) { 257 throw new IllegalArgumentException (section); 258 } 259 s.removeAttribute(name); 260 } 261 262 267 public Set <String > getAttributeNames(String section) throws IllegalArgumentException { 268 Section s = findSection(section); 269 if (s == null) { 270 throw new IllegalArgumentException (section); 271 } 272 return s.getAttributeNames(); 273 } 274 275 private static final class Line { 276 277 private static final Pattern NAME_VALUE = Pattern.compile("([^: ]+) *: *(.*)"); 279 public final String text; 280 public final String name; 281 public final String value; 282 283 public Line(String text) throws IOException { 284 this.text = text; 285 assert text.length() > 0; 286 Matcher m = NAME_VALUE.matcher(text); 287 if (m.matches()) { 288 name = m.group(1); 289 value = m.group(2); 290 } else { 291 throw new IOException ("Malformed line: " + text); } 293 } 294 295 public Line(String name, String value) { 296 this(name, value, name + ": " + value); } 298 299 public Line(String name, String value, String text) { 300 this.name = name; 301 this.value = value; 302 this.text = text; 303 } 304 305 public void write(Writer w) throws IOException { 306 w.write(text); 307 newline(w); 308 } 309 310 } 311 312 private static void newline(Writer w) throws IOException { 313 w.write(System.getProperty("line.separator")); } 315 316 private static final class Section { 317 318 private static final String NAME = "Name"; 320 public final String name; 321 private final List <Line> lines; 322 private final int blankLinesAfter; 323 324 public Section(List <Line> lines, boolean main, int blankLinesAfter) throws IOException { 325 this.lines = new ArrayList (lines); 326 this.blankLinesAfter = blankLinesAfter; 327 if (main) { 328 name = null; 329 if (!lines.isEmpty()) { 330 Line first = (Line) lines.get(0); 331 if (first.name.equalsIgnoreCase(NAME)) { 332 throw new IOException ("Cannot start with a named section"); } 334 } 335 } else { 336 assert !lines.isEmpty(); 337 Line first = (Line) lines.get(0); 338 if (!first.name.equalsIgnoreCase(NAME)) { 339 throw new IOException ("Section did not start with " + NAME); } 341 name = first.value; 342 if (name.length() == 0) { 343 throw new IOException ("Cannot have a blank section name"); } 345 } 346 Set <String > attrNames = new HashSet (); 347 Iterator it = lines.iterator(); 348 if (!main) { 349 it.next(); 350 } 351 while (it.hasNext()) { 352 String name = ((Line) it.next()).name; 353 if (name.equals(NAME)) { 354 throw new IOException ("Sections not separated by blank lines"); } else if (!attrNames.add(name.toLowerCase(Locale.US))) { 356 throw new IOException ("Duplicated attributes in a section: " + name); } 358 } 359 } 360 361 public Section(String name) { 362 this.name = name; 363 lines = new ArrayList (); 364 lines.add(new Line(NAME, name)); blankLinesAfter = 1; 366 } 367 368 private Line findAttribute(String name) { 369 Iterator it = lines.iterator(); 370 if (this.name != null) { 371 it.next(); 372 } 373 while (it.hasNext()) { 374 Line line = (Line) it.next(); 375 if (line.name.equalsIgnoreCase(name)) { 376 return line; 377 } 378 } 379 return null; 380 } 381 382 private int findAttributeIndex(String name) { 383 for (int i = (this.name != null ? 1 : 0); i < lines.size(); i++) { 384 Line line = (Line) lines.get(i); 385 if (line.name.equalsIgnoreCase(name)) { 386 return i; 387 } 388 } 389 return -1; 390 } 391 392 public String getAttribute(String name) { 393 Line line = findAttribute(name); 394 if (line != null) { 395 return line.value; 396 } else { 397 return null; 398 } 399 } 400 401 public void setAttribute(String name, String value) { 402 for (int i = (this.name != null ? 1 : 0); i < lines.size(); i++) { 403 Line line = (Line) lines.get(i); 404 if (name.equalsIgnoreCase(line.name)) { 405 if (line.value.equals(value)) { 406 return; 408 } 409 lines.remove(i); 411 int insertionPoint = name.equalsIgnoreCase(MANIFEST_VERSION) ? 0 : i; 412 lines.add(insertionPoint, new Line(name, value)); 413 return; 414 } 415 } 416 int insertionPoint; 418 if (name.equalsIgnoreCase(MANIFEST_VERSION)) { 419 insertionPoint = 0; 420 } else { 421 insertionPoint = lines.size(); 422 for (int i = (this.name != null ? 1 : 0); i < lines.size(); i++) { 423 Line line = (Line) lines.get(i); 424 int comp = line.name.compareToIgnoreCase(name); 425 assert comp != 0; 426 if (comp > 0 && !line.name.equalsIgnoreCase(MANIFEST_VERSION)) { 427 insertionPoint = i; 428 break; 429 } 430 } 431 } 432 lines.add(insertionPoint, new Line(name, value)); 433 } 434 435 public void removeAttribute(String name) throws IllegalArgumentException { 436 int i = findAttributeIndex(name); 437 if (i != -1) { 438 lines.remove(i); 439 } else { 440 throw new IllegalArgumentException (name); 441 } 442 } 443 444 public Set <String > getAttributeNames() { 445 Set <String > attrNames = new HashSet (); 446 Iterator it = lines.iterator(); 447 if (name != null) { 448 it.next(); 449 } 450 while (it.hasNext()) { 451 attrNames.add(((Line) it.next()).name); 452 } 453 return attrNames; 454 } 455 456 public void write(Writer w, boolean forceBlankLine) throws IOException { 457 Iterator it = lines.iterator(); 458 while (it.hasNext()) { 459 Line line = (Line) it.next(); 460 line.write(w); 461 } 462 for (int i = 0; i < blankLinesAfter; i++) { 463 newline(w); 464 } 465 if (forceBlankLine && blankLinesAfter == 0) { 466 newline(w); 467 } 468 } 469 470 } 471 472 } 473 | Popular Tags |