001
014
015 package com.liferay.portlet.blogs.util;
016
017 import com.liferay.ibm.icu.util.Calendar;
018 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
019 import com.liferay.portal.kernel.log.Log;
020 import com.liferay.portal.kernel.log.LogFactoryUtil;
021 import com.liferay.portal.kernel.servlet.HttpHeaders;
022 import com.liferay.portal.kernel.util.GetterUtil;
023 import com.liferay.portal.kernel.util.HtmlUtil;
024 import com.liferay.portal.kernel.util.Http;
025 import com.liferay.portal.kernel.util.HttpUtil;
026 import com.liferay.portal.kernel.util.ReleaseInfo;
027 import com.liferay.portal.kernel.util.Tuple;
028 import com.liferay.portal.kernel.util.Validator;
029 import com.liferay.portal.kernel.xmlrpc.Response;
030 import com.liferay.portal.kernel.xmlrpc.XmlRpcException;
031 import com.liferay.portal.kernel.xmlrpc.XmlRpcUtil;
032 import com.liferay.portal.util.PropsValues;
033 import com.liferay.portal.xml.StAXReaderUtil;
034
035 import java.util.ArrayList;
036 import java.util.Collections;
037 import java.util.Date;
038 import java.util.List;
039 import java.util.Map;
040
041 import javax.xml.stream.XMLInputFactory;
042 import javax.xml.stream.XMLStreamReader;
043
044 import net.htmlparser.jericho.Source;
045 import net.htmlparser.jericho.StartTag;
046
047
050 public class LinkbackProducerUtil {
051
052 public static void sendPingback(String sourceUri, String targetUri)
053 throws Exception {
054
055 _pingbackQueue.add(new Tuple(new Date(), sourceUri, targetUri));
056 }
057
058 public static synchronized void sendQueuedPingbacks()
059 throws XmlRpcException {
060
061 Calendar cal = Calendar.getInstance();
062
063 cal.add(Calendar.MINUTE, -1);
064
065 Date expiration = cal.getTime();
066
067 while (!_pingbackQueue.isEmpty()) {
068 Tuple tuple = _pingbackQueue.get(0);
069
070 Date time = (Date)tuple.getObject(0);
071
072 if (time.before(expiration)) {
073 _pingbackQueue.remove(0);
074
075 String sourceUri = (String)tuple.getObject(1);
076 String targetUri = (String)tuple.getObject(2);
077
078 String serverUri = _discoverPingbackServer(targetUri);
079
080 if (Validator.isNull(serverUri)) {
081 continue;
082 }
083
084 if (_log.isInfoEnabled()) {
085 _log.info(
086 "XML-RPC pingback " + serverUri + ", source " +
087 sourceUri + ", target " + targetUri);
088 }
089
090 Response response = XmlRpcUtil.executeMethod(
091 serverUri, "pingback.ping",
092 new Object[] {sourceUri, targetUri});
093
094 if (_log.isInfoEnabled()) {
095 _log.info(response.toString());
096 }
097 }
098 else {
099 break;
100 }
101 }
102 }
103
104 public static boolean sendTrackback(
105 String trackback, Map<String, String> parts)
106 throws Exception {
107
108 if (_log.isInfoEnabled()) {
109 _log.info("Pinging trackback " + trackback);
110 }
111
112 Http.Options options = new Http.Options();
113
114 if (_HTTP_HEADER_VERSION_VERBOSITY_DEFAULT) {
115 }
116 else if (_HTTP_HEADER_VERSION_VERBOSITY_PARTIAL) {
117 options.addHeader(HttpHeaders.USER_AGENT, ReleaseInfo.getName());
118 }
119 else {
120 options.addHeader(
121 HttpHeaders.USER_AGENT, ReleaseInfo.getServerInfo());
122 }
123
124 options.setLocation(trackback);
125 options.setParts(parts);
126 options.setPost(true);
127
128 String xml = HttpUtil.URLtoString(options);
129
130 if (_log.isDebugEnabled()) {
131 _log.debug(xml);
132 }
133
134 String error = xml;
135
136 XMLStreamReader xmlStreamReader = null;
137
138 try {
139 XMLInputFactory xmlInputFactory =
140 StAXReaderUtil.getXMLInputFactory();
141
142 xmlStreamReader = xmlInputFactory.createXMLStreamReader(
143 new UnsyncStringReader(xml));
144
145 xmlStreamReader.nextTag();
146 xmlStreamReader.nextTag();
147
148 String name = xmlStreamReader.getLocalName();
149
150 if (name.equals("error")) {
151 int status = GetterUtil.getInteger(
152 xmlStreamReader.getElementText(), 1);
153
154 if (status == 0) {
155 if (_log.isInfoEnabled()) {
156 _log.info("Trackback accepted");
157 }
158
159 return true;
160 }
161
162 xmlStreamReader.nextTag();
163
164 name = xmlStreamReader.getLocalName();
165
166 if (name.equals("message")) {
167 error = xmlStreamReader.getElementText();
168 }
169 }
170 }
171 finally {
172 if (xmlStreamReader != null) {
173 try {
174 xmlStreamReader.close();
175 }
176 catch (Exception e) {
177 }
178 }
179 }
180
181 _log.error(
182 "Error while pinging trackback at " + trackback + ": " + error);
183
184 return false;
185 }
186
187 private static String _discoverPingbackServer(String targetUri) {
188 String serverUri = null;
189
190 try {
191 Http.Options options = new Http.Options();
192
193 if (_HTTP_HEADER_VERSION_VERBOSITY_DEFAULT) {
194 }
195 else if (_HTTP_HEADER_VERSION_VERBOSITY_PARTIAL) {
196 options.addHeader(
197 HttpHeaders.USER_AGENT, ReleaseInfo.getName());
198 }
199 else {
200 options.addHeader(
201 HttpHeaders.USER_AGENT, ReleaseInfo.getServerInfo());
202 }
203
204 options.setLocation(targetUri);
205 options.setHead(true);
206
207 HttpUtil.URLtoByteArray(options);
208
209 Http.Response response = options.getResponse();
210
211 serverUri = response.getHeader("X-Pingback");
212 }
213 catch (Exception e) {
214 _log.error("Unable to call HEAD of " + targetUri, e);
215 }
216
217 if (Validator.isNotNull(serverUri)) {
218 return serverUri;
219 }
220
221 try {
222 Source clientSource = new Source(HttpUtil.URLtoString(targetUri));
223
224 List<StartTag> startTags = clientSource.getAllStartTags("link");
225
226 for (StartTag startTag : startTags) {
227 String rel = startTag.getAttributeValue("rel");
228
229 if (rel.equalsIgnoreCase("pingback")) {
230 String href = startTag.getAttributeValue("href");
231
232 serverUri = HtmlUtil.escape(href);
233
234 break;
235 }
236 }
237 }
238 catch (Exception e) {
239 _log.error("Unable to call GET of " + targetUri, e);
240 }
241
242 return serverUri;
243 }
244
245 private static final boolean _HTTP_HEADER_VERSION_VERBOSITY_DEFAULT =
246 PropsValues.HTTP_HEADER_VERSION_VERBOSITY.equalsIgnoreCase(
247 ReleaseInfo.getName());
248
249 private static final boolean _HTTP_HEADER_VERSION_VERBOSITY_PARTIAL =
250 PropsValues.HTTP_HEADER_VERSION_VERBOSITY.equalsIgnoreCase("partial");
251
252 private static Log _log = LogFactoryUtil.getLog(LinkbackProducerUtil.class);
253
254 private static List<Tuple> _pingbackQueue = Collections.synchronizedList(
255 new ArrayList<Tuple>());
256
257 }