com.zimbra.cs.volume.VolumeCLI.java Source code

Java tutorial

Introduction

Here is the source code for com.zimbra.cs.volume.VolumeCLI.java

Source

/*
 * ***** BEGIN LICENSE BLOCK *****
 * Zimbra Collaboration Suite Server
 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2016 Synacor, Inc.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software Foundation,
 * version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License along with this program.
 * If not, see <https://www.gnu.org/licenses/>.
 * ***** END LICENSE BLOCK *****
 */
package com.zimbra.cs.volume;

import java.io.IOException;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

import com.google.common.base.Strings;
import com.zimbra.common.auth.ZAuthToken;
import com.zimbra.common.service.ServiceException;
import com.zimbra.common.soap.SoapFaultException;
import com.zimbra.common.soap.SoapTransport;
import com.zimbra.common.util.CliUtil;
import com.zimbra.cs.util.BuildInfo;
import com.zimbra.cs.util.SoapCLI;
import com.zimbra.soap.JaxbUtil;
import com.zimbra.soap.admin.message.CreateVolumeRequest;
import com.zimbra.soap.admin.message.CreateVolumeResponse;
import com.zimbra.soap.admin.message.DeleteVolumeRequest;
import com.zimbra.soap.admin.message.GetAllVolumesRequest;
import com.zimbra.soap.admin.message.GetAllVolumesResponse;
import com.zimbra.soap.admin.message.GetVolumeRequest;
import com.zimbra.soap.admin.message.GetVolumeResponse;
import com.zimbra.soap.admin.message.ModifyVolumeRequest;
import com.zimbra.soap.admin.message.SetCurrentVolumeRequest;
import com.zimbra.soap.admin.type.VolumeInfo;

public final class VolumeCLI extends SoapCLI {

    private static final String O_A = "a";
    private static final String O_D = "d";
    private static final String O_L = "l";
    private static final String O_E = "e";
    private static final String O_DC = "dc";
    private static final String O_SC = "sc";
    private static final String O_TS = "ts";
    private static final String O_ID = "id";
    private static final String O_T = "t";
    private static final String O_N = "n";
    private static final String O_P = "p";
    private static final String O_C = "c";
    private static final String O_CT = "ct";

    private VolumeCLI() throws ServiceException {
        super();
        setupCommandLineOptions();
    }

    private ZAuthToken auth;
    private String id;
    private String type;
    private String name;
    private String path;
    private String compress;
    private String compressThreshold;

    private void setArgs(CommandLine cl) throws ServiceException, ParseException, IOException {
        auth = getZAuthToken(cl);
        id = cl.getOptionValue(O_ID);
        type = cl.getOptionValue(O_T);
        name = cl.getOptionValue(O_N);
        path = cl.getOptionValue(O_P);
        compress = cl.getOptionValue(O_C);
        compressThreshold = cl.getOptionValue(O_CT);
    }

