View Javadoc

1   /*
2    * Copyright The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.hadoop.hbase.ipc;
22  
23  import org.apache.hadoop.classification.InterfaceAudience;
24  import org.apache.hadoop.hbase.security.User;
25  
26  import com.google.protobuf.BlockingService;
27  import org.apache.hadoop.hbase.util.Bytes;
28  import org.cloudera.htrace.Trace;
29  
30  import java.net.InetAddress;
31  
32  /**
33   * Represents client information (authenticated username, remote address, protocol)
34   * for the currently executing request within a RPC server handler thread.  If
35   * called outside the context of a RPC request, all values will be
36   * <code>null</code>.
37   */
38  @InterfaceAudience.Private
39  public class RequestContext {
40    private static ThreadLocal<RequestContext> instance =
41        new ThreadLocal<RequestContext>() {
42          protected RequestContext initialValue() {
43            return new RequestContext(null, null, null);
44          }
45        };
46  
47    public static RequestContext get() {
48      return instance.get();
49    }
50  
51  
52    /**
53     * Returns the user credentials associated with the current RPC request or
54     * <code>null</code> if no credentials were provided.
55     * @return A User
56     */
57    public static User getRequestUser() {
58      RequestContext ctx = instance.get();
59      if (ctx != null) {
60        return ctx.getUser();
61      }
62      return null;
63    }
64  
65    /**
66     * Returns the username for any user associated with the current RPC
67     * request or <code>null</code> if no user is set.
68     */
69    public static String getRequestUserName() {
70      User user = getRequestUser();
71      if (user != null) {
72        return user.getShortName();
73      }
74      return null;
75    }
76  
77    /**
78     * Indicates whether or not the current thread is within scope of executing
79     * an RPC request.
80     */
81    public static boolean isInRequestContext() {
82      RequestContext ctx = instance.get();
83      if (ctx != null) {
84        return ctx.isInRequest();
85      }
86      return false;
87    }
88  
89    /**
90     * Initializes the client credentials for the current request.
91     * @param user
92     * @param remoteAddress
93     * @param service
94     */
95    public static void set(User user,
96        InetAddress remoteAddress, BlockingService service) {
97      RequestContext ctx = instance.get();
98      ctx.user = user;
99      ctx.remoteAddress = remoteAddress;
100     ctx.service = service;
101     ctx.inRequest = true;
102     if (Trace.isTracing()) {
103       if (user != null) {
104         Trace.currentSpan().addKVAnnotation(Bytes.toBytes("user"), Bytes.toBytes(user.getName()));
105       }
106       if (remoteAddress != null) {
107         Trace.currentSpan().addKVAnnotation(
108             Bytes.toBytes("remoteAddress"),
109             Bytes.toBytes(remoteAddress.getHostAddress()));
110       }
111     }
112   }
113 
114   /**
115    * Clears out the client credentials for a given request.
116    */
117   public static void clear() {
118     RequestContext ctx = instance.get();
119     ctx.user = null;
120     ctx.remoteAddress = null;
121     ctx.service = null;
122     ctx.inRequest = false;
123   }
124 
125   private User user;
126   private InetAddress remoteAddress;
127   private BlockingService service;
128   // indicates we're within a RPC request invocation
129   private boolean inRequest;
130 
131   private RequestContext(User user, InetAddress remoteAddr, BlockingService service) {
132     this.user = user;
133     this.remoteAddress = remoteAddr;
134     this.service = service;
135   }
136 
137   public User getUser() {
138     return user;
139   }
140 
141   public InetAddress getRemoteAddress() {
142     return remoteAddress;
143   }
144 
145   public BlockingService getService() {
146     return this.service;
147   }
148 
149   public boolean isInRequest() {
150     return inRequest;
151   }
152 }