1
14
15 package com.liferay.portlet.blogs.util;
16
17 import com.liferay.ibm.icu.util.Calendar;
18 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
19 import com.liferay.portal.kernel.log.Log;
20 import com.liferay.portal.kernel.log.LogFactoryUtil;
21 import com.liferay.portal.kernel.servlet.HttpHeaders;
22 import com.liferay.portal.kernel.util.GetterUtil;
23 import com.liferay.portal.kernel.util.HtmlUtil;
24 import com.liferay.portal.kernel.util.Http;
25 import com.liferay.portal.kernel.util.HttpUtil;
26 import com.liferay.portal.kernel.util.ReleaseInfo;
27 import com.liferay.portal.kernel.util.Tuple;
28 import com.liferay.portal.kernel.util.Validator;
29 import com.liferay.portal.kernel.xmlrpc.Response;
30 import com.liferay.portal.kernel.xmlrpc.XmlRpcException;
31 import com.liferay.portal.kernel.xmlrpc.XmlRpcUtil;
32 import com.liferay.portal.xml.StAXReaderUtil;
33
34 import java.util.ArrayList;
35 import java.util.Collections;
36 import java.util.Date;
37 import java.util.List;
38 import java.util.Map;
39
40 import javax.xml.stream.XMLInputFactory;
41 import javax.xml.stream.XMLStreamReader;
42
43 import net.htmlparser.jericho.Source;
44 import net.htmlparser.jericho.StartTag;
45
46
51 public class LinkbackProducerUtil {
52
53 public static void sendPingback(String sourceUri, String targetUri)
54 throws Exception {
55
56 _pingbackQueue.add(new Tuple(new Date(), sourceUri, targetUri));
57 }
58
59 public static synchronized void sendQueuedPingbacks()
60 throws XmlRpcException {
61
62 Calendar cal = Calendar.getInstance();
63
64 cal.add(Calendar.MINUTE, -1);
65
66 Date expiration = cal.getTime();
67
68 while (!_pingbackQueue.isEmpty()) {
69 Tuple tuple = _pingbackQueue.get(0);
70
71 Date time = (Date)tuple.getObject(0);
72
73 if (time.before(expiration)) {
74 _pingbackQueue.remove(0);
75
76 String sourceUri = (String)tuple.getObject(1);
77 String targetUri = (String)tuple.getObject(2);
78
79 String serverUri = _discoverPingbackServer(targetUri);
80
81 if (Validator.isNull(serverUri)) {
82 continue;
83 }
84
85 if (_log.isInfoEnabled()) {
86 _log.info(
87 "XML-RPC pingback " + serverUri + ", source " +
88 sourceUri + ", target " + targetUri);
89 }
90
91 Response response = XmlRpcUtil.executeMethod(
92 serverUri, "pingback.ping",
93 new Object[] {sourceUri, targetUri});
94
95 if (_log.isInfoEnabled()) {
96 _log.info(response.toString());
97 }
98 }
99 else {
100 break;
101 }
102 }
103 }
104
105 public static boolean sendTrackback(
106 String trackback, Map<String, String> parts)
107 throws Exception {
108
109 if (_log.isInfoEnabled()) {
110 _log.info("Pinging trackback " + trackback);
111 }
112
113 Http.Options options = new Http.Options();
114
115 options.addHeader(HttpHeaders.USER_AGENT, ReleaseInfo.getServerInfo());
116 options.setLocation(trackback);
117 options.setParts(parts);
118 options.setPost(true);
119
120 String xml = HttpUtil.URLtoString(options);
121
122 if (_log.isDebugEnabled()) {
123 _log.debug(xml);
124 }
125
126 String error = xml;
127
128 XMLStreamReader xmlStreamReader = null;
129
130 try {
131 XMLInputFactory xmlInputFactory =
132 StAXReaderUtil.getXMLInputFactory();
133
134 xmlStreamReader = xmlInputFactory.createXMLStreamReader(
135 new UnsyncStringReader(xml));
136
137 xmlStreamReader.nextTag();
138 xmlStreamReader.nextTag();
139
140 String name = xmlStreamReader.getLocalName();
141
142 if (name.equals("error")) {
143 int status = GetterUtil.getInteger(
144 xmlStreamReader.getElementText(), 1);
145
146 if (status == 0) {
147 if (_log.isInfoEnabled()) {
148 _log.info("Trackback accepted");
149 }
150
151 return true;
152 }
153
154 xmlStreamReader.nextTag();
155
156 name = xmlStreamReader.getLocalName();
157
158 if (name.equals("message")) {
159 error = xmlStreamReader.getElementText();
160 }
161 }
162 }
163 finally {
164 if (xmlStreamReader != null) {
165 try {
166 xmlStreamReader.close();
167 }
168 catch (Exception e) {
169 }
170 }
171 }
172
173 _log.error(
174 "Error while pinging trackback at " + trackback + ": " + error);
175
176 return false;
177 }
178
179 private static String _discoverPingbackServer(String targetUri) {
180 String serverUri = null;
181
182 try {
183 Http.Options options = new Http.Options();
184
185 options.addHeader(
186 HttpHeaders.USER_AGENT, ReleaseInfo.getServerInfo());
187 options.setLocation(targetUri);
188 options.setHead(true);
189
190 HttpUtil.URLtoByteArray(options);
191
192 Http.Response response = options.getResponse();
193
194 serverUri = response.getHeader("X-Pingback");
195 }
196 catch (Exception e) {
197 _log.error("Unable to call HEAD of " + targetUri, e);
198 }
199
200 if (Validator.isNull(serverUri)) {
201 try {
202 Source clientSource = new Source(
203 HttpUtil.URLtoString(targetUri));
204
205 List<StartTag> startTags = clientSource.getAllStartTags("link");
206
207 for (StartTag startTag : startTags) {
208 String rel = startTag.getAttributeValue("rel");
209
210 if (rel.equalsIgnoreCase("pingback")) {
211 String href = startTag.getAttributeValue("href");
212
213 serverUri = HtmlUtil.escape(href);
214
215 break;
216 }
217 }
218 }
219 catch (Exception e) {
220 _log.error("Unable to call GET of " + targetUri, e);
221 }
222 }
223
224 return serverUri;
225 }
226
227 private static Log _log = LogFactoryUtil.getLog(LinkbackProducerUtil.class);
228
229 private static List<Tuple> _pingbackQueue = Collections.synchronizedList(
230 new ArrayList<Tuple>());
231
232 }