/**
   * 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);
  }
Beispiel #2
0
 /** 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;
 }
Beispiel #3
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;
  }
Beispiel #4
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();
    }
  }
    @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();
    }