@Override
  public void write(T value, Map<String, Object> componentAttributes, Appendable out)
      throws IOException {
    try {

      AuraContext context = Aura.getContextService().getCurrentContext();
      InstanceService instanceService = Aura.getInstanceService();
      RenderingService renderingService = Aura.getRenderingService();
      BaseComponentDef def = value.getDescriptor().getDef();

      ComponentDef templateDef = def.getTemplateDef();
      Map<String, Object> attributes = Maps.newHashMap();

      StringBuilder sb = new StringBuilder();
      writeHtmlStyles(new ArrayList<>(Arrays.asList(Aura.getConfigAdapter().getResetCssURL())), sb);
      attributes.put("auraResetCss", sb.toString());
      sb.setLength(0);
      writeHtmlStyles(AuraServlet.getStyles(), sb);
      attributes.put("auraStyleTags", sb.toString());
      sb.setLength(0);
      writeHtmlScripts(AuraServlet.getScripts(), sb);
      DefDescriptor<StyleDef> styleDefDesc = templateDef.getStyleDescriptor();
      if (styleDefDesc != null) {
        attributes.put("auraInlineStyle", styleDefDesc.getDef().getCode());
      }

      String contextPath = context.getContextPath();
      Mode mode = context.getMode();

      if (mode.allowLocalRendering() && def.isLocallyRenderable()) {
        BaseComponent<?, ?> cmp =
            (BaseComponent<?, ?>) instanceService.getInstance(def, componentAttributes);

        attributes.put("body", Lists.<BaseComponent<?, ?>>newArrayList(cmp));
        attributes.put("bodyClass", "");
        attributes.put("autoInitialize", "false");

        Component template = instanceService.getInstance(templateDef.getDescriptor(), attributes);

        renderingService.render(template, out);
      } else {

        attributes.put("auraScriptTags", sb.toString());
        Map<String, Object> auraInit = Maps.newHashMap();
        if (componentAttributes != null && !componentAttributes.isEmpty()) {
          auraInit.put("attributes", componentAttributes);
        }
        auraInit.put("descriptor", def.getDescriptor());
        auraInit.put("deftype", def.getDescriptor().getDefType());
        auraInit.put("host", contextPath);

        attributes.put("autoInitialize", "false");
        attributes.put("autoInitializeSync", "true");

        auraInit.put("instance", value);
        auraInit.put("token", AuraBaseServlet.getToken());

        StringBuilder contextWriter = new StringBuilder();
        Aura.getSerializationService()
            .write(context, null, AuraContext.class, contextWriter, "JSON");
        auraInit.put("context", new Literal(contextWriter.toString()));

        attributes.put("auraInitSync", JsonEncoder.serialize(auraInit));

        Component template = instanceService.getInstance(templateDef.getDescriptor(), attributes);
        renderingService.render(template, out);
      }
    } catch (QuickFixException e) {
      throw new AuraRuntimeException(e);
    }
  }
Example #2
0
  /**
   * Write out the manifest.
   *
   * <p>This writes out the full manifest for an application so that we can use the AppCache.
   *
   * <p>The manifest contains CSS and JavaScript URLs. These specified resources are copied into the
   * AppCache with the HTML template. When the page is reloaded, the existing manifest is compared
   * to the new manifest. If they are identical, the resources are served from the AppCache.
   * Otherwise, the resources are requested from the server and the AppCache is updated.
   *
   * @param request the request
   * @param response the response
   * @param context the context
   * @throws IOException if unable to write out the response
   */
  @Override
  public void write(HttpServletRequest request, HttpServletResponse response, AuraContext context)
      throws IOException {
    servletUtilAdapter.setNoCache(response);
    try {
      Map<String, Object> attributes = getComponentAttributes(request);
      //
      // First, we make sure that the manifest is enabled.
      //
      if (!manifestUtil.isManifestEnabled(request)) {
        response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        return;
      }
      //
      // Now we validate the cookie, which includes loop detection.
      // this routine sets the response code.
      //
      if (!manifestUtil.checkManifestCookie(request, response)) {
        return;
      }

      boolean appOk = false;

      DefDescriptor<? extends BaseComponentDef> descr = null;
      try {
        descr = context.getApplicationDescriptor();

        if (descr != null) {
          definitionService.updateLoaded(descr);
          appOk = true;
        }
      } catch (QuickFixException qfe) {
        //
        // ignore qfe, since we really don't care... the manifest will be 404ed.
        // This will eventually cause the browser to give up. Note that this case
        // should almost never occur, as it requires the qfe to be introduced between
        // the initial request (which will not set a manifest if it gets a qfe) and
        // the manifest request.
        //
      } catch (ClientOutOfSyncException coose) {
        //
        // In this case, we want to force a reload... A 404 on the manifest is
        // supposed to handle this. we hope that the client will do the right
        // thing, and reload everything. Note that this case really should only
        // happen if the client already has content, and thus should be refreshing
        // However, there are very odd edge cases that we probably can't detect
        // without keeping server side state, such as the case that something
        // is updated between the initial HTML request and the manifest request.
        // Not sure what browsers will do in this case.
        //
      }

      if (!appOk) {
        response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        return;
      }

      //
      // This writes both the app and framework signatures into
      // the manifest, so that if either one changes, the
      // manifest will change. Note that in most cases, we will
      // write these signatures in multiple places, but we just
      // need to make sure that they are in at least one place.
      //
      Map<String, Object> attribs = Maps.newHashMap();
      String appUid = getContextAppUid(context);
      String nonce = configAdapter.getAuraFrameworkNonce();
      // Since we don't get the UID from our URL, we set it here.
      context.setFrameworkUID(nonce);
      attribs.put(LAST_MOD, String.format("app=%s, FW=%s", appUid, nonce));
      attribs.put(UID, appUid);
      StringWriter sw = new StringWriter();

      String resetCssUrl = configAdapter.getResetCssURL();
      if (resetCssUrl != null) {
        sw.write(resetCssUrl);
        sw.write('\n');
      }

      for (String s : servletUtilAdapter.getStyles(context)) {
        sw.write(s);
        sw.write('\n');
      }

      for (String s : servletUtilAdapter.getScripts(context, true, true, attributes)) {
        sw.write(s);
        sw.write('\n');
      }

      // Add locker service safe eval worker url
      String lockerWorkerURL = configAdapter.getLockerWorkerURL();
      if (lockerWorkerURL != null) {
        sw.write(lockerWorkerURL);
        sw.write('\n');
      }

      // Add in any application specific resources
      if (descr != null && descr.getDefType().equals(DefType.APPLICATION)) {
        ApplicationDef def = (ApplicationDef) descr.getDef();
        for (String s : def.getAdditionalAppCacheURLs()) {
          if (s != null) {
            sw.write(s);
            sw.write('\n');
          }
        }
      }

      attribs.put(RESOURCE_URLS, sw.toString());

      DefDescriptor<ComponentDef> tmplDesc =
          definitionService.getDefDescriptor("ui:manifest", ComponentDef.class);
      Component tmpl = instanceService.getInstance(tmplDesc, attribs);
      renderingService.render(tmpl, response.getWriter());
    } catch (Exception e) {
      Aura.getExceptionAdapter().handleException(e);
      // Can't throw exception here: to set manifest OBSOLETE
      response.setStatus(HttpServletResponse.SC_NOT_FOUND);
    }
  }