@BeforeClass
  public static void setUp() throws Exception {
    TransactionManager transact = null;
    Txn transaction = null;
    try {
      pool = startDB();
      broker = pool.get(pool.getSecurityManager().getSystemSubject());
      transact = pool.getTransactionManager();
      transaction = transact.beginTransaction();

      root =
          broker.getOrCreateCollection(
              transaction, XmldbURI.create(XmldbURI.ROOT_COLLECTION + "/test"));
      broker.saveCollection(transaction, root);

      String existHome = System.getProperty("exist.home");
      File existDir = existHome == null ? new File(".") : new File(existHome);
      String directory = "samples/shakespeare";
      File dir = new File(existDir, directory);

      // store some documents.
      for (File f : dir.listFiles(new XMLFilenameFilter())) {
        IndexInfo info =
            root.validateXMLResource(
                transaction,
                broker,
                XmldbURI.create(f.getName()),
                new InputSource(f.toURI().toASCIIString()));
        root.store(transaction, broker, info, new InputSource(f.toURI().toASCIIString()), false);
      }

      IndexInfo info =
          root.validateXMLResource(transaction, broker, XmldbURI.create("nested.xml"), NESTED_XML);
      root.store(transaction, broker, info, NESTED_XML, false);
      transact.commit(transaction);

      // for the tests
      docs = root.allDocs(broker, new DefaultDocumentSet(), true);
      seqSpeech = executeQuery(broker, "//SPEECH", 2628, null);

    } catch (Exception e) {
      if (pool != null) {
        pool.release(broker);
        BrokerPool.stopAll(false);
        pool = null;
        root = null;
      }
      throw e;
    }
  }
