001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.tools;
019
020import java.io.IOException;
021import java.io.PrintStream;
022import java.net.InetSocketAddress;
023
024import org.apache.hadoop.conf.Configuration;
025import org.apache.hadoop.conf.Configured;
026import org.apache.hadoop.ipc.RPC;
027import org.apache.hadoop.net.NetUtils;
028import org.apache.hadoop.security.UserGroupInformation;
029import org.apache.hadoop.util.Tool;
030
031/**
032 * Base class for the HDFS and MR implementations of tools which fetch and
033 * display the groups that users belong to.
034 */
035public abstract class GetGroupsBase extends Configured implements Tool {
036  
037  private PrintStream out;
038  
039  /**
040   * Create an instance of this tool using the given configuration.
041   * @param conf
042   */
043  protected GetGroupsBase(Configuration conf) {
044    this(conf, System.out);
045  }
046  
047  /**
048   * Used exclusively for testing.
049   * 
050   * @param conf The configuration to use.
051   * @param out The PrintStream to write to, instead of System.out
052   */
053  protected GetGroupsBase(Configuration conf, PrintStream out) {
054    super(conf);
055    this.out = out;
056  }
057
058  /**
059   * Get the groups for the users given and print formatted output to the
060   * {@link PrintStream} configured earlier.
061   */
062  @Override
063  public int run(String[] args) throws Exception {
064    if (args.length == 0) {
065      args = new String[] { UserGroupInformation.getCurrentUser().getUserName() }; 
066    }
067
068    for (String username : args) {
069      StringBuilder sb = new StringBuilder();
070      sb.append(username + " :");
071      for (String group : getUgmProtocol().getGroupsForUser(username)) {
072        sb.append(" ");
073        sb.append(group);
074      }
075      out.println(sb);
076    }
077
078    return 0;
079  }
080
081  /**
082   * Must be overridden by subclasses to get the address where the
083   * {@link GetUserMappingsProtocol} implementation is running.
084   * 
085   * @param conf The configuration to use.
086   * @return The address where the service is listening.
087   * @throws IOException
088   */
089  protected abstract InetSocketAddress getProtocolAddress(Configuration conf)
090      throws IOException;
091  
092  /**
093   * Get a client of the {@link GetUserMappingsProtocol}.
094   * @return A {@link GetUserMappingsProtocol} client proxy.
095   * @throws IOException
096   */
097  protected GetUserMappingsProtocol getUgmProtocol() throws IOException {
098    GetUserMappingsProtocol userGroupMappingProtocol =
099      RPC.getProxy(GetUserMappingsProtocol.class, 
100          GetUserMappingsProtocol.versionID,
101          getProtocolAddress(getConf()), UserGroupInformation.getCurrentUser(),
102          getConf(), NetUtils.getSocketFactory(getConf(),
103              GetUserMappingsProtocol.class));
104    return userGroupMappingProtocol;
105  }
106
107}