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.beans.config.ContentRepository;
37 import info.magnolia.cms.core.Content;
38 import info.magnolia.cms.core.HierarchyManager;
39 import info.magnolia.cms.core.ItemType;
40 import info.magnolia.cms.core.MetaData;
41 import info.magnolia.cms.core.Path;
42 import info.magnolia.cms.core.SystemProperty;
43 import info.magnolia.cms.core.version.ContentVersion;
44 import info.magnolia.cms.exchange.ExchangeException;
45 import info.magnolia.cms.exchange.Subscriber;
46 import info.magnolia.cms.exchange.Subscription;
47 import info.magnolia.cms.exchange.Syndicator;
48 import info.magnolia.cms.security.AccessDeniedException;
49 import info.magnolia.cms.security.SecurityUtil;
50 import info.magnolia.cms.security.User;
51 import info.magnolia.cms.util.ContentUtil;
52 import info.magnolia.cms.util.Rule;
53 import info.magnolia.cms.util.RuleBasedContentFilter;
54 import info.magnolia.context.MgnlContext;
55 import info.magnolia.logging.AuditLoggingUtil;
56
57 import java.io.File;
58 import java.io.FileInputStream;
59 import java.io.FileOutputStream;
60 import java.io.IOException;
61 import java.io.OutputStream;
62 import java.io.UnsupportedEncodingException;
63 import java.net.HttpURLConnection;
64 import java.net.MalformedURLException;
65 import java.net.URL;
66 import java.net.URLConnection;
67 import java.net.URLEncoder;
68 import java.util.Calendar;
69 import java.util.Iterator;
70 import java.util.List;
71 import java.util.zip.GZIPOutputStream;
72
73 import javax.jcr.RepositoryException;
74 import javax.jcr.Session;
75
76 import org.apache.commons.codec.binary.Base64;
77 import org.apache.commons.io.IOUtils;
78 import org.apache.commons.lang.StringUtils;
79 import org.apache.xml.serialize.OutputFormat;
80 import org.apache.xml.serialize.XMLSerializer;
81 import org.jdom.Document;
82 import org.jdom.Element;
83 import org.jdom.output.XMLOutputter;
84 import org.slf4j.Logger;
85 import org.slf4j.LoggerFactory;
86 import org.xml.sax.InputSource;
87 import org.xml.sax.SAXException;
88 import org.xml.sax.XMLReader;
89 import org.xml.sax.helpers.XMLReaderFactory;
90
91 import EDU.oswego.cs.dl.util.concurrent.Sync;
92
93
94
95
96
97
98 public abstract class BaseSyndicatorImpl implements Syndicator {
99 private static final Logger log = LoggerFactory.getLogger(BaseSyndicatorImpl.class);
100
101
102
103
104 public static final String DEFAULT_HANDLER = ".magnolia/activation";
105
106 public static final String PARENT_PATH = "mgnlExchangeParentPath";
107
108 public static final String MAPPED_PARENT_PATH = "mgnlExchangeMappedParent";
109
110
111
112
113 public static final String PATH = "mgnlExchangePath";
114
115 public static final String NODE_UUID = "mgnlExchangeNodeUUID";
116
117 public static final String REPOSITORY_NAME = "mgnlExchangeRepositoryName";
118
119 public static final String WORKSPACE_NAME = "mgnlExchangeWorkspaceName";
120
121 public static final String VERSION_NAME = "mgnlExchangeVersionName";
122
123
124
125
126 public static final String RESOURCE_MAPPING_FILE = "mgnlExchangeResourceMappingFile";
127
128 public static final String UTF8_STATUS = "mgnlUTF8Status";
129
130
131
132
133
134
135 public static final String SIBLINGS_ROOT_ELEMENT = "NodeSiblings";
136
137 public static final String SIBLINGS_ELEMENT = "sibling";
138
139 public static final String SIBLING_UUID = "siblingUUID";
140
141 public static final String RESOURCE_MAPPING_FILE_ELEMENT = "File";
142
143 public static final String RESOURCE_MAPPING_NAME_ATTRIBUTE = "name";
144
145 public static final String RESOURCE_MAPPING_UUID_ATTRIBUTE = "contentUUID";
146
147 public static final String RESOURCE_MAPPING_ID_ATTRIBUTE = "resourceId";
148
149 public static final String RESOURCE_MAPPING_ROOT_ELEMENT = "Resources";
150
151 public static final String ACTION = "mgnlExchangeAction";
152
153 public static final String ACTIVATE = "activate";
154
155 public static final String DEACTIVATE = "deactivate";
156
157 public static final String COMMIT = "commit";
158
159 public static final String ROLLBACK = "rollback";
160
161 public static final String AUTHORIZATION = "Authorization";
162
163 public static final String AUTH_CREDENTIALS= "mgnlUserPSWD";
164
165 public static final String AUTH_USER = "mgnlUserId";
166
167 public static final String CONTENT_FILTER_RULE = "mgnlExchangeFilterRule";
168
169 public static final String ACTIVATION_SUCCESSFUL = "sa_success";
170
171 public static final String ACTIVATION_FAILED = "sa_failed";
172
173 public static final String ACTIVATION_ATTRIBUTE_STATUS = "sa_attribute_status";
174
175 public static final String ACTIVATION_ATTRIBUTE_MESSAGE = "sa_attribute_message";
176
177 public static final String ACTIVATION_ATTRIBUTE_VERSION = "sa_attribute_version";
178
179
180
181
182
183
184
185 protected static void executeInPool(Runnable job) throws ExchangeException {
186 try {
187 ThreadPool.getInstance().execute(job);
188 } catch (InterruptedException e) {
189
190
191
192
193 String message = "could not execute job in pool";
194 log.error(message, e);
195 throw new ExchangeException(message, e);
196 }
197 }
198
199
200
201
202
203
204
205
206
207
208 protected static void acquireIgnoringInterruption(Sync latch) {
209 try {
210 latch.acquire();
211 } catch (InterruptedException e) {
212
213 acquireIgnoringInterruption(latch);
214
215 Thread.currentThread().interrupt();
216 }
217 }
218
219 protected String repositoryName;
220
221 protected String workspaceName;
222
223 protected String parent;
224
225 protected Content.ContentFilter contentFilter;
226
227 protected Rule contentFilterRule;
228
229 protected User user;
230
231 protected String basicCredentials;
232
233 private Calendar contentVersionDate;
234
235
236
237
238
239
240
241
242
243 public void init(User user, String repositoryName, String workspaceName, Rule rule) {
244 this.user = user;
245 this.basicCredentials = "Basic "
246 + new String(Base64.encodeBase64((this.user.getName() + ":" + this.user.getPassword()).getBytes()));
247 this.contentFilter = new RuleBasedContentFilter(rule);
248 this.contentFilterRule = rule;
249 this.repositoryName = repositoryName;
250 this.workspaceName = workspaceName;
251 }
252
253
254
255
256
257
258
259
260
261 public void activate(String parent, Content content) throws ExchangeException, RepositoryException {
262 this.activate(parent, content, null);
263 }
264
265
266
267
268
269
270
271
272
273
274
275 public void activate(String parent, Content content, List<String> orderBefore) throws ExchangeException, RepositoryException {
276 this.activate(null, parent, content, orderBefore);
277 }
278
279
280
281
282
283
284
285
286
287
288 public void activate(Subscriber subscriber, String parent, Content content) throws ExchangeException, RepositoryException {
289 this.activate(subscriber, parent, content, null);
290 }
291
292
293
294
295
296
297
298
299
300
301
302 public void activate(Subscriber subscriber, String parent, Content content, List<String> orderBefore) throws ExchangeException, RepositoryException {
303 this.parent = parent;
304 String path = content.getHandle();
305
306 if (content instanceof ContentVersion) {
307 contentVersionDate = ((ContentVersion)content).getCreated();
308 }
309
310 ActivationContent activationContent = null;
311 try {
312 activationContent = this.collect(content, orderBefore);
313 if (null == subscriber) {
314 this.activate(activationContent, path);
315 } else {
316 this.activate(subscriber, activationContent, path);
317 }
318 if (Boolean.parseBoolean(activationContent.getproperty(ItemType.DELETED_NODE_MIXIN))) {
319 final HierarchyManager hm = content.getHierarchyManager();
320 String uuid = content.getUUID();
321 if (StringUtils.isNotBlank(uuid)) {
322 if (content instanceof ContentVersion) {
323
324 content = hm.getContentByUUID(uuid);
325 }
326 Content parentContent = content.getParent();
327 content.delete();
328 parentContent.save();
329 } else {
330 log.warn("Content {}:{} was already removed.", new String[] {hm.getName(), path});
331 }
332 } else {
333 this.updateActivationDetails(path);
334 }
335 log.info("Exchange: activation succeeded [{}]", path);
336 } catch (Exception e) {
337 if (log.isDebugEnabled()) {
338 log.error("Exchange: activation failed for path:" + ((path != null) ? path : "[null]"), e);
339 long timestamp = System.currentTimeMillis();
340 log.warn("moving files from failed activation to *.failed" + timestamp );
341 Iterator<File> keys = activationContent.getFiles().values().iterator();
342 while (keys.hasNext()) {
343 File f = keys.next();
344 f.renameTo(new File(f.getAbsolutePath()+".failed" + timestamp));
345 }
346 activationContent.getFiles().clear();
347
348 }
349 throw new ExchangeException(e);
350 } finally {
351 log.debug("Cleaning temporary files");
352 cleanTemporaryStore(activationContent);
353 }
354 }
355
356
357
358
359 public abstract void activate(ActivationContent activationContent, String nodePath) throws ExchangeException;
360
361
362
363
364
365 public String activate(Subscriber subscriber, ActivationContent activationContent, String nodePath) throws ExchangeException {
366
367 log.debug("activate");
368 if (null == subscriber) {
369 throw new ExchangeException("Null Subscriber");
370 }
371
372 String parentPath = null;
373
374
375 Subscription subscription = subscriber.getMatchedSubscription(nodePath, this.repositoryName);
376 if (null != subscription) {
377
378 parentPath = this.getMappedPath(this.parent, subscription);
379 activationContent.setProperty(PARENT_PATH, parentPath);
380 } else {
381 log.debug("Exchange : subscriber [{}] is not subscribed to {}", subscriber.getName(), nodePath);
382 return "not subscribed";
383 }
384 log.debug("Exchange : sending activation request to {} with user {}", subscriber.getName(), this.user.getName());
385
386 URLConnection urlConnection = null;
387 String versionName = null;
388 try {
389 urlConnection = prepareConnection(subscriber, getActivationURL(subscriber));
390 this.addActivationHeaders(urlConnection, activationContent);
391
392 Transporter.transport((HttpURLConnection) urlConnection, activationContent);
393
394 String status = urlConnection.getHeaderField(ACTIVATION_ATTRIBUTE_STATUS);
395 versionName = urlConnection.getHeaderField(ACTIVATION_ATTRIBUTE_VERSION);
396
397
398 if (StringUtils.equals(status, ACTIVATION_FAILED)) {
399 String message = urlConnection.getHeaderField(ACTIVATION_ATTRIBUTE_MESSAGE);
400 throw new ExchangeException("Message received from subscriber: " + message);
401 }
402 urlConnection.getContent();
403 log.debug("Exchange : activation request sent to {}", subscriber.getName());
404 }
405 catch (ExchangeException e) {
406 throw e;
407 }
408 catch (IOException e) {
409 log.debug("Failed to transport following activated content {" + StringUtils.join(activationContent.getProperties().keySet().iterator(), ',') + "} due to " + e.getMessage(), e);
410 String url = (urlConnection == null ? null : urlConnection.getURL().toString());
411 url = SecurityUtil.stripPasswordFromUrl(url);
412
413 throw new ExchangeException("Not able to send the activation request [" + url + "]: " + e.getMessage(), e);
414 }
415 catch (Exception e) {
416 throw new ExchangeException(e);
417 }
418 return versionName;
419 }
420
421
422
423
424 protected void cleanTemporaryStore(ActivationContent activationContent) {
425 if (activationContent == null) {
426 log.debug("Clean temporary store - nothing to do");
427 return;
428 }
429 if (log.isDebugEnabled()) {
430 log.debug("Debugging is enabled. Keeping temporary files in store for debugging purposes. Clean the store manually once done with debugging.");
431 return;
432 }
433
434 Iterator<String> keys = activationContent.getFiles().keySet().iterator();
435 while (keys.hasNext()) {
436 String key = keys.next();
437 log.debug("Removing temporary file {}", key);
438 activationContent.getFile(key).delete();
439 }
440 }
441
442 public synchronized void deactivate(String path) throws ExchangeException, RepositoryException {
443 final Content node = getHierarchyManager().getContent(path);
444 deactivate(node);
445 }
446
447
448
449
450
451
452 public synchronized void deactivate(Content node) throws ExchangeException, RepositoryException {
453 String nodeUUID = node.getUUID();
454 String path = node.getHandle();
455 this.doDeactivate(nodeUUID, path);
456 updateDeactivationDetails(nodeUUID);
457 }
458
459
460
461
462
463
464
465 public synchronized void deactivate(Subscriber subscriber, Content node) throws ExchangeException, RepositoryException {
466 String nodeUUID = node.getUUID();
467 String path = node.getHandle();
468 this.doDeactivate(subscriber, nodeUUID, path);
469 updateDeactivationDetails(nodeUUID);
470 }
471
472
473
474
475 public abstract void doDeactivate(String nodeUUID, String nodePath) throws ExchangeException;
476
477
478
479
480
481
482 public abstract String doDeactivate(Subscriber subscriber, String nodeUUID, String nodePath) throws ExchangeException;
483
484
485
486
487
488 protected String getDeactivationURL(Subscriber subscriberInfo) {
489 return getActivationURL(subscriberInfo);
490 }
491
492
493
494
495
496 protected void addDeactivationHeaders(URLConnection connection, String nodeUUID) {
497 connection.addRequestProperty(REPOSITORY_NAME, this.repositoryName);
498 connection.addRequestProperty(WORKSPACE_NAME, this.workspaceName);
499 if (nodeUUID != null) {
500 connection.addRequestProperty(NODE_UUID, nodeUUID);
501 }
502 connection.addRequestProperty(ACTION, DEACTIVATE);
503 }
504
505
506
507
508 protected String getActivationURL(Subscriber subscriberInfo) {
509 final String url = subscriberInfo.getURL();
510 if (!url.endsWith("/")) {
511 return url + "/" + DEFAULT_HANDLER;
512 }
513 return url + DEFAULT_HANDLER;
514 }
515
516
517
518
519 protected void addActivationHeaders(URLConnection connection, ActivationContent activationContent) {
520 Iterator<String> headerKeys = activationContent.getProperties().keySet().iterator();
521 while (headerKeys.hasNext()) {
522 String key = headerKeys.next();
523 String value = activationContent.getproperty(key);
524 if(SystemProperty.getBooleanProperty(SystemProperty.MAGNOLIA_UTF8_ENABLED)) {
525 try {
526 value = URLEncoder.encode(value, "UTF-8");
527 }
528 catch (UnsupportedEncodingException e) {
529
530 }
531 }
532 connection.setRequestProperty(key, value);
533 }
534 }
535
536
537
538
539 protected void updateActivationDetails(String path) throws RepositoryException {
540
541 Content page = getSystemHierarchyManager().getContent(path);
542 updateMetaData(page, ACTIVATE);
543 page.save();
544 AuditLoggingUtil.log(AuditLoggingUtil.ACTION_ACTIVATE, this.workspaceName, page.getItemType(), path );
545 }
546
547
548
549
550 protected void updateDeactivationDetails(String nodeUUID) throws RepositoryException {
551
552 Content page = getSystemHierarchyManager().getContentByUUID(nodeUUID);
553 updateMetaData(page, DEACTIVATE);
554 page.save();
555 AuditLoggingUtil.log(AuditLoggingUtil.ACTION_DEACTIVATE, this.workspaceName, page.getItemType(), page.getHandle() );
556 }
557
558
559 private HierarchyManager getHierarchyManager() {
560 return MgnlContext.getHierarchyManager(this.repositoryName, this.workspaceName);
561 }
562
563 private HierarchyManager getSystemHierarchyManager() {
564 return MgnlContext.getSystemContext().getHierarchyManager(this.repositoryName, this.workspaceName);
565 }
566
567
568
569
570
571 protected void updateMetaData(Content node, String type) throws AccessDeniedException {
572
573 MetaData md = node.getMetaData();
574 if (type.equals(ACTIVATE)) {
575 md.setActivated();
576 }
577 else {
578 md.setUnActivated();
579 }
580 md.setActivatorId(this.user.getName());
581 md.setLastActivationActionDate();
582
583 if(type.equals(ACTIVATE)){
584 if(md.getModificationDate() != null && md.getModificationDate().after(contentVersionDate)){
585 try {
586 Thread.sleep(1);
587 } catch (InterruptedException e) {
588 e.printStackTrace();
589 }
590 md.setModificationDate();
591 }
592 }
593
594 Iterator<Content> children;
595 if (type.equals(ACTIVATE)) {
596
597 children = node.getChildren(this.contentFilter).iterator();
598 }
599 else {
600
601 children = node.getChildren(ContentUtil.EXCLUDE_META_DATA_CONTENT_FILTER).iterator();
602 }
603
604 while (children.hasNext()) {
605 Content child = children.next();
606 this.updateMetaData(child, type);
607 }
608
609
610 }
611
612
613
614
615
616 protected ActivationContent collect(Content node, List<String> orderBefore) throws Exception {
617
618 File resourceFile = File.createTempFile("resources", ".xml", Path.getTempDirectory());
619
620 ActivationContent activationContent = new ActivationContent();
621
622 activationContent.addProperty(PARENT_PATH, this.parent);
623 activationContent.addProperty(WORKSPACE_NAME, this.workspaceName);
624 activationContent.addProperty(REPOSITORY_NAME, this.repositoryName);
625 activationContent.addProperty(RESOURCE_MAPPING_FILE, resourceFile.getName());
626 activationContent.addProperty(ACTION, ACTIVATE);
627 activationContent.addProperty(CONTENT_FILTER_RULE, this.contentFilterRule.toString());
628 activationContent.addProperty(NODE_UUID, node.getUUID());
629 activationContent.addProperty(UTF8_STATUS, SystemProperty.getProperty(SystemProperty.MAGNOLIA_UTF8_ENABLED));
630
631
632 Document document = new Document();
633 Element root = new Element(RESOURCE_MAPPING_ROOT_ELEMENT);
634 document.setRootElement(root);
635
636 addOrderingInfo(root, orderBefore);
637
638 this.addResources(root, node.getWorkspace().getSession(), node, this.contentFilter, activationContent);
639 XMLOutputter outputter = new XMLOutputter();
640 outputter.output(document, new FileOutputStream(resourceFile));
641
642 activationContent.addFile(resourceFile.getName(), resourceFile);
643
644
645 activationContent.addProperty(ItemType.DELETED_NODE_MIXIN, "" + node.hasMixin(ItemType.DELETED_NODE_MIXIN));
646
647 return activationContent;
648 }
649
650
651
652
653
654
655 protected void addOrderingInfo(Element root, List<String> orderBefore) {
656
657 Element siblingRoot = new Element(SIBLINGS_ROOT_ELEMENT);
658 root.addContent(siblingRoot);
659 if (orderBefore == null) {
660 return;
661 }
662 Iterator<String> siblings = orderBefore.iterator();
663 while (siblings.hasNext()) {
664 String uuid = siblings.next();
665 Element e = new Element(SIBLINGS_ELEMENT);
666 e.setAttribute(SIBLING_UUID, uuid);
667 siblingRoot.addContent(e);
668 }
669 }
670
671 protected void addResources(Element resourceElement, Session session, final Content content, Content.ContentFilter filter, ActivationContent activationContent) throws IOException, RepositoryException, SAXException, Exception {
672 final String workspaceName = content.getWorkspace().getName();
673 log.debug("Preparing content {}:{} for publishing.", new String[] {workspaceName, content.getHandle()});
674 final String uuid = content.getUUID();
675
676 File file = File.createTempFile("exchange_" + uuid, ".xml.gz", Path.getTempDirectory());
677 GZIPOutputStream gzipOutputStream = new GZIPOutputStream(new FileOutputStream(file));
678
679
680 if (content.isNodeType("nt:frozenNode") || workspaceName.equals(ContentRepository.VERSION_STORE)) {
681 XMLReader elementfilter = new FrozenElementFilter(XMLReaderFactory
682 .createXMLReader(org.apache.xerces.parsers.SAXParser.class.getName()));
683 ((FrozenElementFilter) elementfilter).setNodeName(content.getName());
684
685
686
687 boolean noRecurse = !content.isNodeType(ItemType.NT_FILE);
688 exportAndParse(session, content, elementfilter, gzipOutputStream, noRecurse);
689 } else {
690
691
692
693 if (content.isNodeType(ItemType.NT_FILE)) {
694 session.exportSystemView(content.getJCRNode().getPath(), gzipOutputStream, false, false);
695 } else {
696 session.exportSystemView(content.getJCRNode().getPath(), gzipOutputStream, false, true);
697 }
698 }
699
700 IOUtils.closeQuietly(gzipOutputStream);
701
702 Element element = new Element(RESOURCE_MAPPING_FILE_ELEMENT);
703 element.setAttribute(RESOURCE_MAPPING_NAME_ATTRIBUTE, content.getName());
704 element.setAttribute(RESOURCE_MAPPING_UUID_ATTRIBUTE, uuid);
705 element.setAttribute(RESOURCE_MAPPING_ID_ATTRIBUTE, file.getName());
706 resourceElement.addContent(element);
707
708 activationContent.addFile(file.getName(), file);
709
710 Iterator<Content> children = content.getChildren(filter).iterator();
711 while (children.hasNext()) {
712 Content child = children.next();
713 this.addResources(element, session, child, filter, activationContent);
714 }
715 }
716
717 protected void exportAndParse(Session session, Content content, XMLReader elementfilter, OutputStream os, boolean noRecurse) throws Exception {
718 File tempFile = File.createTempFile("Frozen_"+content.getName(), ".xml");
719 OutputStream tmpFileOutStream = null;
720 FileInputStream tmpFileInStream = null;
721 try {
722 tmpFileOutStream = new FileOutputStream(tempFile);
723
724 session.exportSystemView(content.getJCRNode().getPath(), tmpFileOutStream, false, noRecurse);
725 tmpFileOutStream.flush();
726 tmpFileOutStream.close();
727
728 OutputFormat outputFormat = new OutputFormat();
729 outputFormat.setPreserveSpace(false);
730
731 tmpFileInStream = new FileInputStream(tempFile);
732 elementfilter.setContentHandler(new XMLSerializer(os, outputFormat));
733 elementfilter.parse(new InputSource(tmpFileInStream));
734 tmpFileInStream.close();
735 } catch (Throwable t) {
736 log.error("Failed to parse XML using FrozenElementFilter",t);
737 throw new Exception(t);
738 } finally {
739 IOUtils.closeQuietly(tmpFileInStream);
740 IOUtils.closeQuietly(tmpFileOutStream);
741 tempFile.delete();
742 }
743 }
744
745
746
747
748 protected String getMappedPath(String path, Subscription subscription) {
749 String toURI = subscription.getToURI();
750 if (null != toURI) {
751 String fromURI = subscription.getFromURI();
752
753 fromURI = StringUtils.removeEnd(fromURI, "/");
754 toURI = StringUtils.removeEnd(toURI, "/");
755
756 path = path.replaceFirst(fromURI, toURI);
757 if (path.equals("")) {
758 path = "/";
759 }
760 }
761 return path;
762 }
763
764 protected URLConnection prepareConnection(Subscriber subscriber, String urlString) throws ExchangeException {
765
766
767
768 try {
769 String authMethod = subscriber.getAuthenticationMethod();
770
771 if (authMethod != null && "form".equalsIgnoreCase(authMethod)) {
772 urlString += (urlString.indexOf('?') > 0 ? "&" : "?") + AUTH_USER + "=" + this.user.getName();
773 urlString += "&" + AUTH_CREDENTIALS + "=" + this.user.getPassword();
774 }
775 URL url = new URL(urlString);
776 URLConnection urlConnection = url.openConnection();
777 urlConnection.setConnectTimeout(subscriber.getConnectTimeout());
778 urlConnection.setReadTimeout(subscriber.getReadTimeout());
779
780 if (authMethod == null || "basic".equalsIgnoreCase(authMethod)) {
781 urlConnection.setRequestProperty(AUTHORIZATION, this.basicCredentials);
782 } else if (!"form".equalsIgnoreCase(subscriber.getAuthenticationMethod())) {
783 log.info("Unknown Authentication method for deactivation: " + subscriber.getAuthenticationMethod());
784 }
785
786 return urlConnection;
787 } catch (MalformedURLException e) {
788 throw new ExchangeException("Incorrect URL for subscriber " + subscriber + "[" + SecurityUtil.stripPasswordFromUrl(urlString) + "]");
789 } catch (IOException e) {
790 throw new ExchangeException("Not able to send the activation request [" + SecurityUtil.stripPasswordFromUrl(urlString) + "]: " + e.getMessage());
791 } catch (Exception e) {
792 throw new ExchangeException(e);
793 }
794 }
795
796
797 }