Beispiel #2
0
  public void getEntryById(DBBroker broker, String path, String id, OutgoingMessage response)
      throws EXistException, BadRequestException {
    XQuery xquery = broker.getXQueryService();
    CompiledXQuery feedQuery = xquery.getXQueryPool().borrowCompiledXQuery(broker, entryByIdSource);

    XQueryContext context;
    if (feedQuery == null) {
      context = xquery.newContext(AccessContext.REST);
      try {
        feedQuery = xquery.compile(context, entryByIdSource);
      } catch (XPathException ex) {
        throw new EXistException("Cannot compile xquery " + entryByIdSource.getURL(), ex);
      } catch (IOException ex) {
        throw new EXistException(
            "I/O exception while compiling xquery " + entryByIdSource.getURL(), ex);
      }
    } else {
      context = feedQuery.getContext();
    }
    context.setStaticallyKnownDocuments(
        new XmldbURI[] {XmldbURI.create(path).append(AtomProtocol.FEED_DOCUMENT_NAME)});

    try {
      context.declareVariable("id", id);
      Sequence resultSequence = xquery.execute(feedQuery, null);
      if (resultSequence.isEmpty()) {
        throw new BadRequestException("No topic was found.");
      }
      String charset = getContext().getDefaultCharset();
      response.setContentType("application/atom+xml; charset=" + charset);
      Serializer serializer = broker.getSerializer();
      serializer.reset();
      try {
        Writer w = new OutputStreamWriter(response.getOutputStream(), charset);
        SAXSerializer sax =
            (SAXSerializer) SerializerPool.getInstance().borrowObject(SAXSerializer.class);
        Properties outputProperties = new Properties();
        sax.setOutput(w, outputProperties);
        serializer.setProperties(outputProperties);
        serializer.setSAXHandlers(sax, sax);

        serializer.toSAX(resultSequence, 1, 1, false);

        SerializerPool.getInstance().returnObject(sax);
        w.flush();
        w.close();
      } catch (IOException ex) {
        LOG.fatal("Cannot read resource " + path, ex);
        throw new EXistException("I/O error on read of resource " + path, ex);
      } catch (SAXException saxe) {
        LOG.warn(saxe);
        throw new BadRequestException("Error while serializing XML: " + saxe.getMessage());
      }
      resultSequence.itemAt(0);
    } catch (XPathException ex) {
      throw new EXistException("Cannot execute xquery " + entryByIdSource.getURL(), ex);
    } finally {
      xquery.getXQueryPool().returnCompiledXQuery(entryByIdSource, feedQuery);
    }
  }
  @AfterClass
  public static void tearDown() {

    TransactionManager transact = null;
    Txn transaction = null;
    try {
      transact = pool.getTransactionManager();
      transaction = transact.beginTransaction();
      root =
          broker.getOrCreateCollection(
              transaction, XmldbURI.create(XmldbURI.ROOT_COLLECTION + "/test"));
      //          broker.removeCollection(transaction, root);

      transact.commit(transaction);
    } catch (Exception e) {
      if (transaction != null) {
        transact.abort(transaction);
      }
    } finally {
      if (pool != null) pool.release(broker);
    }
    BrokerPool.stopAll(false);
    pool = null;
    root = null;
  }
  /**
   * Create a {@link Source} object for the given URL.
   *
   * <p>As a special case, if the URL starts with "resource:", the resource will be read from the
   * current context class loader.
   *
   * @param broker broker, can be null if not asking for a database resource
   * @param contextPath
   * @param location
   * @throws MalformedURLException
   * @throws IOException
   */
  public static final Source getSource(
      DBBroker broker, String contextPath, String location, boolean checkXQEncoding)
      throws MalformedURLException, IOException, PermissionDeniedException {
    Source source = null;

    /* file:// or location without scheme is assumed to be a file */
    if (location.startsWith("file:") || location.indexOf(':') == Constants.STRING_NOT_FOUND) {
      location = location.replaceAll("^(file:)?/*(.*)$", "$2");

      File f = new File(contextPath + File.separatorChar + location);
      if (!f.canRead()) {
        File f2 = new File(location);
        if (!f2.canRead()) {
          throw new FileNotFoundException(
              "cannot read module source from file at "
                  + location
                  + ". Tried "
                  + f.getAbsolutePath()
                  + " and "
                  + f2.getAbsolutePath());
        } else {
          f = f2;
        }
      }
      location = f.toURI().toASCIIString();
      source = new FileSource(f, "UTF-8", checkXQEncoding);
    }

    /* xmldb: */
    else if (location.startsWith(XmldbURI.XMLDB_URI_PREFIX)) {
      DocumentImpl resource = null;
      try {
        XmldbURI pathUri = XmldbURI.create(location);
        resource = broker.getXMLResource(pathUri, Lock.READ_LOCK);
        source = new DBSource(broker, (BinaryDocument) resource, true);
      } finally {
        // TODO: this is nasty!!! as we are unlocking the resource whilst there
        // is still a source
        if (resource != null) resource.getUpdateLock().release(Lock.READ_LOCK);
      }
    }

    /* resource: */
    else if (location.startsWith(ClassLoaderSource.PROTOCOL)) {
      source = new ClassLoaderSource(location);
    }

    /* any other URL */
    else {
      URL url = new URL(location);
      source = new URLSource(url);
    }

    return source;
  }
  public void configure(DBBroker broker, Collection parent, Map parameters)
      throws CollectionConfigurationException {
    super.configure(broker, parent, parameters);
    String stylesheet = (String) parameters.get("src");
    if (stylesheet == null)
      throw new CollectionConfigurationException(
          "STXTransformerTrigger requires an " + "attribute 'src'");
    String origProperty = System.getProperty("javax.xml.transform.TransformerFactory");
    System.setProperty(
        "javax.xml.transform.TransformerFactory", "net.sf.joost.trax.TransformerFactoryImpl");
    factory = (SAXTransformerFactory) TransformerFactory.newInstance();
    // reset property to previous setting
    if (origProperty != null)
      System.setProperty("javax.xml.transform.TransformerFactory", origProperty);

    getLogger().debug("compiling stylesheet " + stylesheet);
    XmldbURI stylesheetUri = null;
    try {
      stylesheetUri = XmldbURI.xmldbUriFor(stylesheet);
    } catch (URISyntaxException e) {
    }
    // TODO: allow full XmldbURIs to be used as well.
    if (stylesheetUri == null || stylesheet.indexOf(':') == Constants.STRING_NOT_FOUND) {
      stylesheetUri = parent.getURI().resolveCollectionPath(stylesheetUri);
      DocumentImpl doc;
      try {
        doc = (DocumentImpl) broker.getXMLResource(stylesheetUri);
        if (doc == null)
          throw new CollectionConfigurationException(
              "stylesheet " + stylesheetUri + " not found in database");
        Serializer serializer = broker.getSerializer();
        TemplatesHandler thandler = factory.newTemplatesHandler();
        serializer.setSAXHandlers(thandler, null);
        serializer.toSAX(doc);
        template = thandler.getTemplates();
        handler = factory.newTransformerHandler(template);
      } catch (TransformerConfigurationException e) {
        throw new CollectionConfigurationException(e.getMessage(), e);
      } catch (PermissionDeniedException e) {
        throw new CollectionConfigurationException(e.getMessage(), e);
      } catch (SAXException e) {
        throw new CollectionConfigurationException(e.getMessage(), e);
      }
    } else
      try {
        template = factory.newTemplates(new StreamSource(stylesheet));
        handler = factory.newTransformerHandler(template);
      } catch (TransformerConfigurationException e) {
        throw new CollectionConfigurationException(e.getMessage(), e);
      }
  }
  public void init(ServletConfig config) throws ServletException {
    super.init(config);

    query = config.getInitParameter("xquery");
    if (query == null) {
      throw new ServletException("RedirectorServlet requires a parameter 'xquery'.");
    }
    user = config.getInitParameter("user");
    if (user == null) {
      user = DEFAULT_USER;
    }
    password = config.getInitParameter("password");
    if (password == null) {
      password = DEFAULT_PASS;
    }
    final String confCollectionURI = config.getInitParameter("uri");
    if (confCollectionURI == null) {
      collectionURI = DEFAULT_URI;
    } else {
      try {
        collectionURI = XmldbURI.xmldbUriFor(confCollectionURI);
      } catch (final URISyntaxException e) {
        throw new ServletException("Invalid XmldbURI for parameter 'uri': " + e.getMessage(), e);
      }
    }

    try {
      final Class<?> driver = Class.forName(DRIVER);
      final Database database = (Database) driver.newInstance();
      database.setProperty("create-database", "true");
      DatabaseManager.registerDatabase(database);
    } catch (final Exception e) {
      final String errorMessage = "Failed to initialize database driver";
      LOG.error(errorMessage, e);
      throw new ServletException(errorMessage + ": " + e.getMessage(), e);
    }
  }
