public void addNodes(
     String navType, String navOwner, String nodePrefix, int startIndex, int endIndex) {
   if (startIndex < endIndex) {
     SiteKey key = new SiteKey(navType, navOwner);
     NavigationContext navCtx = navService.loadNavigation(key);
     if (navCtx == null) {
       LOG.error("Navigation type= " + navType + " , owner= " + navOwner + " does not exist");
     } else {
       NavNode rootNode =
           navService.loadNode(new NavNodeModel(), navCtx, Scope.CHILDREN, null).getNode();
       int index = rootNode.getSize();
       for (int i = startIndex; i < endIndex; i++) {
         String nodeName = nodePrefix + "_" + i;
         if (rootNode.getChild(nodeName) != null) {
           LOG.debug(
               "Navigation node named " + nodeName + " already exist, will not add it anymore");
         } else {
           rootNode.addChild(index, nodeName);
           index++;
         }
       }
       navService.saveNode(rootNode.context, null);
     }
   }
 }
  public void createNavigation(
      String type, String owner, String prefix, int startIndex, int endIndex) {
    if (startIndex < endIndex) {
      SiteKey key = new SiteKey(type, owner);
      NavigationContext navCtx = navService.loadNavigation(key);
      if (navCtx != null) {
        LOG.error("Navigation type= " + type + " , owner= " + owner + " already exists");
      } else {
        try {
          if (dataStorage.getPortalConfig(type, owner) == null) {
            dataStorage.create(new PortalConfig(type, owner));
          }
        } catch (Exception ex) {
          LOG.error("Error while load/create site ( type= " + type + " , owner = " + owner, ex);
        }

        navService.saveNavigation(new NavigationContext(key, new NavigationState(0)));
        navCtx = navService.loadNavigation(key);
        NavNode rootNode =
            navService.loadNode(new NavNodeModel(), navCtx, Scope.CHILDREN, null).getNode();
        for (int i = startIndex; i < endIndex; i++) {
          rootNode.addChild(i, prefix + "_" + i);
        }
        navService.saveNode(rootNode.context, null);
      }
    }
  }
  /**
   * The onInit() method is used to prepare the portal to receive requests.
   *
   * <p>1) Get the WebAppController component from the container 2) Create a new PortalApplication,
   * init it with the ServletConfig object (which contains init params) 3) Register that
   * PortalApplication inside WebAppController 4) Create a new PortalRequestHandler object and
   * register it in the WebAppController
   */
  private void onInit(ServletConfig sConfig, PortalContainer portalContainer) {
    // Keep the old ClassLoader
    final ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
    boolean hasChanged = false;
    try {
      ServletConfig config = new PortalServletConfig(sConfig, portalContainer);
      WebAppController controller =
          (WebAppController) portalContainer.getComponentInstanceOfType(WebAppController.class);
      // Set the full classloader of the portal container
      Thread.currentThread().setContextClassLoader(portalContainer.getPortalClassLoader());
      hasChanged = true;

      controller.onHandlersInit(config);
      log.info(
          "The WebAppController has been successfully initialized for the portal '"
              + portalContainer.getName()
              + "'");
    } catch (Throwable t) {
      log.error(
          "The WebAppController could not be initialized for the portal '"
              + portalContainer.getName()
              + "'",
          t);
    } finally {
      if (hasChanged) {
        // Re-set the old classloader
        Thread.currentThread().setContextClassLoader(currentClassLoader);
      }
    }
  }
  public void createNavigation(String type, String owner, List<String> children) {
    SiteKey key = new SiteKey(type, owner);
    NavigationContext navCtx = navService.loadNavigation(key);
    if (navCtx != null) {
      LOG.error("Navigation type= " + type + " , owner= " + owner + " already exists");
    } else {
      try {
        if (dataStorage.getPortalConfig(type, owner) == null) {
          dataStorage.create(new PortalConfig(type, owner));
        }
      } catch (Exception ex) {
        LOG.error("Error while load/create site ( type= " + type + " , owner = " + owner, ex);
      }

      navCtx = new NavigationContext(key, new NavigationState(0));
      NavNode rootNode =
          navService.loadNode(new NavNodeModel(), navCtx, Scope.CHILDREN, null).getNode();
      int index = 0;
      for (String child : children) {
        rootNode.addChild(index, child);
        index++;
      }
      navService.saveNode(rootNode.context, null);
    }
  }
  @Override
  public final void runBare() throws Throwable {
    // Patch a bug with maven that does not pass properly the system property
    // with an empty value
    if ("org.hsqldb.jdbcDriver".equals(System.getProperty("gatein.test.datasource.driver"))) {
      System.setProperty("gatein.test.datasource.password", "");
    }

    //
    log.info("Running unit test:" + getName());
    for (Map.Entry<?, ?> entry : System.getProperties().entrySet()) {
      if (entry.getKey() instanceof String) {
        String key = (String) entry.getKey();
        log.debug(key + "=" + entry.getValue());
      }
    }

    //
    beforeRunBare();

    //
    try {
      super.runBare();
      log.info("Unit test " + getName() + " completed");
    } catch (Throwable throwable) {
      log.error("Unit test " + getName() + " did not complete", throwable);

      //
      throw throwable;
    } finally {
      afterRunBare();
    }
  }
 @Managed
 @ManagedDescription("Delete node specified by path in existing navigation")
 @Impact(ImpactType.READ)
 public void deleteNode(
     @ManagedDescription("Type of target navigation") @ManagedName("navType") String navType,
     @ManagedDescription("Owner of target navigation") @ManagedName("navOwner") String navOwner,
     @ManagedDescription("Path from root to target node") @ManagedName("pathFromRoot")
         String pathFromRoot) {
   try {
     startTransaction();
     NavigationContext ctx = navService.loadNavigation(new SiteKey(navType, navOwner));
     if (ctx == null) {
       LOG.error("Navigation type= " + navType + " , owner= " + navOwner + " does not exist");
     } else {
       String[] path = pathFromRoot.split("/");
       NavNode rootNode =
           navService
               .loadNode(new NavNodeModel(), ctx, GenericScope.branchShape(path), null)
               .getNode();
       NavNode targetNode = rootNode.getDescendant(path);
       if (targetNode != null && targetNode != rootNode) {
         targetNode.remove();
       }
     }
   } finally {
     endTransaction();
   }
 }
  public Set<Portlet> getPortlets() throws PortletInvokerException {
    Set<Portlet> portlets = new HashSet<Portlet>(super.getPortlets());
    Registration registration = RegistrationLocal.getRegistration();

    if (registration != null) {
      Set<PortletContext> contexts = registration.getKnownPortletContexts();
      for (PortletContext context : contexts) {
        try {
          portlets.add(super.getPortlet(context));
        } catch (NoSuchPortletException e) {
          final RegistrationSPI registrationSPI = getRegistrationAsSPI();
          try {
            registrationSPI.removePortletContext(context);
            log.debug(
                "Removed '"
                    + context
                    + "' from Registration '"
                    + registration.getRegistrationHandle()
                    + "' because it cannot be resolved anymore.");
          } catch (RegistrationException e1) {
            throw new PortletInvokerException(e1);
          }
        }
      }
    }

    return portlets;
  }
  @Override
  public boolean hasNext() {
    while (next == null && toConsumeEvents.size() > 0) {
      WindowEvent toConsumeEvent = toConsumeEvents.removeFirst();
      String consumedId = toConsumeEvent.getWindowId();

      //
      PortletInfo consumerPortletInfo = context.getPortletInfo(consumedId);
      if (consumerPortletInfo == null) {
        log.trace(
            "Cannot deliver event "
                + toConsumeEvent
                + " because the consumer of the event does not have a portlet info");
        safeInvoker.eventDiscarded(
            context.getEventControllerContext(),
            this,
            toConsumeEvent,
            EventControllerContext.EVENT_CONSUMER_INFO_NOT_AVAILABLE);
        continue;
      }

      //
      if (!controller.getDistributeNonConsumableEvents()) {
        if (!consumerPortletInfo
            .getEventing()
            .getConsumedEvents()
            .containsKey(toConsumeEvent.getName())) {
          log.trace(
              "Cannot deliver event "
                  + toConsumeEvent
                  + " because the consumer of the event does not accept the event name");
          safeInvoker.eventDiscarded(
              context.getEventControllerContext(),
              this,
              toConsumeEvent,
              EventControllerContext.PORTLET_DOES_NOT_CONSUME_EVENT);
          continue;
        }
      }

      //
      next = toConsumeEvent;
    }

    //
    return next != null;
  }
  /**
   * Destroy the clones scoped by this Registration.
   *
   * @param registration the Registration about to be destroyed
   * @return
   */
  public Vote destructionScheduledFor(Registration registration) {
    if (registration != null) {
      List<PortletContext> portletContexts =
          new ArrayList<PortletContext>(registration.getKnownPortletContexts());
      List<DestroyCloneFailure> failures = Collections.emptyList();
      try {
        failures = super.destroyClones(portletContexts);
      } catch (Exception e) {
        if (log.isDebugEnabled()) {
          log.debug("Couldn't destroy clones", e);
        }
        return Vote.negativeVote("Couldn't destroy clones: " + failures);
      }
    }

    return RegistrationDestructionListener.SUCCESS;
  }
  public void processRender(WebuiRequestContext context) throws Exception {
    ResourceBundle res = context.getApplicationResourceBundle();
    UIForm uiForm = getAncestorOfType(UIForm.class);
    String formId = null;
    if (uiForm.getId().equals("UISearchForm")) formId = uiForm.<UIComponent>getParent().getId();
    else formId = uiForm.getId();

    Writer w = context.getWriter();
    w.write("<select class=\"selectbox\" name=\"");
    w.write(name);
    w.write("\"");
    if (onchange_ != null) {
      w.append(" onchange=\"").append(renderOnChangeEvent(uiForm)).append("\"");
    }

    if (isMultiple_) w.write(" multiple=\"true\"");
    if (size_ > 1) w.write(" size=\"" + size_ + "\"");

    if (isDisabled()) w.write(" disabled ");

    renderHTMLAttributes(w);

    w.write(">\n");

    for (SelectItem item : options_) {
      String label = item.getLabel();
      if (item instanceof SelectOption) {
        try {
          label = res.getString(formId + ".label.option." + ((SelectOption) item).getValue());
        } catch (MissingResourceException ex) {
        }

        w.write(renderOption(((SelectOption) item), label));

      } else if (item instanceof SelectOptionGroup) {
        label = item.getLabel();
        try {
          label = res.getString(getFrom().getId() + ".optionGroup.label." + label);
        } catch (MissingResourceException ex) {
          log.debug("Could not find: " + getFrom().getId() + ".optionGroup.label." + label);
        }
        w.write("<optgroup label=\"");
        w.write(label);
        w.write("\">\n");
        for (SelectOption opt : ((SelectOptionGroup) item).getOptions()) {
          label = opt.getLabel();
          try {
            label = res.getString(formId + ".label.option." + opt.getValue());
          } catch (MissingResourceException ex) {
          }
          w.write(renderOption(opt, label));
        }
        w.write("</optgroup>\n");
      }
    }
    w.write("</select>\n");
    if (this.isMandatory()) w.write(" *");
  }
  /**
   * Called on web application add event if the application contains {@value
   * #GATEIN_CONFIG_RESOURCE} file.
   *
   * @param webApp
   * @param url
   */
  protected void add(final WebApp webApp, final URL url) {

    ServletContext scontext = webApp.getServletContext();
    try {
      /* Validate straight away here before creating the PortalContainerPostInitTask */
      final Document document = GateInResourcesSchemaValidator.validate(url);
      /* Also parse both js and skin resources before creating the PortalContainerPostInitTask */
      final ScriptResources scriptResources =
          new JavascriptConfigParser(scontext, document).parse();
      final List<SkinConfigTask> skinTasks = SkinConfigParser.parse(document);

      /* No exceptions at this point */
      final PortalContainerPostInitTask task =
          new PortalContainerPostInitTask() {
            public void execute(ServletContext scontext, PortalContainer portalContainer) {

              try {

                if (!scriptResources.isEmpty()) {
                  javascriptConfigService.add(scriptResources);
                  scontext.setAttribute(SCRIPT_RESOURCES_ATTR, scriptResources.toImmutable());
                }
                javascriptConfigService.registerContext(webApp);

                if (skinTasks != null && !skinTasks.isEmpty()) {
                  skinService.addSkins(skinTasks, scontext);
                }
                skinService.registerContext(webApp);

              } catch (Exception e) {
                log.error(
                    "Could not register script and skin resources from the context '"
                        + (scontext == null ? "unknown" : scontext.getServletContextName())
                        + "'",
                    e);

                /* try to cleanup if anything went wrong */
                try {
                  remove(webApp);
                } catch (Exception e1) {
                  log.error(
                      "Could not cleanup script and skin resources from the context '"
                          + (scontext == null ? "unknown" : scontext.getServletContextName())
                          + "' after a registration failure",
                      e);
                }
              }
            }
          };
      PortalContainer.addInitTask(scontext, task, portalContainerName);
    } catch (Exception ex) {
      log.error(
          "Could not parse or validate gatein-resources.xml in context '"
              + (scontext == null ? "unknown" : scontext.getServletContextName())
              + "'",
          ex);
    }
  }
