View Javadoc

1   /**
2    * This file Copyright (c) 2008-2013 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.module.rssaggregator.pages;
35  
36  import info.magnolia.cms.core.Content;
37  import info.magnolia.cms.core.HierarchyManager;
38  import info.magnolia.cms.i18n.Messages;
39  import info.magnolia.cms.i18n.MessagesManager;
40  import info.magnolia.cms.security.AccessDeniedException;
41  import info.magnolia.cms.security.AccessManager;
42  import info.magnolia.cms.security.Permission;
43  import info.magnolia.cms.util.AlertUtil;
44  import info.magnolia.cms.util.QueryUtil;
45  import info.magnolia.context.MgnlContext;
46  import info.magnolia.jcr.util.PropertyUtil;
47  import info.magnolia.jcr.util.SessionUtil;
48  import info.magnolia.module.admininterface.TemplatedMVCHandler;
49  import info.magnolia.module.data.commands.ImportCommand;
50  import info.magnolia.module.rssaggregator.command.ReplacePlanetUrlCommand;
51  import info.magnolia.module.rssaggregator.generator.CollectStatisticsCommand;
52  import info.magnolia.module.rssaggregator.generator.PlanetDataGenerator;
53  
54  import java.io.IOException;
55  import java.util.Iterator;
56  
57  import javax.jcr.Node;
58  import javax.jcr.RepositoryException;
59  import javax.jcr.Session;
60  import javax.servlet.ServletException;
61  import javax.servlet.http.HttpServletRequest;
62  import javax.servlet.http.HttpServletResponse;
63  
64  import org.apache.commons.lang.StringUtils;
65  import org.slf4j.Logger;
66  import org.slf4j.LoggerFactory;
67  
68  /**
69   * RSS Aggregator UI.
70   *
71   * @author Jan Haderka
72   */
73  public class RSSAggregatorPage extends TemplatedMVCHandler {
74  
75      /**
76       * Stable serialVersionUID.
77       */
78      public static final long serialVersionUID = 222L;
79  
80      /**
81       * View value for executing the manual backup. (won't render anything)
82       */
83      public static final String VIEW_EXPORT = "rssaggregator";
84  
85      private static final String TASKS = "/modules/data/config/importers/rssaggregator/automatedExecution";
86  
87      private static final String PLANET_DATA_PATH = "/modules/scheduler/config/jobs/generatePlanetData";
88  
89      private static final String PLANET_STATISTICS_PATH = "/modules/scheduler/config/jobs/collectPlanetStatistics";
90  
91      private static final String RSSAGGREGATOR_PAGE = "RSSAggregatorPage";
92  
93      private static Logger log = LoggerFactory.getLogger(RSSAggregatorPage.class);
94  
95      protected boolean mgnlKeepVersions;
96  
97      protected int mgnlMaxEntriesPerFile;
98  
99      private boolean manualRefresh;
100 
101     private boolean manualRefreshStatistics;
102 
103     private boolean manualRefreshData;
104 
105     private String mgnlImportRepeat;
106 
107     private String mgnlPlanetImportRepeat;
108 
109     private String mgnlPlanetStatisticsImportRepeat;
110 
111     /**
112      * Getter for <code>mgnlKeepVersions</code>.
113      *
114      * @return Returns the mgnlKeepVersions.
115      */
116     public boolean isMgnlKeepVersions() {
117         return this.mgnlKeepVersions;
118     }
119 
120     /**
121      * Setter for <code>mgnlKeepVersions</code>.
122      *
123      * @param mgnlKeepVersions The mgnlKeepVersions to set.
124      */
125     public void setMgnlKeepVersions(boolean mgnlKeepVersions) {
126         this.mgnlKeepVersions = mgnlKeepVersions;
127     }
128 
129     /**
130      * Getter for <code>maualBackup</code>.
131      *
132      * @return Returns the manualRefresh flag.
133      */
134     public boolean isManualBackup() {
135         return this.manualRefresh;
136     }
137 
138     /**
139      * Setter for <code>manualRefresh</code>.
140      *
141      * @param backup The manualRefresh to set.
142      */
143     public void setManualRefresh(boolean backup) {
144         this.manualRefresh = backup;
145     }
146 
147     /**
148      * Getter for manualRefreshStatistics.
149      *
150      * @return Returns the manualRefreshStatistics flag.
151      */
152     public boolean isManualRefreshStatistics() {
153         return manualRefreshStatistics;
154     }
155 
156     /**
157      * Setter for manualRefreshStatistics.
158      *
159      * @param manualRefreshStatistics The manualRefreshStatistics to set.
160      */
161     public void setManualRefreshStatistics(boolean manualRefreshStatistics) {
162         this.manualRefreshStatistics = manualRefreshStatistics;
163     }
164 
165     public boolean isManualRefreshData() {
166         return manualRefreshData;
167     }
168 
169     public void setManualRefreshData(boolean manualRefreshData) {
170         this.manualRefreshData = manualRefreshData;
171     }
172 
173     /**
174      * @param name
175      * @param request
176      * @param response
177      */
178     public RSSAggregatorPage(String name, HttpServletRequest request, HttpServletResponse response) {
179         super(name, request, response);
180     }
181 
182     /**
183      * @see info.magnolia.cms.servlets.MVCServletHandlerImpl#getCommand()
184      */
185     @Override
186     public String getCommand() {
187         if (this.manualRefresh) {
188             return "manualRefresh";
189         } else {
190             if (this.manualRefreshStatistics) {
191                 return "manualRefreshStatistics";
192             }
193         }
194         return super.getCommand();
195     }
196 
197     /**
198      * Actually fetch RSS feeds.
199      */
200     public String manualRefresh() throws Exception {
201         if (!checkPermissions(request, "data", "/rssaggregator", Permission.WRITE)) {
202             throw new ServletException(new AccessDeniedException(
203                     "Write permission needed for feed update. User not allowed to WRITE to data workspace.")); //$NON-NLS-1$
204         }
205         ImportCommand cmd = new ImportCommand();
206         cmd.setImporter("rssaggregator");
207         cmd.execute(MgnlContext.getInstance());
208         return RSSAGGREGATOR_PAGE;
209     }
210 
211     public String automaticUpdate() throws Exception {
212         HierarchyManager hm = MgnlContext.getHierarchyManager("config");
213         Content execution = hm.getContent(TASKS);
214         execution.getNodeData("enabled").setValue(true);
215         execution.getNodeData("cron").setValue("0 0/" + getMgnlImportRepeat() + " * * * *");
216         hm.save();
217 
218         return RSSAGGREGATOR_PAGE;
219     }
220 
221     public String manualRefreshData() throws Exception {
222         PlanetDataGenerator pdg = new PlanetDataGenerator();
223         pdg.execute(MgnlContext.getInstance());
224 
225         return RSSAGGREGATOR_PAGE;
226     }
227 
228     public String automaticPlanetUpdate() throws Exception {
229         Session session = MgnlContext.getJCRSession("config");
230         Node planetDataScheduler = session.getNode(PLANET_DATA_PATH);
231         PropertyUtil.setProperty(planetDataScheduler, "active", true);
232         PropertyUtil.setProperty(planetDataScheduler, "cron", "0 0/" + getMgnlPlanetImportRepeat() + " * * * *");
233         session.save();
234 
235         return RSSAGGREGATOR_PAGE;
236     }
237 
238     public String manualRefreshStatistics() throws Exception {
239         CollectStatisticsCommand csc = new CollectStatisticsCommand();
240         csc.execute(MgnlContext.getInstance());
241 
242         return RSSAGGREGATOR_PAGE;
243     }
244 
245     public String automaticPlanetStatisticsUpdate() throws Exception {
246         Session session = MgnlContext.getJCRSession("config");
247         Node planetStatisticsScheduler = session.getNode(PLANET_STATISTICS_PATH);
248         PropertyUtil.setProperty(planetStatisticsScheduler, "active", true);
249         PropertyUtil.setProperty(planetStatisticsScheduler, "cron", "0 0/" + getMgnlPlanetStatisticsImportRepeat() + " * * * *");
250         session.save();
251 
252         return RSSAGGREGATOR_PAGE;
253     }
254 
255     public String replacePlanetFeedUrl() {
256         try {
257             if (StringUtils.isNotBlank(MgnlContext.getParameter(ReplacePlanetUrlCommand.OLD_URL)) && StringUtils.isNotBlank(MgnlContext.getParameter(ReplacePlanetUrlCommand.NEW_URL))) {
258                 AlertUtil.setMessage(replaceUrlCommand());
259             } else {
260                 AlertUtil.setMessage("Please enter both the old and the new Planet feed URL you want to replace.");
261             }
262         } catch (Exception e) {
263             AlertUtil.setMessage("Problem while replacing Planet URL: " + e.getMessage(), e);
264         }
265         return RSSAGGREGATOR_PAGE;
266     }
267 
268     protected String replaceUrlCommand() {
269         ReplacePlanetUrlCommand command = new ReplacePlanetUrlCommand();
270         try {
271             command.execute(MgnlContext.getInstance());
272         } catch (Exception e) {
273             return "A problem occurred while replacing the URL: " + e.getMessage();
274         }
275        return "The existing URL has been replaced with the new one.";
276     }
277 
278     private String getMgnlImportRepeat() {
279         return mgnlImportRepeat;
280     }
281 
282     public String getMgnlPlanetImportRepeat() {
283         return mgnlPlanetImportRepeat;
284     }
285 
286     public String getMgnlPlanetStatisticsImportRepeat() {
287         return mgnlPlanetStatisticsImportRepeat;
288     }
289 
290     public int getAutoUpdate() throws Exception {
291         HierarchyManager hm = MgnlContext.getHierarchyManager("config");
292         Content execution = hm.getContent(TASKS);
293         String[] cron = execution.getNodeData("cron").getString().split(" ");
294         if (cron[1].indexOf('/') < 0) {
295             return 0;
296         } else {
297             return Integer.parseInt(cron[1].substring(cron[1].indexOf('/') + 1));
298         }
299     }
300 
301     public int getPlanetUpdate() throws Exception {
302         return getScheduledMinutes("generatePlanetData");
303     }
304 
305     public int getStatisticsUpdate() throws Exception {
306         return getScheduledMinutes("collectPlanetStatistics");
307     }
308 
309     protected int getScheduledMinutes(String job) throws Exception {
310         int min = 0;
311         Node planetJob = SessionUtil.getNode("config", "/modules/scheduler/config/jobs/" + job);
312 
313         if (planetJob != null && planetJob.hasProperty("cron")) {
314             String[] cron = StringUtils.split(planetJob.getProperty("cron").getString(), " ");
315 
316             if (StringUtils.indexOf(cron[1], "/") > -1) {
317                 min = Integer.parseInt(cron[1].substring(cron[1].indexOf('/') + 1));
318             }
319         } else {
320             log.warn("Could not find job or cron expression in scheduler module for planet job: " + job);
321         }
322         return min;
323     }
324 
325     public String getPlanetJobStatus() throws Exception {
326         return getJobRunningStatus("generatePlanetData");
327     }
328 
329     public String getStatisticsJobStatus() throws Exception {
330         return getJobRunningStatus("collectPlanetStatistics");
331     }
332 
333     protected String getJobRunningStatus(String job) throws Exception {
334         boolean active = false;
335         Node planetJob = SessionUtil.getNode("config", "/modules/scheduler/config/jobs/" + job);
336 
337         if (planetJob != null && planetJob.hasProperty("active")) {
338             active = StringUtils.equalsIgnoreCase("true", planetJob.getProperty("active").getString());
339         } else {
340             log.warn("Could not find job or status information (active) in scheduler module for planet job: " + job);
341         }
342 
343         if (active) {
344             return "Status: Job is ACTIVE.";
345         } else {
346             return "Status: Job is currently not active.";
347         }
348     }
349 
350     /**
351      * Uses access manager to authorize this request.
352      *
353      * @param request HttpServletRequest as received by the service method
354      * @return boolean true if read access is granted
355      */
356     protected boolean checkPermissions(HttpServletRequest request, String repository, String basePath,
357                                        long permissionType) {
358 
359         AccessManager accessManager = MgnlContext.getAccessManager(repository);
360         if (accessManager != null) {
361             if (!accessManager.isGranted(basePath, permissionType)) {
362                 return false;
363             }
364         }
365         return true;
366     }
367 
368     @Override
369     public void renderHtml(String view) throws IOException {
370         // if we are running the backup, everything is already done --> do not render
371         if (VIEW_EXPORT.equals(view)) {
372             return;
373         }
374         super.renderHtml(view);
375     }
376 
377     public Messages getMessages() {
378         return MessagesManager.getMessages("info.magnolia.module.rssaggregator.messages");
379     }
380 
381     public void setMgnlImportRepeat(String mgnlImportRepeat) {
382         this.mgnlImportRepeat = mgnlImportRepeat;
383     }
384 
385     public void setMgnlPlanetImportRepeat(String mgnlPlanetImportRepeat) {
386         this.mgnlPlanetImportRepeat = mgnlPlanetImportRepeat;
387     }
388 
389     public void setMgnlPlanetStatisticsImportRepeat(String mgnlPlanetStatisticsImportRepeat) {
390         this.mgnlPlanetStatisticsImportRepeat = mgnlPlanetStatisticsImportRepeat;
391     }
392 
393     public Iterator getPlanetFeeds() {
394         String sql = "select * from [nt:base] as t where ISDESCENDANTNODE([/rssaggregator]) and t.planetFeed='true' order by t.name";
395 
396         try {
397             return QueryUtil.search("data", sql);
398 
399         } catch (RepositoryException e) {
400             log.error("Problem while getting Planet feed list: " + e.getMessage());
401         }
402 
403         return null;
404     }
405 }