001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.portals.applications.rss;
018:
019: import java.io.BufferedInputStream;
020: import java.io.BufferedReader;
021: import java.io.IOException;
022: import java.io.InputStreamReader;
023: import java.io.Reader;
024: import java.io.StringReader;
025: import java.io.StringWriter;
026: import java.net.URL;
027: import java.net.URLConnection;
028: import java.util.Enumeration;
029: import java.util.HashMap;
030: import java.util.Map;
031:
032: import javax.portlet.PortletConfig;
033: import javax.portlet.PortletException;
034: import javax.portlet.PortletPreferences;
035: import javax.portlet.RenderRequest;
036: import javax.portlet.RenderResponse;
037: import javax.xml.parsers.DocumentBuilder;
038: import javax.xml.parsers.DocumentBuilderFactory;
039:
040: import org.apache.portals.applications.transform.TransformCacheEntry;
041: import org.apache.portals.applications.util.Streams;
042: import org.w3c.dom.Document;
043: import org.w3c.dom.Node;
044: import org.w3c.dom.NodeList;
045: import org.xml.sax.EntityResolver;
046: import org.xml.sax.InputSource;
047:
048: /**
049: * RSSPortlet
050: *
051: * @author <a href="mailto:taylor@apache.org">David Sean Taylor </a>
052: * @version $Id: RSSPortlet.java 517719 2007-03-13 15:05:48Z ate $
053: */
054: public class RSSPortlet extends AbstractRssPortlet implements
055: EntityResolver {
056:
057: private Document document = null;
058:
059: private Map stylesheets = null;
060:
061: public void init(PortletConfig config) throws PortletException {
062: super .init(config);
063:
064: // load stylesheets available
065: stylesheets = new HashMap();
066:
067: Enumeration e = this .getPortletConfig().getInitParameterNames();
068: while (e.hasMoreElements()) {
069: String name = (String) e.nextElement();
070: String base = "text/html";
071:
072: if (name.startsWith("stylesheet")) {
073: int idx = -1;
074: if ((idx = name.indexOf(".")) > -1) {
075: base = name.substring(idx + 1, name.length());
076: }
077: stylesheets.put(base, getPortletConfig()
078: .getInitParameter(name));
079: }
080: }
081: }
082:
083: public InputSource resolveEntity(String publicId, String systemId) {
084: try {
085: //access Jetspeed cache and get a java.io.Reader
086: Reader rdr = openURL(publicId);
087: InputSource is = new InputSource(rdr);
088: is.setPublicId(publicId);
089: is.setSystemId(systemId);
090: return is;
091: } catch (IOException x) {
092: System.err.println("Entity Resolution error: ( " + publicId
093: + " Taking " + systemId
094: + " from cache throwed Exception: " + x);
095:
096: }
097: return null;
098: }
099:
100: private Reader openURL(String urlPath) throws IOException {
101: URL url = new URL(urlPath);
102: URLConnection conn = url.openConnection();
103:
104: String enc = conn.getContentEncoding();
105: if (enc == null) {
106: enc = "ISO-8859-1";
107: }
108:
109: BufferedInputStream is = new BufferedInputStream(conn
110: .getInputStream());
111: is.mark(20480);
112: BufferedReader asciiReader = new BufferedReader(
113: new InputStreamReader(is, "ASCII"));
114: String decl = asciiReader.readLine();
115: String key = "encoding=\"";
116: if (decl != null) {
117: int off = decl.indexOf(key);
118: if (off > 0) {
119: enc = decl.substring(off + key.length(), decl.indexOf(
120: '"', off + key.length()));
121: }
122: }
123: //Reset the bytes read
124: is.reset();
125: Reader rdr = new InputStreamReader(is, enc);
126: return rdr;
127: }
128:
129: public Document getDocument(String url) throws Exception {
130: DocumentBuilder parser = null;
131:
132: // read content, clean it, parse it and cache the DOM try { final
133: DocumentBuilderFactory docfactory = DocumentBuilderFactory
134: .newInstance(); //Have it non-validating
135: docfactory.setValidating(false);
136: parser = docfactory.newDocumentBuilder();
137: parser.setEntityResolver(this );
138:
139: Reader rdr = openURL(url);
140: InputSource isrc = new InputSource(rdr);
141: isrc.setSystemId(url);
142: this .document = parser.parse(isrc);
143: return document;
144: }
145:
146: public void doView(RenderRequest request, RenderResponse response)
147: throws PortletException, IOException {
148: response.setContentType("text/html");
149:
150: PortletPreferences prefs = request.getPreferences();
151:
152: // TODO: use stylesheet based on mimetype
153: String stylesheet = getPortletConfig().getInitParameter(
154: "stylesheet");
155: String realStylesheet = getPortletConfig().getPortletContext()
156: .getRealPath(stylesheet);
157: String url = prefs
158: .getValue(
159: "url",
160: "http://news.bbc.co.uk/rss/sportonline_uk_edition/football/internationals/england/squad_profiles/rss091.xml");
161:
162: String key = cache.constructKey(url, stylesheet); // TODO: use the entire parameter list
163: TransformCacheEntry entry = cache.get(key);
164: if (entry != null) {
165: byte[] bytes = (byte[]) entry.getDocument();
166: Streams.drain(new StringReader(new String(bytes, "UTF-8")),
167: response.getWriter());
168: } else {
169: try {
170: Document document = getDocument(url);
171: InputSource source = new InputSource(url);
172: source.setSystemId(url);
173: source.setEncoding("UTF-8");
174:
175: Map parameters = new HashMap();
176: parameters.put("itemdisplayed", prefs.getValue(
177: "itemdisplayed", "15"));
178: parameters.put("openinpopup", prefs.getValue(
179: "openinpopup", "true"));
180: parameters.put("showdescription", prefs.getValue(
181: "showdescription", "true"));
182: parameters.put("showtitle", prefs.getValue("showtitle",
183: "true"));
184: parameters.put("showtextinput", prefs.getValue(
185: "showtextinput", "true"));
186:
187: StringWriter sw = new StringWriter();
188: transform.transform(realStylesheet, source, sw,
189: parameters); //response.getPortletOutputStream(), parameters);
190: Streams.drain(new StringReader(sw.toString()), response
191: .getWriter());
192: try {
193: // Java 1.5 only
194: // String t = document.getDocumentElement().getElementsByTagName("title").item(0).getTextContent();
195: NodeList nodes = document.getDocumentElement()
196: .getElementsByTagName("title");
197: if (nodes != null) {
198: Node node = nodes.item(0);
199: if (node != null) {
200: Node title = node.getFirstChild();
201: if (title != null)
202: response.setTitle(title.getNodeValue());
203: }
204: }
205: } catch (Exception e) {
206:
207: }
208:
209: cache.put(key, sw.toString().getBytes("UTF-8"), 15);
210: } catch (Exception ex) {
211: response.getPortletOutputStream().write(
212: new String("Failed to process RSS Feed: " + url
213: + ", " + ex).getBytes());
214: }
215: }
216: }
217:
218: }
|