package org.openid4java.discovery.xri; import com.google.inject.Inject; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpStatus; import org.openid4java.discovery.DiscoveryException; import org.openid4java.discovery.DiscoveryInformation; import org.openid4java.discovery.XriIdentifier; import org.openid4java.discovery.xrds.XrdsParser; import org.openid4java.discovery.xrds.XrdsServiceEndpoint; import org.openid4java.util.HttpCache; import org.openid4java.util.HttpFetcher; import org.openid4java.util.HttpFetcherFactory; import org.openid4java.util.HttpRequestOptions; import org.openid4java.util.HttpResponse; import org.openid4java.util.OpenID4JavaUtils; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; /** * @author jbufu */ public class XriDotNetProxyResolver implements XriResolver { private static Log _log = LogFactory.getLog(XriDotNetProxyResolver.class); private static final boolean DEBUG = _log.isDebugEnabled(); private final HttpFetcher _httpFetcher; private final static String PROXY_URL = "https://xri.net/"; private static final String XRDS_QUERY = "_xrd_r=application/xrds+xml"; private static final String XRDS_PARSER_CLASS_NAME_KEY = "discovery.xrds.parser"; private static final XrdsParser XRDS_PARSER; static { String className = OpenID4JavaUtils.getProperty(XRDS_PARSER_CLASS_NAME_KEY); if (DEBUG) _log.debug(XRDS_PARSER_CLASS_NAME_KEY + ":" + className); try { XRDS_PARSER = (XrdsParser) Class.forName(className).newInstance(); } catch (Exception e) { throw new RuntimeException(e); } } /** * Constructor for Guice installations. The default implementation * of the {@link HttpFetcherFactory} returns {@link HttpCache}s. */ @Inject public XriDotNetProxyResolver(HttpFetcherFactory httpFetcherfactory) { _httpFetcher = httpFetcherfactory.createFetcher( HttpRequestOptions.getDefaultOptionsForDiscovery()); } /** * Public constructor for non-guice installations. In this case, * we use the {@link HttpCache}-creating {@link HttpFetcherFactory}. */ public XriDotNetProxyResolver() { this(new HttpFetcherFactory()); } public List discover(XriIdentifier xri) throws DiscoveryException { String hxri = PROXY_URL + xri.getIdentifier() + "?" + XRDS_QUERY; _log.info("Performing discovery on HXRI: " + hxri); try { HttpResponse resp = _httpFetcher.get(hxri); if (resp == null || HttpStatus.SC_OK != resp.getStatusCode()) throw new DiscoveryException("Error retrieving HXRI: " + hxri); Set targetTypes = DiscoveryInformation.OPENID_OP_TYPES; List endpoints = XRDS_PARSER.parseXrds(resp.getBody(), targetTypes); List results = new ArrayList(); Iterator endpointIter = endpoints.iterator(); while (endpointIter.hasNext()) { XrdsServiceEndpoint endpoint = (XrdsServiceEndpoint) endpointIter.next(); Iterator typesIter = endpoint.getTypes().iterator(); while (typesIter.hasNext()) { String type = (String) typesIter.next(); if (!targetTypes.contains(type)) continue; try { results.add(new DiscoveryInformation( new URL(endpoint.getUri()), parseIdentifier(endpoint.getCanonicalId()), DiscoveryInformation.OPENID2.equals(type) ? endpoint.getLocalId() : DiscoveryInformation.OPENID1_SIGNON_TYPES.contains(type) ? endpoint.getDelegate() : null, type)); } catch (MalformedURLException e) { throw new DiscoveryException("Invalid endpoint URL discovered: " + endpoint.getUri()); } } } return results; } catch (IOException e) { throw new DiscoveryException("Error performing discovery on HXRI: " + hxri); } } public XriIdentifier parseIdentifier(String identifier) throws DiscoveryException { // todo: http://code.google.com/p/openid4java/issues/detail?id=63 _log.warn("Creating XRI identifier with the friendly XRI identifier as the IRI/URI normal forms."); return new XriIdentifier(identifier, identifier, identifier); } }