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  
28  import org.apache.hadoop.hbase.util.Bytes;
29  import org.htrace.Trace;
30  
31  import java.net.InetAddress;
32  
33  /**
34   * Represents client information (authenticated username, remote address, protocol)
35   * for the currently executing request.  If called outside the context of a RPC request, all values
36   * will be <code>null</code>. The {@link CallRunner} class before it a call and then on
37   * its way out, it will clear the thread local.
38   */
39  @InterfaceAudience.Private
40  public class RequestContext {
41    private static ThreadLocal<RequestContext> instance =
42        new ThreadLocal<RequestContext>() {
43          protected RequestContext initialValue() {
44            return new RequestContext(null, null, null);
45          }
46        };
47  
48    public static RequestContext get() {
49      return instance.get();
50    }
51  
52  
53    /**
54     * Returns the user credentials associated with the current RPC request or
55     * <code>null</code> if no credentials were provided.
56     * @return A User
57     */
58    public static User getRequestUser() {
59      RequestContext ctx = instance.get();
60      if (ctx != null) {
61        return ctx.getUser();
62      }
63      return null;
64    }
65  
66    /**
67     * Returns the username for any user associated with the current RPC
68     * request or <code>null</code> if no user is set.
69     */
70    public static String getRequestUserName() {
71      User user = getRequestUser();
72      if (user != null) {
73        return user.getShortName();
74      }
75      return null;
76    }
77  
78    /**
79     * Indicates whether or not the current thread is within scope of executing
80     * an RPC request.
81     */
82    public static boolean isInRequestContext() {
83      RequestContext ctx = instance.get();
84      if (ctx != null) {
85        return ctx.isInRequest();
86      }
87      return false;
88    }
89  
90    /**
91     * Initializes the client credentials for the current request.
92     * @param user
93     * @param remoteAddress
94     * @param service
95     */
96    public static void set(User user,
97        InetAddress remoteAddress, BlockingService service) {
98      RequestContext ctx = instance.get();
99      ctx.user = user;
100     ctx.remoteAddress = remoteAddress;
101     ctx.service = service;
102     ctx.inRequest = true;
103     if (Trace.isTracing()) {
104       if (user != null) {
105         Trace.currentSpan().addKVAnnotation(Bytes.toBytes("user"), Bytes.toBytes(user.getName()));
106       }
107       if (remoteAddress != null) {
108         Trace.currentSpan().addKVAnnotation(
109             Bytes.toBytes("remoteAddress"),
110             Bytes.toBytes(remoteAddress.getHostAddress()));
111       }
112     }
113   }
114 
115   /**
116    * Clears out the client credentials for a given request.
117    */
118   public static void clear() {
119     RequestContext ctx = instance.get();
120     ctx.user = null;
121     ctx.remoteAddress = null;
122     ctx.service = null;
123     ctx.inRequest = false;
124   }
125 
126   private User user;
127   private InetAddress remoteAddress;
128   private BlockingService service;
129   // indicates we're within a RPC request invocation
130   private boolean inRequest;
131 
132   private RequestContext(User user, InetAddress remoteAddr, BlockingService service) {
133     this.user = user;
134     this.remoteAddress = remoteAddr;
135     this.service = service;
136   }
137 
138   public User getUser() {
139     return user;
140   }
141 
142   public InetAddress getRemoteAddress() {
143     return remoteAddress;
144   }
145 
146   public BlockingService getService() {
147     return this.service;
148   }
149 
150   boolean isInRequest() {
151     return inRequest;
152   }
153 }