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 this.req = req; 105 this.sreq = req.getHttpServletRequest(); 106 this.vs = req.getVarResolverSession(); 107 } 108 109 /** 110 * Adds default entries to the request attributes. 111 * 112 * @param pairs 113 * The default entries. 114 * <br>Can be <jk>null</jk>. 115 * @return This object. 116 */ 117 public RequestAttributes addDefault(List<NamedAttribute> pairs) { 118 for (NamedAttribute p : pairs) 119 if (sreq.getAttribute(p.getName()) == null) { 120 Object o = p.getValue(); 121 sreq.setAttribute(p.getName(), o instanceof String ? vs.resolve(o) : o); 122 } 123 return this; 124 } 125 126 /** 127 * Adds default entries to the request attributes. 128 * 129 * @param pairs 130 * The default entries. 131 * <br>Can be <jk>null</jk>. 132 * @return This object. 133 */ 134 public RequestAttributes addDefault(NamedAttributeMap pairs) { 135 for (NamedAttribute p : pairs.values()) 136 if (sreq.getAttribute(p.getName()) == null) { 137 Object o = p.getValue(); 138 sreq.setAttribute(p.getName(), o instanceof String ? vs.resolve(o) : o); 139 } 140 return this; 141 } 142 143 /** 144 * Adds default entries to the request attributes. 145 * 146 * @param pairs 147 * The default entries. 148 * <br>Can be <jk>null</jk>. 149 * @return This object. 150 */ 151 public RequestAttributes addDefault(NamedAttribute...pairs) { 152 return addDefault(alist(pairs)); 153 } 154 155 /** 156 * Adds a default entry to the request attributes. 157 * 158 * @param name The name. 159 * @param value The value. 160 * @return This object. 161 */ 162 public RequestAttributes addDefault(String name, Object value) { 163 return addDefault(BasicNamedAttribute.of(name, value)); 164 } 165 166 /** 167 * Returns the request attribute with the specified name. 168 * 169 * @param name The attribute name. 170 * @return The parameter value, or {@link Optional#empty()} if it doesn't exist. 171 */ 172 public RequestAttribute get(String name) { 173 return new RequestAttribute(req, name, sreq.getAttribute(name)); 174 } 175 176 /** 177 * Returns all the attribute on this request. 178 * 179 * @return All the attribute on this request. 180 */ 181 public List<RequestAttribute> getAll() { 182 List<RequestAttribute> l = list(); 183 Enumeration<String> e = sreq.getAttributeNames(); 184 while (e.hasMoreElements()) { 185 String n = e.nextElement(); 186 l.add(new RequestAttribute(req, n, sreq.getAttribute(n))); 187 } 188 return l; 189 } 190 191 /** 192 * Returns <jk>true</jk> if the attributes with the specified names are present. 193 * 194 * @param names The attribute names. Must not be <jk>null</jk>. 195 * @return <jk>true</jk> if the parameters with the specified names are present. 196 */ 197 public boolean contains(String...names) { 198 assertArgNotNull("names", names); 199 for (String n : names) 200 if (sreq.getAttribute(n) == null) 201 return false; 202 return true; 203 } 204 205 /** 206 * Returns <jk>true</jk> if the attribute with any of the specified names are present. 207 * 208 * @param names The attribute names. Must not be <jk>null</jk>. 209 * @return <jk>true</jk> if the attribute with any of the specified names are present. 210 */ 211 public boolean containsAny(String...names) { 212 assertArgNotNull("names", names); 213 for (String n : names) 214 if (sreq.getAttribute(n) != null) 215 return true; 216 return false; 217 } 218 219 /** 220 * Sets a request attribute. 221 * 222 * @param name The attribute name. Must not be <jk>null</jk>. 223 * @param value 224 * The attribute value. 225 * <br>Can be <jk>null</jk>. 226 * @return This object. 227 */ 228 public RequestAttributes set(String name, Object value) { 229 assertArgNotNull("name", name); 230 sreq.setAttribute(name, value); 231 return this; 232 } 233 234 /** 235 * Sets request attributes. 236 * 237 * @param attributes The parameters to set. Must not be <jk>null</jk> or contain <jk>null</jk>. 238 * @return This object. 239 */ 240 public RequestAttributes set(NamedAttribute...attributes) { 241 assertArgNotNull("attributes", attributes); 242 for (NamedAttribute p : attributes) 243 set(p); 244 return this; 245 } 246 247 /** 248 * Remove request attributes. 249 * 250 * @param name The attribute names. Must not be <jk>null</jk>. 251 * @return This object. 252 */ 253 public RequestAttributes remove(String...name) { 254 assertArgNotNull("name", name); 255 for (String n : name) { 256 sreq.removeAttribute(n); 257 } 258 return this; 259 } 260 261 /** 262 * Remove request attributes. 263 * 264 * @param attributes The attributes to remove. Must not be <jk>null</jk>. 265 * @return This object. 266 */ 267 public RequestAttributes remove(NamedAttribute...attributes) { 268 for (NamedAttribute p : attributes) 269 remove(p.getName()); 270 return this; 271 } 272 273 /** 274 * Returns the request attributes as a map. 275 * 276 * @return The request attributes as a map. Never <jk>null</jk>. 277 */ 278 public Map<String,Object> asMap() { 279 JsonMap m = new JsonMap(); 280 Enumeration<String> e = sreq.getAttributeNames(); 281 while (e.hasMoreElements()) { 282 String n = e.nextElement(); 283 m.put(n, sreq.getAttribute(n)); 284 } 285 return m; 286 } 287 288 @Override /* Object */ 289 public String toString() { 290 return asMap().toString(); 291 } 292}