@Override
 public String getBootstrapFallbackUrl(AuraContext context, Map<String, Object> attributes) {
   String contextPath = context.getContextPath();
   String nonce = context.getFrameworkUID();
   return String.format(
       "%s/auraFW/resources/%s/aura/fallback/fallback.bootstrap.js", contextPath, nonce);
 }
  /**
   * check the top level component/app and get dependencies.
   *
   * <p>This routine checks to see that we have a valid top level component. If our top level
   * component is out of sync, we have to ignore it here, but we _must_ force the client to not
   * cache the response.
   *
   * <p>If there is a QFE, we substitute the QFE descriptor for the one given us, and continue.
   * Again, we cannot allow caching.
   *
   * <p>Finally, if there is no descriptor given, we simply ignore the request and give them an
   * empty response. Which is done here by returning null.
   *
   * <p>Also note that this handles the 'if-modified-since' header, as we want to tell the browser
   * that nothing changed in that case.
   *
   * @param request the request (for exception handling)
   * @param response the response (for exception handling)
   * @param context the context to get the definition.
   * @return the set of descriptors we are sending back, or null in the case that we handled the
   *     response.
   * @throws IOException if there was an IO exception handling a client out of sync exception
   * @throws ServletException if there was a problem handling the out of sync
   */
  @Override
  public Set<DefDescriptor<?>> verifyTopLevel(
      HttpServletRequest request, HttpServletResponse response, AuraContext context)
      throws IOException {
    DefDescriptor<? extends BaseComponentDef> appDesc = context.getApplicationDescriptor();
    MasterDefRegistry mdr = context.getDefRegistry();

    context.setPreloading(true);
    if (appDesc == null) {
      //
      // This means we have nothing to say to the client, so the response is
      // left completely empty.
      //
      return null;
    }
    long ifModifiedSince = request.getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);
    String uid = context.getUid(appDesc);
    try {
      try {
        definitionService.updateLoaded(appDesc);
        if (uid != null && ifModifiedSince != -1) {
          //
          // In this case, we have an unmodified descriptor, so just tell
          // the client that.
          //
          response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
          return null;
        }
      } catch (ClientOutOfSyncException coose) {
        //
        // We can't actually handle an out of sync here, since we are doing a
        // resource load. We have to ignore it, and continue as if nothing happened.
        // But in the process, we make sure to set 'no-cache' so that the result
        // is thrown away. This may actually not give the right result in bizarre
        // corner cases... beware cache inconsistencies on revert after a QFE.
        //
        // We actually probably should do something different, like send a minimalist
        // set of stuff to make the client re-try.
        //
        this.setNoCache(response);
        String oosUid = mdr.getUid(null, appDesc);
        return mdr.getDependencies(oosUid);
      }
    } catch (QuickFixException qfe) {
      //
      // A quickfix exception means that we couldn't compile something.
      // In this case, we still want to preload things, but we want to preload
      // quick fix values, note that we force NoCache here.
      //
      this.setNoCache(response);
      this.handleServletException(qfe, true, context, request, response, true);
      return null;
    }
    this.setLongCache(response);
    if (uid == null) {
      uid = context.getUid(appDesc);
    }
    return mdr.getDependencies(uid);
  }
 @Override
 public String getAppCssUrl(AuraContext context) {
   String contextPath = context.getContextPath();
   StringBuilder defs = new StringBuilder(contextPath).append("/l/");
   defs.append(context.getEncodedURL(AuraContext.EncodingStyle.Css));
   defs.append("/app.css");
   return defs.toString();
 }
 private String commonJsUrl(String filepath, AuraContext context, Map<String, Object> attributes) {
   StringBuilder url = new StringBuilder(context.getContextPath()).append("/l/");
   url.append(context.getEncodedURL(AuraContext.EncodingStyle.Normal));
   url.append(filepath);
   if (attributes != null) {
     addAttributes(url, attributes);
   }
   return url.toString();
 }
 /** Start a context and set up default values. */
 protected AuraContext setupContext(
     Mode mode, Format format, DefDescriptor<? extends BaseComponentDef> desc)
     throws QuickFixException {
   ContextService contextService = Aura.getContextService();
   AuraContext ctxt =
       contextService.startContext(mode, format, Authentication.AUTHENTICATED, desc);
   ctxt.setFrameworkUID(Aura.getConfigAdapter().getAuraFrameworkNonce());
   String uid = ctxt.getDefRegistry().getUid(null, desc);
   ctxt.addLoaded(desc, uid);
   return ctxt;
 }
 private Set<String> getClientLibraryUrls(
     DefDescriptor<? extends BaseComponentDef> desc, Type libraryType) throws Exception {
   AuraContext context = Aura.getContextService().getCurrentContext();
   context.setApplicationDescriptor(desc);
   // TODO: Why this extra step, should the Client Library service take care of loading the appDesc
   // def and
   // returning the urls?
   Aura.getDefinitionService().updateLoaded(desc);
   Set<String> urls = clientLibraryService.getUrls(context, libraryType);
   return urls;
 }
  /**
   * get the manifest URL.
   *
   * <p>This routine will simply return the string, it does not check to see if the manifest is
   * enabled first.
   *
   * @return a string for the manifest URL.
   */
  @Override
  public String getManifestUrl(AuraContext context, Map<String, Object> attributes) {
    String contextPath = context.getContextPath();
    String ret = "";

    StringBuilder defs = new StringBuilder(contextPath).append("/l/");
    defs.append(context.getEncodedURL(AuraContext.EncodingStyle.Bare));
    defs.append("/app.manifest");
    addAttributes(defs, attributes);
    ret = defs.toString();
    return ret;
  }
  /** Get the set of base scripts for a context. */
  @Override
  public List<String> getNamespacesScripts(AuraContext context) throws QuickFixException {
    String contextPath = context.getContextPath();
    List<String> ret = Lists.newArrayList();

    StringBuilder defs = new StringBuilder(contextPath).append("/l/");
    defs.append(context.getEncodedURL(AuraContext.EncodingStyle.Normal));
    defs.append("/app.js");

    ret.add(defs.toString());

    return ret;
  }
 private DefDescriptor<ApplicationDef> startAppContext(String markup) {
   DefDescriptor<ApplicationDef> app = addSourceAutoCleanup(ApplicationDef.class, markup);
   if (Aura.getContextService().isEstablished()) {
     Aura.getContextService().endContext();
   }
   AuraContext ctx =
       Aura.getContextService()
           .startContext(
               AuraContext.Mode.UTEST,
               AuraContext.Format.JSON,
               AuraContext.Authentication.UNAUTHENTICATED,
               app);
   ctx.setFrameworkUID("#FAKEUID#");
   return app;
 }
  @Override
  public void serialize(Json json) throws IOException {
    json.writeMapBegin();
    json.writeMapEntry("descriptor", descriptor);

    AuraContext context = Aura.getContextService().getCurrentContext();
    if (!context.isPreloading() && !context.isPreloaded(getDescriptor())) {
      // TODONM: revisit this after removing theme from aura context
      if (context.getThemeList().isEmpty()) {
        context.addAppThemeDescriptors();
      }
      json.writeMapEntry("code", getCode());
    }
    json.writeMapEnd();
  }
  @Override
  public List<String> getStyles(AuraContext context) throws QuickFixException {
    String contextPath = context.getContextPath();

    Set<String> ret = Sets.newLinkedHashSet();

    // add css client libraries
    ret.addAll(getClientLibraryUrls(context, ClientLibraryDef.Type.CSS));

    StringBuilder defs = new StringBuilder(contextPath).append("/l/");
    defs.append(context.getEncodedURL(AuraContext.EncodingStyle.Css));
    defs.append("/app.css");
    ret.add(defs.toString());

    return new ArrayList<>(ret);
  }
  /**
   * finish up the validation of a set of compiling defs.
   *
   * @param context only needed to do setCurrentNamspace.
   */
  private void finishValidation(AuraContext context, Collection<CompilingDef<?>> compiling)
      throws QuickFixException {
    //
    // Now validate our references.
    //
    for (CompilingDef<?> cd : compiling) {
      // FIXME: setting the current namespace on the context seems extremely hackish
      context.setCurrentNamespace(cd.descriptor.getNamespace());
      if (cd.built) {
        // FIXME: this may be incorrect, we may need to validate references even when we did
        // not actually build this, and we may not need to if the registry is pre-compiled.
        cd.def.validateReferences();
      }
    }

    //
    // And finally, mark everything as happily compiled.
    //
    for (CompilingDef<?> cd : compiling) {
      defs.put(cd.descriptor, cd.def);
      if (cd.built) {
        if (cd.cacheable) {
          defsCache.put(cd.descriptor, Optional.of(cd.def));
        }
        cd.def.markValid();
      }
    }
  }