Beispiel #7
0
  protected void handleGet(
      boolean returnContent, DBBroker broker, IncomingMessage request, OutgoingMessage response)
      throws BadRequestException, PermissionDeniedException, NotFoundException, EXistException {
    DocumentImpl resource = null;
    XmldbURI pathUri = XmldbURI.create(request.getPath());
    try {

      resource = broker.getXMLResource(pathUri, Lock.READ_LOCK);

      if (resource == null) {

        String id = request.getParameter("id");
        if (id != null) {
          id = id.trim();
          if (id.length() == 0) {
            id = null;
          }
        }
        // Must be a collection
        Collection collection = broker.getCollection(pathUri);
        if (collection != null) {
          if (!collection.getPermissions().validate(broker.getUser(), Permission.READ)) {
            throw new PermissionDeniedException("Not allowed to read collection");
          }
          DocumentImpl feedDoc = collection.getDocument(broker, FEED_DOCUMENT_URI);
          if (feedDoc == null) {
            throw new BadRequestException(
                "Collection " + request.getPath() + " is not an Atom feed.");
          }

          // Return the collection feed
          String charset = getContext().getDefaultCharset();
          if (returnContent) {
            if (id == null) {
              response.setStatusCode(200);
              getFeed(broker, request.getPath(), response);
            } else {
              response.setStatusCode(200);
              getEntryById(broker, request.getPath(), id, response);
            }
          } else {
            response.setStatusCode(204);
          }
        } else {
          throw new NotFoundException("Resource " + request.getPath() + " not found");
        }
      } else {
        // Do we have permission to read the resource
        if (!resource.getPermissions().validate(broker.getUser(), Permission.READ)) {
          throw new PermissionDeniedException("Not allowed to read resource");
        }

        if (returnContent) {
          response.setStatusCode(200);
          if (resource.getResourceType() == DocumentImpl.BINARY_FILE) {
            response.setContentType(resource.getMetadata().getMimeType());
            try {
              OutputStream os = response.getOutputStream();
              broker.readBinaryResource((BinaryDocument) resource, os);
              os.flush();
            } catch (IOException ex) {
              LOG.fatal("Cannot read resource " + request.getPath(), ex);
              throw new EXistException("I/O error on read of resource " + request.getPath(), ex);
            }
          } else {
            // xml resource
            Serializer serializer = broker.getSerializer();
            serializer.reset();

            String charset = getContext().getDefaultCharset();
            // Serialize the document
            try {
              response.setContentType(
                  resource.getMetadata().getMimeType() + "; charset=" + charset);
              Writer w = new OutputStreamWriter(response.getOutputStream(), charset);
              serializer.serialize(resource, w);
              w.flush();
              w.close();
            } catch (IOException ex) {
              LOG.fatal("Cannot read resource " + request.getPath(), ex);
              throw new EXistException("I/O error on read of resource " + request.getPath(), ex);
            } catch (SAXException saxe) {
              LOG.warn(saxe);
              throw new BadRequestException("Error while serializing XML: " + saxe.getMessage());
            }
          }
        } else {
          response.setStatusCode(204);
        }
      }
    } finally {
      if (resource != null) {
        resource.getUpdateLock().release(Lock.READ_LOCK);
      }
    }
  }
