001/** 002 * Copyright 2011 Bill Brown 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.colorfulsoftware.rss; 017 018import java.io.ByteArrayInputStream; 019import java.io.File; 020import java.io.FileInputStream; 021import java.io.FileOutputStream; 022import java.io.InputStream; 023import java.io.OutputStream; 024import java.io.Serializable; 025import java.io.StringWriter; 026import java.lang.reflect.Constructor; 027import java.util.List; 028import java.util.Properties; 029 030import javax.xml.stream.XMLInputFactory; 031import javax.xml.stream.XMLOutputFactory; 032import javax.xml.stream.XMLStreamWriter; 033 034/** 035 * <p> 036 * This class reads and writes RSS documents to and from xml files, objects or 037 * Strings. It contains all of the factory methods for building immutable copies 038 * of the object elements. 039 * </p> 040 * 041 * <p> 042 * Here are some examples of how to use the RSSpect library in your application: 043 * <br /> 044 * <ul style="margin-left:15px;"> 045 * <li>Read a file from disk into an RSS bean.<br /> 046 * <code style="margin-left:20px;padding-bottom:10px;font-style: italic;">RSS myRSS = new RSSDoc().readRSSToBean(new File("/myPath/myRSS.xml");</code> 047 * </li> 048 * <li>Read a file from the web into an RSS bean.<br /> 049 * <code style="margin-left:20px;padding-bottom:10px;font-style: italic;">RSS myRSS = new RSSDoc().readRSSToBean(new URL("http://www.abcdefg.net/myRSS.xml");</code> 050 * </li> 051 * <li>Read an RSS bean into a String.<br /> 052 * <code style="margin-left:20px;padding-bottom:10px;font-style: italic;">String myRssStr = myRSS.toString();</code> 053 * </li> 054 * <li>Read an RSS bean into a formatted String.<br /> 055 * <code style="margin-left:20px;padding-bottom:10px;font-style: italic;">String myRssStr = new RSSDoc().readRSSToString(myRSS, "javanet.staxutils.IndentingXMLStreamWriter");</code> 056 * </li> 057 * <li>Write an RSS bean to disk.<br /> 058 * <code style="margin-left:20px;padding-bottom:10px;font-style: italic;">String myRssStr = new RSSDoc().writeRSSDoc(new File("/somewhere/myRSS.xml"), myRSS, "UTF-8", "1.0");</code> 059 * </li> 060 * <li>Write a formatted RSS bean to disk.<br /> 061 * <code style="margin-left:20px;padding-bottom:10px;font-style: italic;">String myRssStr = new RSSDoc().writeRSSDoc(new javanet.staxutils.IndentingXMLStreamWriter( XMLOutputFactory.newInstance().createXMLStreamWriter( new FileOutputStream("/somewhere/myRSS.xml"), "UTF-8")), myRSS, "UTF-8", "1.0");</code> 062 * </li> 063 * </ul> 064 * 065 * 066 * @author Bill Brown 067 * 068 */ 069public final class RSSDoc implements Serializable { 070 071 private static final long serialVersionUID = 649162683570000798L; 072 073 /** 074 * the default document encoding of "UTF-8" 075 */ 076 private String encoding = System.getProperty("file.encoding"); 077 078 /** 079 * the default XML version of "1.0" 080 */ 081 private String xmlVersion = "1.0"; 082 083 private Generator libVersion; 084 085 private XMLInputFactory inputFactory; 086 087 private List<ProcessingInstruction> processingInstructions; 088 089 /** 090 * @throws Exception 091 * if the rsspect.properties file cant be read. 092 * 093 */ 094 public RSSDoc() throws Exception { 095 Properties props = new Properties(); 096 props.load(RSSDoc.class.getResourceAsStream("/rsspect.properties")); 097 String libUri = props.getProperty("uri"); 098 String libVersionStr = props.getProperty("version"); 099 100 libVersion = new Generator(libUri + " v" + libVersionStr); 101 inputFactory = XMLInputFactory.newInstance(); 102 // this is done to help for parsing documents that have undeclared and 103 // unescaped html or xhtml entities. 104 inputFactory.setProperty( 105 "javax.xml.stream.isReplacingEntityReferences", Boolean.FALSE); 106 } 107 108 /** 109 * @param processingInstructions 110 * xml processing instructions. 111 * @throws Exception 112 * if the library version information cannot be loaded from the 113 * environment. 114 */ 115 public RSSDoc(List<ProcessingInstruction> processingInstructions) 116 throws Exception { 117 this(); 118 this.processingInstructions = processingInstructions; 119 } 120 121 class ProcessingInstruction implements Serializable { 122 private final String target; 123 private final String data; 124 private static final long serialVersionUID = -4261298860522801834L; 125 126 ProcessingInstruction(String target, String data) { 127 this.target = target; 128 this.data = data; 129 } 130 131 /** 132 * @return the target of the processing instruction 133 */ 134 public String getTarget() { 135 return target; 136 } 137 138 /** 139 * @return the processing instruction data. 140 */ 141 public String getData() { 142 return data; 143 } 144 } 145 146 /** 147 * @return the RSSpect library version in the form of a generator element. 148 * This element is output for all feeds that are generated by 149 * RSSpect. 150 */ 151 public Generator getLibVersion() { 152 return new Generator(libVersion); 153 } 154 155 /** 156 * 157 * @param output 158 * the target output stream for the rss document. 159 * @param rss 160 * the rss object containing the content of the feed 161 * @param encoding 162 * the file encoding (default is UTF-8) 163 * @param version 164 * the xml version (default is 1.0) 165 * @throws Exception 166 * thrown if the feed cannot be written to the output 167 */ 168 public void writeRSSDoc(OutputStream output, RSS rss, String encoding, 169 String version) throws Exception { 170 writeRSSOutput(rss, XMLOutputFactory.newInstance() 171 .createXMLStreamWriter(output, encoding), encoding, version); 172 173 } 174 175 /** 176 * 177 * @param file 178 * the target output file for the document. 179 * @param rss 180 * the rss object containing the content of the feed 181 * @param encoding 182 * the file encoding (default is UTF-8) 183 * @param version 184 * the xml version (default is 1.0) 185 * @throws Exception 186 * thrown if the feed cannot be written to the output 187 */ 188 public void writeRSSDoc(File file, RSS rss, String encoding, String version) 189 throws Exception { 190 writeRSSOutput(rss, XMLOutputFactory.newInstance() 191 .createXMLStreamWriter(new FileOutputStream(file), encoding), 192 encoding, version); 193 } 194 195 /** 196 * For example: to pass the TXW 197 * com.sun.xml.txw2.output.IndentingXMLStreamWriter or the stax-utils 198 * javanet.staxutils.IndentingXMLStreamWriter for indented printing do this: 199 * 200 * <pre> 201 * XmlStreamWriter writer = new IndentingXMLStreamWriter(XMLOutputFactory 202 * .newInstance().createXMLStreamWriter( 203 * new FileOutputStream(outputFilePath), encoding)); 204 * RSSDoc.writeFeedDoc(writer, myFeed, null, null); 205 * </pre> 206 * 207 * @param output 208 * the target output for the feed. 209 * @param rss 210 * the rss object containing the content of the feed 211 * @param encoding 212 * the file encoding (default is UTF-8) 213 * @param version 214 * the xml version (default is 1.0) 215 * @throws Exception 216 * thrown if the feed cannot be written to the output 217 */ 218 public void writeRSSDoc(XMLStreamWriter output, RSS rss, String encoding, 219 String version) throws Exception { 220 writeRSSOutput(rss, output, encoding, version); 221 } 222 223 /** 224 * This method reads in a Feed element and returns the contents as an rss 225 * feed string with formatting specified by the fully qualified 226 * XMLStreamWriter class name (uses reflection internally). For example you 227 * can pass the TXW com.sun.xml.txw2.output.IndentingXMLStreamWriter or the 228 * stax-utils javanet.staxutils.IndentingXMLStreamWriter for indented 229 * printing. It will fall back to the feeds' toString() method if the 230 * xmlStreamWriter is not recognized. 231 * 232 * if the XMLStreamWriter class cannot be found in the classpath. 233 * 234 * @param rss 235 * the rss object to be converted to an rss document string. 236 * @param xmlStreamWriter 237 * the fully qualified XMLStreamWriter class name. 238 * @return an rss feed document string. 239 * @throws Exception 240 * thrown if the feed cannot be returned as a String 241 */ 242 public String readRSSToString(RSS rss, String xmlStreamWriter) 243 throws Exception { 244 if (rss == null) { 245 throw new RSSpectException("The rss feed object cannot be null."); 246 } 247 try { 248 StringWriter theString = new StringWriter(); 249 if (xmlStreamWriter == null || xmlStreamWriter.equals("")) { 250 writeRSSOutput(rss, XMLOutputFactory.newInstance() 251 .createXMLStreamWriter(theString), encoding, xmlVersion); 252 } else { 253 Class<?> cls = Class.forName(xmlStreamWriter); 254 Constructor<?> ct = cls 255 .getConstructor(new Class[] { XMLStreamWriter.class }); 256 Object arglist[] = new Object[] { XMLOutputFactory 257 .newInstance().createXMLStreamWriter(theString) }; 258 XMLStreamWriter writer = (XMLStreamWriter) ct 259 .newInstance(arglist); 260 261 writeRSSOutput(rss, writer, encoding, xmlVersion); 262 } 263 264 return theString.toString(); 265 266 // if the xmlStreamWriter cannot be found, return the default 267 } catch (Exception e) { 268 return rss.toString(); 269 } 270 } 271 272 /** 273 * This method reads an xml string into a Feed element. 274 * 275 * @param xmlString 276 * the xml string to be transformed into a RSS element. 277 * @return the RSS element 278 * @throws Exception 279 * if the string cannot be parsed into a RSS element. 280 */ 281 public RSS readRSSToBean(String xmlString) throws Exception { 282 // try to grab the encoding first: 283 if (xmlString.contains("encoding=\"")) { 284 String localEncoding = xmlString.substring(xmlString 285 .indexOf("encoding=\"") + 10); 286 localEncoding = localEncoding.substring(0, localEncoding 287 .indexOf('"')); 288 encoding = localEncoding; 289 290 } 291 return new RSSReader(this).readRSS(inputFactory 292 .createXMLStreamReader(new ByteArrayInputStream(xmlString 293 .getBytes(encoding)))); 294 } 295 296 /** 297 * This method reads an xml File object into a Feed element. 298 * 299 * @param file 300 * the file object representing an rss feed. 301 * @return the RSS element. 302 * @throws Exception 303 * if the file cannot be parsed into a RSS element. 304 */ 305 public RSS readRSSToBean(File file) throws Exception { 306 return new RSSReader(this).readRSS(inputFactory 307 .createXMLStreamReader(new FileInputStream(file))); 308 } 309 310 /** 311 * This method reads an rss file from a URL into a Feed element. 312 * 313 * @param url 314 * the Internet network location of an rss file. 315 * @return the RSS element. 316 * @throws Exception 317 * if the URL cannot be parsed into a RSS element. 318 */ 319 public RSS readRSSToBean(java.net.URL url) throws Exception { 320 return readRSSToBean(url.openStream()); 321 } 322 323 /** 324 * This method reads an rss file from an input stream into a RSS element. 325 * 326 * @param inputStream 327 * the input stream containing an rss file. 328 * @return the RSS element. 329 * @throws Exception 330 * if the URL cannot be parsed into a RSS element. 331 */ 332 public RSS readRSSToBean(InputStream inputStream) throws Exception { 333 return new RSSReader(this).readRSS(inputFactory 334 .createXMLStreamReader(inputStream)); 335 } 336 337 /** 338 * 339 * @param channel 340 * the unique channel element (required) 341 * @param attributes 342 * additional attributes (optional) 343 * @param extensions 344 * additional extensions (optional) 345 * @return an immutable RSS object. 346 * @throws RSSpectException 347 * if the format of the data is not valid. 348 */ 349 public RSS buildRSS(Channel channel, List<Attribute> attributes, 350 List<Extension> extensions) throws RSSpectException { 351 return new RSS(channel, attributes, extensions); 352 } 353 354 /** 355 * 356 * @param name 357 * the attribute name. 358 * @param value 359 * the attribute value. 360 * @return an immutable Attribute object. 361 * @throws RSSpectException 362 * if the data is not valid. 363 */ 364 public Attribute buildAttribute(String name, String value) 365 throws RSSpectException { 366 return new Attribute(name, value); 367 } 368 369 /** 370 * 371 * @param author 372 * the author element. (required) 373 * @return an immutable Author object. 374 * @throws RSSpectException 375 * if the format of the data is not valid. 376 */ 377 public Author buildAuthor(String author) throws RSSpectException { 378 return new Author(author); 379 } 380 381 /** 382 * @param domain 383 * the domain attribute 384 * @param category 385 * the category text 386 * @return an immutable Category object. 387 * @throws RSSpectException 388 * if the format of the data is not valid. 389 */ 390 public Category buildCategory(Attribute domain, String category) 391 throws RSSpectException { 392 return new Category(domain, category); 393 } 394 395 /** 396 * 397 * @param title 398 * the title element. 399 * @param link 400 * the link element. 401 * @param description 402 * the description element. 403 * @param language 404 * the language element. 405 * @param copyright 406 * the copyright element. 407 * @param managingEditor 408 * the managingEditor element. 409 * @param webMaster 410 * the webMaster element. 411 * @param pubDate 412 * the pubDate element. 413 * @param lastBuildDate 414 * the lastBuildDate element. 415 * @param categories 416 * the list of categories 417 * @param generator 418 * the generator element. 419 * @param docs 420 * the docs element. 421 * @param cloud 422 * the cloud element. 423 * @param ttl 424 * the ttl element. 425 * @param image 426 * the image element. 427 * @param rating 428 * the rating element. 429 * @param textInput 430 * the textInput element. 431 * @param skipHours 432 * the skipHours element. 433 * @param skipDays 434 * the skipDays element. 435 * @param items 436 * the list of items. 437 * @param extensions 438 * the list of extensions. 439 * @return an immutable Channel object. 440 * @throws RSSpectException 441 * if the format of the data is not valid. 442 */ 443 public Channel buildChannel(Title title, Link link, 444 Description description, Language language, Copyright copyright, 445 ManagingEditor managingEditor, WebMaster webMaster, 446 PubDate pubDate, LastBuildDate lastBuildDate, 447 List<Category> categories, Generator generator, Docs docs, 448 Cloud cloud, TTL ttl, Image image, Rating rating, 449 TextInput textInput, SkipHours skipHours, SkipDays skipDays, 450 List<Extension> extensions, List<Item> items) 451 throws RSSpectException { 452 return new Channel(title, link, description, language, copyright, 453 managingEditor, webMaster, pubDate, lastBuildDate, categories, 454 generator, docs, cloud, ttl, image, rating, textInput, 455 skipHours, skipDays, extensions, items); 456 } 457 458 /** 459 * 460 * @param attributes 461 * the list of attributes. 462 * @return an immutable Cloud object. 463 * @throws RSSpectException 464 * if the format of the data is not valid. 465 */ 466 public Cloud buildCloud(List<Attribute> attributes) throws RSSpectException { 467 return new Cloud(attributes); 468 } 469 470 /** 471 * 472 * @param comments 473 * the comments. 474 * @return an immutable Comments object. 475 * @throws RSSpectException 476 * if the format of the data is not valid. 477 */ 478 public Comments buildComments(String comments) throws RSSpectException { 479 return new Comments(comments); 480 } 481 482 /** 483 * 484 * @param copyright 485 * the copyright. 486 * @return an immutable Copyright object. 487 * @throws RSSpectException 488 * if the format of the data is not valid. 489 */ 490 public Copyright buildCopyright(String copyright) throws RSSpectException { 491 return new Copyright(copyright); 492 } 493 494 /** 495 * 496 * @param description 497 * the description. 498 * @return an immutable Description object. 499 * @throws RSSpectException 500 * if the format of the data is not valid. 501 */ 502 public Description buildDescription(String description) 503 throws RSSpectException { 504 return new Description(description); 505 } 506 507 /** 508 * 509 * @param docs 510 * the documentation information. 511 * @return an immutable Docs object. 512 * @throws RSSpectException 513 * if the format of the data is not valid. 514 */ 515 public Docs buildDocs(String docs) throws RSSpectException { 516 return new Docs(docs); 517 } 518 519 /** 520 * 521 * @param attributes 522 * should contain url, length and type 523 * @return an immutable Enclosure object. 524 * @throws RSSpectException 525 * if the format of the data is not valid. 526 */ 527 public Enclosure buildEnclosure(List<Attribute> attributes) 528 throws RSSpectException { 529 return new Enclosure(attributes); 530 } 531 532 /** 533 * 534 * @param elementName 535 * the name of the extension element. 536 * @param attributes 537 * additional attributes. 538 * @param content 539 * the content of the extension element. 540 * @return an immutable Extension object. 541 * @throws RSSpectException 542 * if the format of the data is not valid. 543 */ 544 public Extension buildExtension(String elementName, 545 List<Attribute> attributes, String content) throws RSSpectException { 546 return new Extension(elementName, attributes, content); 547 } 548 549 /** 550 * @param text 551 * the text content. 552 * @return an immutable Generator object. 553 * @throws RSSpectException 554 * if the format of the data is not valid. 555 */ 556 public Generator buildGenerator(String text) throws RSSpectException { 557 return new Generator(text); 558 } 559 560 /** 561 * 562 * @param isPermaLink 563 * the isPermaLink attributes. 564 * @param guid 565 * the guid data. 566 * @return an immutable GUID object. 567 * @throws RSSpectException 568 * if the format of the data is not valid. 569 */ 570 public GUID buildGUID(Attribute isPermaLink, String guid) 571 throws RSSpectException { 572 return new GUID(isPermaLink, guid); 573 } 574 575 /** 576 * 577 * @param height 578 * should be a number 400 or less 579 * @return an immutable Height object. 580 * @throws RSSpectException 581 * if the format of the data is not valid. 582 */ 583 public Height buildHeight(String height) throws RSSpectException { 584 return new Height(height); 585 } 586 587 /** 588 * 589 * @param url 590 * the url element. 591 * @param title 592 * the title element. 593 * @param link 594 * the link element. 595 * @param width 596 * the width element. 597 * @param height 598 * the height element. 599 * @param description 600 * the description element. 601 * @return an immutable Image object. 602 * @throws RSSpectException 603 * if the format of the data is not valid. 604 */ 605 public Image buildImage(URL url, Title title, Link link, Width width, 606 Height height, Description description) throws RSSpectException { 607 return new Image(url, title, link, width, height, description); 608 } 609 610 /** 611 * 612 * @param title 613 * the title element. 614 * @param link 615 * the link element. 616 * @param description 617 * the description element. 618 * @param author 619 * the author element. 620 * @param categories 621 * the list of categories. 622 * @param comments 623 * the comments element. 624 * @param enclosure 625 * the enclosure element. 626 * @param guid 627 * the guid element. 628 * @param pubDate 629 * the published date element. 630 * @param source 631 * the source element. 632 * @param extensions 633 * the list of extensions. 634 * @return an immutable Item object. 635 * @throws RSSpectException 636 * if the format of the data is not valid. 637 */ 638 public Item buildItem(Title title, Link link, Description description, 639 Author author, List<Category> categories, Comments comments, 640 Enclosure enclosure, GUID guid, PubDate pubDate, Source source, 641 List<Extension> extensions) throws RSSpectException { 642 return new Item(title, link, description, author, categories, comments, 643 enclosure, guid, pubDate, source, extensions); 644 } 645 646 /** 647 * 648 * @param language 649 * the language. 650 * @return an immutable Language object. 651 * @throws RSSpectException 652 * if the format of the data is not valid. 653 */ 654 public Language buildLanguage(String language) throws RSSpectException { 655 return new Language(language); 656 } 657 658 /** 659 * 660 * @param lastBuildDate 661 * the last build date. 662 * @return an immutable LastBuildDate object. 663 * @throws RSSpectException 664 * if the format of the data is not valid. 665 */ 666 public LastBuildDate buildLastBuildDate(String lastBuildDate) 667 throws RSSpectException { 668 return new LastBuildDate(lastBuildDate); 669 } 670 671 /** 672 * 673 * @param link 674 * the link information. 675 * @return an immutable Link object. 676 * @throws RSSpectException 677 * if the format of the data is not valid. 678 */ 679 public Link buildLink(String link) throws RSSpectException { 680 return new Link(link); 681 } 682 683 /** 684 * 685 * @param managingEditor 686 * the managing editor. 687 * @return an immutable ManagingEditor object. 688 * @throws RSSpectException 689 * if the format of the data is not valid. 690 */ 691 public ManagingEditor buildManagingEditor(String managingEditor) 692 throws RSSpectException { 693 return new ManagingEditor(managingEditor); 694 } 695 696 /** 697 * 698 * @param name 699 * the name. 700 * @return an immutable Name object. 701 * @throws RSSpectException 702 * if the format of the data is not valid. 703 */ 704 public Name buildName(String name) throws RSSpectException { 705 return new Name(name); 706 } 707 708 /** 709 * 710 * @param pubDate 711 * the published date. 712 * @return an immutable PubDate object. 713 * @throws RSSpectException 714 * If the dateTime format is invalid. 715 */ 716 public PubDate buildPubDate(String pubDate) throws RSSpectException { 717 return new PubDate(pubDate); 718 } 719 720 /** 721 * 722 * @param rating 723 * the rating information. 724 * @return an immutable Rating object. 725 * @throws RSSpectException 726 * if the format of the data is not valid. 727 */ 728 public Rating buildRating(String rating) throws RSSpectException { 729 return new Rating(rating); 730 } 731 732 /** 733 * 734 * @param skipDays 735 * the days to skip. 736 * @throws RSSpectException 737 * if the format of the data is not valid. 738 * @return an immutable SkipDays object. 739 */ 740 public SkipDays buildSkipDays(List<Day> skipDays) throws RSSpectException { 741 return new SkipDays(skipDays); 742 } 743 744 /** 745 * 746 * @param skipHours 747 * the hours to skip. 748 * @throws RSSpectException 749 * if the format of the data is not valid. 750 * @return an immutable SkipHours object. 751 */ 752 public SkipHours buildSkipHours(List<Hour> skipHours) 753 throws RSSpectException { 754 return new SkipHours(skipHours); 755 } 756 757 /** 758 * @param day 759 * the day of the week. 760 * @return a Day object. 761 * @throws RSSpectException 762 * if the format of the data is not valid. 763 */ 764 public Day buildDay(String day) throws RSSpectException { 765 return new Day(day); 766 } 767 768 /** 769 * @param hour 770 * the hour of the day. 771 * @return an Hour object. 772 * @throws RSSpectException 773 * if the format of the data is not valid. 774 */ 775 public Hour buildHour(String hour) throws RSSpectException { 776 return new Hour(hour); 777 } 778 779 /** 780 * 781 * @param url 782 * the url attribute. 783 * @param source 784 * the source information. 785 * @return an immutable Source object. 786 * @throws RSSpectException 787 * if the format of the data is not valid. 788 */ 789 public Source buildSource(Attribute url, String source) 790 throws RSSpectException { 791 return new Source(url, source); 792 } 793 794 /** 795 * 796 * @param title 797 * the title element. 798 * @param description 799 * the description element. 800 * @param name 801 * the name element. 802 * @param link 803 * the link element. 804 * @return an immutable TextInput object. 805 * @throws RSSpectException 806 * if the format of the data is not valid. 807 */ 808 public TextInput buildTextInput(Title title, Description description, 809 Name name, Link link) throws RSSpectException { 810 return new TextInput(title, description, name, link); 811 } 812 813 /** 814 * 815 * @param title 816 * the title. 817 * @return an immutable Title object. 818 * @throws RSSpectException 819 * if the format of the data is not valid. 820 */ 821 public Title buildTitle(String title) throws RSSpectException { 822 return new Title(title); 823 } 824 825 /** 826 * 827 * @param ttl 828 * the time to live. 829 * @return an immutable TTL object. 830 * @throws RSSpectException 831 * if the format of the data is not valid. 832 */ 833 public TTL buildTTL(String ttl) throws RSSpectException { 834 return new TTL(ttl); 835 } 836 837 /** 838 * 839 * @param url 840 * the url. 841 * @return an immutable URL object. 842 * @throws RSSpectException 843 * if the format of the data is not valid. 844 */ 845 public URL buildURL(String url) throws RSSpectException { 846 return new URL(url); 847 } 848 849 /** 850 * 851 * @param webMaster 852 * the web master. 853 * @return an immutable WebMaster object. 854 * @throws RSSpectException 855 * if the format of the data is not valid. 856 */ 857 public WebMaster buildWebMaster(String webMaster) throws RSSpectException { 858 return new WebMaster(webMaster); 859 } 860 861 /** 862 * 863 * @param width 864 * the width. 865 * @return an immutable Width object. 866 * @throws RSSpectException 867 * if the format of the data is not valid. 868 */ 869 public Width buildWidth(String width) throws RSSpectException { 870 return new Width(width); 871 } 872 873 // used to write feed output for several feed writing methods. 874 private void writeRSSOutput(RSS rss, XMLStreamWriter writer, 875 String encoding, String version) throws Exception { 876 877 if (rss == null) { 878 throw new RSSpectException("The rss feed object cannot be null."); 879 } 880 881 Channel channel = rss.getChannel(); 882 883 rss = buildRSS(buildChannel(channel.getTitle(), channel.getLink(), 884 channel.getDescription(), channel.getLanguage(), channel 885 .getCopyright(), channel.getManagingEditor(), channel 886 .getWebMaster(), channel.getPubDate(), channel 887 .getLastBuildDate(), channel.getCategories(), 888 getLibVersion(), channel.getDocs(), channel.getCloud(), channel 889 .getTtl(), channel.getImage(), channel.getRating(), 890 channel.getTextInput(), channel.getSkipHours(), channel 891 .getSkipDays(), channel.getExtensions(), channel 892 .getItems()), rss.getAttributes(), rss.getExtensions()); 893 894 // write the xml header. 895 writer.writeStartDocument(encoding, version); 896 if (this.processingInstructions != null) { 897 for (ProcessingInstruction pi : this.processingInstructions) { 898 writer.writeProcessingInstruction(pi.getTarget(), pi.getData()); 899 } 900 } 901 902 new RSSWriter().writeRSS(writer, rss); 903 writer.flush(); 904 writer.close(); 905 } 906 907 /** 908 * @return the xml encoding of the document eg. UTF-8 909 */ 910 public String getEncoding() { 911 return encoding; 912 } 913 914 /** 915 * @return the xml document version of the document eg. 1.0 916 */ 917 public String getXmlVersion() { 918 return xmlVersion; 919 } 920 921 void setEncoding(String encoding) { 922 this.encoding = encoding; 923 } 924 925 void setXmlVersion(String xmlVersion) { 926 this.xmlVersion = xmlVersion; 927 } 928 929 void setProcessingInstructions( 930 List<ProcessingInstruction> processingInstructions) { 931 this.processingInstructions = processingInstructions; 932 } 933 934 List<ProcessingInstruction> getProcessingInstructions() { 935 // TODO Auto-generated method stub 936 return processingInstructions; 937 } 938 939}