Exemple #12
0
  public void validateTicket(HttpServletRequest httpRequest, String ticket) throws Exception {
    Cas20ProxyTicketValidator ticketValidator = new Cas20ProxyTicketValidator(casServerUrl);
    ticketValidator.setRenew(this.renewTicket);

    // String serviceUrl = "http://"+ httpRequest.getServerName() +":" + httpRequest.getServerPort()
    // +
    // httpRequest.getContextPath() +"/private/classic";
    Assertion assertion = ticketValidator.validate(ticket, this.casServiceUrl);

    log.debug(
        "------------------------------------------------------------------------------------");
    log.debug("Service: " + this.casServiceUrl);
    log.debug("Principal: " + assertion.getPrincipal().getName());
    log.debug(
        "------------------------------------------------------------------------------------");

    String principal = assertion.getPrincipal().getName();
    this.saveSSOCredentials(principal, httpRequest);
  }
 /**
  * @param navType
  * @param navOwner
  * @param absolutePath path from root to targeted node
  * @param nodePrefix
  * @param startIndex
  * @param endIndex
  */
 public void addNodes(
     String navType,
     String navOwner,
     String absolutePath,
     String nodePrefix,
     int startIndex,
     int endIndex) {
   SiteKey key = new SiteKey(navType, navOwner);
   NavigationContext navCtx = navService.loadNavigation(key);
   if (navCtx == null) {
     LOG.error("Navigation type= " + navType + " , owner= " + navOwner + " does not exist");
   } else {
     String[] path = absolutePath.split("/");
     NavNode rootNode =
         navService
             .loadNode(new NavNodeModel(), navCtx, GenericScope.branchShape(path), null)
             .getNode();
     NavNode targetNode = rootNode.getDescendant(path);
     if (targetNode == null) {
       LOG.error(
           "Could not find node specified by path "
               + absolutePath
               + " under navigation type= "
               + navType
               + " , owner= "
               + navOwner);
     } else {
       int index = targetNode.getSize();
       for (int i = startIndex; i < endIndex; i++) {
         String nodeName = nodePrefix + "_" + i;
         if (targetNode.getChild(nodeName) == null) {
           targetNode.addChild(index, nodeName);
           index++;
         }
       }
       navService.saveNode(targetNode.context, null);
     }
   }
 }
  public void addPlugin(ComponentPlugin plugin) {
    if (plugin instanceof SSOFilterIntegratorPlugin) {
      SSOFilterIntegratorPlugin ssoPlugin = (SSOFilterIntegratorPlugin) plugin;

      if (!ssoPlugin.isEnabled()) {
        return;
      }

      SSOInterceptor ssoInterceptor = ssoPlugin.getFilter();
      this.ssoInterceptors.put(ssoInterceptor, ssoPlugin.getFilterMapping());

      log.debug("Added new SSOInterceptor " + ssoInterceptor);
    }
  }
  static {
    // Detecting version from maven properties
    // empty value is ok
    String version = "";
    URL url = ResourceRequestHandler.class.getClassLoader().getResource(PATH);
    if (url != null) {
      log.debug("Loading resource serving version from " + url);
      InputStream in = null;
      try {
        in = url.openStream();
        Properties props = new Properties();
        props.load(in);
        version = props.getProperty("version");
      } catch (IOException e) {
        log.error("Could not read properties from " + url, e);
      } finally {
        IOTools.safeClose(in);
      }
    }

    //
    log.info("Use version \"" + version + "\" for resource serving");
    VERSION = version;
  }
  /**
   * Called on web application remove event if the application contains {@value
   * #GATEIN_CONFIG_RESOURCE} file.
   *
   * @param webApp
   */
  protected void remove(WebApp webApp) {
    String contextPath = webApp.getServletContext().getContextPath();
    javascriptConfigService.unregisterServletContext(webApp);
    try {
      javascriptConfigService.remove(contextPath);
    } catch (Exception ex) {
      log.error(
          "An error occurred while removing script resources for the context '"
              + webApp.getServletContext().getServletContextName()
              + "'",
          ex);
    }

    try {
      skinService.removeSkins(SkinDependentManager.getPortalSkins(contextPath));
      skinService.removeSkins(SkinDependentManager.getPortletSkins(contextPath));

      /*
       * Remove skinName defined by the webApp, if no other webApps supports the skinName
       */
      Set<String> supportedSkins = SkinDependentManager.getSkinNames(contextPath);
      if (supportedSkins != null) {
        for (String skin : supportedSkins) {
          if (SkinDependentManager.skinNameIsRemovable(skin, contextPath)) {
            skinService.removeSupportedSkin(skin);
          }
        }
      }

      // Update the 'skinDependentManager'
      SkinDependentManager.clearAssociatedSkins(contextPath);
    } catch (Exception e) {
      log.error(e.getMessage(), e);
    }
    skinService.unregisterServletContext(webApp);
  }
 @Managed
 @ManagedDescription("Add nodes into root node of existing navigation")
 @Impact(ImpactType.READ)
 public void insertNodes(
     @ManagedDescription("Type of target navigation") @ManagedName("navType") String navType,
     @ManagedDescription("Owner of target navigation") @ManagedName("navOwner") String navOwner,
     @ManagedDescription("Prefix of new node names") @ManagedName("prefix") String nodePrefix,
     @ManagedDescription("Starting index") @ManagedName("startIndex") String startIndex,
     @ManagedDescription("Ending index") @ManagedName("endIndex") String endIndex) {
   int _startIndex = Integer.parseInt(startIndex);
   int _endIndex = Integer.parseInt(endIndex);
   // Invoke from JMX bean will not go through GateIn's servlet filter. Therefore, we need to
   // open/close transaction
   try {
     startTransaction();
     addNodes(navType, navOwner, nodePrefix, _startIndex, _endIndex);
   } catch (Exception ex) {
     LOG.error("Failed to insert new nodes", ex);
   } finally {
     endTransaction();
   }
 }
 @Managed
 @ManagedDescription("Create new navigation")
 @Impact(ImpactType.READ)
 public void createNavs(
     @ManagedDescription("Type of new navigation") @ManagedName("navType") String type,
     @ManagedDescription("Owner of new navigation") @ManagedName("navOwner") String owner,
     @ManagedDescription("Prefix of new node names") @ManagedName("prefix") String prefix,
     @ManagedDescription("Starting index") @ManagedName("startIndex") String startIndex,
     @ManagedDescription("Ending index") @ManagedName("endIndex") String endIndex) {
   int _startIndex = Integer.parseInt(startIndex);
   int _endIndex = Integer.parseInt(endIndex);
   // Invoke from JMX bean will not go through GateIn's servlet filter. Therefore, we need to
   // open/close transaction
   try {
     startTransaction();
     createNavigation(type, owner, prefix, _startIndex, _endIndex);
   } catch (Exception ex) {
     LOG.error("Failed to create new navigation", ex);
   } finally {
     endTransaction();
   }
 }
