1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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 }