Beispiel #8
0
/** @author R. Alexander Milowski */
public class AtomFeeds extends AtomModuleBase implements Atom {

  protected static final Logger LOG = Logger.getLogger(AtomProtocol.class);
  static final String FEED_DOCUMENT_NAME = ".feed.atom";
  static final XmldbURI FEED_DOCUMENT_URI = XmldbURI.create(FEED_DOCUMENT_NAME);
  URLSource entryByIdSource;
  URLSource getFeedSource;

  /** Creates a new instance of AtomProtocol */
  public AtomFeeds() {
    entryByIdSource = new URLSource(this.getClass().getResource("entry-by-id.xq"));
    getFeedSource = new URLSource(this.getClass().getResource("get-feed.xq"));
  }

  public void doGet(DBBroker broker, IncomingMessage request, OutgoingMessage response)
      throws BadRequestException, PermissionDeniedException, NotFoundException, EXistException {
    handleGet(true, broker, request, response);
  }

  public void doHead(DBBroker broker, IncomingMessage request, OutgoingMessage response)
      throws BadRequestException, PermissionDeniedException, NotFoundException, EXistException {
    handleGet(false, broker, request, response);
  }

  protected void handleGet(
      boolean returnContent, DBBroker broker, IncomingMessage request, OutgoingMessage response)
      throws BadRequestException, PermissionDeniedException, NotFoundException, EXistException {
    DocumentImpl resource = null;
    XmldbURI pathUri = XmldbURI.create(request.getPath());
    try {

      resource = broker.getXMLResource(pathUri, Lock.READ_LOCK);

      if (resource == null) {

        String id = request.getParameter("id");
        if (id != null) {
          id = id.trim();
          if (id.length() == 0) {
            id = null;
          }
        }
        // Must be a collection
        Collection collection = broker.getCollection(pathUri);
        if (collection != null) {
          if (!collection.getPermissions().validate(broker.getUser(), Permission.READ)) {
            throw new PermissionDeniedException("Not allowed to read collection");
          }
          DocumentImpl feedDoc = collection.getDocument(broker, FEED_DOCUMENT_URI);
          if (feedDoc == null) {
            throw new BadRequestException(
                "Collection " + request.getPath() + " is not an Atom feed.");
          }

          // Return the collection feed
          String charset = getContext().getDefaultCharset();
          if (returnContent) {
            if (id == null) {
              response.setStatusCode(200);
              getFeed(broker, request.getPath(), response);
            } else {
              response.setStatusCode(200);
              getEntryById(broker, request.getPath(), id, response);
            }
          } else {
            response.setStatusCode(204);
          }
        } else {
          throw new NotFoundException("Resource " + request.getPath() + " not found");
        }
      } else {
        // Do we have permission to read the resource
        if (!resource.getPermissions().validate(broker.getUser(), Permission.READ)) {
          throw new PermissionDeniedException("Not allowed to read resource");
        }

        if (returnContent) {
          response.setStatusCode(200);
          if (resource.getResourceType() == DocumentImpl.BINARY_FILE) {
            response.setContentType(resource.getMetadata().getMimeType());
            try {
              OutputStream os = response.getOutputStream();
              broker.readBinaryResource((BinaryDocument) resource, os);
              os.flush();
            } catch (IOException ex) {
              LOG.fatal("Cannot read resource " + request.getPath(), ex);
              throw new EXistException("I/O error on read of resource " + request.getPath(), ex);
            }
          } else {
            // xml resource
            Serializer serializer = broker.getSerializer();
            serializer.reset();

            String charset = getContext().getDefaultCharset();
            // Serialize the document
            try {
              response.setContentType(
                  resource.getMetadata().getMimeType() + "; charset=" + charset);
              Writer w = new OutputStreamWriter(response.getOutputStream(), charset);
              serializer.serialize(resource, w);
              w.flush();
              w.close();
            } catch (IOException ex) {
              LOG.fatal("Cannot read resource " + request.getPath(), ex);
              throw new EXistException("I/O error on read of resource " + request.getPath(), ex);
            } catch (SAXException saxe) {
              LOG.warn(saxe);
              throw new BadRequestException("Error while serializing XML: " + saxe.getMessage());
            }
          }
        } else {
          response.setStatusCode(204);
        }
      }
    } finally {
      if (resource != null) {
        resource.getUpdateLock().release(Lock.READ_LOCK);
      }
    }
  }

