Пример #1
0
  /**
   * Returns the <code>Dictionary</code> for the given <code>pid</code>.
   *
   * @param pid The identifier for the dictionary to load.
   * @return The dictionary for the identifier. This must not be <code>null</code> but may be empty.
   * @throws IOException If an error occurrs loading the dictionary. An <code>IOException</code>
   *     must also be thrown if no dictionary exists for the given identifier.
   */
  public Dictionary load(String pid) throws IOException {
    logger.debug("Config load call for {}", pid);
    Dictionary result = null;

    try {
      if (isReady(0) && requireRepository) {
        String id = pidToId(pid);
        ReadRequest readRequest = Requests.newReadRequest(id);
        Resource existing = repo.read(readRequest);
        Map<String, Object> existingConfig = existing.getContent().asMap();
        Object configMap = existingConfig.get(JSONEnhancedConfig.JSON_CONFIG_PROPERTY);
        String configString = serializeConfig(configMap);
        existingConfig.put(JSONEnhancedConfig.JSON_CONFIG_PROPERTY, configString);
        logger.debug("Config loaded {} {}", pid, existing);
        result = mapToDict(existingConfig);
      } else if (!requireRepository) {
        result = tempStore.get(pid);
        if (result == null) {
          throw new IOException("No entry for " + pid + " exists.");
        }

        logger.debug("Config loaded from temporary store {} {}", pid, result);
      }
    } catch (NotFoundException ex) {
      result = tempStore.get(pid);
      if (result == null) {
        throw new IOException("No entry for " + pid + " exists.");
      }

      logger.debug("Config loaded from temporary store {} {}", pid, result);
    } catch (ResourceException ex) {
      throw new IOException("Failed to load configuration in repository: " + ex.getMessage(), ex);
    }
    return result;
  }
  @Test
  public void crestReadIsAllowed() throws SSOException, DelegationException {
    // Given...
    final Set<String> actions = new HashSet<>(Arrays.asList("READ"));
    final DelegationPermission permission =
        new DelegationPermission(
            "/abc", "rest", "1.0", "policies", "read", actions, EXTENSIONS, DUMB_FUNC);
    given(factory.newInstance("/abc", "rest", "1.0", "policies", "read", actions, EXTENSIONS))
        .willReturn(permission);

    given(subjectContext.getCallerSSOToken()).willReturn(token);
    given(evaluator.isAllowed(token, permission, ENVIRONMENT)).willReturn(true);

    JsonValue jsonValue = json(object(field("someKey", "someValue")));
    Promise<ResourceResponse, ResourceException> promise =
        Promises.newResultPromise(Responses.newResourceResponse("1", "1.0", jsonValue));
    given(provider.readInstance(isA(Context.class), eq("123"), isA(ReadRequest.class)))
        .willReturn(promise);

    // When...
    final FilterChain chain = AuthorizationFilters.createAuthorizationFilter(provider, module);
    final Router router = new Router();
    router.addRoute(RoutingMode.STARTS_WITH, Router.uriTemplate("/policies"), chain);
    final RealmContext context = new RealmContext(subjectContext);
    final ReadRequest request = Requests.newReadRequest("/policies/123");
    context.setSubRealm("abc", "abc");
    Promise<ResourceResponse, ResourceException> result = router.handleRead(context, request);

    // Then...
    assertThat(result).succeeded().withContent().stringAt("someKey").isEqualTo("someValue");
  }
