1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.module.exchangesimple;
35
36 import info.magnolia.cms.core.SystemProperty;
37 import info.magnolia.cms.exchange.ActivationManagerFactory;
38 import info.magnolia.cms.exchange.ExchangeException;
39 import info.magnolia.cms.exchange.Subscriber;
40 import info.magnolia.cms.exchange.Subscription;
41
42 import java.io.IOException;
43 import java.io.UnsupportedEncodingException;
44 import java.net.HttpURLConnection;
45 import java.net.MalformedURLException;
46 import java.net.URL;
47 import java.net.URLConnection;
48 import java.net.URLEncoder;
49 import java.util.Collection;
50 import java.util.Iterator;
51 import java.util.Map;
52 import java.util.Map.Entry;
53
54 import org.apache.commons.lang.StringUtils;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58 import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
59 import EDU.oswego.cs.dl.util.concurrent.CountDown;
60 import EDU.oswego.cs.dl.util.concurrent.Sync;
61
62
63
64
65
66
67 public class SimpleSyndicator extends BaseSyndicatorImpl {
68 private static final Logger log = LoggerFactory.getLogger(SimpleSyndicator.class);
69
70 public SimpleSyndicator() {
71 }
72
73 public void activate(final ActivationContent activationContent) throws ExchangeException {
74 Collection subscribers = ActivationManagerFactory.getActivationManager().getSubscribers();
75 Iterator subscriberIterator = subscribers.iterator();
76 final Sync done = new CountDown(subscribers.size());
77 final Map errors = new ConcurrentHashMap(subscribers.size());
78 while (subscriberIterator.hasNext()) {
79 final Subscriber subscriber = (Subscriber) subscriberIterator.next();
80 if (subscriber.isActive()) {
81
82 executeInPool(getActivateTask(activationContent, done, errors, subscriber));
83 } else {
84
85 done.release();
86 }
87 }
88
89
90 acquireIgnoringInterruption(done);
91
92 String uuid = activationContent.getproperty(NODE_UUID);
93
94 if (!errors.isEmpty()) {
95 Exception e = null;
96 StringBuffer msg = new StringBuffer(errors.size() + " error").append(errors.size() > 1 ? "s" : "").append(" detected: ");
97 Iterator iter = errors.entrySet().iterator();
98 while (iter.hasNext()) {
99 Entry entry = (Entry) iter.next();
100 e = (Exception) entry.getValue();
101 Subscriber subscriber = (Subscriber) entry.getKey();
102 msg.append("\n").append(e.getMessage()).append(" on ").append(subscriber.getName());
103 log.error(e.getMessage(), e);
104 }
105
106 throw new ExchangeException(msg.toString(), e);
107 }
108
109 executeInPool(new Runnable() {
110 public void run() {
111 cleanTemporaryStore(activationContent);
112 }
113 });
114 }
115
116 private Runnable getActivateTask(final ActivationContent activationContent, final Sync done, final Map errors, final Subscriber subscriber) {
117 Runnable r = new Runnable() {
118 public void run() {
119 try {
120 activate(subscriber, activationContent);
121 } catch (ExchangeException e) {
122 log.error("Failed to activate content.", e);
123 errors.put(subscriber,e);
124 } finally {
125 done.release();
126 }
127 }
128 };
129 return r;
130 }
131
132
133
134
135
136
137
138 public String activate(Subscriber subscriber, ActivationContent activationContent) throws ExchangeException {
139 log.debug("activate");
140 if (null == subscriber) {
141 throw new ExchangeException("Null Subscriber");
142 }
143
144 String parentPath = null;
145
146 Subscription subscription = subscriber.getMatchedSubscription(this.path, this.repositoryName);
147 if (null != subscription) {
148
149
150 parentPath = this.getMappedPath(this.parent, subscription);
151 } else {
152 log.debug("Exchange : subscriber [{}] is not subscribed to {}", subscriber.getName(), this.path);
153 return null;
154 }
155 log.debug("Exchange : sending activation request to {} with user {}", subscriber.getName(), this.user.getName());
156
157 if(SystemProperty.getBooleanProperty(SystemProperty.MAGNOLIA_UTF8_ENABLED)) {
158 try {
159 parentPath = URLEncoder.encode(parentPath, "UTF-8");
160 }
161 catch (UnsupportedEncodingException e) {
162
163 }
164 }
165
166 URLConnection urlConnection = null;
167 try {
168 urlConnection = prepareConnection(subscriber);
169 this.addActivationHeaders(urlConnection, activationContent);
170
171 urlConnection.setRequestProperty(PARENT_PATH, parentPath);
172
173 Transporter.transport((HttpURLConnection) urlConnection, activationContent);
174
175 String status = urlConnection.getHeaderField(ACTIVATION_ATTRIBUTE_STATUS);
176
177
178 if (StringUtils.equals(status, ACTIVATION_FAILED)) {
179 String message = urlConnection.getHeaderField(ACTIVATION_ATTRIBUTE_MESSAGE);
180 throw new ExchangeException("Message received from subscriber: " + message);
181 }
182 urlConnection.getContent();
183 log.debug("Exchange : activation request sent to {}", subscriber.getName());
184 }
185 catch (ExchangeException e) {
186 throw e;
187 }
188 catch (IOException e) {
189 throw new ExchangeException("Not able to send the activation request [" + (urlConnection == null ? null : urlConnection.getURL()) + "]: " + e.getMessage());
190 }
191 catch (Exception e) {
192 throw new ExchangeException(e);
193 }
194 return null;
195 }
196
197 protected URLConnection prepareConnection(Subscriber subscriber) throws ExchangeException {
198
199 String handle = getActivationURL(subscriber);
200
201 try {
202
203 if (subscriber.getAuthenticationMethod() != null && "form".equalsIgnoreCase(subscriber.getAuthenticationMethod())) {
204 handle += (handle.indexOf('?') > 0 ? "&" : "?") + AUTH_USER + "=" + this.user.getName();
205 handle += "&" + AUTH_CREDENTIALS + "=" + this.user.getPassword();
206 }
207 URL url = new URL(handle);
208 URLConnection urlConnection = url.openConnection();
209
210 if (subscriber.getAuthenticationMethod() == null || "basic".equalsIgnoreCase(subscriber.getAuthenticationMethod())) {
211 urlConnection.setRequestProperty(AUTHORIZATION, this.basicCredentials);
212 } else if (!"form".equalsIgnoreCase(subscriber.getAuthenticationMethod())) {
213 log.info("Unknown Authentication method for deactivation: " + subscriber.getAuthenticationMethod());
214 }
215
216 return urlConnection;
217 } catch (MalformedURLException e) {
218 throw new ExchangeException("Incorrect URL for subscriber " + subscriber + "[" + handle + "]");
219 } catch (IOException e) {
220 throw new ExchangeException("Not able to send the activation request [" + handle + "]: " + e.getMessage());
221 } catch (Exception e) {
222 throw new ExchangeException(e);
223 }
224 }
225
226 public void doDeactivate() throws ExchangeException {
227 Collection subscribers = ActivationManagerFactory.getActivationManager().getSubscribers();
228 Iterator subscriberIterator = subscribers.iterator();
229 final Sync done = new CountDown(subscribers.size());
230 final Map errors = new ConcurrentHashMap();
231 while (subscriberIterator.hasNext()) {
232 final Subscriber subscriber = (Subscriber) subscriberIterator.next();
233 if (subscriber.isActive()) {
234
235 executeInPool(getDeactivateTask(done, errors, subscriber));
236 } else {
237
238 done.release();
239 }
240 }
241
242
243 acquireIgnoringInterruption(done);
244
245
246 if (!errors.isEmpty()) {
247 Exception e = null;
248 StringBuffer msg = new StringBuffer(errors.size() + " error").append(
249 errors.size() > 1 ? "s" : "").append(" detected: ");
250 Iterator iter = errors.entrySet().iterator();
251 while (iter.hasNext()) {
252 Entry entry = (Entry) iter.next();
253 e = (Exception) entry.getValue();
254 Subscriber subscriber = (Subscriber) entry.getKey();
255 msg.append("\n").append(e.getMessage()).append(" on ").append(subscriber.getName());
256 log.error(e.getMessage(), e);
257 }
258
259 throw new ExchangeException(msg.toString(), e);
260 }
261 }
262
263 private Runnable getDeactivateTask(final Sync done, final Map errors, final Subscriber subscriber) {
264 Runnable r = new Runnable() {
265 public void run() {
266 try {
267 doDeactivate(subscriber);
268 } catch (ExchangeException e) {
269 log.error("Failed to deactivate content.", e);
270 errors.put(subscriber,e);
271 } finally {
272 done.release();
273 }
274 }
275 };
276 return r;
277 }
278
279
280
281
282
283
284 public String doDeactivate(Subscriber subscriber) throws ExchangeException {
285 Subscription subscription = subscriber.getMatchedSubscription(this.path, this.repositoryName);
286 if (null != subscription) {
287 String handle = getDeactivationURL(subscriber);
288 try {
289 URLConnection urlConnection = prepareConnection(subscriber);
290
291 this.addDeactivationHeaders(urlConnection);
292 String status = urlConnection.getHeaderField(ACTIVATION_ATTRIBUTE_STATUS);
293
294
295 if (StringUtils.equals(status, ACTIVATION_FAILED)) {
296 String message = urlConnection.getHeaderField(ACTIVATION_ATTRIBUTE_MESSAGE);
297 throw new ExchangeException("Message received from subscriber: " + message);
298 }
299
300 urlConnection.getContent();
301
302 }
303 catch (MalformedURLException e) {
304 throw new ExchangeException("Incorrect URL for subscriber " + subscriber + "[" + handle + "]");
305 }
306 catch (IOException e) {
307 throw new ExchangeException("Not able to send the deactivation request [" + handle + "]: " + e.getMessage());
308 }
309 catch (Exception e) {
310 throw new ExchangeException(e);
311 }
312 }
313 return null;
314 }
315
316
317
318
319 protected String getMappedPath(String path, Subscription subscription) {
320 String toURI = subscription.getToURI();
321 if (null != toURI) {
322 String fromURI = subscription.getFromURI();
323
324 fromURI = StringUtils.removeEnd(fromURI, "/");
325 toURI = StringUtils.removeEnd(toURI, "/");
326
327 path = path.replaceFirst(fromURI, toURI);
328 if (path.equals("")) {
329 return "/";
330 }
331 }
332 return path;
333 }
334
335 }