When you validate a XML file, and this has a XSD URL for some namespace, and this XSD URL redirects to another URL, then the default EntityResolver2 takes that as a failure.

Jess noticed (and fixed) this when debugging WINDUP-997.


So for instance, this XML was not valid, because some of the URLs (perhaps in the linked XSD's) is behind a redirect:


<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <mvc:resources mapping="/resources/**" location="/" />



So here's a fixed implementation. It follows only a single redirect, but change the if to a for and it will follow more (don't forget to prevent infinite loop).


package org.jboss.windup.rules.apps.xml.xml;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.ext.EntityResolver2;

* This is an {@link EntityResolver2} that has been enhanced to support URL redirection.
 * @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a>
public class EnhancedEntityResolver2 implements EntityResolver2
  public InputSource getExternalSubset(String name, String baseURI) throws SAXException, IOException
  return null;

  public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException
  return resolveEntity(null, publicId, null, systemId);

  public InputSource resolveEntity(String name, String publicId, String baseURI, String systemId) throws SAXException, IOException
  URL url = baseURI != null ? new URL(new URL(baseURI), systemId) : new URL(systemId);

  URLConnection connection = url.openConnection();

  // Not a HTTP connection... skip redirection logic
  if (!(connection instanceof HttpURLConnection))
  return new InputSource(connection.getInputStream());

  HttpURLConnection httpConnection = (HttpURLConnection)connection;

  int status = httpConnection.getResponseCode();
  if ((status != HttpURLConnection.HTTP_OK) &&
  (status == HttpURLConnection.HTTP_MOVED_TEMP
  || status == HttpURLConnection.HTTP_MOVED_PERM
  || status == HttpURLConnection.HTTP_SEE_OTHER))
  String newUrl = httpConnection.getHeaderField("Location");
  httpConnection = (HttpURLConnection) new URL(newUrl).openConnection();

  InputSource inputSource = new InputSource(httpConnection.getInputStream());
  return inputSource;