Пример #3
0
  /**
   * Returns <code>true</code> if a persisted <code>Dictionary</code> exists for the given <code>pid
   * </code>.
   *
   * @param pid The identifier for the dictionary to test.
   */
  public boolean exists(String pid) {
    logger.debug("Config exists call for {}", pid);

    boolean exists = false;

    if (isReady(0) && requireRepository) {
      String id = pidToId(pid);
      try {
        ReadRequest readRequest = Requests.newReadRequest(id);
        Resource existing = repo.read(readRequest);
        exists = (existing != null);
      } catch (NotFoundException ex) {
        exists = false;
      } catch (ResourceException ex) {
        throw new RuntimeException(
            "Failed to check if configuration exists in repository: " + ex.getMessage(), ex);
      }
    }
    if (!exists) {
      exists = tempStore.containsKey(pid);
      if (exists) {
        logger.debug("Entry exists in temporary store for '{}'", pid);
      }
    } else {
      logger.debug("Entry exists for '{}'", pid);
    }

    if (!exists) {
      logger.debug("Entry does not exist for '{}'", pid);
    }
    return exists;
  }
  @Test
  public void testReadSchedule() throws Exception {
    // given
    final ReadRequest readRequest = Requests.newReadRequest("test1");

    // when
    Promise<ResourceResponse, ResourceException> promise =
        schedulerService.handleRead(new RootContext(), readRequest);

    // then
    AssertJPromiseAssert.assertThat(promise).isNotNull().succeeded();
    ResourceResponse resourceResponse = promise.getOrThrow();
    assertThat(resourceResponse.getContent().asMap()).isEqualTo(testScheduleConfig.asMap());
  }
Пример #5
0
  @Test
  public void testResource() throws Exception {
    ScriptName scriptName = new ScriptName("resource", getLanguageName());
    ScriptEntry scriptEntry = getScriptRegistry().takeScript(scriptName);
    Assert.assertNotNull(scriptEntry);

    Script script = scriptEntry.getScript(new RootContext());
    // Set RequestLevel Scope
    script.put("ketto", 2);
    script.putSafe("callback", mock(Function.class));

    JsonValue createContent = new JsonValue(new LinkedHashMap<String, Object>());
    createContent.put("externalId", "701984");
    createContent.put("userName", "*****@*****.**");
    createContent.put(
        "assignedDashboard", Arrays.asList("Salesforce", "Google", "ConstantContact"));
    createContent.put("displayName", "Babs Jensen");
    createContent.put("nickName", "Babs");

    JsonValue updateContent = createContent.copy();
    updateContent.put("_id", UUID.randomUUID().toString());
    updateContent.put("profileUrl", "https://login.example.com/bjensen");

    final Context context =
        new ApiInfoContext(
            new SecurityContext(new RootContext(), "*****@*****.**", null), "", "");
    script.put("context", context);

    CreateRequest createRequest = Requests.newCreateRequest("/Users", "701984", createContent);
    script.put("createRequest", createRequest);
    ReadRequest readRequest = Requests.newReadRequest("/Users/701984");
    script.put("readRequest", readRequest);
    UpdateRequest updateRequest = Requests.newUpdateRequest("/Users/701984", updateContent);
    script.put("updateRequest", updateRequest);
    PatchRequest patchRequest =
        Requests.newPatchRequest("/Users/701984", PatchOperation.replace("userName", "ddoe"));
    script.put("patchRequest", patchRequest);
    QueryRequest queryRequest = Requests.newQueryRequest("/Users/");
    script.put("queryRequest", queryRequest);
    DeleteRequest deleteRequest = Requests.newDeleteRequest("/Users/701984");
    script.put("deleteRequest", deleteRequest);
    ActionRequest actionRequest = Requests.newActionRequest("/Users", "clear");
    script.put("actionRequest", actionRequest);
    script.eval();
  }
 @Override
 public Promise<ActionResponse, ResourceException> handleAction(
     final Context context, final ActionRequest request) {
   try {
     Map<String, String> params = request.getAdditionalParameters();
     switch (request.getActionAsEnum(Action.class)) {
       case updateDbCredentials:
         String newUser = params.get("user");
         String newPassword = params.get("password");
         if (newUser == null || newPassword == null) {
           return adapt(new BadRequestException("Expecting 'user' and 'password' parameters"))
               .asPromise();
         }
         synchronized (dbLock) {
           DBHelper.updateDbCredentials(dbURL, user, password, newUser, newPassword);
           JsonValue config =
               connectionFactory
                   .getConnection()
                   .read(context, Requests.newReadRequest("config", PID))
                   .getContent();
           config.put("user", newUser);
           config.put("password", newPassword);
           UpdateRequest updateRequest = Requests.newUpdateRequest("config/" + PID, config);
           connectionFactory.getConnection().update(context, updateRequest);
           return newActionResponse(new JsonValue(params)).asPromise();
         }
       case command:
         return newActionResponse(new JsonValue(command(request))).asPromise();
       default:
         return adapt(new BadRequestException("Unknown action: " + request.getAction()))
             .asPromise();
     }
   } catch (IllegalArgumentException e) {
     return adapt(new BadRequestException("Unknown action: " + request.getAction())).asPromise();
   } catch (ResourceException e) {
     return e.asPromise();
   }
 }
