001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.rest.server; 018 019import static java.lang.annotation.RetentionPolicy.*; 020 021import java.lang.annotation.*; 022 023import org.apache.juneau.marshall.encoders.*; 024import org.apache.juneau.marshall.httppart.*; 025import org.apache.juneau.marshall.serializer.*; 026import org.apache.juneau.rest.server.arg.*; 027import org.apache.juneau.rest.server.converter.*; 028import org.apache.juneau.rest.server.guard.*; 029import org.apache.juneau.rest.server.processor.*; 030 031/** 032 * Rich mixin definition for the {@link Rest#mixinDefs() @Rest(mixinDefs=...)} attribute. 033 * 034 * <p> 035 * Declares a mixin class <b>and</b> lets the <i>host</i> override selected {@code @Rest}-level settings for 036 * that mixin's mixed-in endpoints — in one place, without subclassing or editing the mixin class. This 037 * is the host-side complement to {@link Rest#mixins() @Rest(mixins=...)} (which takes bare classes and offers 038 * no override hook). 039 * 040 * <h5 class='section'>Example:</h5> 041 * <p class='bjava'> 042 * <ja>@Rest</ja>( 043 * mixinDefs=<ja>@Mixin</ja>(type=FooMixin.<jk>class</jk>, guards=AdminGuard.<jk>class</jk>) 044 * ) 045 * <jk>public class</jk> MyResource { ... } 046 * </p> 047 * 048 * <p> 049 * Here {@code AdminGuard} is applied to {@code FooMixin}'s endpoints as declared by the host, without 050 * {@code FooMixin} having to declare it. 051 * 052 * <h5 class='section'>Override semantics</h5> 053 * <p> 054 * The override slots mirror the same {@code @Rest} attributes and resolve through the existing host→mixin 055 * inheritance chain, exactly as if the value had been declared on the mixin class itself, but at the 056 * most-derived position so a host override wins over the mixin class's own same-property declaration: 057 * <ul> 058 * <li><b>List-shaped</b> ({@code guards}, {@code converters}, {@code encoders}, {@code serializers}, 059 * {@code parsers}, {@code responseProcessors}, {@code restOpArgs}, default headers/attributes, 060 * {@code produces}/{@code consumes}) — appended after the host chain that the mixin inherits. 061 * <li><b>Replace-shaped</b> ({@code partSerializer}, {@code partParser}, 062 * {@code defaultAccept}/{@code defaultContentType}/{@code defaultCharset}, {@code maxInput}, 063 * {@code roleGuard}/{@code rolesDeclared}, {@code messages}) — the host override wins when set. 064 * </ul> 065 * 066 * <p> 067 * {@link #noInherit()} is the {@code @Mixin}'s own inheritance-cutoff list, applied to this mixin's 068 * sub-context: a token here cuts the host→mixin inheritance walk for that property (same token set as 069 * {@link Rest#noInherit()}). The host override is authoritative <i>but</i> overridable by these 070 * {@code noInherit} rules — e.g. {@code @Mixin(type=X.class, noInherit="guards")} removes the host's 071 * guard chain from {@code X}'s endpoints entirely. 072 * 073 * <p> 074 * {@link #path()}/{@link #paths()} re-mount the mixin's endpoints under host-chosen prefix(es). 075 * 076 * <h5 class='section'>Merging a mixin's list attributes into the host</h5> 077 * <p> 078 * The override slots above apply the <i>host's</i> values to the <i>mixin's</i> endpoints. The separate opt-in 079 * {@link #mergeIntoHost()} directive does the reverse: it appends the <i>mixin's</i> own list-shaped 080 * {@code @Rest} attributes (e.g. {@code responseProcessors}) into the <i>host's</i> own chains, so the host's own 081 * {@code @RestOp} methods pick them up too. It defaults to {@code false} (host endpoints see only the host's 082 * chain, as before) and is only settable on a rich {@code @Mixin} — see {@link #mergeIntoHost()}. 083 * 084 * <h5 class='section'>See Also:</h5><ul> 085 * <li class='ja'>{@link Rest#mixinDefs()} 086 * <li class='ja'>{@link Rest#mixins()} 087 * </ul> 088 * 089 * @since 10.0.0 090 */ 091@Target({}) 092@Retention(RUNTIME) 093public @interface Mixin { 094 095 /** 096 * The mixin class to compose into the host resource. 097 * 098 * <p> 099 * Required. Equivalent to a bare entry in {@link Rest#mixins()}, but with the override slots below. 100 * 101 * @return The mixin class. 102 */ 103 Class<?> type(); 104 105 /** 106 * Opt-in directive: fold this mixin's <b>list-shaped</b> {@code @Rest} attributes into the <i>host</i> 107 * resource's own corresponding chains (not just the mixin's own endpoints). 108 * 109 * <p> 110 * By default ({@code false}) a mixin's list-shaped {@code @Rest} contributions apply only to the mixin's own 111 * endpoints — a host's own {@code @RestOp} methods see only the host's chain (the standard 112 * {@link Rest#mixins() mixin} inheritance rule "host's chain runs first, then the mixin's appended; host 113 * endpoints see only the host's chain"), so a mixin's e.g. {@code responseProcessors} are effectively dropped 114 * for host endpoints. Setting this to {@code true} additionally <b>appends</b> the adopted mixin's own 115 * list-shaped {@code @Rest} attributes to the end of the host's corresponding chains, so the host's own 116 * endpoints pick them up too. 117 * 118 * <p> 119 * The folded set is the list-shaped contribution attributes: {@code serializers}, {@code parsers}, 120 * {@code encoders}, {@code converters}, {@code guards}, {@code responseProcessors}, {@code restOpArgs}, 121 * {@code defaultRequestHeaders}, {@code defaultResponseHeaders}, {@code defaultRequestAttributes}, 122 * {@code produces}, and {@code consumes}. Replace-shaped attributes (e.g. {@code partSerializer}, 123 * {@code partParser}) and host-only attributes ({@code path}/{@code paths}/{@code children}) are never 124 * folded. Same-class de-duplication applies, so a class the host already declares is not added twice. 125 * 126 * <p> 127 * This is strictly opt-in: it has no effect on a bare {@link Rest#mixins()} entry (which cannot set it) or a 128 * {@code @Mixin} that leaves it {@code false}, so existing resources are unaffected. The mixin still mounts 129 * its own endpoints as usual — this directive is purely additive to the host chain. 130 * 131 * <h5 class='section'>Example:</h5> 132 * <p class='bjava'> 133 * <jc>// Auto-wire JspMixin's JspViewRenderer into the host so the host's own @RestOp methods can</jc> 134 * <jc>// return JspView (no need to also list JspViewRenderer in the host's @Rest(responseProcessors)).</jc> 135 * <ja>@Rest</ja>(mixinDefs=<ja>@Mixin</ja>(type=JspMixin.<jk>class</jk>, mergeIntoHost=<jk>true</jk>)) 136 * <jk>public class</jk> AppResource <jk>extends</jk> RestServlet { ... } 137 * </p> 138 * 139 * @return The annotation value. 140 * @since 10.0.0 141 */ 142 boolean mergeIntoHost() default false; 143 144 //----------------------------------------------------------------------------------------------------------------- 145 // Override slots — mirror the corresponding @Rest attribute signatures. 146 //----------------------------------------------------------------------------------------------------------------- 147 148 /** 149 * Host-declared {@link Rest#guards() guards} override for this mixin's endpoints (appended after the host chain). 150 * 151 * @return The annotation value. 152 */ 153 Class<? extends RestGuard>[] guards() default {}; 154 155 /** 156 * Host-declared {@link Rest#roleGuard() roleGuard} override for this mixin's endpoints. 157 * 158 * @return The annotation value. 159 */ 160 String roleGuard() default ""; 161 162 /** 163 * Host-declared {@link Rest#rolesDeclared() rolesDeclared} override for this mixin's endpoints. 164 * 165 * @return The annotation value. 166 */ 167 String rolesDeclared() default ""; 168 169 /** 170 * Host-declared {@link Rest#converters() converters} override for this mixin's endpoints. 171 * 172 * @return The annotation value. 173 */ 174 Class<? extends RestConverter>[] converters() default {}; 175 176 /** 177 * Host-declared {@link Rest#encoders() encoders} override for this mixin's endpoints. 178 * 179 * @return The annotation value. 180 */ 181 Class<? extends Encoder>[] encoders() default {}; 182 183 /** 184 * Host-declared {@link Rest#serializers() serializers} override for this mixin's endpoints. 185 * 186 * @return The annotation value. 187 */ 188 Class<? extends Serializer>[] serializers() default {}; 189 190 /** 191 * Host-declared {@link Rest#parsers() parsers} override for this mixin's endpoints. 192 * 193 * @return The annotation value. 194 */ 195 Class<?>[] parsers() default {}; 196 197 /** 198 * Host-declared {@link Rest#responseProcessors() responseProcessors} override for this mixin's endpoints. 199 * 200 * @return The annotation value. 201 */ 202 Class<? extends ResponseProcessor>[] responseProcessors() default {}; 203 204 /** 205 * Host-declared {@link Rest#restOpArgs() restOpArgs} override for this mixin's endpoints. 206 * 207 * @return The annotation value. 208 */ 209 Class<? extends RestOpArg>[] restOpArgs() default {}; 210 211 /** 212 * Host-declared {@link Rest#partSerializer() partSerializer} override for this mixin's endpoints. 213 * 214 * @return The annotation value. 215 */ 216 Class<? extends HttpPartSerializer> partSerializer() default HttpPartSerializer.Void.class; 217 218 /** 219 * Host-declared {@link Rest#partParser() partParser} override for this mixin's endpoints. 220 * 221 * @return The annotation value. 222 */ 223 Class<? extends HttpPartParser> partParser() default HttpPartParser.Void.class; 224 225 /** 226 * Host-declared {@link Rest#messages() messages} override for this mixin's endpoints. 227 * 228 * @return The annotation value. 229 */ 230 String messages() default ""; 231 232 /** 233 * Host-declared {@link Rest#defaultRequestHeaders() defaultRequestHeaders} override for this mixin's endpoints. 234 * 235 * @return The annotation value. 236 */ 237 String[] defaultRequestHeaders() default {}; 238 239 /** 240 * Host-declared {@link Rest#defaultResponseHeaders() defaultResponseHeaders} override for this mixin's endpoints. 241 * 242 * @return The annotation value. 243 */ 244 String[] defaultResponseHeaders() default {}; 245 246 /** 247 * Host-declared {@link Rest#defaultRequestAttributes() defaultRequestAttributes} override for this mixin's endpoints. 248 * 249 * @return The annotation value. 250 */ 251 String[] defaultRequestAttributes() default {}; 252 253 /** 254 * Host-declared {@link Rest#produces() produces} override for this mixin's endpoints. 255 * 256 * @return The annotation value. 257 */ 258 String[] produces() default {}; 259 260 /** 261 * Host-declared {@link Rest#consumes() consumes} override for this mixin's endpoints. 262 * 263 * @return The annotation value. 264 */ 265 String[] consumes() default {}; 266 267 /** 268 * Host-declared {@link Rest#defaultAccept() defaultAccept} override for this mixin's endpoints. 269 * 270 * @return The annotation value. 271 */ 272 String defaultAccept() default ""; 273 274 /** 275 * Host-declared {@link Rest#defaultContentType() defaultContentType} override for this mixin's endpoints. 276 * 277 * @return The annotation value. 278 */ 279 String defaultContentType() default ""; 280 281 /** 282 * Host-declared {@link Rest#defaultCharset() defaultCharset} override for this mixin's endpoints. 283 * 284 * @return The annotation value. 285 */ 286 String defaultCharset() default ""; 287 288 /** 289 * Host-declared {@link Rest#maxInput() maxInput} override for this mixin's endpoints. 290 * 291 * @return The annotation value. 292 */ 293 String maxInput() default ""; 294 295 /** 296 * Host-chosen single mount prefix for this mixin's endpoints (re-mount). 297 * 298 * @return The annotation value. 299 */ 300 String path() default ""; 301 302 /** 303 * Host-chosen multi-mount prefixes for this mixin's endpoints (re-mount). 304 * 305 * @return The annotation value. 306 */ 307 String[] paths() default {}; 308 309 /** 310 * Inheritance-cutoff list for this mixin's sub-context. 311 * 312 * <p> 313 * Each token names a property whose host→mixin inheritance walk is cut for this mixin (same token set 314 * as {@link Rest#noInherit()}). Authoritative over the host override slots above. 315 * 316 * @return The annotation value. 317 */ 318 String[] noInherit() default {}; 319}