All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.acs.commons.reports.models.QueryReportExecutor Maven / Gradle / Ivy

/*
 * #%L
 * ACS AEM Commons Bundle
 * %%
 * Copyright (C) 2017 Adobe
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
package com.adobe.acs.commons.reports.models;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import javax.jcr.query.Row;
import javax.jcr.query.RowIterator;

import com.adobe.acs.commons.reports.api.ReportException;
import com.adobe.acs.commons.reports.api.ReportExecutor;
import com.adobe.acs.commons.reports.api.ResultsPage;
import com.github.jknack.handlebars.Handlebars;
import com.github.jknack.handlebars.Template;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.Model;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Model for executing report requests.
 */
@Model(adaptables = SlingHttpServletRequest.class)
public class QueryReportExecutor implements ReportExecutor {

  private static final Logger log = LoggerFactory.getLogger(QueryReportExecutor.class);

  private QueryReportConfig config;

  private int page;

  private SlingHttpServletRequest request;

  private String statement;

  public QueryReportExecutor(SlingHttpServletRequest request) {
    this.request = request;
  }

  private ResultsPage fetchResults(int limit, int offset) throws ReportException {
    prepareStatement();
    try {
      ResourceResolver resolver = request.getResourceResolver();
      QueryManager queryMgr = Optional.ofNullable(resolver.adaptTo(Session.class))
          .orElseThrow(() -> new ReportException("Failed to get JCR Session")).getWorkspace().getQueryManager();

      Query query = queryMgr.createQuery(statement, config.getQueryLanguage());

      if (page != -1) {
        log.debug("Fetching results with limit {} and offset {}", limit, offset);
        query.setLimit(limit);
        query.setOffset(offset);
      } else {
        log.debug("Fetching all results");
      }
      QueryResult result = query.execute();

      NodeIterator nodes = result.getNodes();

      Spliterator spliterator = Spliterators.spliteratorUnknownSize(nodes,
          Spliterator.ORDERED | Spliterator.NONNULL);

      Stream results = StreamSupport.stream(spliterator, false).map(n -> getResource(n, resolver));

      return new ResultsPage(results, config.getPageSize(), page, nodes.getSize());
    } catch (RepositoryException re) {
      throw new ReportException("Exception executing search results", re);
    }
  }

  @Override
  public ResultsPage getAllResults() throws ReportException {
    return fetchResults(Integer.MAX_VALUE, 0);
  }

  @Override
  public String getDetails() throws ReportException {
    Map details = new LinkedHashMap<>();
    details.put("Language", config.getQueryLanguage());
    details.put("Page", Integer.toString(page));
    details.put("Page Size", Integer.toString(config.getPageSize()));
    details.put("Query", statement);

    try {
      final QueryManager queryManager = Optional.ofNullable(request.getResourceResolver().adaptTo(Session.class))
          .orElseThrow(() -> new ReportException("Failed to get JCR Session")).getWorkspace().getQueryManager();
      final Query query = queryManager.createQuery("explain " + statement, config.getQueryLanguage());
      final QueryResult queryResult = query.execute();

      final RowIterator rows = queryResult.getRows();
      while (rows.hasNext()) {
        final Row row = rows.nextRow();

        String[] cols = queryResult.getColumnNames();
        Value[] values = row.getValues();

        for (int i = 0; i < cols.length; i++) {
          details.put(cols[i], values[i].getString());
        }
      }

    } catch (RepositoryException re) {
      throw new ReportException("Exception getting details", re);
    }
    StringBuilder sb = new StringBuilder();
    for (Entry entry : details.entrySet()) {
      sb.append("
" + StringEscapeUtils.escapeHtml(entry.getKey()) + "
"); sb.append("
" + StringEscapeUtils.escapeHtml(entry.getValue()) + "
"); } return "
" + sb.toString() + "
"; } @Override public String getParameters() throws ReportException { List params = new ArrayList<>(); Enumeration keys = request.getParameterNames(); while (keys.hasMoreElements()) { String key = keys.nextElement(); for (String value : request.getParameterValues(key)) { try { params.add(URLEncoder.encode(key, "UTF-8") + "=" + URLEncoder.encode(value, "UTF-8")); } catch (UnsupportedEncodingException e) { throw new ReportException("UTF-8 encoding available", e); } } } return StringUtils.join(params, "&"); } private Resource getResource(Node node, ResourceResolver resolver) { try { return resolver.getResource(node.getPath()); } catch (RepositoryException e) { log.warn("Failed to get path from node: {}", node, e); return null; } } @Override public ResultsPage getResults() throws ReportException { return fetchResults(config.getPageSize(), config.getPageSize() * page); } private void prepareStatement() throws ReportException { try { Map parameters = getParamPatternMap(request); Template template = new Handlebars().compileInline(config.getQuery()); statement = template.apply(parameters); log.trace("Loaded statement: {}", statement); } catch (IOException ioe) { throw new ReportException("Exception templating query", ioe); } } @Override public void setConfiguration(Resource config) { this.config = config.adaptTo(QueryReportConfig.class); } @Override public void setPage(int page) { this.page = page; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy