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