Exemple #13
0
  @SuppressWarnings("unchecked")
  private List<DefDescriptor<FlavoredStyleDef>> getDefs() {
    AuraContext context = Aura.getContextService().getCurrentContext();
    MasterDefRegistry mdr = context.getDefRegistry();

    List<DefDescriptor<FlavoredStyleDef>> defs = new ArrayList<>();

    for (DefDescriptor<?> dd : mdr.find(filter)) {
      // currently getBundle will only work with file-based, unless the other loaders also set the
      // bundle
      if (dd.getDefType() == DefType.FLAVORED_STYLE && dd.getBundle().getName().equals(bundle)) {
        defs.add((DefDescriptor<FlavoredStyleDef>) dd);
      }
    }

    return defs;
  }
  public DefOverviewModel() throws QuickFixException {

    AuraContext context = Aura.getContextService().getCurrentContext();
    BaseComponent<?, ?> component = context.getCurrentComponent();

    String desc = (String) component.getAttributes().getValue("descriptor");

    DefType defType =
        DefType.valueOf(((String) component.getAttributes().getValue("defType")).toUpperCase());
    DefinitionService definitionService = Aura.getDefinitionService();
    DefDescriptor<?> descriptor =
        definitionService.getDefDescriptor(desc, defType.getPrimaryInterface());

    Definition def = descriptor.getDef();
    ReferenceTreeModel.assertAccess(def);

    Map<DefType, List<DefModel>> depsMap = Maps.newEnumMap(DefType.class);

    Set<DefDescriptor<?>> deps = Sets.newHashSet();

    def.appendDependencies(deps);

    for (DefDescriptor<?> dep : deps) {
      DefType type = dep.getDefType();

      List<DefModel> depsList = depsMap.get(type);
      if (depsList == null) {
        depsList = Lists.newArrayList();
        depsMap.put(type, depsList);
      }
      depsList.add(new DefModel(dep));
    }

    for (Entry<DefType, List<DefModel>> entry : depsMap.entrySet()) {
      List<DefModel> list = entry.getValue();
      Collections.sort(list);

      Map<String, Object> group = Maps.newHashMap();
      group.put("type", AuraTextUtil.initCap(entry.getKey().toString().toLowerCase()));
      group.put("list", list);
      dependencies.add(group);
    }
  }
  public void testWriteResourcesJS() throws Exception {
    AuraContext context = Aura.getContextService().getCurrentContext();
    DefDescriptor<ApplicationDef> appDesc =
        Aura.getDefinitionService()
            .getDefDescriptor("clientLibraryTest:clientLibraryTest", ApplicationDef.class);
    context.setApplicationDescriptor(appDesc);
    Aura.getDefinitionService().updateLoaded(appDesc);
    StringBuilder sb = new StringBuilder();

    clientLibraryService.writeJs(context, sb);
    String libraryContent = sb.toString();
    assertTrue("Missing resource JS", libraryContent.contains("clientLibraryTest"));

    try {
      clientLibraryService.writeJs(context, null);
      fail("Should not be able to write to null stream");
    } catch (Exception e) {
      checkExceptionFull(e, AuraRuntimeException.class, "Output cannot be null");
    }
  }