Exemple #19
0
  public void doImport() {
    if (portalContainer == null) {
      portalContainer = Utils.getUserInput("Container name (ie portal)", level);
    }

    try {
      client =
          PortalObjectsMgmtClient.Factory.create(
              InetAddress.getByName(host), port, username, password, portalContainer);
    } catch (UnknownHostException e) {
      System.err.println("Unknown host name " + host + ". See log for more details.");
      log.error("Exception retrieving host " + host + " by name.", e);
      System.exit(1);
    }

    if (overwrite == null) {
      String ow =
          Utils.getUserInput(
              "Do you wish to fully overwrite all data defined in import file (N) ? Y/N", level);
      if ("Y".equalsIgnoreCase(ow)) {
        overwrite = Boolean.TRUE;
      } else {
        overwrite = Boolean.FALSE;
      }
    }

    if (overwrite && !force) {
      System.out.println(
          "\nOverwrite set to true. This means that all data for a site will be overwritten and any data not defined will be deleted.");
      String proceed = Utils.getUserInput("Do you wish to proceed (N) ? Y/N", level);
      if (!"Y".equalsIgnoreCase(proceed)) {
        System.exit(0);
      }
    }

    log.info("Starting import of file " + importFile + " for portal container " + portalContainer);
    try {
      ImportContext context = client.importFromZip(importFile);
      if (isEmptyContext(context)) {
        System.out.println(
            "Nothing to import. " + importFile + " did not contain anything to import.");
        log.warn("Nothing imported. Zip file did not contain any data for import.");
        System.exit(0);
      }

      if (overwrite) {
        log.info("Overwrite set to true, overwriting all data.");
      }
      context.setOverwrite(overwrite);
      client.importContext(context);
      log.info("Import was successful.");
    } catch (IOException e) {
      System.err.println("Exception reading zip file. See log for more details.");
      log.error("IOException reading zip file " + importFile, e);
    } catch (ClientException e) {
      System.err.println("Client exception during import. See log for more details.");
      log.error("ClientException during import.", e);
    } catch (Throwable t) {
      System.err.println("Unknown exception occurred during import.  See log for more details.");
      log.error("Uknown exception during import.", t);
    }
  }
  boolean push(WindowEvent consumedEvent, WindowEvent producedEvent) {
    String producerId = producedEvent.getWindowId();
    PortletInfo producerPortletInfo = context.getPortletInfo(producerId);

    //
    if (producerPortletInfo == null) {
      log.trace(
          "Cannot deliver event "
              + producedEvent
              + " because the producer does not have portlet info");
      safeInvoker.eventDiscarded(
          context.getEventControllerContext(),
          this,
          producedEvent,
          EventControllerContext.EVENT_PRODUCER_INFO_NOT_AVAILABLE);
      return true;
    } else {
      //
      if (!controller.getDistributeNonProduceableEvents()) {
        if (!producerPortletInfo
            .getEventing()
            .getProducedEvents()
            .containsKey(producedEvent.getName())) {
          log.trace(
              "Cannot deliver event "
                  + producedEvent
                  + " because the producer of the event does not produce the event name");
          safeInvoker.eventDiscarded(
              context.getEventControllerContext(),
              this,
              producedEvent,
              EventControllerContext.PORTLET_DOES_NOT_CONSUME_EVENT);
          return true;
        }
      }

      // Apply produced event quota if necessary
      int producedEventThreshold = controller.getProducedEventThreshold();
      if (producedEventThreshold >= 0) {
        if (producedEventSize + 1 > producedEventThreshold) {
          log.trace(
              "Event distribution interrupted because the maximum number of produced event is reached");
          safeInvoker.eventDiscarded(
              context.getEventControllerContext(),
              this,
              producedEvent,
              EventControllerContext.PRODUCED_EVENT_FLOODED);
          return false;
        }
      }

      //
      Iterable<WindowEvent> toConsume =
          safeInvoker.eventProduced(
              context.getEventControllerContext(), this, consumedEvent, producedEvent);

      //
      if (toConsume == null) {
        return false;
      } else {
        producedEventSize++;
        for (WindowEvent event : toConsume) {
          toConsumeEvents.add(event);
        }
        return true;
      }
    }
  }
  @Override
  public boolean execute(ControllerContext context) throws Exception {
    String resourceParam = context.getParameter(RESOURCE_QN);
    String scopeParam = context.getParameter(SCOPE_QN);

    //
    if (scopeParam != null && resourceParam != null) {
      String compressParam = context.getParameter(COMPRESS_QN);
      String lang = context.getParameter(LANG_QN);
      String moduleParam = context.getParameter(MODULE_QN);

      //
      Locale locale = null;
      if (lang != null && lang.length() > 0) {
        locale = I18N.parseTagIdentifier(lang);
      }

      //
      ResourceScope scope;
      try {
        scope = ResourceScope.valueOf(ResourceScope.class, scopeParam);
      } catch (IllegalArgumentException e) {
        HttpServletResponse response = context.getResponse();
        String msg = "Unrecognized scope " + scopeParam;
        log.error(msg);
        response.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
        return true;
      }

      //
      ResourceId resource = new ResourceId(scope, resourceParam);

      ScriptKey key = new ScriptKey(resource, moduleParam, "min".equals(compressParam), locale);

      //
      ScriptResult result = cache.get(context, key);
      HttpServletResponse response = context.getResponse();
      HttpServletRequest request = context.getRequest();

      //
      if (result instanceof ScriptResult.Resolved) {
        ScriptResult.Resolved resolved = (ScriptResult.Resolved) result;

        // Content type + charset
        response.setContentType("text/javascript");
        response.setCharacterEncoding("UTF-8");

        // One hour caching
        // make this configurable later
        response.setHeader("Cache-Control", "max-age:3600");
        response.setDateHeader("Expires", System.currentTimeMillis() + 3600 * 1000);

        // Set content length
        response.setContentLength(resolved.bytes.length);

        long ifModifiedSince = request.getDateHeader(IF_MODIFIED_SINCE);
        if (resolved.isModified(ifModifiedSince)) {
          response.setDateHeader(ResourceRequestFilter.LAST_MODIFIED, resolved.lastModified);
          // Send bytes
          ServletOutputStream out = response.getOutputStream();
          try {
            out.write(resolved.bytes);
          } finally {
            Safe.close(out);
          }
        } else {
          response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        }
      } else if (result instanceof ScriptResult.Error) {
        ScriptResult.Error error = (ScriptResult.Error) result;
        log.error("Could not render script " + key + "\n:" + error.message);
        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      } else {
        String msg = "Resource " + key + " cannot be found";
        log.error(msg);
        response.sendError(HttpServletResponse.SC_NOT_FOUND, msg);
      }
    } else {
      HttpServletResponse response = context.getResponse();
      String msg = "Missing scope or resource param";
      log.error(msg);
      response.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
    }

    //
    return true;
  }