  public void getEntryById(DBBroker broker, String path, String id, OutgoingMessage response)
      throws EXistException, BadRequestException {
    XQuery xquery = broker.getXQueryService();
    CompiledXQuery feedQuery = xquery.getXQueryPool().borrowCompiledXQuery(broker, entryByIdSource);

    XQueryContext context;
    if (feedQuery == null) {
      context = xquery.newContext(AccessContext.REST);
      try {
        feedQuery = xquery.compile(context, entryByIdSource);
      } catch (XPathException ex) {
        throw new EXistException("Cannot compile xquery " + entryByIdSource.getURL(), ex);
      } catch (IOException ex) {
        throw new EXistException(
            "I/O exception while compiling xquery " + entryByIdSource.getURL(), ex);
      }
    } else {
      context = feedQuery.getContext();
    }
    context.setStaticallyKnownDocuments(
        new XmldbURI[] {XmldbURI.create(path).append(AtomProtocol.FEED_DOCUMENT_NAME)});

    try {
      context.declareVariable("id", id);
      Sequence resultSequence = xquery.execute(feedQuery, null);
      if (resultSequence.isEmpty()) {
        throw new BadRequestException("No topic was found.");
      }
      String charset = getContext().getDefaultCharset();
      response.setContentType("application/atom+xml; charset=" + charset);
      Serializer serializer = broker.getSerializer();
      serializer.reset();
      try {
        Writer w = new OutputStreamWriter(response.getOutputStream(), charset);
        SAXSerializer sax =
            (SAXSerializer) SerializerPool.getInstance().borrowObject(SAXSerializer.class);
        Properties outputProperties = new Properties();
        sax.setOutput(w, outputProperties);
        serializer.setProperties(outputProperties);
        serializer.setSAXHandlers(sax, sax);

        serializer.toSAX(resultSequence, 1, 1, false);

        SerializerPool.getInstance().returnObject(sax);
        w.flush();
        w.close();
      } catch (IOException ex) {
        LOG.fatal("Cannot read resource " + path, ex);
        throw new EXistException("I/O error on read of resource " + path, ex);
      } catch (SAXException saxe) {
        LOG.warn(saxe);
        throw new BadRequestException("Error while serializing XML: " + saxe.getMessage());
      }
      resultSequence.itemAt(0);
    } catch (XPathException ex) {
      throw new EXistException("Cannot execute xquery " + entryByIdSource.getURL(), ex);
    } finally {
      xquery.getXQueryPool().returnCompiledXQuery(entryByIdSource, feedQuery);
    }
  }