Exemple #16
0
  /**
   * get the manifest URL.
   *
   * <p>This routine will simply return the string, it does not check to see if the manifest is
   * enabled first.
   *
   * @return a string for the manifest URL.
   */
  public static String getManifestUrl() throws QuickFixException {
    AuraContext context = Aura.getContextService().getCurrentContext();
    String contextPath = context.getContextPath();
    String ret = "";

    boolean serLastMod = context.getSerializeLastMod();
    StringBuilder defs = new StringBuilder(contextPath).append("/l/");
    StringBuilder sb = new StringBuilder();
    context.setSerializeLastMod(false);
    try {
      Aura.getSerializationService().write(context, null, AuraContext.class, sb, "HTML");
    } catch (IOException e) {
      throw new AuraRuntimeException(e);
    }
    context.setSerializeLastMod(serLastMod);
    String contextJson = AuraTextUtil.urlencode(sb.toString());
    defs.append(contextJson);
    defs.append("/app.manifest");
    ret = defs.toString();
    return ret;
  }
Exemple #17
0
  /** Is AppCache allowed by the current configuration? */
  public static boolean isManifestEnabled() {
    if (!Aura.getConfigAdapter().isClientAppcacheEnabled()) {
      return false;
    }

    AuraContext context = Aura.getContextService().getCurrentContext();
    DefDescriptor<? extends BaseComponentDef> appDefDesc = context.getApplicationDescriptor();

    if (appDefDesc != null && appDefDesc.getDefType().equals(DefType.APPLICATION)) {
      try {
        Boolean useAppcache = ((ApplicationDef) appDefDesc.getDef()).isAppcacheEnabled();
        if (useAppcache != null) {
          return useAppcache.booleanValue();
        }
        return false;
      } catch (QuickFixException e) {
        return false;
      }
    }
    return false;
  }
  public void testContextPath() throws Exception {
    AuraContext context = Aura.getContextService().getCurrentContext();
    DefDescriptor<ApplicationDef> appDesc =
        Aura.getDefinitionService()
            .getDefDescriptor("clientLibraryTest:clientLibraryTest", ApplicationDef.class);
    context.setApplicationDescriptor(appDesc);
    String coolContext = "/cool";
    context.setContextPath(coolContext);
    Aura.getDefinitionService().updateLoaded(appDesc);

    Set<String> urlSet = clientLibraryService.getUrls(context, Type.JS);
    Pattern pattern = Pattern.compile("/auraFW|/l/");
    for (String url : urlSet) {
      Matcher matcher = pattern.matcher(url);
      while (matcher.find()) {
        int start = matcher.start();
        String cool = url.substring(start - 5, start);
        if (!cool.equals(coolContext)) {
          fail("Context path was not prepended to Aura urls");
        }
      }
    }
  }
Exemple #19
0
  /**
   * Gets the UID for the application descriptor of the current context, or {@code null} if there is
   * no application (probably because of a compile error).
   */
  public String getContextAppUid(AuraContext context) {
    DefDescriptor<? extends BaseComponentDef> app = context.getApplicationDescriptor();

    if (app != null) {
      try {
        return definitionService.getDefRegistry().getUid(null, app);
      } catch (QuickFixException e) {
        // This is perfectly possible, but the error is handled in more
        // contextually-sensible places. For here, we know there's no
        // meaningful uid, so we fall through and return null.
      }
    }
    return null;
  }
  @Override
  public String getCode(List<Plugin> plugins) {
    List<Plugin> augmented = Lists.newArrayList(plugins);

    try {
      AuraContext ctx = Aura.getContextService().getCurrentContext();
      DefDescriptor<? extends BaseComponentDef> top = ctx.getLoadingApplicationDescriptor();
      if (top != null && top.getDefType() == DefType.APPLICATION) {
        DefDescriptor<FlavorAssortmentDef> flavors =
            ((ApplicationDef) top.getDef()).getAppFlavors();
        if (flavors != null) {
          FlavorMapping mapping = flavors.getDef().computeOverrides();
          if (!mapping.isEmpty()) {
            boolean devMode = Aura.getContextService().getCurrentContext().isDevMode();
            augmented.add(new FlavorMappingEnforcerPlugin(getDescriptor(), mapping, devMode));
          }
        }
      }
    } catch (QuickFixException e) {
      throw new AuraRuntimeException(e);
    }

    return super.getCode(augmented);
  }
Exemple #21
0
 /**
  * Get the expected name for the manifest cookie.
  *
  * @return the name (null if none)
  */
 private static String getManifestCookieName() {
   AuraContext context = Aura.getContextService().getCurrentContext();
   if (context.getApplicationDescriptor() != null) {
     StringBuilder sb = new StringBuilder();
     if (context.getMode() != Mode.PROD) {
       sb.append(context.getMode());
       sb.append("_");
     }
     sb.append(context.getApplicationDescriptor().getNamespace());
     sb.append("_");
     sb.append(context.getApplicationDescriptor().getName());
     sb.append(MANIFEST_COOKIE_TAIL);
     return sb.toString();
   }
   return null;
 }
