001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.rest.httppart; 014 015import static org.apache.juneau.common.internal.ArgUtils.*; 016import static org.apache.juneau.internal.CollectionUtils.*; 017 018import java.util.*; 019 020import jakarta.servlet.http.*; 021 022import org.apache.juneau.collections.*; 023import org.apache.juneau.rest.*; 024import org.apache.juneau.svl.*; 025 026/** 027 * Represents the attributes in an HTTP request. 028 * 029 * <p> 030 * The {@link RequestAttributes} object is the API for accessing the standard servlet attributes on an HTTP request 031 * (i.e. {@link jakarta.servlet.ServletRequest#getAttribute(String)}). 032 * </p> 033 * 034 * <p class='bjava'> 035 * <ja>@RestPost</ja>(...) 036 * <jk>public</jk> Object myMethod(RequestAttributes <jv>attributes</jv>) {...} 037 * </p> 038 * 039 * <h5 class='figure'>Example:</h5> 040 * <p class='bjava'> 041 * <ja>@RestPost</ja>(...) 042 * <jk>public</jk> Object myMethod(RequestAttributes <jv>attributes</jv>) { 043 * 044 * <jc>// Add a default value.</jc> 045 * <jv>attributes</jv>.addDefault(<js>"Foo"</js>, 123); 046 * 047 * <jc>// Get an attribute value as a POJO.</jc> 048 * UUID <jv>etag</jv> = <jv>attributes</jv>.get(<js>"ETag"</js>).as(UUID.<jk>class</jk>).orElse(<jk>null</jk>); 049 * } 050 * </p> 051 * 052 * <p> 053 * Some important methods on this class are: 054 * </p> 055 * <ul class='javatree'> 056 * <li class='jc'>{@link RequestHeaders} 057 * <ul class='spaced-list'> 058 * <li>Methods for retrieving request attributes: 059 * <ul class='javatreec'> 060 * <li class='jm'>{@link RequestAttributes#contains(String...) contains(String...)} 061 * <li class='jm'>{@link RequestAttributes#containsAny(String...) containsAny(String...)} 062 * <li class='jm'>{@link RequestAttributes#get(String) get(String)} 063 * <li class='jm'>{@link RequestAttributes#getAll() getAll()} 064 * </ul> 065 * <li>Methods for overriding request attributes: 066 * <ul class='javatreec'> 067 * <li class='jm'>{@link RequestAttributes#addDefault(List) addDefault(List)} 068 * <li class='jm'>{@link RequestAttributes#addDefault(NamedAttribute...) addDefault(NamedAttribute...)} 069 * <li class='jm'>{@link RequestAttributes#addDefault(NamedAttributeMap) addDefault(NamedAttributeMap)} 070 * <li class='jm'>{@link RequestAttributes#addDefault(String,Object) addDefault(String,Object)} 071 * <li class='jm'>{@link RequestAttributes#remove(NamedAttribute...) remove(NamedAttribute...)} 072 * <li class='jm'>{@link RequestAttributes#remove(String...) remove(String...)} 073 * <li class='jm'>{@link RequestAttributes#set(NamedAttribute...) set(NamedAttribute...)} 074 * <li class='jm'>{@link RequestAttributes#set(String,Object) set(String,Object)} 075 * </ul> 076 * <li>Other methods: 077 * <ul class='javatreec'> 078 * <li class='jm'>{@link RequestAttributes#asMap() asMap()} 079 * </ul> 080 * </ul> 081 * </ul> 082 * 083 * <p> 084 * Modifications made to request attributes through the <c>RequestAttributes</c> bean are automatically reflected in 085 * the underlying servlet request attributes making it possible to mix the usage of both APIs. 086 * </p> 087 * 088 * <h5 class='section'>See Also:</h5><ul> 089 * <li class='link'><a class="doclink" href="../../../../../index.html#jrs.HttpParts">HTTP Parts</a> 090 * </ul> 091 */ 092public class RequestAttributes { 093 094 final RestRequest req; 095 final HttpServletRequest sreq; 096 final VarResolverSession vs; 097 098 /** 099 * Constructor. 100 * 101 * @param req The request creating this bean. 102 */ 103 public RequestAttributes(RestRequest req) { 104 super(); 105 this.req = req; 106 this.sreq = req.getHttpServletRequest(); 107 this.vs = req.getVarResolverSession(); 108 } 109 110 /** 111 * Adds default entries to the request attributes. 112 * 113 * @param pairs 114 * The default entries. 115 * <br>Can be <jk>null</jk>. 116 * @return This object. 117 */ 118 public RequestAttributes addDefault(List<NamedAttribute> pairs) { 119 for (NamedAttribute p : pairs) 120 if (sreq.getAttribute(p.getName()) == null) { 121 Object o = p.getValue(); 122 sreq.setAttribute(p.getName(), o instanceof String ? vs.resolve(o) : o); 123 } 124 return this; 125 } 126 127 /** 128 * Adds default entries to the request attributes. 129 * 130 * @param pairs 131 * The default entries. 132 * <br>Can be <jk>null</jk>. 133 * @return This object. 134 */ 135 public RequestAttributes addDefault(NamedAttributeMap pairs) { 136 for (NamedAttribute p : pairs.values()) 137 if (sreq.getAttribute(p.getName()) == null) { 138 Object o = p.getValue(); 139 sreq.setAttribute(p.getName(), o instanceof String ? vs.resolve(o) : o); 140 } 141 return this; 142 } 143 144 /** 145 * Adds default entries to the request attributes. 146 * 147 * @param pairs 148 * The default entries. 149 * <br>Can be <jk>null</jk>. 150 * @return This object. 151 */ 152 public RequestAttributes addDefault(NamedAttribute...pairs) { 153 return addDefault(alist(pairs)); 154 } 155 156 /** 157 * Adds a default entry to the request attributes. 158 * 159 * @param name The name. 160 * @param value The value. 161 * @return This object. 162 */ 163 public RequestAttributes addDefault(String name, Object value) { 164 return addDefault(BasicNamedAttribute.of(name, value)); 165 } 166 167 /** 168 * Returns the request attribute with the specified name. 169 * 170 * @param name The attribute name. 171 * @return The parameter value, or {@link Optional#empty()} if it doesn't exist. 172 */ 173 public RequestAttribute get(String name) { 174 return new RequestAttribute(req, name, sreq.getAttribute(name)); 175 } 176 177 /** 178 * Returns all the attribute on this request. 179 * 180 * @return All the attribute on this request. 181 */ 182 public List<RequestAttribute> getAll() { 183 List<RequestAttribute> l = list(); 184 Enumeration<String> e = sreq.getAttributeNames(); 185 while (e.hasMoreElements()) { 186 String n = e.nextElement(); 187 l.add(new RequestAttribute(req, n, sreq.getAttribute(n))); 188 } 189 return l; 190 } 191 192 /** 193 * Returns <jk>true</jk> if the attributes with the specified names are present. 194 * 195 * @param names The attribute names. Must not be <jk>null</jk>. 196 * @return <jk>true</jk> if the parameters with the specified names are present. 197 */ 198 public boolean contains(String...names) { 199 assertArgNotNull("names", names); 200 for (String n : names) 201 if (sreq.getAttribute(n) == null) 202 return false; 203 return true; 204 } 205 206 /** 207 * Returns <jk>true</jk> if the attribute with any of the specified names are present. 208 * 209 * @param names The attribute names. Must not be <jk>null</jk>. 210 * @return <jk>true</jk> if the attribute with any of the specified names are present. 211 */ 212 public boolean containsAny(String...names) { 213 assertArgNotNull("names", names); 214 for (String n : names) 215 if (sreq.getAttribute(n) != null) 216 return true; 217 return false; 218 } 219 220 /** 221 * Sets a request attribute. 222 * 223 * @param name The attribute name. Must not be <jk>null</jk>. 224 * @param value 225 * The attribute value. 226 * <br>Can be <jk>null</jk>. 227 * @return This object. 228 */ 229 public RequestAttributes set(String name, Object value) { 230 assertArgNotNull("name", name); 231 sreq.setAttribute(name, value); 232 return this; 233 } 234 235 /** 236 * Sets request attributes. 237 * 238 * @param attributes The parameters to set. Must not be <jk>null</jk> or contain <jk>null</jk>. 239 * @return This object. 240 */ 241 public RequestAttributes set(NamedAttribute...attributes) { 242 assertArgNotNull("attributes", attributes); 243 for (NamedAttribute p : attributes) 244 set(p); 245 return this; 246 } 247 248 /** 249 * Remove request attributes. 250 * 251 * @param name The attribute names. Must not be <jk>null</jk>. 252 * @return This object. 253 */ 254 public RequestAttributes remove(String...name) { 255 assertArgNotNull("name", name); 256 for (String n : name) { 257 sreq.removeAttribute(n); 258 } 259 return this; 260 } 261 262 /** 263 * Remove request attributes. 264 * 265 * @param attributes The attributes to remove. Must not be <jk>null</jk>. 266 * @return This object. 267 */ 268 public RequestAttributes remove(NamedAttribute...attributes) { 269 for (NamedAttribute p : attributes) 270 remove(p.getName()); 271 return this; 272 } 273 274 /** 275 * Returns the request attributes as a map. 276 * 277 * @return The request attributes as a map. Never <jk>null</jk>. 278 */ 279 public Map<String,Object> asMap() { 280 JsonMap m = new JsonMap(); 281 Enumeration<String> e = sreq.getAttributeNames(); 282 while (e.hasMoreElements()) { 283 String n = e.nextElement(); 284 m.put(n, sreq.getAttribute(n)); 285 } 286 return m; 287 } 288 289 @Override /* Object */ 290 public String toString() { 291 return asMap().toString(); 292 } 293}