@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); } }
/** * 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); } }