Exemple #22
0
  private void loadTestMocks(AuraContext context, boolean doReset, Collection<Definition> mocks) {
    // TODO: fix error handling
    if (mocks == null || mocks.isEmpty()) {
      return;
    }

    boolean error = false;
    MasterDefRegistry registry = context.getDefRegistry();
    for (Definition def : mocks) {
      try {
        if (doReset && def instanceof Resettable) {
          ((Resettable) def).reset();
        }
        registry.addLocalDef(def);
      } catch (Throwable t) {
        LOG.error("Failed to add mock " + def, t);
        error = true;
      }
    }
    if (error) {
      Aura.get(TestContextAdapter.class).release();
    }
  }
  /**
   * Fill a compiling def for a descriptor.
   *
   * <p>This makes sure that we can get a registry for a given def, then tries to get the def from
   * the global cache, if that fails, it retrieves from the registry, and marks the def as locally
   * built.
   *
   * @param compiling the current compiling def (if there is one).
   * @throws QuickFixException if validateDefinition caused a quickfix.
   */
  private <D extends Definition> boolean fillCompilingDef(
      CompilingDef<D> compiling, AuraContext context) throws QuickFixException {
    assert compiling.def == null;
    {
      //
      // First, check our local cached defs to see if we have a fully compiled version.
      // in this case, we don't care about caching, since we are done.
      //
      @SuppressWarnings("unchecked")
      D localDef = (D) defs.get(compiling.descriptor);
      if (localDef != null) {
        compiling.def = localDef;
        compiling.built = !localDef.isValid();
        if (compiling.built) {
          localDef.validateDefinition();
        }
        return true;
      }
    }

    //
    // If there is no local cache, we must first check to see if there is a registry, as we may not
    // have
    // a registry (depending on configuration). In the case that we don't find one, we are done
    // here.
    //
    DefRegistry<D> registry = getRegistryFor(compiling.descriptor);
    if (registry == null) {
      defs.put(compiling.descriptor, null);
      return false;
    }

    //
    // Now, check if we can cache the def later, as we won't have the registry to check at a later
    // time.
    // If we can cache, look it up in the cache. If we find it, we have a built definition.
    //
    if (isCacheable(registry)) {
      compiling.cacheable = true;

      @SuppressWarnings("unchecked")
      Optional<D> opt = (Optional<D>) defsCache.getIfPresent(compiling.descriptor);
      if (opt != null) {
        D cachedDef = opt.orNull();

        if (cachedDef != null) {
          @SuppressWarnings("unchecked")
          DefDescriptor<D> canonical = (DefDescriptor<D>) cachedDef.getDescriptor();

          compiling.def = cachedDef;
          compiling.descriptor = canonical;
          compiling.built = false;
          defs.put(canonical, cachedDef);
          return true;
        } else {
          return false;
        }
      }
    }

    //
    // The last case. This is our first compile or the def is uncacheable.
    // In this case, we make sure that the initial validation is called, and put
    // the def in the non-validated set.
    //
    compiling.def = registry.getDef(compiling.descriptor);
    if (compiling.def == null) {
      return false;
    }
    @SuppressWarnings("unchecked")
    DefDescriptor<D> canonical = (DefDescriptor<D>) compiling.def.getDescriptor();
    compiling.descriptor = canonical;

    // cc.loggingService.incrementNum(LoggingService.DEF_COUNT);
    // FIXME: setting the current namespace on the context seems
    // extremely hackish
    context.setCurrentNamespace(canonical.getNamespace());
    compiling.def.validateDefinition();
    compiling.built = true;
    defs.put(canonical, compiling.def);
    return true;
  }
  @Override
  public void assertAccess(DefDescriptor<?> desc) throws QuickFixException {

    if (!accessCache.contains(desc)) {
      Aura.getLoggingService().incrementNum("SecurityProviderCheck");
      DefType defType = desc.getDefType();
      String ns = desc.getNamespace();
      AuraContext context = Aura.getContextService().getCurrentContext();
      Mode mode = context.getMode();
      String prefix = desc.getPrefix();
      //
      // This breaks encapsulation! -gordon
      //
      boolean isTopLevel = desc.equals(context.getApplicationDescriptor());

      if (isTopLevel) {
        //
        // If we are trying to access the top level component, we need to ensure
        // that it is _not_ abstract.
        //
        BaseComponentDef def = getDef(context.getApplicationDescriptor());
        if (def != null && def.isAbstract() && def.getProviderDescriptor() == null) {
          throw new NoAccessException(
              String.format("Access to %s disallowed. Abstract definition.", desc));
        }
      }
      //
      // If this is _not_ the top level, we allow circumventing the security provider.
      // This means that certain things will short-circuit, hopefully making checks faster...
      // Not sure if this is premature optimization or not.
      //
      if (!isTopLevel || desc.getDefType().equals(DefType.COMPONENT)) {
        if (!securedDefTypes.contains(defType)
            || unsecuredPrefixes.contains(prefix)
            || unsecuredNamespaces.contains(ns)
            || (mode != Mode.PROD
                && (!Aura.getConfigAdapter().isProduction())
                && unsecuredNonProductionNamespaces.contains(ns))) {
          accessCache.add(desc);
          return;
        }

        if (ns != null && DefDescriptor.JAVA_PREFIX.equals(prefix)) {
          // handle java packages that have namespaces like aura.impl.blah
          for (String okNs : unsecuredNamespaces) {
            if (ns.startsWith(okNs)) {
              accessCache.add(desc);
              return;
            }
          }
        }
      }

      SecurityProviderDef securityProviderDef = getSecurityProvider();
      if (securityProviderDef == null) {
        if (mode != Mode.PROD && !Aura.getConfigAdapter().isProduction()) {
          accessCache.add(desc);
          return;
        } else {
          throw new NoAccessException(
              String.format("Access to %s disallowed.  No Security Provider found.", desc));
        }
      } else {
        if (!securityProviderDef.isAllowed(desc)) {
          throw new NoAccessException(
              String.format(
                  "Access to %s disallowed by %s",
                  desc, securityProviderDef.getDescriptor().getName()));
        }
      }
      accessCache.add(desc);
    }
  }
