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.servlet; 014 015import static org.apache.juneau.internal.ClassUtils.*; 016 017import java.text.*; 018import java.util.concurrent.atomic.*; 019import java.util.function.*; 020import java.util.logging.*; 021 022import jakarta.servlet.*; 023import jakarta.servlet.http.*; 024 025import org.apache.juneau.common.internal.*; 026import org.apache.juneau.http.response.*; 027import org.apache.juneau.rest.*; 028 029/** 030 * Identical to {@link RestServlet} but doesn't extend from {@link HttpServlet}. 031 * 032 * <p> 033 * This is particularly useful in Spring Boot environments that auto-detect servlets to deploy in servlet containers, 034 * but you want this resource to be deployed as a child instead. 035 * 036 * <h5 class='section'>See Also:</h5><ul> 037 * <li class='link'><a class="doclink" href="../../../../../index.html#jrs.AnnotatedClasses">@Rest-Annotated Classes</a> 038 * </ul> 039 */ 040public abstract class RestObject { 041 042 private AtomicReference<RestContext> context = new AtomicReference<>(); 043 044 //----------------------------------------------------------------------------------------------------------------- 045 // Context methods. 046 //----------------------------------------------------------------------------------------------------------------- 047 048 /** 049 * Sets the context object for this servlet. 050 * 051 * @param context Sets the context object on this servlet. 052 * @throws ServletException If error occurred during post-initialiation. 053 */ 054 protected void setContext(RestContext context) throws ServletException { 055 this.context.set(context); 056 } 057 058 /** 059 * Returns the read-only context object that contains all the configuration information about this resource. 060 * 061 * @return The context information on this servlet. 062 */ 063 protected RestContext getContext() { 064 if (context.get() == null) 065 throw new InternalServerError("RestContext object not set on resource."); 066 return context.get(); 067 } 068 069 //----------------------------------------------------------------------------------------------------------------- 070 // Convenience logger methods 071 //----------------------------------------------------------------------------------------------------------------- 072 073 /** 074 * Log a message. 075 * 076 * <p> 077 * Subclasses can intercept the handling of these messages by overriding {@link #doLog(Level, Throwable, Supplier)}. 078 * 079 * @param level The log level. 080 * @param msg The message to log. 081 * @param args Optional {@link MessageFormat}-style arguments. 082 */ 083 public void log(Level level, String msg, Object...args) { 084 doLog(level, null, () -> StringUtils.format(msg, args)); 085 } 086 087 /** 088 * Log a message. 089 * 090 * <p> 091 * Subclasses can intercept the handling of these messages by overriding {@link #doLog(Level, Throwable, Supplier)}. 092 * 093 * @param level The log level. 094 * @param cause The cause. 095 * @param msg The message to log. 096 * @param args Optional {@link MessageFormat}-style arguments. 097 */ 098 public void log(Level level, Throwable cause, String msg, Object...args) { 099 doLog(level, cause, () -> StringUtils.format(msg, args)); 100 } 101 102 /** 103 * Main logger method. 104 * 105 * <p> 106 * The default behavior logs a message to the Java logger of the class name. 107 * 108 * <p> 109 * Subclasses can override this method to implement their own logger handling. 110 * 111 * @param level The log level. 112 * @param cause Optional throwable. 113 * @param msg The message to log. 114 */ 115 protected void doLog(Level level, Throwable cause, Supplier<String> msg) { 116 RestContext c = context.get(); 117 Logger logger = c == null ? null : c.getLogger(); 118 if (logger == null) 119 logger = Logger.getLogger(className(this)); 120 logger.log(level, cause, msg); 121 } 122 123 //----------------------------------------------------------------------------------------------------------------- 124 // Other methods 125 //----------------------------------------------------------------------------------------------------------------- 126 127 /** 128 * Returns the current thread-local HTTP request. 129 * 130 * @return The current thread-local HTTP request, or <jk>null</jk> if it wasn't created. 131 */ 132 public synchronized RestRequest getRequest() { 133 return getContext().getLocalSession().getOpSession().getRequest(); 134 } 135 136 /** 137 * Returns the current thread-local HTTP response. 138 * 139 * @return The current thread-local HTTP response, or <jk>null</jk> if it wasn't created. 140 */ 141 public synchronized RestResponse getResponse() { 142 return getContext().getLocalSession().getOpSession().getResponse(); 143 } 144}