/* * Copyright 2017-present Facebook, 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 com.facebook.buck.rules; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.CmdLineException; import org.kohsuke.args4j.CmdLineParser; import org.kohsuke.args4j.Option; import org.kohsuke.args4j.OptionDef; import org.kohsuke.args4j.spi.EnumOptionHandler; import org.kohsuke.args4j.spi.Setter; import org.mapdb.DB; import org.mapdb.DBMaker; import org.mapdb.Serializer; public class MapDBCommandLine { enum MapType { TREE, HASH, } enum Command { PUT, GET, DELETE, SCAN, } public static class MapTypeOptionHandler extends EnumOptionHandler<MapType> { public MapTypeOptionHandler( CmdLineParser parser, OptionDef option, Setter<? super MapType> setter) { super(parser, option, setter, MapType.class); } } public static class CommandOptionHandler extends EnumOptionHandler<Command> { public CommandOptionHandler( CmdLineParser parser, OptionDef option, Setter<? super Command> setter) { super(parser, option, setter, Command.class); } } @Option(name = "--db", usage = "path to database file", required = true) private String dbPath; @Option(name = "--map", usage = "name of map within database") private String mapName = "map"; @Option(name = "--type", handler = MapTypeOptionHandler.class, usage = "type of map") private MapType mapType = MapType.TREE; @Argument(index = 0, handler = CommandOptionHandler.class, required = true, metaVar = "COMMAND") private Command command; @Argument(index = 1) private List<String> arguments = new ArrayList<>(); Map<String, String> getMap(DB db) { switch (mapType) { case HASH: return db.hashMap(mapName, Serializer.STRING, Serializer.STRING).createOrOpen(); case TREE: return db.treeMap(mapName, Serializer.STRING, Serializer.STRING).createOrOpen(); } throw new IllegalArgumentException(); } private void runCommand(DB db) { Map<String, String> map = getMap(db); switch (command) { case PUT: if (arguments.size() != 2) { throw new IllegalArgumentException("PUT requires exactly two arguments (KEY and VALUE)"); } map.put(arguments.get(0), arguments.get(1)); break; case GET: if (arguments.size() != 1) { throw new IllegalArgumentException("GET requires exactly one argument (KEY)"); } String value = map.get(arguments.get(0)); if (value != null) { System.out.println(value); } else { System.err.format("%s: key not found\n", arguments.get(0)); } break; case DELETE: if (arguments.size() != 1) { throw new IllegalArgumentException("DELETE requires exactly one argument (KEY)"); } map.remove(arguments.get(0)); break; case SCAN: for (Map.Entry<String, String> e : map.entrySet()) { System.out.format("%s : %s\n", e.getKey(), e.getValue()); } break; } } private void runMain(String[] args) { CmdLineParser parser = new CmdLineParser(this); try { parser.parseArgument(args); } catch (CmdLineException e) { // XXX: do something with it System.err.println(e.getLocalizedMessage()); parser.printUsage(System.err); System.exit(1); } try (DB db = DBMaker.fileDB(dbPath.toString()).fileMmapEnableIfSupported().make()) { runCommand(db); } catch (IllegalArgumentException e) { System.err.println(e.getLocalizedMessage()); System.exit(1); } } public static void main(String[] args) { new MapDBCommandLine().runMain(args); } }