Пример #7
0
  /**
   * Removes the <code>Dictionary</code> for the given <code>pid</code>. If such a dictionary does
   * not exist, this method has no effect.
   *
   * @param pid The identifier of the dictionary to delet.
   * @throws IOException If an error occurrs deleting the dictionary. This exception must not be
   *     thrown if no dictionary with the given identifier exists.
   */
  public void delete(String pid) throws IOException {
    logger.debug("delete call for {}", pid);
    Object removed = tempStore.remove(pid);
    if (removed != null) {
      logger.debug("Deleted {} from temporary store", pid);
    }
    try {
      if (isReady(0) && requireRepository) {
        String id = pidToId(pid);
        boolean retry;
        String rev = null;
        do {
          retry = false;
          try {

            ReadRequest readRequest = Requests.newReadRequest(id);
            Map<String, Object> existing = repo.read(readRequest).getContent().asMap();
            if (existing != null) {
              rev = (String) existing.get("_rev");
              DeleteRequest r = Requests.newDeleteRequest(id);
              r.setRevision(rev);
              repo.delete(r);
              logger.debug("Deleted {}", pid);
            }
          } catch (PreconditionFailedException ex) {
            logger.debug("Concurrent change during delete, retrying {} {}", pid, rev);
            retry = true;
          } catch (NotFoundException ex) {
            // If it doesn't exists (anymore) that's fine
          }
        } while (retry);
      }
    } catch (ResourceException ex) {
      throw new IOException(
          "Failed to delete configuration + " + pid + " in repository: " + ex.getMessage(), ex);
    }
  }
  void doGet(final HttpServletRequest req, final HttpServletResponse resp) {
    try {
      // Parse out the required API versions.
      final AcceptAPIVersion acceptVersion = parseAcceptAPIVersion(req);

      // Prepare response.
      prepareResponse(req, resp);

      // Validate request.
      preprocessRequest(req);
      rejectIfMatch(req);

      final Map<String, String[]> parameters = req.getParameterMap();
      if (hasParameter(req, PARAM_QUERY_ID)
          || hasParameter(req, PARAM_QUERY_EXPRESSION)
          || hasParameter(req, PARAM_QUERY_FILTER)) {
        // Additional pre-validation for queries.
        rejectIfNoneMatch(req);

        // Query against collection.
        final QueryRequest request = Requests.newQueryRequest(getResourceName(req));

        for (final Map.Entry<String, String[]> p : parameters.entrySet()) {
          final String name = p.getKey();
          final String[] values = p.getValue();

          if (parseCommonParameter(name, values, request)) {
            continue;
          } else if (name.equalsIgnoreCase(PARAM_SORT_KEYS)) {
            for (final String s : values) {
              try {
                request.addSortKey(s.split(SORT_KEYS_DELIMITER));
              } catch (final IllegalArgumentException e) {
                // FIXME: i18n.
                throw new BadRequestException(
                    "The value '"
                        + s
                        + "' for parameter '"
                        + name
                        + "' could not be parsed as a comma "
                        + "separated list of sort keys");
              }
            }
          } else if (name.equalsIgnoreCase(PARAM_QUERY_ID)) {
            request.setQueryId(asSingleValue(name, values));
          } else if (name.equalsIgnoreCase(PARAM_QUERY_EXPRESSION)) {
            request.setQueryExpression(asSingleValue(name, values));
          } else if (name.equalsIgnoreCase(PARAM_PAGED_RESULTS_COOKIE)) {
            request.setPagedResultsCookie(asSingleValue(name, values));
          } else if (name.equalsIgnoreCase(PARAM_PAGED_RESULTS_OFFSET)) {
            request.setPagedResultsOffset(asIntValue(name, values));
          } else if (name.equalsIgnoreCase(PARAM_PAGE_SIZE)) {
            request.setPageSize(asIntValue(name, values));
          } else if (name.equalsIgnoreCase(PARAM_QUERY_FILTER)) {
            final String s = asSingleValue(name, values);
            try {
              request.setQueryFilter(QueryFilter.valueOf(s));
            } catch (final IllegalArgumentException e) {
              // FIXME: i18n.
              throw new BadRequestException(
                  "The value '"
                      + s
                      + "' for parameter '"
                      + name
                      + "' could not be parsed as a valid query filter");
            }
          } else {
            request.setAdditionalParameter(name, asSingleValue(name, values));
          }
        }

        // Check for incompatible arguments.
        if (request.getQueryId() != null && request.getQueryFilter() != null) {
          // FIXME: i18n.
          throw new BadRequestException(
              "The parameters "
                  + PARAM_QUERY_ID
                  + " and "
                  + PARAM_QUERY_FILTER
                  + " are mutually exclusive");
        }

        if (request.getQueryId() != null && request.getQueryExpression() != null) {
          // FIXME: i18n.
          throw new BadRequestException(
              "The parameters "
                  + PARAM_QUERY_ID
                  + " and "
                  + PARAM_QUERY_EXPRESSION
                  + " are mutually exclusive");
        }

        if (request.getQueryFilter() != null && request.getQueryExpression() != null) {
          // FIXME: i18n.
          throw new BadRequestException(
              "The parameters "
                  + PARAM_QUERY_FILTER
                  + " and "
                  + PARAM_QUERY_EXPRESSION
                  + " are mutually exclusive");
        }

        doRequest(req, resp, acceptVersion, request);
      } else {
        // Read of instance within collection or singleton.
        final String rev = getIfNoneMatch(req);
        if (ETAG_ANY.equals(rev)) {
          // FIXME: i18n
          throw new PreconditionFailedException(
              "If-None-Match * not appropriate for " + getMethod(req) + " requests");
        }

        final ReadRequest request = Requests.newReadRequest(getResourceName(req));
        for (final Map.Entry<String, String[]> p : parameters.entrySet()) {
          final String name = p.getKey();
          final String[] values = p.getValue();
          if (parseCommonParameter(name, values, request)) {
            continue;
          } else if (PARAM_MIME_TYPE.equalsIgnoreCase(name)) {
            if (values.length != 1 || values[0].split(FIELDS_DELIMITER).length > 1) {
              // FIXME: i18n.
              throw new BadRequestException("Only one mime type value allowed");
            }
            if (parameters.get(PARAM_FIELDS).length != 1) {
              // FIXME: i18n.
              throw new BadRequestException(
                  "The mime type parameter requires only 1 field to be specified");
            }
          } else {
            request.setAdditionalParameter(name, asSingleValue(name, values));
          }
        }
        doRequest(req, resp, acceptVersion, request);
      }
    } catch (final Exception e) {
      fail(req, resp, e);
    }
  }
