Beispiel #1
0
 /**
  * Queries all the links for a given mapping, indexed by the source identifier
  *
  * <p>This method expects a {@code "links-for-linkType"} defined with a parameter of {@code
  * "linkType"}.
  *
  * @param mapping the mapping to look up the links for
  * @throws SynchronizationException if the query could not be performed.
  * @return the mapping from source identifier to the link object for it
  */
 public static Map<String, Link> getLinksForMapping(ObjectMapping mapping, String linkQualifier)
     throws SynchronizationException {
   Map<String, Link> sourceIdToLink = new ConcurrentHashMap<String, Link>();
   if (mapping != null) {
     JsonValue query = new JsonValue(new HashMap<String, Object>());
     query.put(
         PARAM_QUERY_FILTER,
         QueryFilter.and(
                 Arrays.asList(
                     QueryFilter.equalTo("/linkType", mapping.getLinkType().getName()),
                     QueryFilter.equalTo("/linkQualifier", linkQualifier)))
             .toString());
     JsonValue queryResults =
         linkQuery(
             mapping.getService().getServerContext(),
             mapping.getService().getConnectionFactory(),
             query);
     for (JsonValue entry : queryResults) {
       Link link = new Link(mapping);
       link.fromJsonValue(entry);
       sourceIdToLink.put(link.sourceId, link);
     }
   }
   return sourceIdToLink;
 }
 /** {@inheritDoc} */
 @Override
 public Set<SearchFilter> visitAndFilter(Set<SearchFilter> filters, List<QueryFilter> subFilters) {
   for (QueryFilter queryFilter : subFilters) {
     queryFilter.accept(this, filters);
   }
   return filters;
 }
Beispiel #3
0
 /**
  * Queries the links for a match on the second system (links can be bi-directional)
  *
  * <p>This method expects a {@code "links-for-targetId"} defined with a parameter of {@code
  * "targetId"}.
  *
  * @param targetId TODO.
  * @throws SynchronizationException TODO.
  */
 void getLinkFromSecond(String id) throws SynchronizationException {
   clear();
   if (id != null) {
     JsonValue query = new JsonValue(new HashMap<String, Object>());
     query.put(
         PARAM_QUERY_FILTER,
         QueryFilter.and(
                 Arrays.asList(
                     QueryFilter.equalTo("/linkType", mapping.getLinkType().getName()),
                     QueryFilter.equalTo("/linkQualifier", linkQualifier),
                     QueryFilter.equalTo("/secondId", id)))
             .toString());
     getLink(query);
   }
 }
  @Test
  public void nameQueryShouldBeSupported() throws Exception {

    // Given
    ServerContext context = mock(ServerContext.class);
    QueryRequest request = mock(QueryRequest.class);
    given(request.getFields()).willReturn(Arrays.asList(new JsonPointer("/fred")));
    QueryResultHandler handler = mock(QueryResultHandler.class);
    ResourceSetDescription resourceSet = mock(ResourceSetDescription.class);
    QueryFilter queryFilter =
        QueryFilter.and(
            QueryFilter.equalTo("/name", "NAME"),
            QueryFilter.equalTo("/resourceServer", "myclient"),
            QueryFilter.equalTo("/policy/permissions/subject", "SUBJECT"));
    Promise<Collection<ResourceSetDescription>, ResourceException> resourceSetsPromise =
        Promises.newSuccessfulPromise((Collection<ResourceSetDescription>) asSet(resourceSet));

    given(contextHelper.getRealm(context)).willReturn("REALM");
    given(contextHelper.getUserId(context)).willReturn("RESOURCE_OWNER_ID");
    given(request.getQueryFilter()).willReturn(queryFilter);
    given(
            resourceSetService.getResourceSets(
                eq(context),
                eq("REALM"),
                Matchers.<ResourceSetWithPolicyQuery>anyObject(),
                eq("RESOURCE_OWNER_ID"),
                eq(false)))
        .willReturn(resourceSetsPromise);

    // When
    resource.queryCollection(context, request, handler);

    // Then
    ArgumentCaptor<ResourceSetWithPolicyQuery> queryCaptor =
        ArgumentCaptor.forClass(ResourceSetWithPolicyQuery.class);
    verify(resourceSetService)
        .getResourceSets(
            eq(context), eq("REALM"), queryCaptor.capture(), eq("RESOURCE_OWNER_ID"), eq(false));
    assertThat(queryCaptor.getValue().getOperator()).isEqualTo(AggregateQuery.Operator.AND);
    assertThat(queryCaptor.getValue().getPolicyQuery())
        .isEqualTo(QueryFilter.equalTo("/permissions/subject", "SUBJECT"));
    assertThat(queryCaptor.getValue().getResourceSetQuery())
        .isEqualTo(
            org.forgerock.util.query.QueryFilter.and(
                org.forgerock.util.query.QueryFilter.equalTo("name", "NAME"),
                org.forgerock.util.query.QueryFilter.equalTo("clientId", "myclient")));
    verify(handler).handleResult(any(QueryResult.class));
  }
  @Override
  public List<Privilege> query(QueryRequest request) throws EntitlementException {
    QueryFilter queryFilter = request.getQueryFilter();
    if (queryFilter == null) {
      // Return everything
      queryFilter = QueryFilter.alwaysTrue();
    }

    try {
      Set<SearchFilter> searchFilters =
          queryFilter.accept(
              new PrivilegeQueryBuilder(queryAttributes), new HashSet<SearchFilter>());

      return privilegeManager.search(searchFilters);
    } catch (UnsupportedOperationException ex) {
      throw new EntitlementException(
          EntitlementException.INVALID_SEARCH_FILTER, new Object[] {ex.getMessage()});
    } catch (IllegalArgumentException ex) {
      throw new EntitlementException(
          EntitlementException.INVALID_VALUE, new Object[] {ex.getMessage()});
    }
  }
  @Test
  public void queryShouldNotBeSupported() {

    // Given
    ServerContext context = mock(ServerContext.class);
    QueryRequest request = mock(QueryRequest.class);
    QueryResultHandler handler = mock(QueryResultHandler.class);
    given(request.getQueryFilter()).willReturn(QueryFilter.equalTo(new JsonPointer("/fred"), 5));

    // When
    resource.queryCollection(context, request, handler);

    // Then
    verify(handler).handleError(Matchers.<NotSupportedException>anyObject());
  }
  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);
    }
  }
