View Javadoc

1   /*
2    * SymmetricDS is an open source database synchronization solution.
3    *   
4    * Copyright (C) Chris Henson <chenson42@users.sourceforge.net>,
5    *               Eric Long <erilong@users.sourceforge.net>,
6    *               Keith Naas <knaas@users.sourceforge.net>
7    *               
8    *
9    * This library is free software; you can redistribute it and/or
10   * modify it under the terms of the GNU Lesser General Public
11   * License as published by the Free Software Foundation; either
12   * version 3 of the License, or (at your option) any later version.
13   *
14   * This library is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this library; if not, see
21   * <http://www.gnu.org/licenses/>.
22   */
23  
24  package org.jumpmind.symmetric.transport.handler;
25  
26  import java.io.IOException;
27  import java.io.Writer;
28  import java.util.ArrayList;
29  import java.util.Collections;
30  import java.util.Comparator;
31  import java.util.Date;
32  import java.util.Iterator;
33  import java.util.List;
34  
35  import org.apache.commons.lang.StringUtils;
36  import org.apache.commons.lang.time.FastDateFormat;
37  import org.jumpmind.symmetric.model.IncomingBatch;
38  import org.jumpmind.symmetric.model.IncomingBatchHistory;
39  import org.jumpmind.symmetric.model.OutgoingBatch;
40  import org.jumpmind.symmetric.model.OutgoingBatchHistory;
41  import org.jumpmind.symmetric.model.OutgoingBatchHistory.Status;
42  import org.jumpmind.symmetric.service.IIncomingBatchService;
43  import org.jumpmind.symmetric.service.INodeService;
44  import org.jumpmind.symmetric.service.IOutgoingBatchService;
45  import org.jumpmind.symmetric.service.IParameterService;
46  
47  import com.sun.syndication.feed.synd.SyndContent;
48  import com.sun.syndication.feed.synd.SyndContentImpl;
49  import com.sun.syndication.feed.synd.SyndEntry;
50  import com.sun.syndication.feed.synd.SyndEntryImpl;
51  import com.sun.syndication.feed.synd.SyndFeed;
52  import com.sun.syndication.feed.synd.SyndFeedImpl;
53  import com.sun.syndication.io.FeedException;
54  import com.sun.syndication.io.SyndFeedOutput;
55  
56  public class AlertResourceHandler extends AbstractTransportResourceHandler {
57      private static final int MAX_ERRORS = 1000;
58  
59      private static final FastDateFormat formatter = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
60  
61      private IIncomingBatchService incomingBatchService;
62  
63      private IOutgoingBatchService outgoingBatchService;
64  
65      private IParameterService parameterService;
66      
67      private INodeService nodeService;
68  
69      public void write(CharSequence feedURL, Writer outputWriter) throws IOException, FeedException {
70          SyndFeed feed = new SyndFeedImpl();
71          feed.setFeedType("rss_2.0");
72          feed.setTitle("SymmetricDS Alerts for " + parameterService.getMyUrl());
73          feed.setDescription("Problems synchronizing data");
74          feed.setLink(feedURL.toString());
75  
76          List<SyndEntry> entries = new ArrayList<SyndEntry>();
77  
78          for (IncomingBatch batch : findIncomingBatchErrors()) {
79              String title = "Incoming Batch " + batch.getNodeBatchId();
80              StringBuilder value = new StringBuilder("Node ");
81              value.append(batch.getNodeId());
82              value.append(" incoming batch ");
83              value.append(batch.getBatchId());
84              value.append(" is in error at ");
85              value.append(formatDate(batch.getCreateTime()));
86              value.append(".  ");
87              List<IncomingBatchHistory> list = filterOutIncomingHistoryErrors(incomingBatchService
88                      .findIncomingBatchHistory(batch.getBatchId(), batch.getNodeId()));
89              if (list.size() > 0) {
90                  value.append("The batch has been attempted ");
91                  value.append(list.size());
92                  value.append(" times.  ");
93                  IncomingBatchHistory history = list.get(list.size() - 1);
94                  int sqlCode = history.getSqlCode();
95                  String msg = history.getSqlMessage();
96                  if (sqlCode > 0 || !StringUtils.isBlank(msg)) {
97                      value.append("The sql error code is ");
98                      value.append(sqlCode);
99                      value.append(" and the error message is: ");
100                     value.append(msg);
101                 }
102             }
103             entries.add(createEntry(title, value.toString(), batch.getCreateTime(), nodeService.findNode(batch.getNodeId()).getSyncURL() + "/batch/" + batch.getBatchId()));
104         }
105 
106         for (OutgoingBatch batch : findOutgoingBatchErrors()) {
107             String title = "Outgoing Batch " + batch.getNodeBatchId();
108             StringBuilder value = new StringBuilder("Node ");
109             value.append(batch.getNodeId());
110             value.append(" outgoing batch ");
111             value.append(batch.getBatchId());
112             value.append(" is in error at ");
113             value.append(formatDate(batch.getCreateTime()));
114             value.append(".  ");
115             List<OutgoingBatchHistory> histories = filterOutOutgoingHistoryErrors(outgoingBatchService
116                     .findOutgoingBatchHistory(batch.getBatchId(), batch.getNodeId()));
117             if (histories.size() > 0) {
118                 value.append("The batch has been attempted ");
119                 value.append(histories.size());
120                 value.append(" times.  ");
121                 OutgoingBatchHistory history = histories.get(histories.size() - 1);
122                 int sqlCode = history.getSqlCode();
123                 String msg = history.getSqlMessage();
124                 if (sqlCode > 0 || !StringUtils.isBlank(msg)) {
125                     value.append("The sql error code is ");
126                     value.append(sqlCode);
127                     value.append(" and the error message is: ");
128                     value.append(msg);
129                 }
130             }
131 
132             entries.add(createEntry(title, value.toString(), batch.getCreateTime(), "batch/" + batch.getBatchId()));
133         }
134 
135         Collections.sort(entries, new SyndEntryOrderer());
136         feed.setEntries(entries);
137 
138         SyndFeedOutput out = new SyndFeedOutput();
139         out.output(feed, outputWriter);
140     }
141 
142     private List<IncomingBatchHistory> filterOutIncomingHistoryErrors(List<IncomingBatchHistory> list) {
143         for (Iterator<IncomingBatchHistory> iterator = list.iterator(); iterator.hasNext();) {
144             IncomingBatchHistory outgoingBatchHistory = iterator.next();
145             if (outgoingBatchHistory.getStatus() != org.jumpmind.symmetric.model.IncomingBatchHistory.Status.ER) {
146                 iterator.remove();
147             }
148         }
149         return list;
150     }
151 
152     private List<OutgoingBatchHistory> filterOutOutgoingHistoryErrors(List<OutgoingBatchHistory> list) {
153         for (Iterator<OutgoingBatchHistory> iterator = list.iterator(); iterator.hasNext();) {
154             OutgoingBatchHistory outgoingBatchHistory = iterator.next();
155             if (outgoingBatchHistory.getStatus() != Status.ER) {
156                 iterator.remove();
157             }
158         }
159         return list;
160     }
161 
162     class SyndEntryOrderer implements Comparator<SyndEntry> {
163         public int compare(SyndEntry o1, SyndEntry o2) {
164             return o1.getPublishedDate().compareTo(o2.getPublishedDate());
165         }
166     }
167 
168     private SyndEntry createEntry(String title, String value, Date publishedDate, String sourceLink) {
169         SyndEntry entry = new SyndEntryImpl();
170         entry.setTitle(title);
171         if (sourceLink != null) {
172             entry.setLink(sourceLink);
173         }
174         entry.setPublishedDate(publishedDate);
175         SyndContent content = new SyndContentImpl();
176         content.setType("text/html");
177         content.setValue(value);
178         entry.setDescription(content);
179         return entry;
180     }
181 
182     private String formatDate(Date date) {
183         return formatter.format(date);
184     }
185 
186     private List<IncomingBatch> findIncomingBatchErrors() {
187         return getIncomingBatchService().findIncomingBatchErrors(MAX_ERRORS);
188     }
189 
190     private List<OutgoingBatch> findOutgoingBatchErrors() {
191 
192         return getOutgoingBatchService().getOutgoingBatcheErrors(MAX_ERRORS);
193     }
194 
195     private IIncomingBatchService getIncomingBatchService() {
196         return incomingBatchService;
197     }
198 
199     public void setIncomingBatchService(IIncomingBatchService incomingBatchService) {
200         this.incomingBatchService = incomingBatchService;
201     }
202 
203     private IOutgoingBatchService getOutgoingBatchService() {
204         return outgoingBatchService;
205     }
206 
207     public void setOutgoingBatchService(IOutgoingBatchService outgoingBatchService) {
208         this.outgoingBatchService = outgoingBatchService;
209     }
210 
211     public void setParameterService(IParameterService parameterService) {
212         this.parameterService = parameterService;
213     }
214 
215     public void setNodeService(INodeService nodeService) {
216         this.nodeService = nodeService;
217     }
218 
219 }