Пример #9
0
  /**
   * Stores the <code>Dictionary</code> under the given <code>pid</code>.
   *
   * @param pid The identifier of the dictionary.
   * @param properties The <code>Dictionary</code> to store.
   * @throws IOException If an error occurrs storing the dictionary. If this exception is thrown, it
   *     is expected, that {@link #exists(String) exists(pid} returns <code>false</code>.
   */
  public void store(String pid, Dictionary properties) throws IOException {
    logger.debug("Store call for {} {}", pid, properties);

    // Store config handling settings in memory
    if (pid.startsWith("org.apache.felix.fileinstall")) {
      tempStore.put(pid, properties);
      return;
    }

    try {
      if (isReady(0) && requireRepository) {
        String id = pidToId(pid);

        Map<String, Object> obj = dictToMap(properties);
        JsonValue content = new JsonValue(obj);
        String configResourceId =
            ConfigBootstrapHelper.getId(
                content.get(ConfigBootstrapHelper.CONFIG_ALIAS).asString(),
                content.get(ConfigBootstrapHelper.SERVICE_PID).asString(),
                content.get(ConfigBootstrapHelper.SERVICE_FACTORY_PID).asString());
        String configString = (String) obj.get(JSONEnhancedConfig.JSON_CONFIG_PROPERTY);
        Map<Object, Object> configMap = deserializeConfig(configString);
        if (configMap != null) {
          configMap.put("_id", configResourceId);
        }
        obj.put(JSONEnhancedConfig.JSON_CONFIG_PROPERTY, configMap);

        Map<String, Object> existing = null;
        try {
          ReadRequest readRequest = Requests.newReadRequest(id);
          existing = repo.read(readRequest).getContent().asMap();
        } catch (NotFoundException ex) {
          // Just detect that it doesn't exist
        }
        if (existing != null) {
          String rev = (String) existing.get("_rev");

          existing.remove("_rev");
          existing.remove("_id");
          obj.remove("_rev"); // beware, this means _id and _rev should not be in config file
          obj.remove("_id"); // beware, this means _id and _rev should not be in config file
          obj.remove(RepoPersistenceManager.BUNDLE_LOCATION);
          obj.remove(RepoPersistenceManager.FELIX_FILEINSTALL_FILENAME);
          if (!existing.equals(obj)) {
            logger.trace("Not matching {} {}", existing, obj);
            boolean retry;
            do {
              retry = false;
              try {
                UpdateRequest r = Requests.newUpdateRequest(id, new JsonValue(obj));
                r.setRevision(rev);
                repo.update(r);
              } catch (PreconditionFailedException ex) {
                logger.debug("Concurrent change during update, retrying {} {}", pid, rev);
                ReadRequest readRequest = Requests.newReadRequest(id);
                existing = repo.read(readRequest).getContent().asMap();
                retry = true;
              }
            } while (retry);
            logger.debug("Updated existing config {} {} {}", new Object[] {pid, rev, obj});
          } else {
            logger.debug(
                "Existing config same as store request, ignoring {} {} {}",
                new Object[] {pid, rev, obj});
          }
        } else {
          logger.trace("Creating: {} {} ", id, obj);
          // This may create a new (empty) configuration, which felix marks with
          // _felix___cm__newConfiguration=true
          String newResourceId = id.substring(CONFIG_CONTEXT_PREFIX.length());
          CreateRequest createRequest =
              Requests.newCreateRequest(CONFIG_CONTEXT_PREFIX, new JsonValue(obj));
          createRequest.setNewResourceId(newResourceId);
          obj = repo.create(createRequest).getContent().asMap();
          logger.debug("Stored new config in repository {} {}", pid, obj);
        }
      } else {
        tempStore.put(pid, properties);
        logger.debug("Stored in memory {} {}", pid, properties);
      }
    } catch (ResourceException ex) {
      throw new IOException("Failed to store configuration in repository: " + ex.getMessage(), ex);
    }
  }