/** * Copyright © 2006-2016 Web Cohesion (info@webcohesion.com) * * 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 com.webcohesion.enunciate.rt; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.xml.namespace.NamespaceContext; import javax.xml.namespace.QName; import javax.xml.stream.*; import javax.xml.stream.events.*; import java.io.IOException; import java.io.InputStream; import java.io.Writer; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * @author Ryan Heaton */ public class IDLFilter implements Filter { private ServletContext servletContext = null; private XMLInputFactory inputFactory; private XMLOutputFactory outputFactory; public void init(FilterConfig filterConfig) throws ServletException { this.inputFactory = XMLInputFactory.newInstance(); this.outputFactory = XMLOutputFactory.newInstance(); this.servletContext = filterConfig.getServletContext(); } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; RequestURIParts parts = parseParts(request); if (parts != null) { String realBaseAddress = parts.getBaseAddress(); String idlPath = parts.getFilePath(); InputStream idl = this.servletContext.getResourceAsStream(idlPath); if (idl != null) { servletResponse.setContentType("text/xml"); String assumedBaseAddress = this.servletContext.getInitParameter("assumed-base-uri"); try { XMLEventReader eventReader = this.inputFactory.createXMLEventReader(idl); XMLEventWriter eventWriter = this.outputFactory.createXMLEventWriter(servletResponse.getWriter()); while (eventReader.hasNext()) { XMLEvent event = eventReader.nextEvent(); if (event.isProcessingInstruction()) { String target = ((ProcessingInstruction) event).getTarget(); if ("enunciate-assumed-base-uri".equals(target)) { assumedBaseAddress = ((ProcessingInstruction) event).getData(); if (assumedBaseAddress.endsWith("/")) { assumedBaseAddress = assumedBaseAddress.substring(0, assumedBaseAddress.length() - 1); } } continue; } else if (event.getEventType() == XMLStreamConstants.CDATA || event.getEventType() == XMLStreamConstants.CHARACTERS) { String data = ((Characters) event).getData(); if (assumedBaseAddress != null && data.contains(assumedBaseAddress)) { data = data.replace(assumedBaseAddress, realBaseAddress); event = new DelegatingCharacters(((Characters) event), data); } } else if (event.getEventType() == XMLStreamConstants.START_ELEMENT) { List<Attribute> attributes = new ArrayList<Attribute>(); Iterator attributesIt = ((StartElement) event).getAttributes(); while (attributesIt.hasNext()) { Attribute attribute = (Attribute) attributesIt.next(); String value = attribute.getValue(); if (assumedBaseAddress != null && value.contains(assumedBaseAddress)) { value = value.replace(assumedBaseAddress, realBaseAddress); attribute = new DelegatingAttribute(attribute, value); event = new DelegatingStartElement(((StartElement) event), attributes); } attributes.add(attribute); } } eventWriter.add(event); } eventReader.close(); eventWriter.flush(); eventWriter.close(); return; } catch (XMLStreamException e) { throw new ServletException(e); } } } chain.doFilter(servletRequest, servletResponse); } protected RequestURIParts parseParts(HttpServletRequest request) { StringBuffer requestURI = request.getRequestURL(); String contextPath = request.getContextPath(); String baseAddress; String filePath; if ("".equals(contextPath)) { URI uri; try { uri = new URI(requestURI.toString()); } catch (URISyntaxException e) { return null; } filePath = uri.getPath(); baseAddress = requestURI.substring(0, requestURI.length() - filePath.length()); } else { int splitIndex = requestURI.indexOf(contextPath) + contextPath.length(); baseAddress = requestURI.substring(0, splitIndex); filePath = requestURI.substring(splitIndex); } return new RequestURIParts(baseAddress, filePath); } public void destroy() { } public static class RequestURIParts { private final String baseAddress; private final String idlPath; public RequestURIParts(String baseAddress, String idlPath) { this.baseAddress = baseAddress; this.idlPath = idlPath; } public String getBaseAddress() { return baseAddress; } public String getFilePath() { return idlPath; } } public static class DelegatingXMLEvent implements XMLEvent { private final XMLEvent delegate; public DelegatingXMLEvent(XMLEvent delegate) { this.delegate = delegate; } @Override public int getEventType() { return delegate.getEventType(); } @Override public Location getLocation() { return delegate.getLocation(); } @Override public boolean isStartElement() { return delegate.isStartElement(); } @Override public boolean isAttribute() { return delegate.isAttribute(); } @Override public boolean isNamespace() { return delegate.isNamespace(); } @Override public boolean isEndElement() { return delegate.isEndElement(); } @Override public boolean isEntityReference() { return delegate.isEntityReference(); } @Override public boolean isProcessingInstruction() { return delegate.isProcessingInstruction(); } @Override public boolean isCharacters() { return delegate.isCharacters(); } @Override public boolean isStartDocument() { return delegate.isStartDocument(); } @Override public boolean isEndDocument() { return delegate.isEndDocument(); } @Override public StartElement asStartElement() { return delegate.asStartElement(); } @Override public EndElement asEndElement() { return delegate.asEndElement(); } @Override public Characters asCharacters() { return delegate.asCharacters(); } @Override public QName getSchemaType() { return delegate.getSchemaType(); } @Override public void writeAsEncodedUnicode(Writer writer) throws XMLStreamException { delegate.writeAsEncodedUnicode(writer); } } public static class DelegatingCharacters extends DelegatingXMLEvent implements Characters { private final Characters delegate; private final String data; public DelegatingCharacters(Characters delegate, String data) { super(delegate); this.delegate = delegate; this.data = data; } @Override public String getData() { return this.data; } @Override public boolean isWhiteSpace() { return delegate.isWhiteSpace(); } @Override public boolean isCData() { return delegate.isCData(); } @Override public boolean isIgnorableWhiteSpace() { return delegate.isIgnorableWhiteSpace(); } @Override public boolean isCharacters() { return true; } @Override public Characters asCharacters() { return this; } } public static class DelegatingAttribute extends DelegatingXMLEvent implements Attribute { private final Attribute delegate; private final String value; public DelegatingAttribute(Attribute delegate, String value) { super(delegate); this.delegate = delegate; this.value = value; } @Override public QName getName() { return delegate.getName(); } @Override public String getValue() { return this.value; } @Override public String getDTDType() { return delegate.getDTDType(); } @Override public boolean isSpecified() { return delegate.isSpecified(); } @Override public boolean isAttribute() { return true; } } public static class DelegatingStartElement extends DelegatingXMLEvent implements StartElement { private final StartElement delegate; private final List<Attribute> attributes; public DelegatingStartElement(StartElement delegate, List<Attribute> attributes) { super(delegate); this.delegate = delegate; this.attributes = attributes; } @Override public QName getName() { return delegate.getName(); } @Override public Iterator getAttributes() { return this.attributes.iterator(); } @Override public Iterator getNamespaces() { return delegate.getNamespaces(); } @Override public Attribute getAttributeByName(QName name) { for (Attribute attribute : attributes) { if (attribute.getName().equals(name)) { return attribute; } } return null; } @Override public NamespaceContext getNamespaceContext() { return delegate.getNamespaceContext(); } @Override public String getNamespaceURI(String prefix) { return delegate.getNamespaceURI(prefix); } @Override public boolean isStartElement() { return true; } @Override public StartElement asStartElement() { return this; } } }