Exemple #25
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);
    }
  }
    @Override
    public void serialize(Json json, AuraContext ctx) throws IOException {
      json.writeMapBegin();
      json.writeMapEntry("mode", ctx.getMode());

      DefDescriptor<? extends BaseComponentDef> appDesc = ctx.getApplicationDescriptor();
      if (appDesc != null) {
        if (appDesc.getDefType().equals(DefType.APPLICATION)) {
          json.writeMapEntry(
              "app", String.format("%s:%s", appDesc.getNamespace(), appDesc.getName()));
        } else {
          json.writeMapEntry(
              "cmp", String.format("%s:%s", appDesc.getNamespace(), appDesc.getName()));
        }
      }

      if (ctx.getSerializeThemes()) {
        ThemeList themes = ctx.getThemeList();
        if (!themes.isEmpty()) {
          List<String> stringed = Lists.newArrayList();
          for (DefDescriptor<ThemeDef> theme : themes) {
            stringed.add(theme.getQualifiedName());
          }
          json.writeMapEntry("themes", stringed);
        }

        Optional<String> dynamicVarsUid = themes.getActiveDynamicVarsUid();
        if (dynamicVarsUid.isPresent()) {
          json.writeMapEntry("dynamicVarsUid", dynamicVarsUid.get());
        }
      }

      if (ctx.getRequestedLocales() != null) {
        List<String> locales = new ArrayList<>();
        for (Locale locale : ctx.getRequestedLocales()) {
          locales.add(locale.toString());
        }
        json.writeMapEntry("requestedLocales", locales);
      }
      Map<String, String> loadedStrings = Maps.newHashMap();
      Map<DefDescriptor<?>, String> clientLoaded = Maps.newHashMap();
      clientLoaded.putAll(ctx.getClientLoaded());
      for (Map.Entry<DefDescriptor<?>, String> entry : ctx.getLoaded().entrySet()) {
        loadedStrings.put(
            String.format(
                "%s@%s", entry.getKey().getDefType().toString(), entry.getKey().getQualifiedName()),
            entry.getValue());
        clientLoaded.remove(entry.getKey());
      }
      if (forClient) {
        for (DefDescriptor<?> deleted : clientLoaded.keySet()) {
          loadedStrings.put(
              String.format("%s@%s", deleted.getDefType().toString(), deleted.getQualifiedName()),
              DELETED);
        }
      }
      if (loadedStrings.size() > 0) {
        json.writeMapKey("loaded");
        json.writeMap(loadedStrings);
      }
      if (ctx.getSerializeLastMod()) {
        json.writeMapEntry("lastmod", Long.toString(AuraBaseServlet.getLastMod()));
      }

      TestContextAdapter testContextAdapter = Aura.get(TestContextAdapter.class);
      if (testContextAdapter != null) {
        TestContext testContext = testContextAdapter.getTestContext();
        if (testContext != null) {
          json.writeMapEntry("test", testContext.getName());
        }
      }

      if (ctx.getFrameworkUID() != null) {
        json.writeMapEntry("fwuid", ctx.getFrameworkUID());
      }

      if (forClient) {
        // client needs value providers, urls don't
        boolean started = false;

        for (GlobalValueProvider valueProvider : ctx.getGlobalProviders().values()) {
          if (!valueProvider.isEmpty()) {
            if (!started) {
              json.writeMapKey("globalValueProviders");
              json.writeArrayBegin();
              started = true;
            }
            json.writeComma();
            json.writeIndent();
            json.writeMapBegin();
            json.writeMapEntry("type", valueProvider.getValueProviderKey().getPrefix());
            json.writeMapEntry("values", valueProvider.getData());
            json.writeMapEnd();
          }
        }

        if (started) {
          json.writeArrayEnd();
        }

        //
        // Now comes the tricky part, we have to serialize all of the definitions that are
        // required on the client side, and, of all types. This way, we won't have to handle
        // ugly cases of actual definitions nested inside our configs, and, we ensure that
        // all dependencies actually get sent to the client. Note that the 'loaded' set needs
        // to be updated as well, but that needs to happen prior to this.
        //
        Map<DefDescriptor<? extends Definition>, Definition> defMap;

        defMap = ctx.getDefRegistry().filterRegistry(ctx.getPreloadedDefinitions());

        if (defMap.size() > 0) {
          List<Definition> componentDefs = Lists.newArrayList();
          List<Definition> eventDefs = Lists.newArrayList();
          List<Definition> libraryDefs = Lists.newArrayList();

          for (Map.Entry<DefDescriptor<? extends Definition>, Definition> entry :
              defMap.entrySet()) {
            DefDescriptor<? extends Definition> desc = entry.getKey();
            DefType dt = desc.getDefType();
            Definition d = entry.getValue();
            //
            // Ignore defs that ended up not being valid. This is arguably something
            // that the MDR should have done when filtering.
            //
            if (d != null) {
              if (DefType.COMPONENT.equals(dt) || DefType.APPLICATION.equals(dt)) {
                componentDefs.add(d);
              } else if (DefType.EVENT.equals(dt)) {
                eventDefs.add(d);
              } else if (DefType.LIBRARY.equals(dt)) {
                libraryDefs.add(d);
              }
            }
          }
          writeDefs(json, "componentDefs", componentDefs);
          writeDefs(json, "eventDefs", eventDefs);
          writeDefs(json, "libraryDefs", libraryDefs);
        }
        ctx.serializeAsPart(json);
      }
      json.writeMapEnd();
    }
  /**
   * Handle an exception in the servlet.
   *
   * <p>This routine should be called whenever an exception has surfaced to the top level of the
   * servlet. It should not be overridden unless Aura is entirely subsumed. Most special cases can
   * be handled by the Aura user by implementing {@link ExceptionAdapter ExceptionAdapter}.
   *
   * @param t the throwable to write out.
   * @param quickfix is this exception a valid quick-fix
   * @param context the aura context.
   * @param request the request.
   * @param response the response.
   * @param written true if we have started writing to the output stream.
   * @throws IOException if the output stream does.
   * @throws ServletException if send404 does (should not generally happen).
   */
  @Override
  public void handleServletException(
      Throwable t,
      boolean quickfix,
      AuraContext context,
      HttpServletRequest request,
      HttpServletResponse response,
      boolean written)
      throws IOException {
    try {
      Throwable mappedEx = t;
      boolean map = !quickfix;
      Format format = context.getFormat();

      //
      // This seems to fail, though the documentation implies that you can do
      // it.
      //
      // if (written && !response.isCommitted()) {
      // response.resetBuffer();
      // written = false;
      // }
      if (!written) {
        // Should we only delete for JSON?
        setNoCache(response);
      }
      if (mappedEx instanceof IOException) {
        //
        // Just re-throw IOExceptions.
        //
        throw (IOException) mappedEx;
      } else if (mappedEx instanceof NoAccessException) {
        Throwable cause = mappedEx.getCause();
        String denyMessage = mappedEx.getMessage();

        map = false;
        if (cause != null) {
          //
          // Note that the exception handler can remap the cause here.
          //
          cause = exceptionAdapter.handleException(cause);
          denyMessage += ": cause = " + cause.getMessage();
        }
        //
        // Is this correct?!?!?!
        //
        if (format != Format.JSON) {
          this.send404(request.getServletContext(), request, response);
          if (!isProductionMode(context.getMode())) {
            // Preserve new lines and tabs in the stacktrace since this is directly being written on
            // to the
            // page
            denyMessage = "<pre>" + AuraTextUtil.escapeForHTML(denyMessage) + "</pre>";
            response.getWriter().println(denyMessage);
          }
          return;
        }
      } else if (mappedEx instanceof QuickFixException) {
        if (isProductionMode(context.getMode())) {
          //
          // In production environments, we want wrap the quick-fix. But be a little careful here.
          // We should never mark the top level as a quick-fix, because that means that we gack
          // on every mis-spelled app. In this case we simply send a 404 and bolt.
          //
          if (mappedEx instanceof DefinitionNotFoundException) {
            DefinitionNotFoundException dnfe = (DefinitionNotFoundException) mappedEx;

            if (dnfe.getDescriptor() != null
                && dnfe.getDescriptor().equals(context.getApplicationDescriptor())) {
              // We're in production and tried to hit an aura app that doesn't exist.
              // just show the standard 404 page.
              this.send404(request.getServletContext(), request, response);
              return;
            }
          }
          map = true;
          mappedEx = new AuraUnhandledException("404 Not Found (Application Error)", mappedEx);
        }
      }
      if (map) {
        mappedEx = exceptionAdapter.handleException(mappedEx);
      }

      PrintWriter out = response.getWriter();

      //
      // If we have written out data, We are kinda toast in this case.
      // We really want to roll it all back, but we can't, so we opt
      // for the best we can do. For HTML we can do nothing at all.
      //
      if (format == Format.JSON) {
        if (!written) {
          out.write(CSRF_PROTECT);
        }
        //
        // If an exception happened while we were emitting JSON, we want the
        // client to ignore the now-corrupt data structure. 404s and 500s
        // cause the client to prepend /*, so we can effectively erase the
        // bad data by appending a */ here and then serializing the exception
        // info.
        //
        out.write("*/");
        //
        // Unfortunately we can't do the following now. It might be possible
        // in some cases, but we don't want to go there unless we have to.
        //
      }
      if (format == Format.JS || format == Format.CSS) {
        // Make sure js and css doesn't get cached in browser, appcache, etc
        response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR);
      }
      if (format == Format.JSON
          || format == Format.HTML
          || format == Format.JS
          || format == Format.CSS) {
        //
        // We only write out exceptions for HTML or JSON.
        // Seems bogus, but here it is.
        //
        // Start out by cleaning out some settings to ensure we don't
        // check too many things, leading to a circular failure. Note
        // that this is still a bit dangerous, as we seem to have a lot
        // of magic in the serializer.
        //
        // Clear the InstanceStack before trying to serialize the exception since the Throwable has
        // likely
        // rendered the stack inaccurate, and may falsely trigger NoAccessExceptions.
        InstanceStack stack = this.contextService.getCurrentContext().getInstanceStack();
        List<String> list = stack.getStackInfo();
        for (int count = list.size(); count > 0; count--) {
          stack.popInstance(stack.peek());
        }

        serializationService.write(mappedEx, null, out);
        if (format == Format.JSON) {
          out.write("/*ERROR*/");
        }
      }
    } catch (IOException ioe) {
      throw ioe;
    } catch (Throwable death) {
      //
      // Catch any other exception and log it. This is actually kinda bad, because something has
      // gone horribly wrong. We should write out some sort of generic page other than a 404,
      // but at this point, it is unclear what we can do, as stuff is breaking right and left.
      //
      try {
        response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR);
        exceptionAdapter.handleException(death);
        if (!isProductionMode(context.getMode())) {
          response.getWriter().println(death.getMessage());
        }
      } catch (IOException ioe) {
        throw ioe;
      } catch (Throwable doubleDeath) {
        // we are totally hosed.
        if (!isProductionMode(context.getMode())) {
          response.getWriter().println(doubleDeath.getMessage());
        }
      }
    } finally {
      this.contextService.endContext();
    }
  }
