コード例 #1
0
ファイル: AuraTestFilter.java プロジェクト: herinjaka/aura
  @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);
  }
コード例 #2
0
    @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();
    }