Skip to content
Commits on Source (12)
# Set the default behavior, in case people don't have core.autocrlf set. See http://git-scm.com/docs/gitattributes
* text=auto
target
.checkstyle
.project
.settings
.classpath
.idea
*.iml
node {
stage 'Checkout'
checkout scm
stage 'Build'
def mvnHome = tool 'Maven 3.3.9'
sh "${mvnHome}/bin/mvn clean install"
}
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
# ROME
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.rometools/rome/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.rometools/rome)
ROME is a Java framework for RSS and Atom feeds. The framework consist of several modules:
| Module | Description |
| ------ | ----------- |
| rome-parent | is the parent project for all ROME modules and contains the common Maven configuration. |
| rome-utils | provides utility classes that are used in several ROME modules. |
| rome | is the main RSS and Atom library. It makes it easy to work with most syndication formats: RSS 0.90, RSS 0.91 Netscape, RSS 0.91 Userland, RSS 0.92, RSS 0.93, RSS 0.94, RSS 1.0, RSS 2.0, Atom 0.3, Atom 1.0. |
| rome-modules| enables rome to handle several feed extensions like MediaRSS, GeoRSS and others. |
| rome-opml | contains [OPML](https://en.wikipedia.org/wiki/OPML) parsers and tools. |
| rome-fetcher | is a caching feed fetcher that supports retrieval of feeds via HTTP conditional GET. Supports ETags, GZip compression, and RFC3229 Delta encoding. |
| rome-certiorem | is a [PubSubHubub](https://en.wikipedia.org/wiki/PubSubHubbub) implementation based on rome. |
| rome-certiorem-webapp | is an example webapp for rome-certiorem |
| rome-propono | supports publishing protocols, specifically the Atom Publishing Protocol and the legacy MetaWeblog API. Propono includes an Atom client library, an Atom server framework and a Blog client that supports both Atom protocol and the MetaWeblog API. |
## Changelog
### 1.6.0
- [Upgrade of JDOM to version 2.0.5](https://github.com/rometools/rome/issues/197)
- [Maven plugin and dependency updates](https://github.com/rometools/rome/issues/268)
- [Support for allowing Doctype declarations in rome-fetcher](https://github.com/rometools/rome/issues/234)
- [OSGi improvements](https://github.com/rometools/rome/issues/143)
### 1.5.1
- solved an [XML bomb](https://en.wikipedia.org/wiki/Billion_laughs) vulnerability
Important note: due to the security fix ROME now forbids all Doctype declarations by default. This will break compatibility with RSS 0.91 Netscape
because it requires a Doctype declaration. When you experience problems you have to activate the property **allowDoctypes** on the SyndFeedInput object. You
should only use this possibility when the feeds that you process are absolutely trustful.
### 1.5.0
- many (untracked) enhancements
- code cleanup
- renamed packages (was required to be able to push to Maven Central after years again)
- updated sourcecode to Java 1.6
### Prior to 1.5.0
- see [http://rometools.github.io/rome/ROMEReleases](http://rometools.github.io/rome/ROMEReleases)
/*
* Copyright 2004 Sun Microsystems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.sun.syndication.feed.impl;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
/**
* Obtains all property descriptors from a bean (interface or implementation).
* <p>
* The java.beans.Introspector does not process the interfaces hierarchy chain, this one does.
* <p>
* @author Alejandro Abdelnur
*
*/
public class BeanIntrospector {
private static final Map _introspected = new HashMap();
public static synchronized PropertyDescriptor[] getPropertyDescriptors(Class klass) throws IntrospectionException {
PropertyDescriptor[] descriptors = (PropertyDescriptor[]) _introspected.get(klass);
if (descriptors==null) {
descriptors = getPDs(klass);
_introspected.put(klass,descriptors);
}
return descriptors;
}
private static PropertyDescriptor[] getPDs(Class klass) throws IntrospectionException {
Method[] methods = klass.getMethods();
Map getters = getPDs(methods,false);
Map setters = getPDs(methods,true);
List pds = merge(getters,setters);
PropertyDescriptor[] array = new PropertyDescriptor[pds.size()];
pds.toArray(array);
return array;
}
private static final String SETTER = "set";
private static final String GETTER = "get";
private static final String BOOLEAN_GETTER = "is";
private static Map getPDs(Method[] methods,boolean setters) throws IntrospectionException {
Map pds = new HashMap();
for (int i=0;i<methods.length;i++) {
String pName = null;
PropertyDescriptor pDescriptor = null;
if ((methods[i].getModifiers()&Modifier.PUBLIC)!=0) {
if (setters) {
if (methods[i].getName().startsWith(SETTER) &&
methods[i].getReturnType()==void.class && methods[i].getParameterTypes().length==1) {
pName = Introspector.decapitalize(methods[i].getName().substring(3));
pDescriptor = new PropertyDescriptor(pName,null,methods[i]);
}
}
else {
if (methods[i].getName().startsWith(GETTER) &&
methods[i].getReturnType()!=void.class && methods[i].getParameterTypes().length==0) {
pName = Introspector.decapitalize(methods[i].getName().substring(3));
pDescriptor = new PropertyDescriptor(pName,methods[i],null);
}
else
if (methods[i].getName().startsWith(BOOLEAN_GETTER) &&
methods[i].getReturnType()==boolean.class && methods[i].getParameterTypes().length==0) {
pName = Introspector.decapitalize(methods[i].getName().substring(2));
pDescriptor = new PropertyDescriptor(pName,methods[i],null);
}
}
}
if (pName!=null) {
pds.put(pName,pDescriptor);
}
}
return pds;
}
private static List merge(Map getters,Map setters) throws IntrospectionException {
List props = new ArrayList();
Set processedProps = new HashSet();
Iterator gs = getters.keySet().iterator();
while (gs.hasNext()) {
String name = (String) gs.next();
PropertyDescriptor getter = (PropertyDescriptor) getters.get(name);
PropertyDescriptor setter = (PropertyDescriptor) setters.get(name);
if (setter!=null) {
processedProps.add(name);
PropertyDescriptor prop = new PropertyDescriptor(name,getter.getReadMethod(),setter.getWriteMethod());
props.add(prop);
}
else {
props.add(getter);
}
}
Set writeOnlyProps = new HashSet(setters.keySet());
writeOnlyProps.removeAll(processedProps);
Iterator ss = writeOnlyProps.iterator();
while (ss.hasNext()) {
String name = (String) ss.next();
PropertyDescriptor setter = (PropertyDescriptor) setters.get(name);
props.add(setter);
}
return props;
}
}
/*
* Copyright 2004 Sun Microsystems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.sun.syndication.feed.impl;
import com.sun.syndication.feed.CopyFrom;
import com.sun.syndication.feed.impl.BeanIntrospector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.*;
/**
* @author Alejandro Abdelnur
*/
public class CopyFromHelper {
private static final Object[] NO_PARAMS = new Object[0];
private Class _beanInterfaceClass;
private Map _baseInterfaceMap; //ENTRIES(propertyName,interface.class)
private Map _baseImplMap; //ENTRIES(interface.class,implementation.class)
public CopyFromHelper(Class beanInterfaceClass,Map basePropInterfaceMap,Map basePropClassImplMap) {
_beanInterfaceClass = beanInterfaceClass;
_baseInterfaceMap = basePropInterfaceMap;
_baseImplMap = basePropClassImplMap;
}
public void copy(Object target,Object source) {
try {
PropertyDescriptor[] pds = BeanIntrospector.getPropertyDescriptors(_beanInterfaceClass);
if (pds!=null) {
for (int i=0;i<pds.length;i++) {
String propertyName = pds[i].getName();
Method pReadMethod = pds[i].getReadMethod();
Method pWriteMethod = pds[i].getWriteMethod();
if (pReadMethod!=null && pWriteMethod!=null && // ensure it has getter and setter methods
pReadMethod.getDeclaringClass()!=Object.class && // filter Object.class getter methods
pReadMethod.getParameterTypes().length==0 && // filter getter methods that take parameters
_baseInterfaceMap.containsKey(propertyName)) { // only copies properties defined as copyFrom-able
Object value = pReadMethod.invoke(source,NO_PARAMS);
if (value!=null) {
Class baseInterface = (Class) _baseInterfaceMap.get(propertyName);
value = doCopy(value,baseInterface);
pWriteMethod.invoke(target,new Object[]{value});
}
}
}
}
}
catch (Exception ex) {
throw new RuntimeException("Could not do a copyFrom "+ex, ex);
}
}
private CopyFrom createInstance(Class interfaceClass) throws Exception {
if( _baseImplMap.get(interfaceClass) == null ){
return null;
}
else {
return (CopyFrom) ((Class)_baseImplMap.get(interfaceClass)).newInstance();
}
}
private Object doCopy(Object value,Class baseInterface) throws Exception {
if (value!=null) {
Class vClass = value.getClass();
if (vClass.isArray()) {
value = doCopyArray(value,baseInterface);
}
else
if (value instanceof Collection) {
value = doCopyCollection((Collection)value,baseInterface);
}
else
if (value instanceof Map) {
value = doCopyMap((Map)value,baseInterface);
}
else
if (isBasicType(vClass)) {
// value = value; // nothing to do here
if (value instanceof Date) { // because Date it is not inmutable
value = ((Date)value).clone();
}
}
else { // it goes CopyFrom
if (value instanceof CopyFrom) {
CopyFrom source = (CopyFrom) value;
CopyFrom target = createInstance(source.getInterface());
target = target == null ? (CopyFrom) value.getClass().newInstance() : target;
target.copyFrom(source);
value = target;
}
else {
throw new Exception("unsupported class for 'copyFrom' "+value.getClass());
}
}
}
return value;
}
private Object doCopyArray(Object array,Class baseInterface) throws Exception {
Class elementClass = array.getClass().getComponentType();
int length = Array.getLength(array);
Object newArray = Array.newInstance(elementClass,length);
for (int i=0;i<length;i++) {
Object element = doCopy(Array.get(array,i),baseInterface);
Array.set(newArray,i,element);
}
return newArray;
}
private Object doCopyCollection(Collection collection,Class baseInterface) throws Exception {
// expecting SETs or LISTs only, going default implementation of them
Collection newColl = (collection instanceof Set) ? (Collection)new HashSet() : (Collection)new ArrayList();
Iterator i = collection.iterator();
while (i.hasNext()) {
Object element = doCopy(i.next(),baseInterface);
newColl.add(element);
}
return newColl;
}
private Object doCopyMap(Map map,Class baseInterface) throws Exception {
Map newMap = new HashMap();
Iterator entries = map.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
Object key = entry.getKey(); // we are assuming string KEYS
Object element = doCopy(entry.getValue(),baseInterface);
newMap.put(key,element);
}
return newMap;
}
private static final Set BASIC_TYPES = new HashSet();
static {
BASIC_TYPES.add(Boolean.class);
BASIC_TYPES.add(Byte.class);
BASIC_TYPES.add(Character.class);
BASIC_TYPES.add(Double.class);
BASIC_TYPES.add(Float.class);
BASIC_TYPES.add(Integer.class);
BASIC_TYPES.add(Long.class);
BASIC_TYPES.add(Short.class);
BASIC_TYPES.add(String.class);
BASIC_TYPES.add(Date.class);
}
private boolean isBasicType(Class vClass) {
return BASIC_TYPES.contains(vClass);
}
}
/*
* Copyright 2004 Sun Microsystems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.sun.syndication.feed.synd.impl;
import com.sun.syndication.feed.WireFeed;
import com.sun.syndication.feed.module.DCModule;
import com.sun.syndication.feed.rss.Channel;
import com.sun.syndication.feed.rss.Guid;
import com.sun.syndication.feed.rss.Item;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.feed.synd.SyndPerson;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
*/
public class ConverterForRSS094 extends ConverterForRSS093 {
public ConverterForRSS094() {
this("rss_0.94");
}
protected ConverterForRSS094(String type) {
super(type);
}
public void copyInto(WireFeed feed,SyndFeed syndFeed) {
Channel channel = (Channel) feed;
super.copyInto(channel,syndFeed);
List cats = channel.getCategories(); //c
if (cats.size()>0) {
Set s = new HashSet(); // using a set to remove duplicates
s.addAll(createSyndCategories(cats)); // feed native categories (as syndcat)
s.addAll(syndFeed.getCategories()); // DC subjects (as syndcat)
syndFeed.setCategories(new ArrayList(s));
}
}
protected SyndEntry createSyndEntry(Item item, boolean preserveWireItem) {
SyndEntry syndEntry = super.createSyndEntry(item, preserveWireItem);
// adding native feed author to DC creators list
String author = item.getAuthor();
if (author!=null) {
List creators = ((DCModule)syndEntry.getModule(DCModule.URI)).getCreators();
if (!creators.contains(author)) {
Set s = new HashSet(); // using a set to remove duplicates
s.addAll(creators); // DC creators
s.add(author); // feed native author
creators.clear();
creators.addAll(s);
}
}
Guid guid = item.getGuid();
if (guid!=null) {
syndEntry.setUri(guid.getValue());
if (item.getLink()==null && guid.isPermaLink()) {
syndEntry.setLink(guid.getValue());
}
}
else {
syndEntry.setUri(item.getLink());
}
return syndEntry;
}
protected WireFeed createRealFeed(String type,SyndFeed syndFeed) {
Channel channel = (Channel) super.createRealFeed(type,syndFeed);
List cats = syndFeed.getCategories(); //c
if (cats.size()>0) {
channel.setCategories(createRSSCategories(cats));
}
return channel;
}
protected Item createRSSItem(SyndEntry sEntry) {
Item item = super.createRSSItem(sEntry);
if (sEntry.getAuthors()!=null && sEntry.getAuthors().size() > 0) {
SyndPerson author = (SyndPerson)sEntry.getAuthors().get(0);
item.setAuthor(author.getEmail());
}
Guid guid = null;
String uri = sEntry.getUri();
if (uri!=null) {
guid = new Guid();
guid.setPermaLink(false);
guid.setValue(uri);
}
else {
String link = sEntry.getLink();
if (link!=null) {
guid = new Guid();
guid.setPermaLink(true);
guid.setValue(link);
}
}
item.setGuid(guid);
return item;
}
}
package com.sun.syndication.feed.synd.impl;
/**
* Utility class for normalizing an URI as specified in RFC 2396bis.
* <p>
* @author Alejandro Abdelnur
*/
public class URINormalizer {
/**
* Normalizes an URI as specified in RFC 2396bis.
* <p>
* @param uri to normalize.
* @return the normalized value of the given URI, or <b>null</b> if the given URI was <b>null</b>.
*/
public static String normalize(String uri) {
String normalizedUri = null;
if (uri!=null) {
normalizedUri = uri; //TODO THIS HAS TO BE IMPLEMENTED
}
return normalizedUri;
}
}
package com.sun.syndication.io;
/**
* Adds the ability to give a direct wire feed generator reference to plugin
* modules that need to call back to their wire feed to complete
* generation of their particular namespace. Examples of such parsers
* include the SSE091Generator.
*/
public interface DelegatingModuleGenerator extends ModuleGenerator {
/**
* Provides a parent wirefeed reference to this ModuleParser,
* or "plugin-in".
*
* @param feedGenerator the parent wirefeed generator for this plugin.
*/
void setFeedGenerator(WireFeedGenerator feedGenerator);
}
package com.sun.syndication.io;
/**
* Adds the ability to give a direct wire feed reference to plugin
* modules that need to call back to their wire feed to complete
* parsing of their particular namespace. Examples of such parsers
* include the SSE091Parser.
*/
public interface DelegatingModuleParser extends ModuleParser {
/**
* Provides a parent wirefeed reference to this ModuleParser,
* or "plugin-in".
*
* @param feedParser the parent wirefeed parser for this plugin.
*/
void setFeedParser(WireFeedParser feedParser);
}
package com.sun.syndication.io;
import org.jdom.JDOMException;
import org.xml.sax.XMLReader;
/*
* This code is needed to fix the security problem outlined in http://www.securityfocus.com/archive/1/297714
*
* Unfortunately there isn't an easy way to check if an XML parser supports a particular feature, so
* we need to set it and catch the exception if it fails. We also need to subclass the JDom SAXBuilder
* class in order to get access to the underlying SAX parser - otherwise the features don't get set until
* we are already building the document, by which time it's too late to fix the problem.
*
* Crimson is one parser which is known not to support these features.
*
*/
public class SAXBuilder extends org.jdom.input.SAXBuilder {
public SAXBuilder(boolean _validate) {
super(_validate);
}
public XMLReader createParser() throws JDOMException {
return super.createParser();
}
}
/*
* Copyright 2004 Sun Microsystems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.sun.syndication.io.impl;
import com.sun.syndication.feed.WireFeed;
import com.sun.syndication.feed.atom.*;
import com.sun.syndication.io.FeedException;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import java.io.StringReader;
import java.util.List;
/**
* Feed Generator for Atom
* <p/>
*
* @author Elaine Chien
*
*/
public class Atom03Generator extends BaseWireFeedGenerator {
private static final String ATOM_03_URI = "http://purl.org/atom/ns#";
private static final Namespace ATOM_NS = Namespace.getNamespace(ATOM_03_URI);
private String _version;
public Atom03Generator() {
this("atom_0.3","0.3");
}
protected Atom03Generator(String type,String version) {
super(type);
_version = version;
}
protected String getVersion() {
return _version;
}
protected Namespace getFeedNamespace() {
return ATOM_NS;
}
public Document generate(WireFeed wFeed) throws FeedException {
Feed feed = (Feed) wFeed;
Element root = createRootElement(feed);
populateFeed(feed,root);
purgeUnusedNamespaceDeclarations(root);
return createDocument(root);
}
protected Document createDocument(Element root) {
return new Document(root);
}
protected Element createRootElement(Feed feed) {
Element root = new Element("feed",getFeedNamespace());
root.addNamespaceDeclaration(getFeedNamespace());
Attribute version = new Attribute("version", getVersion());
root.setAttribute(version);
generateModuleNamespaceDefs(root);
return root;
}
protected void populateFeed(Feed feed,Element parent) throws FeedException {
addFeed(feed,parent);
addEntries(feed,parent);
}
protected void addFeed(Feed feed, Element parent) throws FeedException {
Element eFeed = parent;
populateFeedHeader(feed,eFeed);
checkFeedHeaderConstraints(eFeed);
generateFeedModules(feed.getModules(),eFeed);
generateForeignMarkup(eFeed, (List)feed.getForeignMarkup());
}
protected void addEntries(Feed feed,Element parent) throws FeedException {
List items = feed.getEntries();
for (int i=0;i<items.size();i++) {
addEntry((Entry)items.get(i),parent);
}
checkEntriesConstraints(parent);
}
protected void addEntry(Entry entry,Element parent) throws FeedException {
Element eEntry = new Element("entry", getFeedNamespace());
populateEntry(entry,eEntry);
checkEntryConstraints(eEntry);
generateItemModules(entry.getModules(),eEntry);
parent.addContent(eEntry);
}
protected void populateFeedHeader(Feed feed, Element eFeed) throws FeedException {
if (feed.getTitleEx() != null) {
Element titleElement = new Element("title", getFeedNamespace());
fillContentElement(titleElement, feed.getTitleEx());
eFeed.addContent(titleElement);
}
List links = feed.getAlternateLinks();
for (int i = 0; i < links.size(); i++) {
eFeed.addContent(generateLinkElement((Link)links.get(i)));
}
links = feed.getOtherLinks();
for (int i = 0; i < links.size(); i++) {
eFeed.addContent(generateLinkElement((Link)links.get(i)));
}
if (feed.getAuthors()!=null && feed.getAuthors().size() > 0) {
Element authorElement = new Element("author", getFeedNamespace());
fillPersonElement(authorElement, (Person)feed.getAuthors().get(0));
eFeed.addContent(authorElement);
}
List contributors = feed.getContributors();
for (int i = 0; i < contributors.size(); i++) {
Element contributorElement = new Element("contributor", getFeedNamespace());
fillPersonElement(contributorElement, (Person)contributors.get(i));
eFeed.addContent(contributorElement);
}
if (feed.getTagline() != null) {
Element taglineElement = new Element("tagline", getFeedNamespace());
fillContentElement(taglineElement, feed.getTagline());
eFeed.addContent(taglineElement);
}
if (feed.getId() != null) {
eFeed.addContent(generateSimpleElement("id", feed.getId()));
}
if (feed.getGenerator() != null) {
eFeed.addContent(generateGeneratorElement(feed.getGenerator()));
}
if (feed.getCopyright() != null) {
eFeed.addContent(generateSimpleElement("copyright", feed.getCopyright()));
}
if (feed.getInfo() != null) {
Element infoElement = new Element("info", getFeedNamespace());
fillContentElement(infoElement, feed.getInfo());
eFeed.addContent(infoElement);
}
if (feed.getModified() != null) {
Element modifiedElement = new Element("modified", getFeedNamespace());
modifiedElement.addContent(DateParser.formatW3CDateTime(feed.getModified()));
eFeed.addContent(modifiedElement);
}
}
protected void populateEntry(Entry entry, Element eEntry) throws FeedException {
if (entry.getTitleEx() != null) {
Element titleElement = new Element("title", getFeedNamespace());
fillContentElement(titleElement, entry.getTitleEx());
eEntry.addContent(titleElement);
}
List links = entry.getAlternateLinks();
for (int i = 0; i < links.size(); i++) {
eEntry.addContent(generateLinkElement((Link)links.get(i)));
}
links = entry.getOtherLinks();
for (int i = 0; i < links.size(); i++) {
eEntry.addContent(generateLinkElement((Link)links.get(i)));
}
if (entry.getAuthors()!=null && entry.getAuthors().size() > 0) {
Element authorElement = new Element("author", getFeedNamespace());
fillPersonElement(authorElement, (Person)entry.getAuthors().get(0));
eEntry.addContent(authorElement);
}
List contributors = entry.getContributors();
for (int i = 0; i < contributors.size(); i++) {
Element contributorElement = new Element("contributor", getFeedNamespace());
fillPersonElement(contributorElement, (Person)contributors.get(i));
eEntry.addContent(contributorElement);
}
if (entry.getId() != null) {
eEntry.addContent(generateSimpleElement("id", entry.getId()));
}
if (entry.getModified() != null) {
Element modifiedElement = new Element("modified", getFeedNamespace());
modifiedElement.addContent(DateParser.formatW3CDateTime(entry.getModified()));
eEntry.addContent(modifiedElement);
}
if (entry.getIssued() != null) {
Element issuedElement = new Element("issued", getFeedNamespace());
issuedElement.addContent(DateParser.formatW3CDateTime(entry.getIssued()));
eEntry.addContent(issuedElement);
}
if (entry.getCreated() != null) {
Element createdElement = new Element("created", getFeedNamespace());
createdElement.addContent(DateParser.formatW3CDateTime(entry.getCreated()));
eEntry.addContent(createdElement);
}
if (entry.getSummary() != null) {
Element summaryElement = new Element("summary", getFeedNamespace());
fillContentElement(summaryElement, entry.getSummary());
eEntry.addContent(summaryElement);
}
List contents = entry.getContents();
for (int i = 0; i < contents.size(); i++) {
Element contentElement = new Element("content", getFeedNamespace());
fillContentElement(contentElement, (Content)contents.get(i));
eEntry.addContent(contentElement);
}
generateForeignMarkup(eEntry, (List)entry.getForeignMarkup());
}
protected void checkFeedHeaderConstraints(Element eFeed) throws FeedException {
}
protected void checkEntriesConstraints(Element parent) throws FeedException {
}
protected void checkEntryConstraints(Element eEntry) throws FeedException {
}
protected Element generateLinkElement(Link link) {
Element linkElement = new Element("link", getFeedNamespace());
if (link.getRel() != null) {
Attribute relAttribute = new Attribute("rel", link.getRel().toString());
linkElement.setAttribute(relAttribute);
}
if (link.getType() != null) {
Attribute typeAttribute = new Attribute("type", link.getType());
linkElement.setAttribute(typeAttribute);
}
if (link.getHref() != null) {
Attribute hrefAttribute = new Attribute("href", link.getHref());
linkElement.setAttribute(hrefAttribute);
}
return linkElement;
}
protected void fillPersonElement(Element element, Person person) {
if (person.getName() != null) {
element.addContent(generateSimpleElement("name", person.getName()));
}
if (person.getUrl() != null) {
element.addContent(generateSimpleElement("url", person.getUrl()));
}
if (person.getEmail() != null) {
element.addContent(generateSimpleElement("email", person.getEmail()));
}
}
protected Element generateTagLineElement(Content tagline) {
Element taglineElement = new Element("tagline", getFeedNamespace());
if (tagline.getType() != null) {
Attribute typeAttribute = new Attribute("type", tagline.getType());
taglineElement.setAttribute(typeAttribute);
}
if (tagline.getValue() != null) {
taglineElement.addContent(tagline.getValue());
}
return taglineElement;
}
protected void fillContentElement(Element contentElement, Content content)
throws FeedException {
if (content.getType() != null) {
Attribute typeAttribute = new Attribute("type", content.getType());
contentElement.setAttribute(typeAttribute);
}
String mode = content.getMode();
if (mode != null) {
Attribute modeAttribute = new Attribute("mode", content.getMode().toString());
contentElement.setAttribute(modeAttribute);
}
if (content.getValue() != null) {
if (mode == null || mode.equals(Content.ESCAPED)) {
contentElement.addContent(content.getValue());
} else if (mode.equals(Content.BASE64)) {
contentElement.addContent(Base64.encode(content.getValue()));
} else if (mode.equals(Content.XML)) {
StringBuffer tmpDocString = new StringBuffer("<tmpdoc>");
tmpDocString.append(content.getValue());
tmpDocString.append("</tmpdoc>");
StringReader tmpDocReader = new StringReader(tmpDocString.toString());
Document tmpDoc;
try {
SAXBuilder saxBuilder = new SAXBuilder();
tmpDoc = saxBuilder.build(tmpDocReader);
}
catch (Exception ex) {
throw new FeedException("Invalid XML",ex);
}
List children = tmpDoc.getRootElement().removeContent();
contentElement.addContent(children);
}
}
}
protected Element generateGeneratorElement(Generator generator) {
Element generatorElement = new Element("generator", getFeedNamespace());
if (generator.getUrl() != null) {
Attribute urlAttribute = new Attribute("url", generator.getUrl());
generatorElement.setAttribute(urlAttribute);
}
if (generator.getVersion() != null) {
Attribute versionAttribute = new Attribute("version", generator.getVersion());
generatorElement.setAttribute(versionAttribute);
}
if (generator.getValue() != null) {
generatorElement.addContent(generator.getValue());
}
return generatorElement;
}
protected Element generateSimpleElement(String name, String value) {
Element element = new Element(name, getFeedNamespace());
element.addContent(value);
return element;
}
}
/*
* Copyright 2004 Sun Microsystems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.sun.syndication.io.impl;
import com.sun.syndication.feed.WireFeed;
import com.sun.syndication.feed.atom.*;
import com.sun.syndication.io.FeedException;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.output.XMLOutputter;
import java.util.*;
/**
*/
public class Atom03Parser extends BaseWireFeedParser {
private static final String ATOM_03_URI = "http://purl.org/atom/ns#";
private static final Namespace ATOM_03_NS = Namespace.getNamespace(ATOM_03_URI);
public Atom03Parser() {
this("atom_0.3", ATOM_03_NS);
}
protected Atom03Parser(String type, Namespace ns) {
super(type, ns);
}
protected Namespace getAtomNamespace() {
return ATOM_03_NS;
}
public boolean isMyType(Document document) {
Element rssRoot = document.getRootElement();
Namespace defaultNS = rssRoot.getNamespace();
return (defaultNS!=null) && defaultNS.equals(getAtomNamespace());
}
public WireFeed parse(Document document, boolean validate) throws IllegalArgumentException,FeedException {
if (validate) {
validateFeed(document);
}
Element rssRoot = document.getRootElement();
return parseFeed(rssRoot);
}
protected void validateFeed(Document document) throws FeedException {
// TBD
// here we have to validate the Feed against a schema or whatever
// not sure how to do it
// one posibility would be to produce an ouput and attempt to parse it again
// with validation turned on.
// otherwise will have to check the document elements by hand.
}
protected WireFeed parseFeed(Element eFeed) {
com.sun.syndication.feed.atom.Feed feed = new com.sun.syndication.feed.atom.Feed(getType());
Element e = eFeed.getChild("title",getAtomNamespace());
if (e!=null) {
feed.setTitleEx(parseContent(e));
}
List eList = eFeed.getChildren("link",getAtomNamespace());
feed.setAlternateLinks(parseAlternateLinks(eList));
feed.setOtherLinks(parseOtherLinks(eList));
e = eFeed.getChild("author",getAtomNamespace());
if (e!=null) {
List authors = new ArrayList();
authors.add(parsePerson(e));
feed.setAuthors(authors);
}
eList = eFeed.getChildren("contributor",getAtomNamespace());
if (eList.size()>0) {
feed.setContributors(parsePersons(eList));
}
e = eFeed.getChild("tagline",getAtomNamespace());
if (e!=null) {
feed.setTagline(parseContent(e));
}
e = eFeed.getChild("id",getAtomNamespace());
if (e!=null) {
feed.setId(e.getText());
}
e = eFeed.getChild("generator",getAtomNamespace());
if (e!=null) {
Generator gen = new Generator();
gen.setValue(e.getText());
String att = getAttributeValue(e, "url");
if (att!=null) {
gen.setUrl(att);
}
att = getAttributeValue(e, "version");
if (att!=null) {
gen.setVersion(att);
}
feed.setGenerator(gen);
}
e = eFeed.getChild("copyright",getAtomNamespace());
if (e!=null) {
feed.setCopyright(e.getText());
}
e = eFeed.getChild("info",getAtomNamespace());
if (e!=null) {
feed.setInfo(parseContent(e));
}
e = eFeed.getChild("modified",getAtomNamespace());
if (e!=null) {
feed.setModified(DateParser.parseDate(e.getText()));
}
feed.setModules(parseFeedModules(eFeed));
eList = eFeed.getChildren("entry",getAtomNamespace());
if (eList.size()>0) {
feed.setEntries(parseEntries(eList));
}
List foreignMarkup =
extractForeignMarkup(eFeed, feed, getAtomNamespace());
if (foreignMarkup.size() > 0) {
feed.setForeignMarkup(foreignMarkup);
}
return feed;
}
private Link parseLink(Element eLink) {
Link link = new Link();
String att = getAttributeValue(eLink, "rel");
if (att!=null) {
link.setRel(att);
}
att = getAttributeValue(eLink, "type");
if (att!=null) {
link.setType(att);
}
att = getAttributeValue(eLink, "href");
if (att!=null) {
link.setHref(att);
}
return link;
}
// List(Elements) -> List(Link)
private List parseLinks(List eLinks,boolean alternate) {
List links = new ArrayList();
for (int i=0;i<eLinks.size();i++) {
Element eLink = (Element) eLinks.get(i);
String rel = getAttributeValue(eLink, "rel");
if (alternate) {
if ("alternate".equals(rel)) {
links.add(parseLink(eLink));
}
}
else {
if (!("alternate".equals(rel))) {
links.add(parseLink(eLink));
}
}
}
return (links.size()>0) ? links : null;
}
// List(Elements) -> List(Link)
private List parseAlternateLinks(List eLinks) {
return parseLinks(eLinks,true);
}
// List(Elements) -> List(Link)
private List parseOtherLinks(List eLinks) {
return parseLinks(eLinks,false);
}
private Person parsePerson(Element ePerson) {
Person person = new Person();
Element e = ePerson.getChild("name",getAtomNamespace());
if (e!=null) {
person.setName(e.getText());
}
e = ePerson.getChild("url",getAtomNamespace());
if (e!=null) {
person.setUrl(e.getText());
}
e = ePerson.getChild("email",getAtomNamespace());
if (e!=null) {
person.setEmail(e.getText());
}
return person;
}
// List(Elements) -> List(Persons)
private List parsePersons(List ePersons) {
List persons = new ArrayList();
for (int i=0;i<ePersons.size();i++) {
persons.add(parsePerson((Element)ePersons.get(i)));
}
return (persons.size()>0) ? persons : null;
}
private Content parseContent(Element e) {
String value = null;
String type = getAttributeValue(e, "type");
type = (type!=null) ? type : "text/plain";
String mode = getAttributeValue(e, "mode");
if (mode == null) {
mode = Content.XML; // default to xml content
}
if (mode.equals(Content.ESCAPED)) {
// do nothing XML Parser took care of this
value = e.getText();
}
else
if (mode.equals(Content.BASE64)) {
value = Base64.decode(e.getText());
}
else
if (mode.equals(Content.XML)) {
XMLOutputter outputter = new XMLOutputter();
List eContent = e.getContent();
Iterator i = eContent.iterator();
while (i.hasNext()) {
org.jdom.Content c = (org.jdom.Content) i.next();
if (c instanceof Element) {
Element eC = (Element) c;
if (eC.getNamespace().equals(getAtomNamespace())) {
((Element)c).setNamespace(Namespace.NO_NAMESPACE);
}
}
}
value = outputter.outputString(eContent);
}
Content content = new Content();
content.setType(type);
content.setMode(mode);
content.setValue(value);
return content;
}
// List(Elements) -> List(Entries)
private List parseEntries(List eEntries) {
List entries = new ArrayList();
for (int i=0;i<eEntries.size();i++) {
entries.add(parseEntry((Element)eEntries.get(i)));
}
return (entries.size()>0) ? entries : null;
}
private Entry parseEntry(Element eEntry) {
Entry entry = new Entry();
Element e = eEntry.getChild("title",getAtomNamespace());
if (e!=null) {
entry.setTitleEx(parseContent(e));
}
List eList = eEntry.getChildren("link",getAtomNamespace());
entry.setAlternateLinks(parseAlternateLinks(eList));
entry.setOtherLinks(parseOtherLinks(eList));
e = eEntry.getChild("author",getAtomNamespace());
if (e!=null) {
List authors = new ArrayList();
authors.add(parsePerson(e));
entry.setAuthors(authors);
}
eList = eEntry.getChildren("contributor",getAtomNamespace());
if (eList.size()>0) {
entry.setContributors(parsePersons(eList));
}
e = eEntry.getChild("id",getAtomNamespace());
if (e!=null) {
entry.setId(e.getText());
}
e = eEntry.getChild("modified",getAtomNamespace());
if (e!=null) {
entry.setModified(DateParser.parseDate(e.getText()));
}
e = eEntry.getChild("issued",getAtomNamespace());
if (e!=null) {
entry.setIssued(DateParser.parseDate(e.getText()));
}
e = eEntry.getChild("created",getAtomNamespace());
if (e!=null) {
entry.setCreated(DateParser.parseDate(e.getText()));
}
e = eEntry.getChild("summary",getAtomNamespace());
if (e!=null) {
entry.setSummary(parseContent(e));
}
eList = eEntry.getChildren("content",getAtomNamespace());
if (eList.size()>0) {
List content = new ArrayList();
for (int i=0;i<eList.size();i++) {
content.add(parseContent((Element)eList.get(i)));
}
entry.setContents(content);
}
entry.setModules(parseItemModules(eEntry));
List foreignMarkup =
extractForeignMarkup(eEntry, entry, getAtomNamespace());
if (foreignMarkup.size() > 0) {
entry.setForeignMarkup(foreignMarkup);
}
return entry;
}
}
/*
* Copyright 2004 Sun Microsystems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.sun.syndication.io.impl;
import java.io.StringReader;
import java.util.Iterator;
import java.util.List;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import com.sun.syndication.feed.WireFeed;
import com.sun.syndication.feed.atom.Category;
import com.sun.syndication.feed.atom.Content;
import com.sun.syndication.feed.atom.Entry;
import com.sun.syndication.feed.atom.Feed;
import com.sun.syndication.feed.atom.Generator;
import com.sun.syndication.feed.atom.Link;
import com.sun.syndication.feed.atom.Person;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.WireFeedOutput;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import org.jdom.output.XMLOutputter;
/**
* Feed Generator for Atom
* <p/>
*
* @author Elaine Chien
* @author Dave Johnson (updated for Atom 1.0)
*
*/
public class Atom10Generator extends BaseWireFeedGenerator {
private static final String ATOM_10_URI = "http://www.w3.org/2005/Atom";
private static final Namespace ATOM_NS = Namespace.getNamespace(ATOM_10_URI);
private String _version;
public Atom10Generator() {
this("atom_1.0","1.0");
}
protected Atom10Generator(String type,String version) {
super(type);
_version = version;
}
protected String getVersion() {
return _version;
}
protected Namespace getFeedNamespace() {
return ATOM_NS;
}
public Document generate(WireFeed wFeed) throws FeedException {
Feed feed = (Feed) wFeed;
Element root = createRootElement(feed);
populateFeed(feed,root);
purgeUnusedNamespaceDeclarations(root);
return createDocument(root);
}
protected Document createDocument(Element root) {
return new Document(root);
}
protected Element createRootElement(Feed feed) {
Element root = new Element("feed",getFeedNamespace());
root.addNamespaceDeclaration(getFeedNamespace());
//Attribute version = new Attribute("version", getVersion());
//root.setAttribute(version);
if (feed.getXmlBase() != null) {
root.setAttribute("base", feed.getXmlBase(), Namespace.XML_NAMESPACE);
}
generateModuleNamespaceDefs(root);
return root;
}
protected void populateFeed(Feed feed,Element parent) throws FeedException {
addFeed(feed,parent);
addEntries(feed,parent);
}
protected void addFeed(Feed feed,Element parent) throws FeedException {
Element eFeed = parent;
populateFeedHeader(feed,eFeed);
generateForeignMarkup(eFeed, (List)feed.getForeignMarkup());
checkFeedHeaderConstraints(eFeed);
generateFeedModules(feed.getModules(),eFeed);
}
protected void addEntries(Feed feed,Element parent) throws FeedException {
List items = feed.getEntries();
for (int i=0;i<items.size();i++) {
addEntry((Entry)items.get(i),parent);
}
checkEntriesConstraints(parent);
}
protected void addEntry(Entry entry,Element parent) throws FeedException {
Element eEntry = new Element("entry", getFeedNamespace());
if (entry.getXmlBase() != null) {
eEntry.setAttribute("base", entry.getXmlBase(), Namespace.XML_NAMESPACE);
}
populateEntry(entry,eEntry);
generateForeignMarkup(eEntry, (List)entry.getForeignMarkup());
checkEntryConstraints(eEntry);
generateItemModules(entry.getModules(),eEntry);
parent.addContent(eEntry);
}
protected void populateFeedHeader(Feed feed,Element eFeed) throws FeedException {
if (feed.getTitleEx() != null) {
Element titleElement = new Element("title", getFeedNamespace());
fillContentElement(titleElement, feed.getTitleEx());
eFeed.addContent(titleElement);
}
List links = feed.getAlternateLinks();
if (links != null) for (int i = 0; i < links.size(); i++) {
eFeed.addContent(generateLinkElement((Link)links.get(i)));
}
links = feed.getOtherLinks();
if (links != null) for (int j = 0; j < links.size(); j++) {
eFeed.addContent(generateLinkElement((Link)links.get(j)));
}
List cats = feed.getCategories();
if (cats != null) for (Iterator iter=cats.iterator(); iter.hasNext();) {
eFeed.addContent(generateCategoryElement((Category)iter.next()));
}
List authors = feed.getAuthors();
if (authors != null && authors.size() > 0) {
for (int i = 0; i < authors.size(); i++) {
Element authorElement = new Element("author", getFeedNamespace());
fillPersonElement(authorElement, (Person)feed.getAuthors().get(i));
eFeed.addContent(authorElement);
}
}
List contributors = feed.getContributors();
if (contributors != null && contributors.size() > 0) {
for (int i = 0; i < contributors.size(); i++) {
Element contributorElement = new Element("contributor", getFeedNamespace());
fillPersonElement(contributorElement, (Person)contributors.get(i));
eFeed.addContent(contributorElement);
}
}
if (feed.getSubtitle() != null) {
Element subtitleElement = new Element("subtitle", getFeedNamespace());
fillContentElement(subtitleElement, feed.getSubtitle());
eFeed.addContent(subtitleElement);
}
if (feed.getId() != null) {
eFeed.addContent(generateSimpleElement("id", feed.getId()));
}
if (feed.getGenerator() != null) {
eFeed.addContent(generateGeneratorElement(feed.getGenerator()));
}
if (feed.getRights() != null) {
eFeed.addContent(generateSimpleElement("rights", feed.getRights()));
}
if (feed.getIcon() != null) {
eFeed.addContent(generateSimpleElement("icon", feed.getIcon()));
}
if (feed.getLogo() != null) {
eFeed.addContent(generateSimpleElement("logo", feed.getLogo()));
}
if (feed.getUpdated() != null) {
Element updatedElement = new Element("updated", getFeedNamespace());
updatedElement.addContent(DateParser.formatW3CDateTime(feed.getUpdated()));
eFeed.addContent(updatedElement);
}
}
protected void populateEntry(Entry entry, Element eEntry) throws FeedException {
if (entry.getTitleEx() != null) {
Element titleElement = new Element("title", getFeedNamespace());
fillContentElement(titleElement, entry.getTitleEx());
eEntry.addContent(titleElement);
}
List links = entry.getAlternateLinks();
if (links != null) {
for (int i = 0; i < links.size(); i++) {
eEntry.addContent(generateLinkElement((Link)links.get(i)));
}
}
links = entry.getOtherLinks();
if (links != null) {
for (int i = 0; i < links.size(); i++) {
eEntry.addContent(generateLinkElement((Link)links.get(i)));
}
}
List cats = entry.getCategories();
if (cats != null) {
for (int i = 0; i < cats.size(); i++) {
eEntry.addContent(generateCategoryElement((Category)cats.get(i)));
}
}
List authors = entry.getAuthors();
if (authors != null && authors.size() > 0) {
for (int i = 0; i < authors.size(); i++) {
Element authorElement = new Element("author", getFeedNamespace());
fillPersonElement(authorElement, (Person)entry.getAuthors().get(i));
eEntry.addContent(authorElement);
}
}
List contributors = entry.getContributors();
if (contributors != null && contributors.size() > 0) {
for (int i = 0; i < contributors.size(); i++) {
Element contributorElement = new Element("contributor", getFeedNamespace());
fillPersonElement(contributorElement, (Person)contributors.get(i));
eEntry.addContent(contributorElement);
}
}
if (entry.getId() != null) {
eEntry.addContent(generateSimpleElement("id", entry.getId()));
}
if (entry.getUpdated() != null) {
Element updatedElement = new Element("updated", getFeedNamespace());
updatedElement.addContent(DateParser.formatW3CDateTime(entry.getUpdated()));
eEntry.addContent(updatedElement);
}
if (entry.getPublished() != null) {
Element publishedElement = new Element("published", getFeedNamespace());
publishedElement.addContent(DateParser.formatW3CDateTime(entry.getPublished()));
eEntry.addContent(publishedElement);
}
if (entry.getContents() != null && entry.getContents().size() > 0) {
Element contentElement = new Element("content", getFeedNamespace());
Content content = (Content)entry.getContents().get(0);
fillContentElement(contentElement, content);
eEntry.addContent(contentElement);
}
if (entry.getSummary() != null) {
Element summaryElement = new Element("summary", getFeedNamespace());
fillContentElement(summaryElement, entry.getSummary());
eEntry.addContent(summaryElement);
}
if (entry.getSource() != null) {
Element sourceElement = new Element("source", getFeedNamespace());
populateFeedHeader(entry.getSource(), sourceElement);
eEntry.addContent(sourceElement);
}
}
protected void checkFeedHeaderConstraints(Element eFeed) throws FeedException {
}
protected void checkEntriesConstraints(Element parent) throws FeedException {
}
protected void checkEntryConstraints(Element eEntry) throws FeedException {
}
protected Element generateCategoryElement(Category cat) {
Element catElement = new Element("category", getFeedNamespace());
if (cat.getTerm() != null) {
Attribute termAttribute = new Attribute("term", cat.getTerm());
catElement.setAttribute(termAttribute);
}
if (cat.getLabel() != null) {
Attribute labelAttribute = new Attribute("label", cat.getLabel());
catElement.setAttribute(labelAttribute);
}
if (cat.getScheme() != null) {
Attribute schemeAttribute = new Attribute("scheme", cat.getScheme());
catElement.setAttribute(schemeAttribute);
}
return catElement;
}
protected Element generateLinkElement(Link link) {
Element linkElement = new Element("link", getFeedNamespace());
if (link.getRel() != null) {
Attribute relAttribute = new Attribute("rel", link.getRel());
linkElement.setAttribute(relAttribute);
}
if (link.getType() != null) {
Attribute typeAttribute = new Attribute("type", link.getType());
linkElement.setAttribute(typeAttribute);
}
if (link.getHref() != null) {
Attribute hrefAttribute = new Attribute("href", link.getHref());
linkElement.setAttribute(hrefAttribute);
}
if (link.getHreflang() != null) {
Attribute hreflangAttribute = new Attribute("hreflang", link.getHreflang());
linkElement.setAttribute(hreflangAttribute);
}
if (link.getTitle() != null) {
Attribute title = new Attribute("title", link.getTitle());
linkElement.setAttribute(title);
}
if (link.getLength() != 0) {
Attribute lenght = new Attribute("length", Long.toString(link.getLength()));
linkElement.setAttribute(lenght);
}
return linkElement;
}
protected void fillPersonElement(Element element, Person person) {
if (person.getName() != null) {
element.addContent(generateSimpleElement("name", person.getName()));
}
if (person.getUri() != null) {
element.addContent(generateSimpleElement("uri", person.getUri()));
}
if (person.getEmail() != null) {
element.addContent(generateSimpleElement("email", person.getEmail()));
}
generatePersonModules(person.getModules(), element);
}
protected Element generateTagLineElement(Content tagline) {
Element taglineElement = new Element("subtitle", getFeedNamespace());
if (tagline.getType() != null) {
Attribute typeAttribute = new Attribute("type", tagline.getType());
taglineElement.setAttribute(typeAttribute);
}
if (tagline.getValue() != null) {
taglineElement.addContent(tagline.getValue());
}
return taglineElement;
}
protected void fillContentElement(Element contentElement, Content content)
throws FeedException {
String type = content.getType();
String atomType = type;
if (type != null) {
// Fix for issue #39 "Atom 1.0 Text Types Not Set Correctly"
// we're not sure who set this value, so ensure Atom types are used
if ("text/plain".equals(type)) atomType = Content.TEXT;
else if ("text/html".equals(type)) atomType = Content.HTML;
else if ("application/xhtml+xml".equals(type)) atomType = Content.XHTML;
Attribute typeAttribute = new Attribute("type", atomType);
contentElement.setAttribute(typeAttribute);
}
String href = content.getSrc();
if (href != null) {
Attribute srcAttribute = new Attribute("src", href);
contentElement.setAttribute(srcAttribute);
}
if (content.getValue() != null) {
if (atomType != null && (atomType.equals(Content.XHTML) || (atomType.indexOf("/xml")) != -1 ||
(atomType.indexOf("+xml")) != -1)) {
StringBuffer tmpDocString = new StringBuffer("<tmpdoc>");
tmpDocString.append(content.getValue());
tmpDocString.append("</tmpdoc>");
StringReader tmpDocReader = new StringReader(tmpDocString.toString());
Document tmpDoc;
try {
SAXBuilder saxBuilder = new SAXBuilder();
tmpDoc = saxBuilder.build(tmpDocReader);
}
catch (Exception ex) {
throw new FeedException("Invalid XML",ex);
}
List children = tmpDoc.getRootElement().removeContent();
contentElement.addContent(children);
} else {
// must be type html, text or some other non-XML format
// JDOM will escape property for XML
contentElement.addContent(content.getValue());
}
}
}
protected Element generateGeneratorElement(Generator generator) {
Element generatorElement = new Element("generator", getFeedNamespace());
if (generator.getUrl() != null) {
Attribute urlAttribute = new Attribute("uri", generator.getUrl());
generatorElement.setAttribute(urlAttribute);
}
if (generator.getVersion() != null) {
Attribute versionAttribute = new Attribute("version", generator.getVersion());
generatorElement.setAttribute(versionAttribute);
}
if (generator.getValue() != null) {
generatorElement.addContent(generator.getValue());
}
return generatorElement;
}
protected Element generateSimpleElement(String name, String value) {
Element element = new Element(name, getFeedNamespace());
element.addContent(value);
return element;
}
/**
* Utility method to serialize an entry to writer.
*/
public static void serializeEntry(Entry entry, Writer writer)
throws IllegalArgumentException, FeedException, IOException {
// Build a feed containing only the entry
List entries = new ArrayList();
entries.add(entry);
Feed feed1 = new Feed();
feed1.setFeedType("atom_1.0");
feed1.setEntries(entries);
// Get Rome to output feed as a JDOM document
WireFeedOutput wireFeedOutput = new WireFeedOutput();
Document feedDoc = wireFeedOutput.outputJDom(feed1);
// Grab entry element from feed and get JDOM to serialize it
Element entryElement= (Element)feedDoc.getRootElement().getChildren().get(0);
XMLOutputter outputter = new XMLOutputter();
outputter.output(entryElement, writer);
}
}
package com.sun.syndication.io.impl;
import com.sun.syndication.io.WireFeedGenerator;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.Parent;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* @author Alejandro Abdelnur
*/
public abstract class BaseWireFeedGenerator implements WireFeedGenerator {
/**
* [TYPE].feed.ModuleParser.classes= [className] ...
*/
private static final String FEED_MODULE_GENERATORS_POSFIX_KEY = ".feed.ModuleGenerator.classes";
/**
* [TYPE].item.ModuleParser.classes= [className] ...
*/
private static final String ITEM_MODULE_GENERATORS_POSFIX_KEY = ".item.ModuleGenerator.classes";
/**
* [TYPE].person.ModuleParser.classes= [className] ...
*/
private static final String PERSON_MODULE_GENERATORS_POSFIX_KEY = ".person.ModuleGenerator.classes";
private String _type;
private ModuleGenerators _feedModuleGenerators;
private ModuleGenerators _itemModuleGenerators;
private ModuleGenerators _personModuleGenerators;
private Namespace[] _allModuleNamespaces;
protected BaseWireFeedGenerator(String type) {
_type = type;
_feedModuleGenerators = new ModuleGenerators(type + FEED_MODULE_GENERATORS_POSFIX_KEY, this);
_itemModuleGenerators = new ModuleGenerators(type + ITEM_MODULE_GENERATORS_POSFIX_KEY, this);
_personModuleGenerators = new ModuleGenerators(type + PERSON_MODULE_GENERATORS_POSFIX_KEY, this);
Set allModuleNamespaces = new HashSet();
Iterator i = _feedModuleGenerators.getAllNamespaces().iterator();
while (i.hasNext()) {
allModuleNamespaces.add(i.next());
}
i = _itemModuleGenerators.getAllNamespaces().iterator();
while (i.hasNext()) {
allModuleNamespaces.add(i.next());
}
i = _personModuleGenerators.getAllNamespaces().iterator();
while (i.hasNext()) {
allModuleNamespaces.add(i.next());
}
_allModuleNamespaces = new Namespace[allModuleNamespaces.size()];
allModuleNamespaces.toArray(_allModuleNamespaces);
}
public String getType() {
return _type;
}
protected void generateModuleNamespaceDefs(Element root) {
for (int i = 0; i < _allModuleNamespaces.length; i++) {
root.addNamespaceDeclaration(_allModuleNamespaces[i]);
}
}
protected void generateFeedModules(List modules, Element feed) {
_feedModuleGenerators.generateModules(modules, feed);
}
public void generateItemModules(List modules, Element item) {
_itemModuleGenerators.generateModules(modules, item);
}
public void generatePersonModules(List modules, Element person) {
_personModuleGenerators.generateModules(modules, person);
}
protected void generateForeignMarkup(Element e, List foreignMarkup) {
if (foreignMarkup != null) {
Iterator elems = (Iterator) foreignMarkup.iterator();
while (elems.hasNext()) {
Element elem = (Element) elems.next();
Parent parent = elem.getParent();
if (parent != null) {
parent.removeContent(elem);
}
e.addContent(elem);
}
}
}
/**
* Purging unused declarations is less optimal, performance-wise, than never adding them in the first place. So, we
* should still ask the ROME guys to fix their code (not adding dozens of unnecessary module declarations). Having
* said that: purging them here, before XML generation, is more efficient than parsing and re-molding the XML after
* ROME generates it.
* <p/>
* Note that the calling app could still add declarations/modules to the Feed tree after this. Which is fine. But
* those modules are then responsible for crawling to the root of the tree, at generate() time, to make sure their
* namespace declarations are present.
*/
protected static void purgeUnusedNamespaceDeclarations(Element root) {
java.util.Set usedPrefixes = new java.util.HashSet();
collectUsedPrefixes(root, usedPrefixes);
List list = root.getAdditionalNamespaces();
List additionalNamespaces = new java.util.ArrayList();
additionalNamespaces.addAll(list); // the duplication will prevent a ConcurrentModificationException below
for (int i = 0; i < additionalNamespaces.size(); i++) {
Namespace ns = (Namespace) additionalNamespaces.get(i);
String prefix = ns.getPrefix();
if (prefix != null && prefix.length() > 0 && !usedPrefixes.contains(prefix)) {
root.removeNamespaceDeclaration(ns);
}
}
}
private static void collectUsedPrefixes(Element el, java.util.Set collector) {
String prefix = el.getNamespacePrefix();
if (prefix != null && prefix.length() > 0 && !collector.contains(prefix)) {
collector.add(prefix);
}
List kids = el.getChildren();
for (int i = 0; i < kids.size(); i++) {
collectUsedPrefixes((Element) kids.get(i), collector); // recursion - worth it
}
}
}
package com.sun.syndication.io.impl;
import com.sun.syndication.feed.WireFeed;
import com.sun.syndication.feed.module.Extendable;
import com.sun.syndication.io.WireFeedParser;
import java.util.ArrayList;
import java.util.Iterator;
import org.jdom.Element;
import java.util.List;
import org.jdom.Namespace;
import org.jdom.Attribute;
/**
* @author Alejandro Abdelnur
*/
public abstract class BaseWireFeedParser implements WireFeedParser {
/**
* [TYPE].feed.ModuleParser.classes= [className] ...
*
*/
private static final String FEED_MODULE_PARSERS_POSFIX_KEY = ".feed.ModuleParser.classes";
/**
* [TYPE].item.ModuleParser.classes= [className] ...
*
*/
private static final String ITEM_MODULE_PARSERS_POSFIX_KEY = ".item.ModuleParser.classes";
/**
* [TYPE].person.ModuleParser.classes= [className] ...
*
*/
private static final String PERSON_MODULE_PARSERS_POSFIX_KEY = ".person.ModuleParser.classes";
private String _type;
private ModuleParsers _feedModuleParsers;
private ModuleParsers _itemModuleParsers;
private ModuleParsers _personModuleParsers;
private Namespace _namespace;
protected BaseWireFeedParser(String type, Namespace namespace) {
_type = type;
_namespace = namespace;
_feedModuleParsers = new ModuleParsers(type+FEED_MODULE_PARSERS_POSFIX_KEY, this);
_itemModuleParsers = new ModuleParsers(type+ITEM_MODULE_PARSERS_POSFIX_KEY, this);
_personModuleParsers = new ModuleParsers(type+PERSON_MODULE_PARSERS_POSFIX_KEY, this);
}
/**
* Returns the type of feed the parser handles.
* <p>
* @see WireFeed for details on the format of this string.
* <p>
* @return the type of feed the parser handles.
*
*/
public String getType() {
return _type;
}
protected List parseFeedModules(Element feedElement) {
return _feedModuleParsers.parseModules(feedElement);
}
protected List parseItemModules(Element itemElement) {
return _itemModuleParsers.parseModules(itemElement);
}
protected List parsePersonModules(Element itemElement) {
return _personModuleParsers.parseModules(itemElement);
}
protected List extractForeignMarkup(Element e, Extendable ext, Namespace basens) {
ArrayList foreignMarkup = new ArrayList();
Iterator children = e.getChildren().iterator();
while (children.hasNext()) {
Element elem = (Element)children.next();
if (
// if elemet not in the RSS namespace
!basens.equals(elem.getNamespace())
// and elem was not handled by a module
&& null == ext.getModule(elem.getNamespaceURI())) {
// save it as foreign markup,
// but we can't detach it while we're iterating
foreignMarkup.add(elem.clone());
}
}
// Now we can detach the foreign markup elements
Iterator fm = foreignMarkup.iterator();
while (fm.hasNext()) {
Element elem = (Element)fm.next();
elem.detach();
}
return foreignMarkup;
}
protected Attribute getAttribute(Element e, String attributeName) {
Attribute attribute = e.getAttribute(attributeName);
if (attribute == null) {
attribute = e.getAttribute(attributeName, _namespace);
}
return attribute;
}
protected String getAttributeValue(Element e, String attributeName) {
Attribute attr = getAttribute(e, attributeName);
return (attr != null) ? attr.getValue() : null;
}
}
package com.sun.syndication.io.impl;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
/**
* Properties loader that aggregates a master properties file and several extra properties files,
* all from the current classpath.
* <P>
* The master properties file has to be in a distinct location than the extra properties files.
* First the master properties file is loaded, then all the extra properties files in their order
* of appearance in the classpath.
* <P>
* Current use cases (plugin manager for parsers/converters/generators for feeds and modules
* and date formats) assume properties are list of tokens, that why the only method to get
* property values is the getTokenizedProperty().
* <p>
*
* @author Alejandro Abdelnur
*
*/
public class PropertiesLoader {
private static final String MASTER_PLUGIN_FILE = "com/sun/syndication/rome.properties";
private static final String EXTRA_PLUGIN_FILE = "rome.properties";
private static Map clMap =
new WeakHashMap();
/**
* Returns the PropertiesLoader singleton used by ROME to load plugin components.
*
* @return PropertiesLoader singleton.
*
*/
public static PropertiesLoader getPropertiesLoader() {
synchronized(PropertiesLoader.class) {
PropertiesLoader loader = (PropertiesLoader)
clMap.get(Thread.currentThread().getContextClassLoader());
if (loader == null) {
try {
loader = new PropertiesLoader(MASTER_PLUGIN_FILE, EXTRA_PLUGIN_FILE);
clMap.put(Thread.currentThread().getContextClassLoader(), loader);
}
catch (IOException ex) {
throw new RuntimeException(ex);
}
}
return loader;
}
}
private Properties[] _properties;
/**
* Creates a PropertiesLoader.
* <p>
* @param masterFileLocation master file location, there must be only one.
* @param extraFileLocation extra file location, there may be many.
* @throws IOException thrown if one of the properties file could not be read.
*
*/
private PropertiesLoader(String masterFileLocation,String extraFileLocation) throws IOException {
List propertiesList = new ArrayList();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try {
InputStream is = classLoader.getResourceAsStream(masterFileLocation);
Properties p = new Properties();
p.load(is);
is.close();
propertiesList.add(p);
}
catch (IOException ioex) {
IOException ex = new IOException("could not load ROME master plugins file ["+masterFileLocation+"], "+
ioex.getMessage());
ex.setStackTrace(ioex.getStackTrace());
throw ex;
}
Enumeration urls = classLoader.getResources(extraFileLocation);
while (urls.hasMoreElements()) {
URL url = (URL) urls.nextElement();
Properties p = new Properties();
try {
InputStream is = url.openStream();
p.load(is);
is.close();
}
catch (IOException ioex) {
IOException ex = new IOException("could not load ROME extensions plugins file ["+url.toString()+"], "+
ioex.getMessage());
ex.setStackTrace(ioex.getStackTrace());
throw ex;
}
propertiesList.add(p);
}
_properties = new Properties[propertiesList.size()];
propertiesList.toArray(_properties);
}
/**
* Returns an array of tokenized values stored under a property key in all properties files.
* If the master file has this property its tokens will be the first ones in the array.
* <p>
* @param key property key to retrieve values
* @param separator String with all separator characters to tokenize from the values in all
* properties files.
* @return all the tokens for the given property key from all the properties files.
*
*/
public String[] getTokenizedProperty(String key,String separator) {
List entriesList = new ArrayList();
for (int i=0;i<_properties.length;i++) {
String values = _properties[i].getProperty(key);
if (values!=null) {
StringTokenizer st = new StringTokenizer(values,separator);
while (st.hasMoreTokens()) {
String token = st.nextToken();
entriesList.add(token);
}
}
}
String[] entries = new String[entriesList.size()];
entriesList.toArray(entries);
return entries;
}
/**
* Returns an array of values stored under a property key in all properties files.
* If the master file has this property it will be the first ones in the array.
* <p>
* @param key property key to retrieve values
* @return all the values for the given property key from all the properties files.
*
*/
public String[] getProperty(String key) {
List entriesList = new ArrayList();
for (int i=0;i<_properties.length;i++) {
String values = _properties[i].getProperty(key);
if (values!=null) {
entriesList.add(values);
}
}
String[] entries = new String[entriesList.size()];
entriesList.toArray(entries);
return entries;
}
}
/*
* Copyright 2004 Sun Microsystems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.sun.syndication.io.impl;
import com.sun.syndication.feed.rss.*;
import com.sun.syndication.io.FeedException;
import org.jdom.Attribute;
import org.jdom.Element;
import java.util.List;
/**
* Feed Generator for RSS 0.92
* <p/>
*
* @author Elaine Chien
*
*/
public class RSS092Generator extends RSS091UserlandGenerator {
public RSS092Generator() {
this("rss_0.92","0.92");
}
protected RSS092Generator(String type,String version) {
super(type,version);
}
protected void populateChannel(Channel channel,Element eChannel) {
super.populateChannel(channel,eChannel);
Cloud cloud = channel.getCloud();
if (cloud!=null) {
eChannel.addContent(generateCloud(cloud));
}
}
protected Element generateCloud(Cloud cloud) {
Element eCloud = new Element("cloud",getFeedNamespace());
if (cloud.getDomain() != null) {
eCloud.setAttribute(new Attribute("domain", cloud.getDomain()));
}
if (cloud.getPort() != 0) {
eCloud.setAttribute(new Attribute("port", String.valueOf(cloud.getPort())));
}
if (cloud.getPath() != null) {
eCloud.setAttribute(new Attribute("path", cloud.getPath()));
}
if (cloud.getRegisterProcedure() != null) {
eCloud.setAttribute(new Attribute("registerProcedure", cloud.getRegisterProcedure()));
}
if (cloud.getProtocol() != null) {
eCloud.setAttribute(new Attribute("protocol", cloud.getProtocol()));
}
return eCloud;
}
// Another one to thanks DW for
protected int getNumberOfEnclosures(List enclosures) {
return (enclosures.size()>0) ? 1 : 0;
}
protected void populateItem(Item item, Element eItem, int index) {
super.populateItem(item,eItem, index);
Source source =item.getSource();
if (source != null) {
eItem.addContent(generateSourceElement(source));
}
List enclosures = item.getEnclosures();
for(int i = 0; i < getNumberOfEnclosures(enclosures); i++) {
eItem.addContent(generateEnclosure((Enclosure)enclosures.get(i)));
}
List categories = item.getCategories();
for(int i = 0; i < categories.size(); i++) {
eItem.addContent(generateCategoryElement((Category)categories.get(i)));
}
}
protected Element generateSourceElement(Source source) {
Element sourceElement = new Element("source",getFeedNamespace());
if (source.getUrl() != null) {
sourceElement.setAttribute(new Attribute("url", source.getUrl()));
}
sourceElement.addContent(source.getValue());
return sourceElement;
}
protected Element generateEnclosure(Enclosure enclosure) {
Element enclosureElement = new Element("enclosure",getFeedNamespace());
if (enclosure.getUrl() != null) {
enclosureElement.setAttribute("url", enclosure.getUrl());
}
if (enclosure.getLength() != 0) {
enclosureElement.setAttribute("length", String.valueOf(enclosure.getLength()));
}
if (enclosure.getType() != null) {
enclosureElement.setAttribute("type", enclosure.getType());
}
return enclosureElement;
}
protected Element generateCategoryElement(Category category) {
Element categoryElement = new Element("category",getFeedNamespace());
if (category.getDomain() != null) {
categoryElement.setAttribute("domain", category.getDomain());
}
categoryElement.addContent(category.getValue());
return categoryElement;
}
protected void checkChannelConstraints(Element eChannel) throws FeedException {
checkNotNullAndLength(eChannel,"title", 0, -1);
checkNotNullAndLength(eChannel,"description", 0, -1);
checkNotNullAndLength(eChannel,"link", 0, -1);
}
protected void checkImageConstraints(Element eImage) throws FeedException {
checkNotNullAndLength(eImage,"title", 0, -1);
checkNotNullAndLength(eImage,"url", 0, -1);
}
protected void checkTextInputConstraints(Element eTextInput) throws FeedException {
checkNotNullAndLength(eTextInput,"title", 0, -1);
checkNotNullAndLength(eTextInput,"description", 0, -1);
checkNotNullAndLength(eTextInput,"name", 0, -1);
checkNotNullAndLength(eTextInput,"link", 0, -1);
}
protected void checkItemsConstraints(Element parent) throws FeedException {
}
protected void checkItemConstraints(Element eItem) throws FeedException {
}
}
/*
* Copyright 2004 Sun Microsystems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.sun.syndication.io.impl;
import com.sun.syndication.feed.WireFeed;
import com.sun.syndication.feed.rss.Category;
import com.sun.syndication.feed.rss.Channel;
import com.sun.syndication.feed.rss.Cloud;
import com.sun.syndication.feed.rss.Description;
import com.sun.syndication.feed.rss.Enclosure;
import com.sun.syndication.feed.rss.Item;
import com.sun.syndication.feed.rss.Source;
import org.jdom.Element;
import java.util.ArrayList;
import java.util.List;
/**
*/
public class RSS092Parser extends RSS091UserlandParser {
public RSS092Parser() {
this("rss_0.92");
}
protected RSS092Parser(String type) {
super(type);
}
protected String getRSSVersion() {
return "0.92";
}
protected WireFeed parseChannel(Element rssRoot) {
Channel channel = (Channel) super.parseChannel(rssRoot);
Element eChannel = rssRoot.getChild("channel",getRSSNamespace());
Element eCloud = eChannel.getChild("cloud",getRSSNamespace());
if (eCloud!=null) {
Cloud cloud = new Cloud();
String att = eCloud.getAttributeValue("domain");//getRSSNamespace()); DONT KNOW WHY DOESN'T WORK
if (att!=null) {
cloud.setDomain(att);
}
att = eCloud.getAttributeValue("port");//getRSSNamespace()); DONT KNOW WHY DOESN'T WORK
if (att!=null) {
cloud.setPort(Integer.parseInt(att.trim()));
}
att = eCloud.getAttributeValue("path");//getRSSNamespace()); DONT KNOW WHY DOESN'T WORK
if (att!=null) {
cloud.setPath(att);
}
att = eCloud.getAttributeValue("registerProcedure");//getRSSNamespace()); DONT KNOW WHY DOESN'T WORK
if (att!=null) {
cloud.setRegisterProcedure(att);
}
att = eCloud.getAttributeValue("protocol");//getRSSNamespace()); DONT KNOW WHY DOESN'T WORK
if (att!=null) {
cloud.setProtocol(att);
}
channel.setCloud(cloud);
}
return channel;
}
protected Item parseItem(Element rssRoot,Element eItem) {
Item item = super.parseItem(rssRoot,eItem);
Element e = eItem.getChild("source",getRSSNamespace());
if (e!=null) {
Source source = new Source();
String url = e.getAttributeValue("url");//getRSSNamespace()); DONT KNOW WHY DOESN'T WORK
source.setUrl(url);
source.setValue(e.getText());
item.setSource(source);
}
// 0.92 allows one enclosure occurrence, 0.93 multiple
// just saving to write some code.
List eEnclosures = eItem.getChildren("enclosure");//getRSSNamespace()); DONT KNOW WHY DOESN'T WORK
if (eEnclosures.size()>0) {
List enclosures = new ArrayList();
for (int i=0;i<eEnclosures.size();i++) {
e = (Element) eEnclosures.get(i);
Enclosure enclosure = new Enclosure();
String att = e.getAttributeValue("url");//getRSSNamespace()); DONT KNOW WHY DOESN'T WORK
if (att!=null) {
enclosure.setUrl(att);
}
att = e.getAttributeValue("length");//getRSSNamespace()); DONT KNOW WHY DOESN'T WORK
enclosure.setLength(NumberParser.parseLong(att,0L));
att = e.getAttributeValue("type");//getRSSNamespace()); DONT KNOW WHY DOESN'T WORK
if (att!=null) {
enclosure.setType(att);
}
enclosures.add(enclosure);
}
item.setEnclosures(enclosures);
}
List eCats = eItem.getChildren("category");//getRSSNamespace()); DONT KNOW WHY DOESN'T WORK
item.setCategories(parseCategories(eCats));
return item;
}
protected List parseCategories(List eCats) {
List cats = null;
if (eCats.size()>0) {
cats = new ArrayList();
for (int i=0;i<eCats.size();i++) {
Category cat = new Category();
Element e = (Element) eCats.get(i);
String att = e.getAttributeValue("domain");//getRSSNamespace()); DONT KNOW WHY DOESN'T WORK
if (att!=null) {
cat.setDomain(att);
}
cat.setValue(e.getText());
cats.add(cat);
}
}
return cats;
}
protected Description parseItemDescription(Element rssRoot,Element eDesc) {
Description desc = super.parseItemDescription(rssRoot,eDesc);
desc.setType("text/html");
return desc;
}
}