001: /*
002: * (C) Copyright 2004 Nabh Information Systems, Inc.
003: *
004: * This program is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU General Public License
006: * as published by the Free Software Foundation; either version 2
007: * of the License, or (at your option) any later version.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
017: *
018: */
019: package com.nabhinc.portlet.news;
020:
021: import java.io.File;
022: import java.io.FileOutputStream;
023: import java.io.IOException;
024: import java.io.OutputStreamWriter;
025: import java.net.MalformedURLException;
026: import java.sql.Connection;
027: import java.sql.PreparedStatement;
028: import java.sql.ResultSet;
029: import java.sql.SQLException;
030: import java.sql.Timestamp;
031: import java.util.Date;
032:
033: import javax.portlet.ActionRequest;
034: import javax.portlet.ActionResponse;
035: import javax.portlet.PortletException;
036: import javax.sql.DataSource;
037:
038: import org.w3c.dom.Element;
039:
040: import com.nabhinc.portlet.mvcportlet.core.ActionConfig;
041: import com.nabhinc.portlet.mvcportlet.core.ActionProcessor;
042: import com.nabhinc.portlet.mvcportlet.core.BaseRequestProcessor;
043: import com.nabhinc.portlet.mvcportlet.core.ControllerPortletConfig;
044: import com.nabhinc.util.IOUtil;
045: import com.nabhinc.util.XMLUtil;
046: import com.nabhinc.util.db.DBUtil;
047: import com.nabhinc.util.i18n.DateTimeFormatUtil;
048:
049: /**
050: *
051: *
052: * @author Padmanabh Dabke
053: * (c) 2004 Nabh Information Systems, Inc. All Rights Reserved.
054: */
055: public class CreateChannelFiles extends BaseRequestProcessor implements
056: ActionProcessor {
057:
058: private String ccfBaseDir = null;
059: private String ccfRealBaseDir = null;
060: private String ccfBaseURL = null;
061: private int ccfSiteChannelID = 1;
062: private String ccfChannelSQL = "SELECT cname, cformat, cright, descr, clang, lastupdate,creator FROM SB_NEWS_CHANNELS WHERE id = ?";
063: private String ccfStorySQL = "SELECT headline, summary, content, reported,id FROM SB_NEWS_STORIES WHERE channelid = ? AND sdisplay <> 0 ORDER BY reported DESC";
064: private String ccfSiteStorySQL = "SELECT headline, summary, content, reported,id FROM SB_NEWS_STORIES WHERE sdisplay <> 0 ORDER BY reported DESC";
065:
066: public void init(Element config, ControllerPortletConfig conConfig)
067: throws PortletException {
068: super .init(config, conConfig);
069: ccfBaseDir = conConfig.getParameter("base-news-dir");
070: if (ccfBaseDir == null) {
071: throw new PortletException(
072: "Missing required global parameter: base-news-dir.");
073: }
074: ccfRealBaseDir = getRealPath(brpConfig.getPortletContext(),
075: ccfBaseDir);
076:
077: String temp = XMLUtil.getSubElementText(config, "channel-sql");
078: if (temp != null)
079: ccfChannelSQL = temp;
080:
081: temp = XMLUtil.getSubElementText(config, "story-sql");
082: if (temp != null)
083: ccfStorySQL = temp;
084:
085: temp = XMLUtil.getSubElementText(config, "site-story-sql");
086: if (temp != null)
087: ccfSiteStorySQL = temp;
088:
089: temp = XMLUtil.getSubElementText(config, "base-url");
090: if (temp != null)
091: ccfBaseURL = temp;
092:
093: temp = XMLUtil.getSubElementText(config, "site-channel-id");
094: if (temp != null)
095: ccfSiteChannelID = Integer.parseInt(temp);
096:
097: File baseDir = new File(ccfRealBaseDir);
098: if (!baseDir.exists()) {
099: throw new PortletException("Base news directory: "
100: + ccfRealBaseDir + " does not exist.");
101: }
102:
103: // Check if we can find a template.html file used to create news html files.
104: if (!new File(ccfRealBaseDir, "template.html").exists()) {
105: throw new PortletException(
106: "You must place a template.html file in news base directory.");
107: }
108: }
109:
110: /**
111: * @param request
112: * @param response
113: * @param actionConfig
114: * @return
115: * @throws PortletException
116: * @throws IOException
117: */
118: public String process(ActionRequest request,
119: ActionResponse response, ActionConfig actionConfig)
120: throws PortletException, IOException {
121:
122: String channelIDStr = request.getParameter("channel_id");
123: if (channelIDStr == null)
124: throw new PortletException("Missing channel ID.");
125:
126: int channelID = 0;
127:
128: try {
129: channelID = Integer.parseInt(channelIDStr);
130: } catch (Exception ex) {
131: throw new PortletException("Invalid channel ID: "
132: + channelIDStr);
133: }
134: ResultSet rs = null;
135: PreparedStatement st = null;
136: Connection conn = null;
137: String baseURL = ccfBaseURL;
138: if (baseURL == null) {
139: baseURL = "http://" + request.getServerName() + ":"
140: + request.getServerPort()
141: + request.getContextPath()
142: + brpConfig.getBasePath();
143: }
144: try {
145: DataSource ds = brpConfig.getDataSource();
146: //}
147: conn = ds.getConnection();
148: createChannelFiles(channelID, conn, baseURL, request);
149: if (channelID != ccfSiteChannelID) {
150: createChannelFiles(ccfSiteChannelID, conn, baseURL,
151: request);
152: }
153:
154: } catch (SQLException ex) {
155: throw new PortletException(
156: "Encountered database error in fetching channel data.",
157: ex);
158: } finally {
159: DBUtil.close(rs);
160: DBUtil.close(st);
161: DBUtil.close(conn);
162: }
163: return "success";
164: }
165:
166: private void createChannelFiles(int channelID, Connection conn,
167: String baseURL, ActionRequest request)
168: throws PortletException {
169: ResultSet rs = null;
170: PreparedStatement st = null;
171: try {
172: // Get channel metadata
173: st = conn.prepareStatement(ccfChannelSQL);
174: st.setInt(1, channelID);
175: rs = st.executeQuery();
176: if (!rs.next()) {
177: throw new PortletException("Invalid channel ID: "
178: + channelID + ".");
179: }
180: String channelName = rs.getString(1);
181: String channelFormat = rs.getString(2);
182: String channelCopyright = rs.getString(3);
183: String channelDescr = rs.getString(4);
184: String channelLang = rs.getString(5);
185: Timestamp channelLastUpdate = rs.getTimestamp(6);
186: String channelCreator = rs.getString(7);
187: rs.close();
188: st.close();
189:
190: // Construct the channel object.
191: NewsChannel channel = new NewsChannel();
192: channel.setTitle(channelName);
193: channel.setCopyright(channelCopyright);
194: channel.setCreator(channelCreator);
195: channel.setDescription(channelDescr);
196: channel.setGenerator("Stringbeans News Portlet");
197: channel.setLanguage(channelLang);
198: channel
199: .setLastUpdated(new Date(channelLastUpdate
200: .getTime()));
201: channel.setLastBuildDate(new Date());
202: channel.setLink("http://" + request.getServerName() + ":"
203: + request.getServerPort()
204: + request.getContextPath());
205: // Get news stories
206: if (channelID == ccfSiteChannelID) {
207: st = conn.prepareStatement(ccfSiteStorySQL);
208: } else {
209: st = conn.prepareStatement(ccfStorySQL);
210: st.setInt(1, channelID);
211: }
212: rs = st.executeQuery();
213: boolean atleastOneHeadline = false;
214:
215: // Create news story directory and clear old files
216: File channelDir = new File(ccfRealBaseDir, channelName
217: .replaceAll(" ", "_"));
218: channelDir.mkdir();
219: String[] oldFiles = channelDir.list();
220: if (oldFiles != null) {
221: for (int i = 0; i < oldFiles.length; i++) {
222: new File(channelDir, oldFiles[i]).delete();
223: }
224: }
225:
226: // Get content of the story template file as a string
227: String template = IOUtil.getFileContentAsString(new File(
228: ccfRealBaseDir, "template.html"));
229:
230: while (rs.next()) {
231: atleastOneHeadline = true;
232: String headline = rs.getString(1);
233: String summary = rs.getString(2);
234: String story = rs.getString(3);
235: Timestamp publishTime = rs.getTimestamp(4);
236: Date itemPubDate = new Date(publishTime.getTime());
237: String storyID = rs.getString(5);
238: String publishTimeStr = DateTimeFormatUtil
239: .getDateTimeFormat(request.getLocale()).format(
240: publishTime);
241:
242: // Add channel item
243: NewsItem item = new NewsItem(itemPubDate, headline,
244: baseURL + "/" + channelName + "/" + storyID
245: + ".html", summary);
246: channel.addItem(item);
247: // Create story file
248: File f = new File(channelDir, storyID + ".html");
249: OutputStreamWriter writer = new OutputStreamWriter(
250: new FileOutputStream(f), "UTF-8");
251:
252: String storyContent = template.replaceAll(
253: "\\$timestamp", publishTimeStr);
254: storyContent = storyContent.replaceFirst("\\$story",
255: story);
256: storyContent = storyContent.replaceAll("\\$headline",
257: headline);
258: storyContent = storyContent.replaceAll("\\$copyright",
259: channelCopyright);
260: writer.write(storyContent);
261: writer.flush();
262: writer.close();
263:
264: }
265:
266: if (!atleastOneHeadline) {
267: return;
268: }
269:
270: FileOutputStream fos = new FileOutputStream(new File(
271: channelDir, "rss.xml"));
272: OutputStreamWriter channelWriter = new OutputStreamWriter(
273: fos, "UTF-8");
274:
275: if ("RSS 0.91".equals(channelFormat)) {
276: RSSExporter.exportRSS091(channel, channelWriter);
277: } else if ("RSS 1.0".equals(channelFormat)) {
278: RSSExporter.exportRSS10(channel, channelWriter);
279: } else if ("RSS 2.0".equals(channelFormat)) {
280: RSSExporter.exportRSS20(channel, channelWriter);
281: } else {
282: throw new PortletException(
283: "Unknown news export format: " + channelFormat);
284: }
285:
286: channelWriter.close();
287:
288: return;
289: } catch (SQLException ex) {
290: throw new PortletException(
291: "Database exception in fetching channel data.", ex);
292: } catch (MalformedURLException ex) {
293: throw new PortletException("Malformed base url.", ex);
294: } catch (IOException ex) {
295: throw new PortletException(
296: "IO exception in writing channel files.", ex);
297: } finally {
298: DBUtil.close(rs);
299: DBUtil.close(st);
300: }
301:
302: }
303:
304: }
|