Exemple #28
0
  @Override
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
      throws ServletException, IOException {

    if (!Aura.getConfigAdapter().isTestAllowed()) {
      chain.doFilter(req, res);
      return;
    }

    TestContextAdapter testContextAdapter = Aura.get(TestContextAdapter.class);
    if (testContextAdapter == null) {
      chain.doFilter(req, res);
      return;
    }

    // Check for requests to execute a JSTest, i.e. initial component GETs with particular
    // parameters.
    HttpServletRequest request = (HttpServletRequest) req;
    if ("GET".equals(request.getMethod())) {
      String contextPath = request.getContextPath();
      String uri = request.getRequestURI();
      String browserType = request.getParameter("aura.browserType");
      if (browserType == null) {
        // read it from request header
        String ua = request.getHeader(HttpHeaders.USER_AGENT);
        if (ua != null) {
          ua = ua.toLowerCase();
          if (ua.contains("chrome")) {
            browserType = "GOOGLECHROME";
          } else if (ua.contains("safari")) {
            browserType = "SAFARI";
          } else if (ua.contains("firefox")) {
            browserType = "FIREFOX";
          } else if (ua.contains("ipad")) {
            browserType = "IPAD";
          } else if (ua.contains("iphone")) {
            browserType = "IPHONE";
          } else if (ua.contains("msie 10")) {
            browserType = "IE10";
          } else if (ua.contains("msie 9")) {
            browserType = "IE9";
          } else if (ua.contains("msie 8")) {
            browserType = "IE8";
          } else if (ua.contains("msie 7")) {
            browserType = "IE7";
          } else if (ua.contains("msie 6")) {
            browserType = "IE6";
          } else if (ua.contains("trident/7.0")) {
            browserType = "IE11";
          } else if (ua.contains("edge/12")) {
            browserType = "IE12";
          } else {
            browserType = "OTHER";
          }
        }
      }
      String path;
      if (uri.startsWith(contextPath)) {
        path = uri.substring(contextPath.length());
      } else {
        path = uri;
      }
      Matcher matcher = AuraRewriteFilter.DESCRIPTOR_PATTERN.matcher(path);
      if (matcher.matches()) {
        // Extract the target component since AuraContext usually does not have the app descriptor
        // set yet.
        DefType type = "app".equals(matcher.group(3)) ? DefType.APPLICATION : DefType.COMPONENT;
        String namespace = matcher.group(1);
        String name = matcher.group(2);
        DefDescriptor<?> targetDescriptor =
            Aura.getDefinitionService()
                .getDefDescriptor(
                    String.format("%s:%s", namespace, name), type.getPrimaryInterface());

        // Check if a single jstest is being requested.
        String testToRun = jstestToRun.get(request);
        if (testToRun != null && !testToRun.isEmpty()) {
          AuraContext context = Aura.getContextService().getCurrentContext();
          Format format = context.getFormat();
          switch (format) {
            case HTML:
              TestCaseDef testDef;
              TestContext testContext;
              String targetUri;
              try {
                TestSuiteDef suiteDef = getTestSuite(targetDescriptor);
                testDef = getTestCase(suiteDef, testToRun);
                testDef.validateDefinition();
                testDef.setCurrentBrowser(browserType);
                testContextAdapter.getTestContext(testDef.getQualifiedName());
                testContextAdapter.release();
                testContext = testContextAdapter.getTestContext(testDef.getQualifiedName());
                targetUri = buildJsTestTargetUri(targetDescriptor, testDef);
              } catch (QuickFixException e) {
                ((HttpServletResponse) res).setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR);
                res.setCharacterEncoding(AuraBaseServlet.UTF_ENCODING);
                res.getWriter().append(e.getMessage());
                Aura.getExceptionAdapter().handleException(e);
                return;
              }

              // Load any test mocks.
              Collection<Definition> mocks = testDef.getLocalDefs();
              testContext.getLocalDefs().addAll(mocks);
              loadTestMocks(context, true, testContext.getLocalDefs());

              // Capture the response and inject tags to load jstest.
              String capturedResponse = captureResponse(req, res, targetUri);
              if (capturedResponse != null) {
                res.setCharacterEncoding(AuraBaseServlet.UTF_ENCODING);
                if (!Aura.getContextService().isEstablished()) {
                  // There was an error in the original response, so just write the response out.
                  res.getWriter().write(capturedResponse);
                } else {
                  String testTag =
                      buildJsTestScriptTag(targetDescriptor, testToRun, capturedResponse);
                  injectScriptTags(res.getWriter(), capturedResponse, testTag);
                }
                return;
              }
            case JS:
              res.setCharacterEncoding(AuraBaseServlet.UTF_ENCODING);
              writeJsTestScript(res.getWriter(), targetDescriptor, testToRun);
              return;
            default:
              // Pass it on.
          }
        }

        // aurajstest:jstest app is invokable in the following ways:
        // ?aura.mode=JSTEST - run all tests
        // ?aura.mode JSTEST&test=XXX - run single test
        // ?aura.jstest - run all tests
        // ?aura.jstest=XXX - run single test
        // ?aura.jstestrun - run all tests
        // TODO: delete JSTEST mode
        String jstestAppRequest = jstestAppFlag.get(request);
        Mode mode = AuraContextFilter.mode.get(request, Mode.PROD);
        if (mode == Mode.JSTEST
            || mode == Mode.JSTESTDEBUG
            || jstestAppRequest != null
            || testToRun != null) {

          mode = mode.toString().endsWith("DEBUG") ? Mode.AUTOJSTESTDEBUG : Mode.AUTOJSTEST;

          String qs = String.format("descriptor=%s:%s&defType=%s", namespace, name, type.name());
          String testName = null;
          if (jstestAppRequest != null && !jstestAppRequest.isEmpty()) {
            testName = jstestAppRequest;
          } else if (testToRun != null && !testToRun.isEmpty()) {
            testName = testToRun;
          }
          if (testName != null) {
            qs = qs + "&test=" + testName;
          }

          String newUri =
              createURI(
                  "aurajstest",
                  "jstest",
                  DefType.APPLICATION,
                  mode,
                  Authentication.AUTHENTICATED.name(),
                  qs);
          RequestDispatcher dispatcher =
              servletContext.getContext(newUri).getRequestDispatcher(newUri);
          if (dispatcher != null) {
            dispatcher.forward(req, res);
            return;
          }
        }
      }
    }

    // Handle mock definitions specified in the tests.
    TestContext testContext = getTestContext(request);
    if (testContext == null) {
      // During manual testing, the test context adapter may not always get cleared.
      testContextAdapter.clear();
    } else {
      ContextService contextService = Aura.getContextService();
      if (!contextService.isEstablished()) {
        LOG.error("Aura context is not established! New context will NOT be created.");
        chain.doFilter(req, res);
        return;
      }
      AuraContext context = contextService.getCurrentContext();

      // Reset mocks if requested, or for the initial GET.
      boolean doResetMocks = testReset.get(request, Format.HTML.equals(context.getFormat()));
      loadTestMocks(context, doResetMocks, testContext.getLocalDefs());
    }
    chain.doFilter(req, res);
  }
