/* * Copyright 2011 <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a> * * 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.ocpsoft.rewrite.servlet.impl; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Stack; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.XMLEvent; import org.ocpsoft.rewrite.servlet.ServletRegistration; class WebXmlServletRegistrationParser { private final List<ServletRegistration> registrations = new ArrayList<ServletRegistration>(); private final Stack<String> stack = new Stack<String>(); private List<ServletEntry> servlets = new ArrayList<ServletEntry>(); private Map<String, ServletMappingEntry> servletMappings = new LinkedHashMap<String, ServletMappingEntry>(); private ServletEntry currentServlet; private ServletMappingEntry currentServletMapping; public void parse(InputStream stream) throws IOException { try { XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); XMLEventReader reader = xmlInputFactory.createXMLEventReader(stream); // parse the complete document while (reader.hasNext()) { XMLEvent event = reader.nextEvent(); // this events means we can abort if (event.isEndDocument()) { break; } // we need the element name on the stack before processing the event if (event.isStartElement()) { stack.push(event.asStartElement().getName().getLocalPart()); } // any event processing is done in this method handleEvent(event); // we can remove the last element from the stack after the event has been processed if (event.isEndElement()) { stack.pop(); } } // each ServletEntry creates one registration for (ServletEntry servletEntry : servlets) { ServletRegistration reg = new ServletRegistration(); reg.setClassName(servletEntry.servletClass); // we can lookup the mappings from the mappings map ServletMappingEntry mapping = servletMappings.get(servletEntry.servletName); if (mapping != null) { reg.addMappings(mapping.mappings); } registrations.add(reg); } } catch (XMLStreamException e) { throw new IOException(e); } } private void handleEvent(XMLEvent event) { /* * Parse <servlet> entries */ if (isParsePosition("web-app", "servlet")) { if (event.isStartElement()) { currentServlet = new ServletEntry(); } if (event.isEndElement()) { servlets.add(currentServlet); currentServlet = null; } } if (event.isCharacters() && isParsePosition("web-app", "servlet", "servlet-name")) { currentServlet.servletName = event.asCharacters().getData().trim(); } if (event.isCharacters() && isParsePosition("web-app", "servlet", "servlet-class")) { currentServlet.servletClass = event.asCharacters().getData().trim(); } /* * Parse <servlet-mapping> entries */ if (isParsePosition("web-app", "servlet-mapping")) { if (event.isStartElement()) { currentServletMapping = new ServletMappingEntry(); } if (event.isEndElement() && isNotBlank(currentServletMapping.servletName)) { String key = currentServletMapping.servletName.trim(); ServletMappingEntry existingMapping = servletMappings.get(key); if (existingMapping != null) { existingMapping.mappings.addAll(currentServletMapping.mappings); } else { servletMappings.put(key, currentServletMapping); } currentServletMapping = null; } } if (event.isCharacters() && isParsePosition("web-app", "servlet-mapping", "servlet-name")) { currentServletMapping.servletName = event.asCharacters().getData().trim(); } if (event.isCharacters() && isParsePosition("web-app", "servlet-mapping", "url-pattern")) { currentServletMapping.mappings.add(event.asCharacters().getData().trim()); } } private static boolean isNotBlank(String s) { return s != null && s.trim().length() > 0; } private boolean isParsePosition(String... path) { if (path.length != stack.size()) { return false; } for (int i = 0; i < stack.size(); i++) { if (!path[i].equals(stack.get(i))) { return false; } } return true; } public List<ServletRegistration> getRegistrations() { return registrations; } private class ServletEntry { public String servletName; public String servletClass; } private class ServletMappingEntry { public String servletName; public final List<String> mappings = new ArrayList<String>(); } }