mrglavas 2004/09/29 13:23:58 Modified: java/src/org/apache/xerces/xinclude XIncludeHandler.java XIncludeTextReader.java java/src/org/apache/xerces/impl XMLEntityManager.java Added: java/src/org/apache/xerces/util HTTPInputSource.java Log: XInclude: Support content negotation for parse='xml'.
Restructured interaction between XIncludeTextReader and XIncludeHandler for accept and accept-language attributes. Created new HTTPInputSource class which glues it all together. Revision Changes Path 1.36 +36 -19 xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeHandler.java Index: XIncludeHandler.java =================================================================== RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeHandler.java,v retrieving revision 1.35 retrieving revision 1.36 diff -u -r1.35 -r1.36 --- XIncludeHandler.java 16 Aug 2004 01:27:29 -0000 1.35 +++ XIncludeHandler.java 29 Sep 2004 20:23:58 -0000 1.36 @@ -28,6 +28,7 @@ import org.apache.xerces.impl.io.MalformedByteSequenceException; import org.apache.xerces.impl.msg.XMLMessageFormatter; import org.apache.xerces.util.AugmentationsImpl; +import org.apache.xerces.util.HTTPInputSource; import org.apache.xerces.util.IntStack; import org.apache.xerces.util.ParserConfigurationSettings; import org.apache.xerces.util.SecurityManager; @@ -1377,6 +1378,16 @@ includedSource = fEntityResolver.resolveEntity(resourceIdentifier); + + if (includedSource != null && + !(includedSource instanceof HTTPInputSource) && + (accept != null || acceptLanguage != null) && + includedSource.getCharacterStream() == null && + includedSource.getByteStream() == null) { + + includedSource = createInputSource(includedSource.getPublicId(), includedSource.getSystemId(), + includedSource.getBaseSystemId(), accept, acceptLanguage); + } } catch (IOException e) { reportResourceError( @@ -1387,12 +1398,15 @@ } if (includedSource == null) { - includedSource = - new XMLInputSource( - null, - href, - fCurrentBaseURI.getExpandedSystemId()); + // setup an HTTPInputSource if either of the content negotation attributes were specified. + if (accept != null || acceptLanguage != null) { + includedSource = createInputSource(null, href, fCurrentBaseURI.getExpandedSystemId(), accept, acceptLanguage); + } + else { + includedSource = new XMLInputSource(null, href, fCurrentBaseURI.getExpandedSystemId()); + } } + if (parse.equals(XINCLUDE_PARSE_XML)) { // Instead of always creating a new configuration, the first one can be reused if (fChildConfig == null) { @@ -1429,15 +1443,6 @@ copyFeatures(fSettings, fChildConfig); try { - // REVISIT: If we're going to support content negotation for - // parse=xml we need to find a clean way to propogate the - // parameters to the child parser. We cannot set those parameters - // here because we may lose some information if we process the - // URLConnection and then open a stream. The parser needs a - // URLConnection to follow HTTP redirects and may also need - // this object in the future to read external encoding information - // which may be available in the Content-Type. -- mrglavas - fNamespaceContext.pushScope(); fChildConfig.parse(includedSource); // necessary to make sure proper location is reported in errors @@ -1495,10 +1500,6 @@ } textReader = fXInclude11TextReader; } - if (includedSource.getCharacterStream() == null - && includedSource.getByteStream() == null) { - textReader.setHttpProperties(accept, acceptLanguage); - } textReader.setErrorReporter(fErrorReporter); textReader.parse(); } @@ -2565,4 +2566,20 @@ return true; } + /** + * Returns a new <code>XMLInputSource</code> from the given parameters. + */ + private XMLInputSource createInputSource(String publicId, + String systemId, String baseSystemId, + String accept, String acceptLanguage) { + + HTTPInputSource httpSource = new HTTPInputSource(publicId, systemId, baseSystemId); + if (accept != null && accept.length() > 0) { + httpSource.setHTTPRequestProperty(XIncludeHandler.HTTP_ACCEPT, accept); + } + if (acceptLanguage != null && acceptLanguage.length() > 0) { + httpSource.setHTTPRequestProperty(XIncludeHandler.HTTP_ACCEPT_LANGUAGE, acceptLanguage); + } + return httpSource; + } } 1.12 +17 -24 xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeTextReader.java Index: XIncludeTextReader.java =================================================================== RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeTextReader.java,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- XIncludeTextReader.java 18 Jul 2004 19:57:42 -0000 1.11 +++ XIncludeTextReader.java 29 Sep 2004 20:23:58 -0000 1.12 @@ -23,7 +23,9 @@ import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; +import java.util.Iterator; import java.util.Locale; +import java.util.Map; import org.apache.xerces.impl.XMLEntityManager; import org.apache.xerces.impl.XMLErrorReporter; @@ -31,6 +33,7 @@ import org.apache.xerces.impl.io.UTF8Reader; import org.apache.xerces.impl.msg.XMLMessageFormatter; import org.apache.xerces.util.EncodingMap; +import org.apache.xerces.util.HTTPInputSource; import org.apache.xerces.util.MessageFormatter; import org.apache.xerces.util.XMLChar; import org.apache.xerces.xni.XMLString; @@ -64,10 +67,6 @@ private XMLInputSource fSource; private XMLErrorReporter fErrorReporter; private XMLString fTempString = new XMLString(); - - // Content negotation parameters - private String fAccept; - private String fAcceptLanguage; /** * Construct the XIncludeReader using the XMLInputSource and XIncludeHandler. @@ -93,17 +92,6 @@ public void setErrorReporter(XMLErrorReporter errorReporter) { fErrorReporter = errorReporter; } - - /** - * Sets content negotation parameters to be attached to an HTTP request. - * - * @param accept the Accept HTTP request property - * @param acceptLanguage the Accept-Language HTTP request property - */ - public void setHttpProperties(String accept, String acceptLanguage) { - fAccept = accept; - fAcceptLanguage = acceptLanguage; - } /** * Return the Reader for given XMLInputSource. @@ -134,15 +122,20 @@ URL url = new URL(expandedSystemId); URLConnection urlCon = url.openConnection(); - // If this is an HTTP connection attach any - // content negotation parameters to the request. - if (urlCon instanceof HttpURLConnection) { - if( fAccept != null && fAccept.length() > 0) { - urlCon.setRequestProperty(XIncludeHandler.HTTP_ACCEPT, fAccept); - } - if( fAcceptLanguage != null && fAcceptLanguage.length() > 0) { - urlCon.setRequestProperty(XIncludeHandler.HTTP_ACCEPT_LANGUAGE, fAcceptLanguage); + // If this is an HTTP connection attach any request properties to the request. + if (urlCon instanceof HttpURLConnection && source instanceof HTTPInputSource) { + final HttpURLConnection urlConnection = (HttpURLConnection) urlCon; + final HTTPInputSource httpInputSource = (HTTPInputSource) source; + + // set request properties + Iterator propIter = httpInputSource.getHTTPRequestProperties(); + while (propIter.hasNext()) { + Map.Entry entry = (Map.Entry) propIter.next(); + urlConnection.setRequestProperty((String) entry.getKey(), (String) entry.getValue()); } + + // set preference for redirection + urlConnection.setInstanceFollowRedirects(httpInputSource.getFollowHTTPRedirects()); } // Wrap the InputStream so that it is possible to rewind it. 1.87 +41 -13 xml-xerces/java/src/org/apache/xerces/impl/XMLEntityManager.java Index: XMLEntityManager.java =================================================================== RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/XMLEntityManager.java,v retrieving revision 1.86 retrieving revision 1.87 diff -u -r1.86 -r1.87 --- XMLEntityManager.java 24 Sep 2004 18:03:01 -0000 1.86 +++ XMLEntityManager.java 29 Sep 2004 20:23:58 -0000 1.87 @@ -25,6 +25,8 @@ import java.net.URL; import java.net.URLConnection; import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; import java.util.Locale; import java.util.Stack; @@ -35,6 +37,7 @@ import org.apache.xerces.impl.validation.ValidationManager; import org.apache.xerces.util.AugmentationsImpl; import org.apache.xerces.util.EncodingMap; +import org.apache.xerces.util.HTTPInputSource; import org.apache.xerces.util.SecurityManager; import org.apache.xerces.util.SymbolTable; import org.apache.xerces.util.URI; @@ -923,18 +926,43 @@ if (stream == null) { URL location = new URL(expandedSystemId); URLConnection connect = location.openConnection(); - stream = connect.getInputStream(); - - // REVISIT: If the URLConnection has external encoding - // information, we should be reading it here. It's located - // in the charset parameter of Content-Type. -- mrglavas - if (connect instanceof HttpURLConnection) { - String redirect = connect.getURL().toString(); - // E43: Check if the URL was redirected, and then - // update literal and expanded system IDs if needed. - if (!redirect.equals(expandedSystemId)) { - literalSystemId = redirect; - expandedSystemId = redirect; + if (!(connect instanceof HttpURLConnection)) { + stream = connect.getInputStream(); + } + else { + boolean followRedirects = true; + + // setup URLConnection if we have an HTTPInputSource + if (xmlInputSource instanceof HTTPInputSource) { + final HttpURLConnection urlConnection = (HttpURLConnection) connect; + final HTTPInputSource httpInputSource = (HTTPInputSource) xmlInputSource; + + // set request properties + Iterator propIter = httpInputSource.getHTTPRequestProperties(); + while (propIter.hasNext()) { + Map.Entry entry = (Map.Entry) propIter.next(); + urlConnection.setRequestProperty((String) entry.getKey(), (String) entry.getValue()); + } + + // set preference for redirection + followRedirects = httpInputSource.getFollowHTTPRedirects(); + urlConnection.setInstanceFollowRedirects(followRedirects); + } + + stream = connect.getInputStream(); + + // REVISIT: If the URLConnection has external encoding + // information, we should be reading it here. It's located + // in the charset parameter of Content-Type. -- mrglavas + + if (followRedirects) { + String redirect = connect.getURL().toString(); + // E43: Check if the URL was redirected, and then + // update literal and expanded system IDs if needed. + if (!redirect.equals(expandedSystemId)) { + literalSystemId = redirect; + expandedSystemId = redirect; + } } } } 1.1 xml-xerces/java/src/org/apache/xerces/util/HTTPInputSource.java Index: HTTPInputSource.java =================================================================== /* * Copyright 2004 The Apache Software Foundation. * * 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.apache.xerces.util; import java.io.InputStream; import java.io.Reader; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.apache.xerces.xni.XMLResourceIdentifier; import org.apache.xerces.xni.parser.XMLInputSource; /** * This class represents an input source for an XML resource * retrievable over HTTP. In addition to the properties * provided by an <code>XMLInputSource</code> an HTTP input * source also has HTTP request properties and a preference * whether HTTP redirects will be followed. Note that these * properties will only be used if reading this input source * will induce an HTTP connection. * * @author Michael Glavassevich, IBM * * @version $Id: HTTPInputSource.java,v 1.1 2004/09/29 20:23:58 mrglavas Exp $ */ public class HTTPInputSource extends XMLInputSource { // // Data // /** Preference for whether HTTP redirects should be followed. **/ protected boolean fFollowRedirects = true; /** HTTP request properties. **/ protected Map fHTTPRequestProperties = new HashMap(); // // Constructors // /** * Constructs an input source from just the public and system * identifiers, leaving resolution of the entity and opening of * the input stream up to the caller. * * @param publicId The public identifier, if known. * @param systemId The system identifier. This value should * always be set, if possible, and can be * relative or absolute. If the system identifier * is relative, then the base system identifier * should be set. * @param baseSystemId The base system identifier. This value should * always be set to the fully expanded URI of the * base system identifier, if possible. */ public HTTPInputSource(String publicId, String systemId, String baseSystemId) { super(publicId, systemId, baseSystemId); } // <init>(String,String,String) /** * Constructs an input source from a XMLResourceIdentifier * object, leaving resolution of the entity and opening of * the input stream up to the caller. * * @param resourceIdentifier the XMLResourceIdentifier containing the information */ public HTTPInputSource(XMLResourceIdentifier resourceIdentifier) { super(resourceIdentifier); } // <init>(XMLResourceIdentifier) /** * Constructs an input source from a byte stream. * * @param publicId The public identifier, if known. * @param systemId The system identifier. This value should * always be set, if possible, and can be * relative or absolute. If the system identifier * is relative, then the base system identifier * should be set. * @param baseSystemId The base system identifier. This value should * always be set to the fully expanded URI of the * base system identifier, if possible. * @param byteStream The byte stream. * @param encoding The encoding of the byte stream, if known. */ public HTTPInputSource(String publicId, String systemId, String baseSystemId, InputStream byteStream, String encoding) { super(publicId, systemId, baseSystemId, byteStream, encoding); } // <init>(String,String,String,InputStream,String) /** * Constructs an input source from a character stream. * * @param publicId The public identifier, if known. * @param systemId The system identifier. This value should * always be set, if possible, and can be * relative or absolute. If the system identifier * is relative, then the base system identifier * should be set. * @param baseSystemId The base system identifier. This value should * always be set to the fully expanded URI of the * base system identifier, if possible. * @param charStream The character stream. * @param encoding The original encoding of the byte stream * used by the reader, if known. */ public HTTPInputSource(String publicId, String systemId, String baseSystemId, Reader charStream, String encoding) { super(publicId, systemId, baseSystemId, charStream, encoding); } // <init>(String,String,String,Reader,String) // // Public methods // /** * Returns the preference whether HTTP redirects should * be followed. By default HTTP redirects will be followed. */ public boolean getFollowHTTPRedirects() { return fFollowRedirects; } // getFollowHTTPRedirects():boolean /** * Sets the preference whether HTTP redirects should * be followed. By default HTTP redirects will be followed. */ public void setFollowHTTPRedirects(boolean followRedirects) { fFollowRedirects = followRedirects; } // setFollowHTTPRedirects(boolean) /** * Returns the value of the request property * associated with the given property name. * * @param key the name of the request property * @return the value of the request property or * <code>null</code> if this property has not * been set */ public String getHTTPRequestProperty(String key) { return (String) fHTTPRequestProperties.get(key); } // getHTTPRequestProperty(String):String /** * Returns an iterator for the request properties this * input source contains. Each object returned by the * iterator is an instance of <code>java.util.Map.Entry</code> * where each key and value are a pair of strings corresponding * to the name and value of a request property. * * @return an iterator for the request properties this * input source contains */ public Iterator getHTTPRequestProperties() { return fHTTPRequestProperties.entrySet().iterator(); } // getHTTPRequestProperties():Iterator /** * Sets the value of the request property * associated with the given property name. * * @param key the name of the request property * @param value the value of the request property */ public void setHTTPRequestProperty(String key, String value) { if (value != null) { fHTTPRequestProperties.put(key, value); } else { fHTTPRequestProperties.remove(key); } } // setHTTPRequestProperty(String,String) } // class HTTPInputSource --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]