    public static void main(String[] args) {
        CliUtil.toolSetup();
        SoapTransport.setDefaultUserAgent("zmvolume", BuildInfo.VERSION);
        VolumeCLI util = null;
        try {
            util = new VolumeCLI();
        } catch (ServiceException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
        try {
            CommandLine cl = util.getCommandLine(args);
            if (cl == null) {
                return;
            }
            util.setArgs(cl);

            if (cl.hasOption(O_A)) {
                util.addVolume();
            } else if (cl.hasOption(O_D)) {
                util.deleteVolume();
            } else if (cl.hasOption(O_L)) {
                util.getVolume();
            } else if (cl.hasOption(O_E)) {
                util.editVolume();
            } else if (cl.hasOption(O_DC)) {
                util.getCurrentVolumes();
            } else if (cl.hasOption(O_SC)) {
                util.setCurrentVolume();
            } else if (cl.hasOption(O_TS)) {
                util.unsetCurrentSecondaryMessageVolume();
            } else {
                throw new ParseException("No action (-a,-d,-l,-e,-dc,-sc,-ts) is specified");
            }
            System.exit(0);
        } catch (ParseException e) {
            util.usage(e);
        } catch (Exception e) {
            System.err.println("Error occurred: " + e.getMessage());
        }
        System.exit(1);
    }

    private void setCurrentVolume() throws ParseException, SoapFaultException, IOException, ServiceException {
        if (id == null) {
            throw new ParseException("id is missing");
        }

        auth(auth);
        GetVolumeResponse resp = JaxbUtil.elementToJaxb(getTransport()
                .invokeWithoutSession(JaxbUtil.jaxbToElement(new GetVolumeRequest(Short.valueOf(id)))));
        VolumeInfo vol = resp.getVolume();
        SetCurrentVolumeRequest req = new SetCurrentVolumeRequest(vol.getId(), vol.getType());
        getTransport().invokeWithoutSession(JaxbUtil.jaxbToElement(req));

        System.out.println("Volume " + id + " is now the current " + toTypeName(vol.getType()) + " volume.");
    }

    private void unsetCurrentSecondaryMessageVolume() throws SoapFaultException, IOException, ServiceException {
        SetCurrentVolumeRequest req = new SetCurrentVolumeRequest(Volume.ID_NONE, Volume.TYPE_MESSAGE_SECONDARY);
        auth(auth);
        getTransport().invokeWithoutSession(JaxbUtil.jaxbToElement(req));
        System.out.println("Turned off the current secondary message volume.");
    }

    private void getCurrentVolumes() throws SoapFaultException, IOException, ServiceException {
        GetAllVolumesRequest req = new GetAllVolumesRequest();
        auth(auth);
        GetAllVolumesResponse all = JaxbUtil
                .elementToJaxb(getTransport().invokeWithoutSession(JaxbUtil.jaxbToElement(req)));
        for (VolumeInfo vol : all.getVolumes()) {
            if (vol.isCurrent()) {
                print(vol);
            }
        }
    }

    private void getVolume() throws IOException, ServiceException {
        if (id == null) {
            GetAllVolumesRequest req = new GetAllVolumesRequest();
            auth(auth);
            GetAllVolumesResponse resp = JaxbUtil
                    .elementToJaxb(getTransport().invokeWithoutSession(JaxbUtil.jaxbToElement(req)));
            for (VolumeInfo vol : resp.getVolumes()) {
                print(vol);
            }
        } else {
            GetVolumeRequest req = new GetVolumeRequest(Short.parseShort(id));
            auth(auth);
            GetVolumeResponse resp = JaxbUtil
                    .elementToJaxb(getTransport().invokeWithoutSession(JaxbUtil.jaxbToElement(req)));
            print(resp.getVolume());
        }
    }

    private void print(VolumeInfo vol) {
        System.out.println("   Volume id: " + vol.getId());
        System.out.println("        name: " + vol.getName());
        System.out.println("        type: " + toTypeName(vol.getType()));
        System.out.println("        path: " + vol.getRootPath());
        System.out.print("  compressed: " + vol.isCompressBlobs());
        if (vol.isCompressBlobs()) {
            System.out.println("\t         threshold: " + vol.getCompressionThreshold() + " bytes");
        } else {
            System.out.println();
        }
        System.out.println("     current: " + vol.isCurrent());
        System.out.println();
    }

    private void deleteVolume() throws ParseException, SoapFaultException, IOException, ServiceException {
        if (id == null) {
            throw new ParseException("id is missing");
        }

        DeleteVolumeRequest req = new DeleteVolumeRequest(Short.parseShort(id));
        auth(auth);
        getTransport().invokeWithoutSession(JaxbUtil.jaxbToElement(req));
        System.out.println("Deleted volume " + id);
    }

    private void editVolume() throws ParseException, SoapFaultException, IOException, ServiceException {
        if (Strings.isNullOrEmpty(id)) {
            throw new ParseException("id is missing");
        }

        VolumeInfo vol = new VolumeInfo();
        if (!Strings.isNullOrEmpty(type)) {
            vol.setType(toType(type));
        }
        if (!Strings.isNullOrEmpty(name)) {
            vol.setName(name);
        }
        if (!Strings.isNullOrEmpty(path)) {
            vol.setRootPath(path);
        }
        if (!Strings.isNullOrEmpty(compress)) {
            vol.setCompressBlobs(Boolean.parseBoolean(compress));
        }
        if (!Strings.isNullOrEmpty(compressThreshold)) {
            vol.setCompressionThreshold(Long.parseLong(compressThreshold));
        }
        ModifyVolumeRequest req = new ModifyVolumeRequest(Short.parseShort(id), vol);
        auth(auth);
        getTransport().invokeWithoutSession(JaxbUtil.jaxbToElement(req));
        System.out.println("Edited volume " + id);
    }

    private void addVolume() throws ParseException, SoapFaultException, IOException, ServiceException {
        if (id != null) {
            throw new ParseException("id cannot be specified when adding a volume");
        }
        if (Strings.isNullOrEmpty(type)) {
            throw new ParseException("type is missing");
        }
        if (Strings.isNullOrEmpty(name)) {
            throw new ParseException("name is missing");
        }
        if (Strings.isNullOrEmpty(path)) {
            throw new ParseException("path is missing");
        }

        VolumeInfo vol = new VolumeInfo();
        vol.setType(toType(type));
        vol.setName(name);
        vol.setRootPath(path);
        vol.setCompressBlobs(compress != null ? Boolean.parseBoolean(compress) : false);
        vol.setCompressionThreshold(compressThreshold != null ? Long.parseLong(compressThreshold) : 4096L);
        CreateVolumeRequest req = new CreateVolumeRequest(vol);
        auth();
        CreateVolumeResponse resp = JaxbUtil
                .elementToJaxb(getTransport().invokeWithoutSession(JaxbUtil.jaxbToElement(req)));
        System.out.println("Volume " + resp.getVolume().getId() + " is created");
    }

    @Override
    protected String getCommandUsage() {
        return "zmvolume {-a | -d | -l | -e | -dc | -sc } <options>";
    }

    @Override
    protected void setupCommandLineOptions() {
        super.setupCommandLineOptions();
        Options options = getOptions();
        OptionGroup og = new OptionGroup();
        og.addOption(new Option(O_A, "add", false, "Adds a volume."));
        og.addOption(new Option(O_D, "delete", false, "Deletes a volume."));
        og.addOption(new Option(O_L, "list", false, "Lists volumes."));
        og.addOption(new Option(O_E, "edit", false, "Edits a volume."));
        og.addOption(new Option(O_DC, "displayCurrent", false, "Displays the current volumes."));
        og.addOption(new Option(O_SC, "setCurrent", false, "Sets the current volume."));
        og.addOption(new Option(O_TS, "turnOffSecondary", false, "Turns off the current secondary message volume"));
        og.setRequired(true);
        options.addOptionGroup(og);
        options.addOption(O_ID, "id", true, "Volume ID");
        options.addOption(O_T, "type", true, "Volume type (primaryMessage, secondaryMessage, or index)");
        options.addOption(O_N, "name", true, "volume name");
        options.addOption(O_P, "path", true, "Root path");
        options.addOption(O_C, "compress", true, "Compress blobs; \"true\" or \"false\"");
        options.addOption(O_CT, "compressionThreshold", true, "Compression threshold; default 4KB");
        options.addOption(SoapCLI.OPT_AUTHTOKEN);
        options.addOption(SoapCLI.OPT_AUTHTOKENFILE);
    }

    @Override
    protected void usage(ParseException e) {
        if (e != null) {
            System.err.println("Error parsing command line arguments: " + e.getMessage());
        }

        System.err.println(getCommandUsage());
        printOpt(O_A, 0);
        printOpt(O_N, 2);
        printOpt(O_T, 2);
        printOpt(O_P, 2);
        printOpt(O_C, 2);
        printOpt(O_CT, 2);
        printOpt(O_E, 0);
        printOpt(O_ID, 2);
        System.err.println("  any of the options listed under -a can also be specified ");
        System.err.println("  to have its value modified.");
        printOpt(O_D, 0);
        printOpt(O_ID, 2);
        printOpt(O_L, 0);
        printOpt(O_ID, 2);
        System.err.println("  -id is optional.");
        printOpt(O_DC, 0);
        printOpt(O_SC, 0);
        printOpt(O_ID, 2);
        printOpt(O_TS, 0);
        printOpt(SoapCLI.O_AUTHTOKEN, 0);
        printOpt(SoapCLI.O_AUTHTOKENFILE, 0);
    }

    private void printOpt(String optStr, int leftPad) {
        Options options = getOptions();
        Option opt = options.getOption(optStr);
        StringBuilder buf = new StringBuilder();
        buf.append(Strings.repeat(" ", leftPad));
        buf.append('-').append(opt.getOpt()).append(",--").append(opt.getLongOpt());
        if (opt.hasArg()) {
            buf.append(" <arg>");
        }
        buf.append(Strings.repeat(" ", 35 - buf.length()));
        buf.append(opt.getDescription());
        System.err.println(buf.toString());
    }

    /**
     * Returns the type id for the given name.
     */
    private short toType(String name) throws ParseException {
        if ("primaryMessage".equalsIgnoreCase(name)) {
            return Volume.TYPE_MESSAGE;
        }
        if ("secondaryMessage".equalsIgnoreCase(name)) {
            return Volume.TYPE_MESSAGE_SECONDARY;
        }
        if ("index".equalsIgnoreCase(name)) {
            return Volume.TYPE_INDEX;
        }
        throw new ParseException("invalid volume type: " + name);
    }

    /**
     * Returns the human-readable name for the given volume type.
     */
    private String toTypeName(short type) {
        switch (type) {
        case Volume.TYPE_MESSAGE:
            return "primaryMessage";
        case Volume.TYPE_MESSAGE_SECONDARY:
            return "secondaryMessage";
        case Volume.TYPE_INDEX:
            return "index";
        }
        return "Unrecognized type " + type;
    }
}