Exemple #29
0
  public ComponentDefModel() throws QuickFixException {
    AuraContext context = Aura.getContextService().getCurrentContext();
    BaseComponent<?, ?> component = context.getCurrentComponent();

    String desc = (String) component.getAttributes().getValue("descriptor");

    DefType defType =
        DefType.valueOf(((String) component.getAttributes().getValue("defType")).toUpperCase());
    DefinitionService definitionService = Aura.getDefinitionService();
    descriptor = definitionService.getDefDescriptor(desc, defType.getPrimaryInterface());
    definition = descriptor.getDef();

    ReferenceTreeModel.assertAccess(definition);

    String type = null;
    if (definition instanceof RootDefinition) {
      RootDefinition rootDef = (RootDefinition) definition;
      for (AttributeDef attribute : rootDef.getAttributeDefs().values()) {
        if (ReferenceTreeModel.hasAccess(attribute)) {
          attributes.add(new AttributeModel(attribute));
        }
      }

      DocumentationDef docDef = rootDef.getDocumentationDef();
      doc = docDef != null ? new DocumentationDefModel(docDef) : null;

      if (definition instanceof BaseComponentDef) {
        BaseComponentDef cmpDef = (BaseComponentDef) definition;
        for (RegisterEventDef reg : cmpDef.getRegisterEventDefs().values()) {
          if (ReferenceTreeModel.hasAccess(reg)) {
            events.add(new AttributeModel(reg));
          }
        }

        for (EventHandlerDef handler : cmpDef.getHandlerDefs()) {
          handledEvents.add(new AttributeModel(handler));
        }

        for (DefDescriptor<InterfaceDef> intf : cmpDef.getInterfaces()) {
          if (ReferenceTreeModel.hasAccess(intf.getDef())) {
            interfaces.add(intf.getNamespace() + ":" + intf.getName());
          }
        }

        DefDescriptor<?> superDesc = cmpDef.getExtendsDescriptor();
        if (superDesc != null) {
          theSuper = superDesc.getNamespace() + ":" + superDesc.getName();
        } else {
          theSuper = null;
        }

        isAbstract = cmpDef.isAbstract();
        isExtensible = cmpDef.isExtensible();

      } else if (definition instanceof EventDef) {
        EventDef eventDef = (EventDef) definition;
        DefDescriptor<?> superDesc = eventDef.getExtendsDescriptor();
        if (superDesc != null) {
          theSuper = superDesc.getNamespace() + ":" + superDesc.getName();
        } else {
          theSuper = null;
        }

        type = eventDef.getEventType().name();
        isExtensible = true;
        isAbstract = false;
      } else {
        theSuper = null;
        isExtensible = true;
        isAbstract = false;
      }

      support = rootDef.getSupport().name();

      if (definition instanceof RootDefinition) {
        List<DefDescriptor<?>> deps = ((RootDefinition) definition).getBundle();

        for (DefDescriptor<?> dep : deps) {
          // we already surface the documentation--users don't need to see the source for it.
          if (dep.getDefType() != DefType.DOCUMENTATION) {
            Definition def = dep.getDef();
            if (ReferenceTreeModel.hasAccess(def)) {
              defs.add(new DefModel(dep));
            }
          }
        }
      }
    } else {
      support = null;
      theSuper = null;
      isExtensible = false;
      isAbstract = false;
      doc = null;
    }
    this.type = type;
  }
  @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);
    }
  }