/* * Copyright © 2015 Cask Data, Inc. *   * 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. */ package co.cask.cdap.explore.executor; import co.cask.cdap.explore.service.ExploreException; import co.cask.cdap.explore.service.HandleNotFoundException; import co.cask.cdap.proto.ColumnDesc; import co.cask.cdap.proto.QueryInfo; import co.cask.cdap.proto.QueryResult; import co.cask.http.AbstractHttpHandler; import com.google.common.base.Charsets; import com.google.common.base.Predicate; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.primitives.Longs; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBufferInputStream; import org.jboss.netty.handler.codec.http.HttpRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.lang.reflect.Type; import java.sql.SQLException; import java.util.Comparator; import java.util.List; import java.util.Map; import javax.annotation.Nullable; /** * An abstract class that provides common functionality for namespaced and non-namespaced ExploreQuery handlers. */ public class AbstractQueryExecutorHttpHandler extends AbstractHttpHandler { private static final Logger LOG = LoggerFactory.getLogger(AbstractQueryExecutorHttpHandler.class); protected static final Gson GSON = new Gson(); protected static final int DOWNLOAD_FETCH_CHUNK_SIZE = 1000; protected static final Type STRING_MAP_TYPE = new TypeToken<Map<String, String>>() { }.getType(); protected List<QueryInfo> filterQueries(List<QueryInfo> queries, final long offset, final boolean isForward, final int limit) { // Reverse the list if the pagination is in the reverse from the offset until the max limit if (!isForward) { queries = Lists.reverse(queries); } return FluentIterable.from(queries) .filter(new Predicate<QueryInfo>() { @Override public boolean apply(@Nullable QueryInfo queryInfo) { if (isForward) { return queryInfo.getTimestamp() < offset; } else { return queryInfo.getTimestamp() > offset; } } }) .limit(limit) .toSortedImmutableList(new Comparator<QueryInfo>() { @Override public int compare(QueryInfo first, QueryInfo second) { //sort descending. return Longs.compare(second.getTimestamp(), first.getTimestamp()); } }); } // get arguments contained in the request body protected Map<String, String> decodeArguments(HttpRequest request) throws IOException { ChannelBuffer content = request.getContent(); if (!content.readable()) { return ImmutableMap.of(); } try (Reader reader = new InputStreamReader(new ChannelBufferInputStream(content), Charsets.UTF_8)) { Map<String, String> args = GSON.fromJson(reader, STRING_MAP_TYPE); return args == null ? ImmutableMap.<String, String>of() : args; } catch (JsonSyntaxException e) { LOG.info("Failed to parse runtime arguments on {}", request.getUri(), e); throw e; } } protected String getCSVHeaders(List<ColumnDesc> schema) throws HandleNotFoundException, SQLException, ExploreException { StringBuffer sb = new StringBuffer(); boolean first = true; for (ColumnDesc columnDesc : schema) { if (first) { first = false; } else { sb.append(','); } sb.append(columnDesc.getName()); } return sb.toString(); } protected String appendCSVRow(StringBuffer sb, QueryResult result) throws HandleNotFoundException, SQLException, ExploreException { boolean first = true; for (Object o : result.getColumns()) { if (first) { first = false; } else { sb.append(','); } // Using GSON toJson will serialize objects - in particular, strings will be quoted sb.append(GSON.toJson(o)); } return sb.toString(); } }