UnixUserGroupInformation.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:14k
源码类别:
网格计算
开发平台:
Java
- /**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 org.apache.hadoop.security;
- import java.io.DataInput;
- import java.io.DataOutput;
- import java.io.IOException;
- import java.util.Arrays;
- import java.util.HashMap;
- import java.util.StringTokenizer;
- import java.util.TreeSet;
- import javax.security.auth.login.LoginException;
- import org.apache.hadoop.conf.Configuration;
- import org.apache.hadoop.util.Shell;
- import org.apache.hadoop.io.Text;
- import org.apache.hadoop.io.WritableUtils;
- /** An implementation of UserGroupInformation in the Unix system */
- public class UnixUserGroupInformation extends UserGroupInformation {
- public static final String DEFAULT_USERNAME = "DrWho";
- public static final String DEFAULT_GROUP = "Tardis";
- final static public String UGI_PROPERTY_NAME = "hadoop.job.ugi";
- final static private HashMap<String, UnixUserGroupInformation> user2UGIMap =
- new HashMap<String, UnixUserGroupInformation>();
- /** Create an immutable {@link UnixUserGroupInformation} object. */
- public static UnixUserGroupInformation createImmutable(String[] ugi) {
- return new UnixUserGroupInformation(ugi) {
- public void readFields(DataInput in) throws IOException {
- throw new UnsupportedOperationException();
- }
- };
- }
- private String userName;
- private String[] groupNames;
- /** Default constructor
- */
- public UnixUserGroupInformation() {
- }
- /** Constructor with parameters user name and its group names.
- * The first entry in the groups list is the default group.
- *
- * @param userName a user's name
- * @param groupNames groups list, first of which is the default group
- * @exception IllegalArgumentException if any argument is null
- */
- public UnixUserGroupInformation(String userName, String[] groupNames) {
- setUserGroupNames(userName, groupNames);
- }
- /** Constructor with parameter user/group names
- *
- * @param ugi an array containing user/group names, the first
- * element of which is the user name, the second of
- * which is the default group name.
- * @exception IllegalArgumentException if the array size is less than 2
- * or any element is null.
- */
- public UnixUserGroupInformation(String[] ugi) {
- if (ugi==null || ugi.length < 2) {
- throw new IllegalArgumentException( "Parameter does contain at least "+
- "one user name and one group name");
- }
- String[] groupNames = new String[ugi.length-1];
- System.arraycopy(ugi, 1, groupNames, 0, groupNames.length);
- setUserGroupNames(ugi[0], groupNames);
- }
- /* Set this object's user name and group names
- *
- * @param userName a user's name
- * @param groupNames groups list, the first of which is the default group
- * @exception IllegalArgumentException if any argument is null
- */
- private void setUserGroupNames(String userName, String[] groupNames) {
- if (userName==null || userName.length()==0 ||
- groupNames== null || groupNames.length==0) {
- throw new IllegalArgumentException(
- "Parameters should not be null or an empty string/array");
- }
- for (int i=0; i<groupNames.length; i++) {
- if(groupNames[i] == null || groupNames[i].length() == 0) {
- throw new IllegalArgumentException("A null group name at index " + i);
- }
- }
- this.userName = userName;
- this.groupNames = groupNames;
- }
- /** Return an array of group names
- */
- public String[] getGroupNames() {
- return groupNames;
- }
- /** Return the user's name
- */
- public String getUserName() {
- return userName;
- }
- /* The following two methods implements Writable interface */
- final private static String UGI_TECHNOLOGY = "STRING_UGI";
- /** Deserialize this object
- * First check if this is a UGI in the string format.
- * If no, throw an IOException; otherwise
- * set this object's fields by reading them from the given data input
- *
- * @param in input stream
- * @exception IOException is thrown if encounter any error when reading
- */
- public void readFields(DataInput in) throws IOException {
- // read UGI type first
- String ugiType = Text.readString(in);
- if (!UGI_TECHNOLOGY.equals(ugiType)) {
- throw new IOException("Expect UGI prefix: " + UGI_TECHNOLOGY +
- ", but receive a prefix: " + ugiType);
- }
- // read this object
- userName = Text.readString(in);
- int numOfGroups = WritableUtils.readVInt(in);
- groupNames = new String[numOfGroups];
- for (int i = 0; i < numOfGroups; i++) {
- groupNames[i] = Text.readString(in);
- }
- }
- /** Serialize this object
- * First write a string marking that this is a UGI in the string format,
- * then write this object's serialized form to the given data output
- *
- * @param out output stream
- * @exception IOException if encounter any error during writing
- */
- public void write(DataOutput out) throws IOException {
- // write a prefix indicating the type of UGI being written
- Text.writeString(out, UGI_TECHNOLOGY);
- // write this object
- Text.writeString(out, userName);
- WritableUtils.writeVInt(out, groupNames.length);
- for (String groupName : groupNames) {
- Text.writeString(out, groupName);
- }
- }
- /* The following two methods deal with transferring UGI through conf.
- * In this pass of implementation we store UGI as a string in conf.
- * Later we may change it to be a more general approach that stores
- * it as a byte array */
- /** Store the given <code>ugi</code> as a comma separated string in
- * <code>conf</code> as a property <code>attr</code>
- *
- * The String starts with the user name followed by the default group names,
- * and other group names.
- *
- * @param conf configuration
- * @param attr property name
- * @param ugi a UnixUserGroupInformation
- */
- public static void saveToConf(Configuration conf, String attr,
- UnixUserGroupInformation ugi ) {
- conf.set(attr, ugi.toString());
- }
- /** Read a UGI from the given <code>conf</code>
- *
- * The object is expected to store with the property name <code>attr</code>
- * as a comma separated string that starts
- * with the user name followed by group names.
- * If the property name is not defined, return null.
- * It's assumed that there is only one UGI per user. If this user already
- * has a UGI in the ugi map, return the ugi in the map.
- * Otherwise, construct a UGI from the configuration, store it in the
- * ugi map and return it.
- *
- * @param conf configuration
- * @param attr property name
- * @return a UnixUGI
- * @throws LoginException if the stored string is ill-formatted.
- */
- public static UnixUserGroupInformation readFromConf(
- Configuration conf, String attr) throws LoginException {
- String[] ugi = conf.getStrings(attr);
- if(ugi == null) {
- return null;
- }
- UnixUserGroupInformation currentUGI = null;
- if (ugi.length>0 ){
- currentUGI = user2UGIMap.get(ugi[0]);
- }
- if (currentUGI == null) {
- try {
- currentUGI = new UnixUserGroupInformation(ugi);
- user2UGIMap.put(currentUGI.getUserName(), currentUGI);
- } catch (IllegalArgumentException e) {
- throw new LoginException("Login failed: "+e.getMessage());
- }
- }
- return currentUGI;
- }
- /**
- * Get current user's name and the names of all its groups from Unix.
- * It's assumed that there is only one UGI per user. If this user already
- * has a UGI in the ugi map, return the ugi in the map.
- * Otherwise get the current user's information from Unix, store it
- * in the map, and return it.
- *
- * If the current user's UNIX username or groups are configured in such a way
- * to throw an Exception, for example if the user uses LDAP, then this method
- * will use a the {@link #DEFAULT_USERNAME} and {@link #DEFAULT_GROUP}
- * constants.
- */
- public static UnixUserGroupInformation login() throws LoginException {
- try {
- String userName;
- // if an exception occurs, then uses the
- // default user
- try {
- userName = getUnixUserName();
- } catch (Exception e) {
- userName = DEFAULT_USERNAME;
- }
- // check if this user already has a UGI object in the ugi map
- UnixUserGroupInformation ugi = user2UGIMap.get(userName);
- if (ugi != null) {
- return ugi;
- }
- /* get groups list from UNIX.
- * It's assumed that the first group is the default group.
- */
- String[] groupNames;
- // if an exception occurs, then uses the
- // default group
- try {
- groupNames = getUnixGroups();
- } catch (Exception e) {
- groupNames = new String[1];
- groupNames[0] = DEFAULT_GROUP;
- }
- // construct a Unix UGI
- ugi = new UnixUserGroupInformation(userName, groupNames);
- user2UGIMap.put(ugi.getUserName(), ugi);
- return ugi;
- } catch (Exception e) {
- throw new LoginException("Login failed: "+e.getMessage());
- }
- }
- /** Equivalent to login(conf, false). */
- public static UnixUserGroupInformation login(Configuration conf)
- throws LoginException {
- return login(conf, false);
- }
- /** Get a user's name & its group names from the given configuration;
- * If it is not defined in the configuration, get the current user's
- * information from Unix.
- * If the user has a UGI in the ugi map, return the one in
- * the UGI map.
- *
- * @param conf either a job configuration or client's configuration
- * @param save saving it to conf?
- * @return UnixUserGroupInformation a user/group information
- * @exception LoginException if not able to get the user/group information
- */
- public static UnixUserGroupInformation login(Configuration conf, boolean save
- ) throws LoginException {
- UnixUserGroupInformation ugi = readFromConf(conf, UGI_PROPERTY_NAME);
- if (ugi == null) {
- ugi = login();
- LOG.debug("Unix Login: " + ugi);
- if (save) {
- saveToConf(conf, UGI_PROPERTY_NAME, ugi);
- }
- }
- return ugi;
- }
- /* Return a string representation of a string array.
- * Two strings are separated by a blank.
- */
- private static String toString(String[] strArray) {
- if (strArray==null || strArray.length==0) {
- return "";
- }
- StringBuilder buf = new StringBuilder(strArray[0]);
- for (int i=1; i<strArray.length; i++) {
- buf.append(' ');
- buf.append(strArray[i]);
- }
- return buf.toString();
- }
- /** Get current user's name from Unix by running the command whoami.
- *
- * @return current user's name
- * @throws IOException if encounter any error while running the command
- */
- static String getUnixUserName() throws IOException {
- String[] result = executeShellCommand(
- new String[]{Shell.USER_NAME_COMMAND});
- if (result.length!=1) {
- throw new IOException("Expect one token as the result of " +
- Shell.USER_NAME_COMMAND + ": " + toString(result));
- }
- return result[0];
- }
- /** Get the current user's group list from Unix by running the command groups
- *
- * @return the groups list that the current user belongs to
- * @throws IOException if encounter any error when running the command
- */
- private static String[] getUnixGroups() throws IOException {
- return executeShellCommand(Shell.getGROUPS_COMMAND());
- }
- /* Execute a command and return the result as an array of Strings */
- private static String[] executeShellCommand(String[] command)
- throws IOException {
- String groups = Shell.execCommand(command);
- StringTokenizer tokenizer = new StringTokenizer(groups);
- int numOfTokens = tokenizer.countTokens();
- String[] tokens = new String[numOfTokens];
- for (int i=0; tokenizer.hasMoreTokens(); i++) {
- tokens[i] = tokenizer.nextToken();
- }
- return tokens;
- }
- /** Decide if two UGIs are the same
- *
- * @param other other object
- * @return true if they are the same; false otherwise.
- */
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- }
- if (!(other instanceof UnixUserGroupInformation)) {
- return false;
- }
- UnixUserGroupInformation otherUGI = (UnixUserGroupInformation)other;
- // check userName
- if (userName == null) {
- if (otherUGI.getUserName() != null) {
- return false;
- }
- } else {
- if (!userName.equals(otherUGI.getUserName())) {
- return false;
- }
- }
- // checkGroupNames
- if (groupNames == otherUGI.groupNames) {
- return true;
- }
- if (groupNames.length != otherUGI.groupNames.length) {
- return false;
- }
- // check default group name
- if (groupNames.length>0 && !groupNames[0].equals(otherUGI.groupNames[0])) {
- return false;
- }
- // check all group names, ignoring the order
- return new TreeSet<String>(Arrays.asList(groupNames)).equals(
- new TreeSet<String>(Arrays.asList(otherUGI.groupNames)));
- }
- /** Returns a hash code for this UGI.
- * The hash code for a UGI is the hash code of its user name string.
- *
- * @return a hash code value for this UGI.
- */
- public int hashCode() {
- return getUserName().hashCode();
- }
- /** Convert this object to a string
- *
- * @return a comma separated string containing the user name and group names
- */
- public String toString() {
- StringBuilder buf = new StringBuilder();
- buf.append(userName);
- for (String groupName : groupNames) {
- buf.append(',');
- buf.append(groupName);
- }
- return buf.toString();
- }
- @Override
- public String getName() {
- return toString();
- }
- }