@Override
  public TextTag getRequestedBean(
      HttpServletRequest req,
      HttpServletResponse res,
      User user,
      URIParser uriParser,
      String getMode)
      throws SQLException, AccessDeniedException {

    String beanID = null;

    if (uriParser.size() > 2 && (beanID = uriParser.get(2)) != null) {

      return crudDAO.get(beanID);
    }

    return null;
  }
  private String getFilePath(URIParser uriParser, int startIndex) {

    // Parse & build requested file path
    if (uriParser.size() > (startIndex + 1)) {

      StringBuilder stringBuilder = new StringBuilder();

      for (int i = startIndex + 1; i < uriParser.size(); i++) {
        stringBuilder.append("/" + uriParser.get(i));
      }

      return stringBuilder.toString();

    } else {

      return "/" + uriParser.get(startIndex);
    }
  }
  @Override
  protected List<Breadcrumb> getUpdateBreadcrumbs(
      SimpleDataSourceDescriptor bean, HttpServletRequest req, User user, URIParser uriParser) {

    return CollectionUtils.getList(
        this.callback.getDefaultBreadcrumb(),
        new Breadcrumb(
            callback.getUpdateDataSourceBreadcrumbText() + bean.getName(),
            callback.getUpdateDataSourceBreadcrumbText() + bean.getName(),
            uriParser.getFormattedURI(),
            URLType.RELATIVE_FROM_CONTEXTPATH));
  }
  @Override
  protected List<Breadcrumb> getAddBreadcrumbs(
      HttpServletRequest req, User user, URIParser uriParser) {

    return CollectionUtils.getList(
        this.callback.getDefaultBreadcrumb(),
        new Breadcrumb(
            callback.getAddDataSourceBreadcrumbText(),
            callback.getAddDataSourceBreadcrumbText(),
            uriParser.getFormattedURI(),
            URLType.RELATIVE_FROM_CONTEXTPATH));
  }
  private void sendFile(
      HttpServletRequest req,
      HttpServletResponse res,
      URIParser uriParser,
      URL url,
      InputStream fileStream,
      User user,
      String staticContentPackage,
      String filePath,
      ModuleDescriptor moduleDescriptor,
      String moduletype) {

    OutputStream outstream = null;

    try {
      Date lastModified = this.getLastModified(url, uriParser);

      if (lastModified != null) {

        String lastModifiedString = RFC1123_DATE_FORMATTER.format(lastModified);

        String modifiedSinceString = req.getHeader("If-Modified-Since");

        if (modifiedSinceString != null
            && lastModifiedString.equalsIgnoreCase(modifiedSinceString)) {

          res.setStatus(304);
          res.flushBuffer();

          return;
        }

        res.setHeader("Last-Modified", lastModifiedString);
      }

      // Set content type, filename
      String filename = FileUtils.toValidHttpFilename(uriParser.get(uriParser.size() - 1));

      res.setStatus(200);
      res.setHeader("Content-Disposition", "inline; filename=\"" + filename + "\"");

      String contentType = MimeUtils.getMimeType(filename);

      if (contentType != null) {
        res.setContentType(contentType);
      } else {
        res.setContentType("application/x-unknown-mime-type");
      }

      outstream = res.getOutputStream();

      StreamUtils.transfer(fileStream, outstream);

      if (log.isDebugEnabled()) {

        if (moduleDescriptor != null) {

          log.debug(
              "Sent file "
                  + staticContentPackage
                  + filePath
                  + " from "
                  + moduletype
                  + " "
                  + moduleDescriptor
                  + " to user "
                  + user);

        } else {

          log.debug(
              "Sent file "
                  + staticContentPackage
                  + filePath
                  + " from global content links to user "
                  + user);
        }
      }

    } catch (IOException e) {

      if (log.isDebugEnabled()) {

        if (moduleDescriptor != null) {

          log.info(
              "Error sending file "
                  + staticContentPackage
                  + filePath
                  + " from "
                  + moduletype
                  + " "
                  + moduleDescriptor
                  + " to user "
                  + user
                  + ", "
                  + e);

        } else {

          log.info(
              "Error sending file "
                  + staticContentPackage
                  + filePath
                  + " from global content links to user "
                  + user
                  + ", "
                  + e);
        }
      }

    } finally {
      try {
        StreamUtils.closeStream(fileStream);
      } catch (NullPointerException e) {
        // Workaround for JVM bug http://bugs.java.com/bugdatabase/view_bug.do?bug_id=5041014
        // (Windows only)
      }
      StreamUtils.closeStream(outstream);
    }
  }
  @Override
  public SimpleForegroundModuleResponse processRequest(
      HttpServletRequest req, HttpServletResponse res, User user, URIParser uriParser)
      throws AccessDeniedException, URINotFoundException {

    // TODO add support to separate numeric foreground module aliases from moduleID's (fv prefix?)
    // TODO add support to separate background module hashcodes from moduleID's (bv prefix?)

    Integer sectionID;

    if (uriParser.size() >= 3 && uriParser.get(1).equals("global")) {

      if (!enableGlobalContentLinks) {

        throw new AccessDeniedException("Global content links are disabled");
      }

      Properties globalContentLinks = this.globalContentLinks;

      if (globalContentLinks == null) {

        throw new URINotFoundException(uriParser);
      }

      if (!globalContentLinks.isEmpty()) {

        String filePath = getFilePath(uriParser, 1);

        for (Entry<Object, Object> linkEntry : globalContentLinks.entrySet()) {

          if (filePath.startsWith(linkEntry.getKey().toString())) {

            URL linkedURL = this.getClass().getResource(linkEntry.getValue() + filePath);

            if (linkedURL != null) {

              try {
                InputStream fileStream = linkedURL.openStream();

                if (fileStream != null) {

                  this.sendFile(
                      req,
                      res,
                      uriParser,
                      linkedURL,
                      fileStream,
                      user,
                      linkEntry.getValue().toString(),
                      filePath,
                      null,
                      null);

                  return null;
                }
              } catch (IOException e) {
                log.error(
                    "Unable to load file from url "
                        + linkedURL
                        + " belonging to global content links",
                    e);
              }
            }
          }
        }
      }

    } else if (uriParser.size() >= 5
        && (uriParser.get(1).equals("f") || uriParser.get(1).equals("b"))
        && !uriParser.getFormattedURI().contains("..")
        && (sectionID = NumberUtils.toInt(uriParser.get(2))) != null) {

      // Get the requested section
      SectionInterface sectionInterface = systemInterface.getSectionInterface(sectionID);

      if (sectionInterface == null) {

        // The requested section is not started or does not exist
        throw new AccessDeniedException(
            "The requested section ID was not found in cache (URI: "
                + uriParser.getFormattedURI()
                + ")");

      } else if (!AccessUtils.checkAccess(user, sectionInterface.getSectionDescriptor())) {

        // The user does not have access to the requested section
        throw new AccessDeniedException(
            "User does not have access to section "
                + sectionInterface.getSectionDescriptor()
                + " (URI: "
                + uriParser.getFormattedURI()
                + ")");
      }

      // Check that the user has access to all parent section
      SectionInterface parentSection = sectionInterface.getParentSectionInterface();

      while (parentSection != null) {

        if (!AccessUtils.checkAccess(user, parentSection.getSectionDescriptor())) {

          // User does not have access to a parent section
          throw new AccessDeniedException(
              "User does not have access to section "
                  + sectionInterface.getSectionDescriptor()
                  + " (URI: "
                  + uriParser.getFormattedURI()
                  + ")");
        }

        parentSection = parentSection.getParentSectionInterface();
      }

      boolean foreground = uriParser.get(1).equals("f");

      String moduletype;

      if (foreground) {

        moduletype = "foreground module";

      } else {

        moduletype = "background module";
      }

      Integer moduleID = NumberUtils.toInt(uriParser.get(3));

      // Get the requested module
      Entry<? extends VisibleModuleDescriptor, ? extends Module<?>> moduleEntry = null;

      if (moduleID != null) {

        if (foreground) {

          moduleEntry = sectionInterface.getForegroundModuleCache().getEntry(moduleID);

        } else {

          moduleEntry = sectionInterface.getBackgroundModuleCache().getEntry(moduleID);
        }
      }

      if (moduleEntry == null) {

        if (foreground) {

          String alias = uriParser.get(3);

          moduleEntry = sectionInterface.getForegroundModuleCache().getEntry(alias);

        } else if (moduleID != null) {

          moduleEntry = sectionInterface.getBackgroundModuleCache().getEntryByHashCode(moduleID);
        }
      }

      if (moduleEntry != null) {

        VisibleModuleDescriptor moduleDescriptor = moduleEntry.getKey();

        // Check if the user has access to this module
        if (AccessUtils.checkAccess(user, moduleDescriptor)) {

          // Check that the module has a static content directory set
          if (!StringUtils.isEmpty(moduleDescriptor.getStaticContentPackage())) {

            // Check that the requested file exists in the specified classpath directory

            String filePath = getFilePath(uriParser, 3);

            URL url =
                moduleEntry
                    .getValue()
                    .getClass()
                    .getResource(moduleDescriptor.getStaticContentPackage() + filePath);

            InputStream fileStream = null;

            if (url != null) {

              try {
                fileStream = url.openStream();
              } catch (IOException e) {
              }
            }

            if (fileStream != null) {

              log.debug(
                  "Sending file "
                      + moduleDescriptor.getStaticContentPackage()
                      + filePath
                      + " from "
                      + moduletype
                      + " "
                      + moduleDescriptor
                      + " reqested using URI "
                      + uriParser.getFormattedURI()
                      + " to user "
                      + user);

              this.sendFile(
                  req,
                  res,
                  uriParser,
                  url,
                  fileStream,
                  user,
                  moduleDescriptor.getStaticContentPackage(),
                  filePath,
                  moduleDescriptor,
                  moduletype);

              return null;

            } else if ((fileStream =
                    moduleEntry
                        .getValue()
                        .getClass()
                        .getResourceAsStream(
                            moduleDescriptor.getStaticContentPackage()
                                + "/StaticContentLinks.properties"))
                != null) {

              Properties links = new Properties();

              try {
                links.load(fileStream);

              } catch (IOException e) {
                log.error(
                    "Unable to load static content links belonging to "
                        + moduletype
                        + " "
                        + moduleDescriptor,
                    e);
              } finally {
                StreamUtils.closeStream(fileStream);
              }

              if (!links.isEmpty()) {

                for (Entry<Object, Object> linkEntry : links.entrySet()) {

                  if (filePath.startsWith(linkEntry.getKey().toString())) {

                    URL linkedURL =
                        moduleEntry
                            .getValue()
                            .getClass()
                            .getResource(linkEntry.getValue() + filePath);

                    if (linkedURL != null) {

                      try {
                        fileStream = linkedURL.openStream();

                        if (fileStream != null) {

                          this.sendFile(
                              req,
                              res,
                              uriParser,
                              linkedURL,
                              fileStream,
                              user,
                              linkEntry.getValue().toString(),
                              filePath,
                              moduleDescriptor,
                              moduletype);

                          return null;
                        }

                      } catch (IOException e) {
                        log.error(
                            "Unable to load file from url "
                                + linkedURL
                                + " belonging to "
                                + moduletype
                                + " "
                                + moduleDescriptor,
                            e);
                      }
                    }
                  }
                }
              }

            } else {
              log.info(
                  "File "
                      + uriParser.getFormattedURI()
                      + " requested from "
                      + moduletype
                      + " "
                      + moduleDescriptor
                      + " by user "
                      + user
                      + " not found");
            }

          } else {
            log.info(
                "User "
                    + user
                    + " requested static content from "
                    + moduletype
                    + " "
                    + moduleDescriptor
                    + " which has no static content package set, using URI "
                    + uriParser.getFormattedURI());
          }
        } else {
          throw new AccessDeniedException(
              "User does not have access to "
                  + moduletype
                  + " "
                  + moduleEntry.getKey()
                  + " (URI: "
                  + uriParser.getFormattedURI()
                  + ")");
        }
      } else {
        log.info(
            "Invalid sectionID or moduleID in URI "
                + uriParser.getFormattedURI()
                + " requested by user "
                + user);
      }
    } else {
      log.info("Invalid URI " + uriParser.getFormattedURI() + " requested by user " + user);
    }

    throw new URINotFoundException(uriParser);
  }