Beispiel #8
0
  /**
   * Execute a query, either a pre-configured query by using the query ID, or a query expression
   * passed as part of the params.
   *
   * <p>The keys for the input parameters as well as the return map entries are in QueryConstants.
   *
   * @param type the resource component name targeted by the URI
   * @param params the parameters which include the query id, or the query expression, as well as
   *     the token key/value pairs to replace in the query
   * @param con a handle to a database connection newBuilder for exclusive use by the query method
   *     whilst it is executing.
   * @return The query result, which includes meta-data about the query, and the result set itself.
   * @throws BadRequestException if the passed request parameters are invalid, e.g. missing query id
   *     or query expression or tokens.
   * @throws InternalServerErrorException if the preparing or executing the query fails because of
   *     configuration or DB issues
   */
  public List<Map<String, Object>> query(
      final String type, Map<String, Object> params, Connection con) throws ResourceException {

    List<Map<String, Object>> result = null;
    params.put(ServerConstants.RESOURCE_NAME, type);

    // If paged results are requested then decode the cookie in order to determine
    // the index of the first result to be returned.
    final int requestPageSize = (Integer) params.get(PAGE_SIZE);

    final String offsetParam;
    final String pageSizeParam;

    if (requestPageSize > 0) {
      offsetParam = String.valueOf((Integer) params.get(PAGED_RESULTS_OFFSET));
      pageSizeParam = String.valueOf(requestPageSize);
    } else {
      offsetParam = "0";
      pageSizeParam = String.valueOf(Integer.MAX_VALUE);
    }

    params.put(PAGED_RESULTS_OFFSET, offsetParam);
    params.put(PAGE_SIZE, pageSizeParam);
    QueryFilter queryFilter = (QueryFilter) params.get(QUERY_FILTER);
    String queryExpression = (String) params.get(QUERY_EXPRESSION);
    String queryId = (String) params.get(QUERY_ID);
    if (queryId == null && queryExpression == null && queryFilter == null) {
      throw new BadRequestException(
          "Either "
              + QUERY_ID
              + ", "
              + QUERY_EXPRESSION
              + ", or "
              + QUERY_FILTER
              + " to identify/define a query must be passed in the parameters. "
              + params);
    }
    logger.debug("Querying " + params);
    final PreparedStatement foundQuery;
    try {
      if (queryFilter != null) {
        foundQuery = parseQueryFilter(con, queryFilter, params);
      } else if (queryExpression != null) {
        foundQuery = resolveInlineQuery(con, queryExpression, params);
      } else if (queries.queryIdExists(queryId)) {
        foundQuery = queries.getQuery(con, queryId, type, params);
      } else {
        throw new BadRequestException(
            "The passed query identifier "
                + queryId
                + " does not match any configured queries on the JDBC repository service.");
      }
    } catch (SQLException ex) {
      final String queryDescription;
      if (queryFilter != null) {
        queryDescription = queryFilter.toString();
      } else if (queryExpression != null) {
        queryDescription = queryExpression;
      } else {
        queryDescription = queries.getQueryInfo(queryId).getQueryString();
      }
      throw new InternalServerErrorException(
          "DB reported failure preparing query: "
              + queryDescription
              + " with params: "
              + params
              + " error code: "
              + ex.getErrorCode()
              + " sqlstate: "
              + ex.getSQLState()
              + " message: "
              + ex.getMessage(),
          ex);
    }

    Name eventName = getEventName(queryId);
    EventEntry measure = Publisher.start(eventName, foundQuery, null);
    ResultSet rs = null;
    try {
      rs = foundQuery.executeQuery();
      result = resultMapper.mapQueryToObject(rs, queryId, type, params, this);
      measure.setResult(result);
    } catch (SQLException ex) {
      throw new InternalServerErrorException(
          "DB reported failure executing query "
              + foundQuery.toString()
              + " with params: "
              + params
              + " error code: "
              + ex.getErrorCode()
              + " sqlstate: "
              + ex.getSQLState()
              + " message: "
              + ex.getMessage(),
          ex);
    } catch (IOException ex) {
      throw new InternalServerErrorException(
          "Failed to convert result objects for query "
              + foundQuery.toString()
              + " with params: "
              + params
              + " message: "
              + ex.getMessage(),
          ex);
    } finally {
      CleanupHelper.loggedClose(rs);
      CleanupHelper.loggedClose(foundQuery);
      measure.end();
    }
    return result;
  }