com.google.gerrit.sshd.AliasCommand.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gerrit.sshd.AliasCommand.java

Source

// Copyright (C) 2012 The Android Open Source Project
//
// 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.google.gerrit.sshd;

import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Atomics;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.CapabilityControl;
import com.google.inject.Provider;

import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

/** Command that executes some other command. */
public class AliasCommand extends BaseCommand {
    private final DispatchCommandProvider root;
    private final Provider<CurrentUser> currentUser;
    private final CommandName command;
    private final AtomicReference<Command> atomicCmd;

    AliasCommand(@CommandName(Commands.ROOT) DispatchCommandProvider root, Provider<CurrentUser> currentUser,
            CommandName command) {
        this.root = root;
        this.currentUser = currentUser;
        this.command = command;
        this.atomicCmd = Atomics.newReference();
    }

    @Override
    public void start(Environment env) throws IOException {
        try {
            begin(env);
        } catch (UnloggedFailure e) {
            String msg = e.getMessage();
            if (!msg.endsWith("\n")) {
                msg += "\n";
            }
            err.write(msg.getBytes(ENC));
            err.flush();
            onExit(e.exitCode);
        }
    }

    private void begin(Environment env) throws UnloggedFailure, IOException {
        Map<String, CommandProvider> map = root.getMap();
        for (String name : chain(command)) {
            CommandProvider p = map.get(name);
            if (p == null) {
                throw new UnloggedFailure(1, getName() + ": not found");
            }

            Command cmd = p.getProvider().get();
            if (!(cmd instanceof DispatchCommand)) {
                throw new UnloggedFailure(1, getName() + ": not found");
            }
            map = ((DispatchCommand) cmd).getMap();
        }

        CommandProvider p = map.get(command.value());
        if (p == null) {
            throw new UnloggedFailure(1, getName() + ": not found");
        }

        Command cmd = p.getProvider().get();
        checkRequiresCapability(cmd);
        if (cmd instanceof BaseCommand) {
            BaseCommand bc = (BaseCommand) cmd;
            bc.setName(getName());
            bc.setArguments(getArguments());
        }
        provideStateTo(cmd);
        atomicCmd.set(cmd);
        cmd.start(env);
    }

    @Override
    public void destroy() {
        Command cmd = atomicCmd.getAndSet(null);
        if (cmd != null) {
            cmd.destroy();
        }
    }

    private void checkRequiresCapability(Command cmd) throws UnloggedFailure {
        RequiresCapability rc = cmd.getClass().getAnnotation(RequiresCapability.class);
        if (rc != null) {
            CurrentUser user = currentUser.get();
            CapabilityControl ctl = user.getCapabilities();
            if (!ctl.canPerform(rc.value()) && !ctl.canAdministrateServer()) {
                String msg = String.format("fatal: %s does not have \"%s\" capability.", user.getUserName(),
                        rc.value());
                throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, msg);
            }
        }
    }

    private static LinkedList<String> chain(CommandName command) {
        LinkedList<String> chain = Lists.newLinkedList();
        while (command != null) {
            chain.addFirst(command.value());
            command = Commands.parentOf(command);
        }
        chain.removeLast();
        return chain;
    }
}