View Javadoc

1   /**
2    * This file Copyright (c) 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.app.subapps.aggregationconfig;
35  
36  import info.magnolia.cms.security.AccessManager;
37  import info.magnolia.cms.security.Permission;
38  import info.magnolia.context.MgnlContext;
39  import info.magnolia.i18nsystem.SimpleTranslator;
40  import info.magnolia.jcr.util.NodeUtil;
41  import info.magnolia.jcr.util.NodeVisitor;
42  import info.magnolia.jcr.util.PropertyUtil;
43  import info.magnolia.module.data.commands.ImportCommand;
44  import info.magnolia.module.rssaggregator.RSSAggregatorConstants;
45  import info.magnolia.module.rssaggregator.RSSAggregatorNodeTypes;
46  import info.magnolia.module.rssaggregator.app.subapps.aggregationconfig.view.RSSAggregatorConfigurationView;
47  import info.magnolia.module.rssaggregator.generator.CollectStatisticsCommand;
48  import info.magnolia.module.rssaggregator.generator.PlanetDataGenerator;
49  import info.magnolia.repository.RepositoryConstants;
50  import info.magnolia.ui.api.app.AppContext;
51  import info.magnolia.ui.api.context.UiContext;
52  import info.magnolia.ui.api.view.View;
53  import info.magnolia.ui.vaadin.overlay.MessageStyleTypeEnum;
54  
55  import javax.inject.Inject;
56  import javax.jcr.Node;
57  import javax.jcr.RepositoryException;
58  import javax.jcr.Session;
59  
60  import org.apache.jackrabbit.commons.predicate.IsNodePredicate;
61  import org.slf4j.Logger;
62  import org.slf4j.LoggerFactory;
63  
64  
65  /**
66   * Presenter class, holds logic of
67   * {@link info.magnolia.module.rssaggregator.app.subapps.aggregationconfig.RSSAggregatorConfigurationSubApp} sub-app.
68   */
69  public class RSSAggregatorConfigurationPresenter implements RSSAggregatorConfigurationView.Listener {
70  
71      private static final String IMPORT_ERROR_LABEL = "rssAggregator.config.notification.import_error";
72  
73      private static final String TASKS = "/modules/data/config/importers/rssaggregator/automatedExecution";
74  
75      private static final String PLANET_DATA_PATH = "/modules/scheduler/config/jobs/generatePlanetData";
76  
77      private static final String PLANET_STATISTICS_PATH = "/modules/scheduler/config/jobs/collectPlanetStatistics";
78  
79      private static final String IMPORT_COMPLETE_LABEL = "rssAggregator.config.notification.import_complete";
80  
81      private static final String SETTINGS_CHANGED_LABEL = "rssAggregator.config.notification.settings_changed";
82  
83      public static final String PLANET_DATA_CHANGED_LABEL = "rssAggregator.config.notification.planet_data_changed";
84  
85      public static final String STATISTICS_COLLECTED_LABEL = "rssAggregator.config.notification.stats_collected";
86  
87      private Logger log = LoggerFactory.getLogger(getClass());
88  
89      private RSSAggregatorConfigurationView view;
90  
91      private UiContext uiContext;
92  
93      private SimpleTranslator translator;
94  
95      @Inject
96      public RSSAggregatorConfigurationPresenter(RSSAggregatorConfigurationView view, AppContext uiContext, SimpleTranslator translator) {
97          this.view = view;
98          this.uiContext = uiContext;
99          this.translator = translator;
100     }
101 
102     public View start() {
103         view.setListener(this);
104         return view;
105     }
106 
107     protected boolean checkPermissions(String repository, String basePath, long permissionType) {
108         AccessManager accessManager = MgnlContext.getAccessManager(repository);
109         if (accessManager != null) {
110             if (!accessManager.isGranted(basePath, permissionType)) {
111                 return false;
112             }
113         }
114         return true;
115     }
116 
117     @Override
118     public void onManualImport() {
119         if (!checkPermissions(RSSAggregatorConstants.WORKSPACE, "/", Permission.WRITE)) {
120             uiContext.openNotification(MessageStyleTypeEnum.ERROR, false, translator.translate(IMPORT_ERROR_LABEL));
121         } else {
122             ImportCommand cmd = new ImportCommand();
123             cmd.setImporter("rssaggregator");
124             cmd.execute(MgnlContext.getInstance());
125             uiContext.openNotification(MessageStyleTypeEnum.INFO, true, translator.translate(IMPORT_COMPLETE_LABEL));
126         }
127     }
128 
129     @Override
130     public void onAutomaticImportChanged(int periodMinutes) {
131         try {
132             Session session = MgnlContext.getJCRSession("config");
133             Node execution = session.getNode(TASKS);
134             execution.setProperty("enabled", true);
135             execution.setProperty("cron", "0 0/" + periodMinutes + " * * * *");
136             session.save();
137             uiContext.openNotification(MessageStyleTypeEnum.INFO, true, translator.translate(SETTINGS_CHANGED_LABEL));
138         } catch (RepositoryException e) {
139             displayException(e, "Failed to update automatic update period");
140         }
141 
142     }
143 
144     @Override
145     public void onAutomaticPlanetUpdateChanged(int value) {
146         try {
147             Session session = MgnlContext.getJCRSession("config");
148             Node planetDataScheduler = session.getNode(PLANET_DATA_PATH);
149             PropertyUtil.setProperty(planetDataScheduler, "active", true);
150             PropertyUtil.setProperty(planetDataScheduler, "cron", "0 0/" + value + " * * * *");
151             session.save();
152             uiContext.openNotification(MessageStyleTypeEnum.INFO, true, SETTINGS_CHANGED_LABEL);
153         }  catch (RepositoryException e) {
154             displayException(e, "Failed to change planet update period: ");
155         }
156     }
157 
158     @Override
159     public void onPlanetDataManualUpdate() {
160         try {
161             PlanetDataGenerator pdg = new PlanetDataGenerator();
162             pdg.execute(MgnlContext.getInstance());
163             uiContext.openNotification(MessageStyleTypeEnum.INFO, true, translator.translate(PLANET_DATA_CHANGED_LABEL));
164         } catch (Exception e) {
165             displayException(e, "Failed to update planet data: ");
166         }
167 
168     }
169 
170     @Override
171     public void onPlanetStatisticsManualUpdate() {
172         CollectStatisticsCommand csc = new CollectStatisticsCommand();
173         try {
174             csc.execute(MgnlContext.getInstance());
175             uiContext.openNotification(MessageStyleTypeEnum.INFO, true, translator.translate(STATISTICS_COLLECTED_LABEL));
176         } catch (Exception e) {
177             displayException(e, "Failed to collect statistics: ");
178         }
179     }
180 
181     @Override
182     public void onPlanetStatisticsAutomaticUpdatePeriodChanged(int value) {
183         try {
184             Session session = MgnlContext.getJCRSession("config");
185             Node planetStatisticsScheduler = session.getNode(PLANET_STATISTICS_PATH);
186             PropertyUtil.setProperty(planetStatisticsScheduler, "active", true);
187             PropertyUtil.setProperty(planetStatisticsScheduler, "cron", "0 0/" + value + " * * * *");
188             session.save();
189             uiContext.openNotification(MessageStyleTypeEnum.INFO, true, translator.translate(SETTINGS_CHANGED_LABEL));
190         } catch (RepositoryException e) {
191             displayException(e, "Failed to update planet update period: ");
192         }
193 
194     }
195 
196     private void displayException(Exception e, String msg) {
197         uiContext.openNotification(MessageStyleTypeEnum.ERROR, false, msg + e.getMessage());
198         log.error(msg, e);
199     }
200 
201     public void updateConfiguration() {
202         view.setDataImportPeriod(parseAutoUpdatePeriod(TASKS));
203         view.setPlanetStatsImportPeriod(parseAutoUpdatePeriod(PLANET_STATISTICS_PATH));
204         view.setPlanetDataImportPeriod(parseAutoUpdatePeriod(PLANET_DATA_PATH));
205 
206         boolean isPlanetVisible = false;
207         try {
208             Node root = MgnlContext.getJCRSession(RSSAggregatorConstants.WORKSPACE).getRootNode();
209             PlanetFeedSearcher searcher = new PlanetFeedSearcher();
210             NodeUtil.visit(root, searcher, new IsNodePredicate());
211             isPlanetVisible = searcher.isPlanetFeedFound();
212         } catch (RepositoryException e) {
213             log.warn("Problem occurred while checking planet config visibility ", e);
214         }
215 
216         view.setPlanetConfigVisible(isPlanetVisible);
217     }
218 
219     private int parseAutoUpdatePeriod(String path) {
220         try {
221             Session session = MgnlContext.getJCRSession(RepositoryConstants.CONFIG);
222             Node execution = session.getNode(path);
223             String[] cron = execution.getProperty("cron").getString().split(" ");
224             if (cron[1].indexOf('/') < 0) {
225                 return 0;
226             } else {
227                 return Integer.parseInt(cron[1].substring(cron[1].indexOf('/') + 1));
228             }
229         } catch (RepositoryException e) {
230             return 0;
231         }
232     }
233 
234     private static class PlanetFeedSearcher implements NodeVisitor {
235 
236         private boolean isPlanetFeedFound = false;
237 
238         @Override
239         public void visit(Node node) throws RepositoryException {
240             isPlanetFeedFound = isPlanetFeedFound ||
241                                     (NodeUtil.isNodeType(node, RSSAggregatorNodeTypes.RSSAggregator.NAME) &&
242                                         PropertyUtil.getBoolean(node, "planetFeed", false));
243         }
244 
245         public boolean isPlanetFeedFound() {
246             return isPlanetFeedFound;
247         }
248     }
249 }