Java tutorial
/* * $HeadURL$ * $Id$ * * Copyright (c) 2007-2012 by Public Library of Science * http://plos.org * http://ambraproject.org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.ambraproject.service.trackback; import org.ambraproject.models.Article; import org.ambraproject.models.Journal; import org.ambraproject.models.Pingback; import org.apache.commons.configuration.Configuration; import org.apache.xmlrpc.XmlRpcException; import org.hibernate.Criteria; import org.hibernate.FetchMode; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Required; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.util.List; public class PingbackServiceImpl extends LinkbackServiceImpl implements PingbackService { private static final Logger log = LoggerFactory.getLogger(PingbackServiceImpl.class); private Configuration configuration; @Required public void setConfiguration(Configuration configuration) { this.configuration = configuration; } @Override protected Configuration getConfiguration() { return configuration; } /** * {@inheritDoc} */ @Override public Long createPingback(URI sourceUri, URI targetUri, String pbServerHost) throws XmlRpcException { final URL targetUrl; try { targetUrl = targetUri.toURL(); } catch (MalformedURLException e) { throw PingbackFault.TARGET_DNE.getException(); } Article target = getArticleFromTargetUri(targetUrl, pbServerHost); LinkValidator matchTarget = new LinkValidator() { @Override public boolean isValid(URL link) { // They give us the URL they claim to use, so just check for that without worrying about cross-published URLs return targetUrl.equals(link); } }; BlogLinkDigest blogInfo; try { blogInfo = examineBlogPage(sourceUri.toURL(), matchTarget); } catch (IOException e) { // Generally means that the source page can't be accessed or parsed throw PingbackFault.SOURCE_DNE.getException(e); } if (blogInfo.getLink() == null) { throw PingbackFault.NO_LINK_TO_TARGET.getException(); } Long preexisting = (Long) hibernateTemplate.findByCriteria(DetachedCriteria.forClass(Pingback.class) .setProjection(Projections.rowCount()).add(Restrictions.eq("url", sourceUri.toString())) .add(Restrictions.eq("articleID", target.getID()))).get(0); if (preexisting > 0) { throw PingbackFault.ALREADY_REGISTERED.getException(); } Pingback pb = new Pingback(); pb.setUrl(sourceUri.toString()); pb.setTitle(blogInfo.getTitle()); pb.setArticleID(target.getID()); return (Long) hibernateTemplate.save(pb); } /** * Look up an article from the absolute target URI provided within a pingback request. If the argument (which * originated from an external source) can't be resolved to an article, throw an exception containing the fault code * to send as a response to the server that provided the URI. * <p/> * We want journals to behave independently whether or not they share a back end. So, the link is valid only if: <ul> * <li>the link contains the DOI of an article,</li> <li>the link's hostname belongs to a journal where that article * was published, and</li> <li>the pingback was addressed to the same hostname.</li> </ul> * * @param link an absolute URI * @param pbServerHost the host on which the pingback was received * @return the article * @throws XmlRpcException with the {@link PingbackFault#TARGET_DNE} fault code if the target URI does not exist or is * not recognizable (where possible, it is preferable to throw a {@link * PingbackFault#INVALID_TARGET} fault code if the target URI goes to an existing page other * than a permalink to a pingback-supporting article) */ private Article getArticleFromTargetUri(URL link, String pbServerHost) throws XmlRpcException { // Find the DOI boolean usesResolver = true; String doi = InboundLinkTranslator.GLOBAL_RESOLVER.getDoi(link); if (doi == null) { doi = InboundLinkTranslator.forLocalResolver(configuration).getDoi(link); } if (doi == null) { usesResolver = false; // Need to validate the hostname against journals after we have the article doi = InboundLinkTranslator.forAnyJournal(configuration).getDoi(link); } if (doi == null) { throw PingbackFault.TARGET_DNE.getException(); } // Look up the article referenced by that DOI, if any List<Article> queryResults = (List<Article>) hibernateTemplate.findByCriteria(DetachedCriteria .forClass(Article.class).add(Restrictions.eq("doi", doi)).setFetchMode("journals", FetchMode.JOIN) .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)); if (queryResults.isEmpty()) { throw PingbackFault.TARGET_DNE.getException(); } Article article = queryResults.get(0); if (usesResolver) { return article; } // Validate the hostname for (Journal journal : article.getJournals()) { String journalHost = InboundLinkTranslator.getHostnameForJournal(journal.getJournalKey(), configuration); if (journalHost.equals(pbServerHost)) { // This journal's site received the pingback, so require that the link goes there InboundLinkTranslator journalTranslator = InboundLinkTranslator.forJournal(journal, configuration); if (journalTranslator.getDoi(link) != null) { return article; } break; // The link destination doesn't match the pingback destination } } throw PingbackFault.TARGET_DNE.getException(); } }