  public void getFeed(DBBroker broker, String path, OutgoingMessage response)
      throws EXistException, BadRequestException {
    XQuery xquery = broker.getXQueryService();
    CompiledXQuery feedQuery = xquery.getXQueryPool().borrowCompiledXQuery(broker, getFeedSource);

    XQueryContext context;
    if (feedQuery == null) {
      context = xquery.newContext(AccessContext.REST);
      try {
        feedQuery = xquery.compile(context, getFeedSource);
      } catch (XPathException ex) {
        throw new EXistException("Cannot compile xquery " + getFeedSource.getURL(), ex);
      } catch (IOException ex) {
        throw new EXistException(
            "I/O exception while compiling xquery " + getFeedSource.getURL(), ex);
      }
    } else {
      context = feedQuery.getContext();
    }
    context.setStaticallyKnownDocuments(
        new XmldbURI[] {XmldbURI.create(path).append(AtomProtocol.FEED_DOCUMENT_NAME)});

    try {
      Sequence resultSequence = xquery.execute(feedQuery, null);
      if (resultSequence.isEmpty()) {
        throw new BadRequestException("No feed was found.");
      }
      String charset = getContext().getDefaultCharset();
      response.setContentType("application/atom+xml; charset=" + charset);
      Serializer serializer = broker.getSerializer();
      serializer.reset();
      try {
        Writer w = new OutputStreamWriter(response.getOutputStream(), charset);
        SAXSerializer sax =
            (SAXSerializer) SerializerPool.getInstance().borrowObject(SAXSerializer.class);
        Properties outputProperties = new Properties();
        sax.setOutput(w, outputProperties);
        serializer.setProperties(outputProperties);
        serializer.setSAXHandlers(sax, sax);

        serializer.toSAX(resultSequence, 1, 1, false);

        SerializerPool.getInstance().returnObject(sax);
        w.flush();
        w.close();
      } catch (IOException ex) {
        LOG.fatal("Cannot read resource " + path, ex);
        throw new EXistException("I/O error on read of resource " + path, ex);
      } catch (SAXException saxe) {
        LOG.warn(saxe);
        throw new BadRequestException("Error while serializing XML: " + saxe.getMessage());
      }
      resultSequence.itemAt(0);
    } catch (XPathException ex) {
      throw new EXistException("Cannot execute xquery " + getFeedSource.getURL(), ex);
    } finally {
      xquery.getXQueryPool().returnCompiledXQuery(getFeedSource, feedQuery);
    }
  }
}
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    if (request.getCharacterEncoding() == null)
      try {
        request.setCharacterEncoding("UTF-8");
      } catch (final IllegalStateException e) {
      }
    // Try to find the XQuery
    final String qpath = getServletContext().getRealPath(query);
    final File f = new File(qpath);
    if (!(f.canRead() && f.isFile())) {
      throw new ServletException("Cannot read XQuery source from " + f.getAbsolutePath());
    }
    final FileSource source = new FileSource(f, "UTF-8", true);

    try {
      // Prepare and execute the XQuery
      final Collection collection =
          DatabaseManager.getCollection(collectionURI.toString(), user, password);
      final XQueryService service = (XQueryService) collection.getService("XQueryService", "1.0");
      if (!((CollectionImpl) collection).isRemoteCollection()) {
        service.declareVariable(
            RequestModule.PREFIX + ":request", new HttpRequestWrapper(request, "UTF-8", "UTF-8"));
        service.declareVariable(
            ResponseModule.PREFIX + ":response", new HttpResponseWrapper(response));
        service.declareVariable(
            SessionModule.PREFIX + ":session", new HttpSessionWrapper(request.getSession(false)));
      }
      final ResourceSet result = service.execute(source);

      String redirectTo = null;
      String servletName = null;
      String path = null;
      RequestWrapper modifiedRequest = null;
      // parse the query result element
      if (result.getSize() == 1) {
        final XMLResource resource = (XMLResource) result.getResource(0);
        Node node = resource.getContentAsDOM();
        if (node.getNodeType() == Node.DOCUMENT_NODE) {
          node = ((Document) node).getDocumentElement();
        }
        if (node.getNodeType() != Node.ELEMENT_NODE) {
          response.sendError(
              HttpServletResponse.SC_BAD_REQUEST,
              "Redirect XQuery should return an XML element. Received: " + resource.getContent());
          return;
        }
        Element elem = (Element) node;
        if (!(Namespaces.EXIST_NS.equals(elem.getNamespaceURI())
            && "dispatch".equals(elem.getLocalName()))) {
          response.sendError(
              HttpServletResponse.SC_BAD_REQUEST,
              "Redirect XQuery should return an element <exist:dispatch>. Received: "
                  + resource.getContent());
          return;
        }
        if (elem.hasAttribute("path")) {
          path = elem.getAttribute("path");
        } else if (elem.hasAttribute("servlet-name")) {
          servletName = elem.getAttribute("servlet-name");
        } else if (elem.hasAttribute("redirect")) {
          redirectTo = elem.getAttribute("redirect");
        } else {
          response.sendError(
              HttpServletResponse.SC_BAD_REQUEST,
              "Element <exist:dispatch> should either provide an attribute 'path' or 'servlet-name'. Received: "
                  + resource.getContent());
          return;
        }

        // Check for add-parameter elements etc.
        if (elem.hasChildNodes()) {
          node = elem.getFirstChild();
          while (node != null) {
            if (node.getNodeType() == Node.ELEMENT_NODE
                && Namespaces.EXIST_NS.equals(node.getNamespaceURI())) {
              elem = (Element) node;
              if ("add-parameter".equals(elem.getLocalName())) {
                if (modifiedRequest == null) {
                  modifiedRequest = new RequestWrapper(request);
                }
                modifiedRequest.addParameter(elem.getAttribute("name"), elem.getAttribute("value"));
              }
            }
            node = node.getNextSibling();
          }
        }
      }

      if (redirectTo != null) {
        // directly redirect to the specified URI
        response.sendRedirect(redirectTo);
        return;
      }

      // Get a RequestDispatcher, either from the servlet context or the request
      RequestDispatcher dispatcher;
      if (servletName != null && servletName.length() > 0) {
        dispatcher = getServletContext().getNamedDispatcher(servletName);
      } else {
        LOG.debug("Dispatching to " + path);
        dispatcher = getServletContext().getRequestDispatcher(path);
        if (dispatcher == null) {
          dispatcher = request.getRequestDispatcher(path);
        }
      }
      if (dispatcher == null) {
        response.sendError(
            HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
            "Could not create a request dispatcher. Giving up.");
        return;
      }

      if (modifiedRequest != null) {
        request = modifiedRequest;
      }
      // store the original request URI to org.exist.forward.request-uri
      request.setAttribute("org.exist.forward.request-uri", request.getRequestURI());
      request.setAttribute("org.exist.forward.servlet-path", request.getServletPath());

      // finally, execute the forward
      dispatcher.forward(request, response);
    } catch (final XMLDBException e) {
      throw new ServletException(
          "An error occurred while initializing RedirectorServlet: " + e.getMessage(), e);
    }
  }