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