/* * Copyright © 2014 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.cli.util; import co.cask.cdap.api.common.Bytes; import co.cask.cdap.cli.CLIConfig; import co.cask.cdap.cli.exception.CommandInputError; import co.cask.cdap.proto.Id; import co.cask.cdap.proto.ProgramType; import co.cask.common.cli.util.Parser; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import java.nio.ByteBuffer; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; /** * */ public abstract class AbstractCommand extends AbstractAuthCommand { private static final int DEFAULT_MAX_BODY_SIZE = 256; private static final int DEFAULT_LINE_WRAP_LIMIT = 64; private static final String DEFAULT_LINE_SEPARATOR = System.getProperty("line.separator"); public AbstractCommand(CLIConfig cliConfig) { super(cliConfig); } protected Map<String, String> parseMap(@Nullable String value) { return ArgumentParser.parseMap(value); } protected List<String> parseList(@Nullable String value) { if (value == null) { return ImmutableList.of(); } return Parser.parseInput(value); } /** * Creates a string representing the body in the output. It only prints up to {@link #DEFAULT_MAX_BODY_SIZE}, * with line wrap at each {@link #DEFAULT_LINE_WRAP_LIMIT} character. */ protected String getBody(ByteBuffer body) { return getBody(body, DEFAULT_MAX_BODY_SIZE, DEFAULT_LINE_WRAP_LIMIT, DEFAULT_LINE_SEPARATOR); } /** * Creates a string representing the body in the output. It only prints up to {@code maxBodySize}, with line * wrap at each {@code lineWrapLimit} character. */ protected String getBody(ByteBuffer body, int maxBodySize, int lineWrapLimit, String lineSeparator) { ByteBuffer bodySlice = body.slice(); boolean hasMore = false; if (bodySlice.remaining() > maxBodySize) { bodySlice.limit(maxBodySize); hasMore = true; } String str = Bytes.toStringBinary(bodySlice) + (hasMore ? "..." : ""); if (str.length() <= lineWrapLimit) { return str; } return Joiner.on(lineSeparator).join(Splitter.fixedLength(lineWrapLimit).split(str)); } protected void checkInputLength(String[] inputParts, int requiredLength) { if (inputParts.length != requiredLength) { throw new CommandInputError(this); } } /** * Creates a string representing the output of response headers. Each key/value pair is outputted on its own * line in the form {@code <key> : <value>}. */ protected String formatHeader(Map<String, String> headers) { StringBuilder builder = new StringBuilder(); String separator = ""; for (Map.Entry<String, String> entry : headers.entrySet()) { builder.append(separator).append(entry.getKey()).append(" : ").append(entry.getValue()); separator = DEFAULT_LINE_SEPARATOR; } return builder.toString(); } /** * Returns a timestamp in milliseconds. * * @param arg The string argument user provided. * @param base The base timestamp to relative from if the time format provided is a relative time. * @return Timestamp in milliseconds * @throws co.cask.cdap.cli.exception.CommandInputError if failed to parse input. */ protected long getTimestamp(String arg, long base) { try { if (arg.startsWith("+") || arg.startsWith("-")) { int dir = arg.startsWith("+") ? 1 : -1; char type = arg.charAt(arg.length() - 1); int offset = Integer.parseInt(arg.substring(1, arg.length() - 1)); switch (type) { case 's': return base + dir * TimeUnit.SECONDS.toMillis(offset); case 'm': return base + dir * TimeUnit.MINUTES.toMillis(offset); case 'h': return base + dir * TimeUnit.HOURS.toMillis(offset); case 'd': return base + dir * TimeUnit.DAYS.toMillis(offset); default: throw new CommandInputError(this, "Unsupported relative time format: " + type); } } if (arg.equalsIgnoreCase("min")) { return 0L; } if (arg.equalsIgnoreCase("max")) { return Long.MAX_VALUE; } return Long.parseLong(arg); } catch (NumberFormatException e) { throw new CommandInputError(this, "Invalid number value: " + arg + ". Reason: " + e.getMessage()); } } protected Id.Application parseAppId(String[] programIdParts) { checkInputLength(programIdParts, 1); return Id.Application.from(cliConfig.getCurrentNamespace(), programIdParts[0]); } protected Id.Program parseProgramId(String[] programIdParts, ProgramType programType) { checkInputLength(programIdParts, 2); return Id.Program.from(Id.Application.from(cliConfig.getCurrentNamespace(), programIdParts[0]), programType, programIdParts[1]); } }