
cat.inspiracio.orange.OrangeServlet Maven / Gradle / Ivy
Show all versions of orange-servlet Show documentation
/* Copyright 2019 Alexander Bunkenburg
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cat.inspiracio.orange;
import cat.inspiracio.servlet.jsp.ServletPageContext;
import cat.inspiracio.util.Timber;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.jsp.PageContext;
import java.io.IOException;
import java.io.Serial;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import static jakarta.servlet.RequestDispatcher.*;
/** For requests to orange templates. */
public class OrangeServlet extends HttpServlet {
// not state --------------
@Serial private static final long serialVersionUID = -1871765722924200945L;
/** The resolver that can find a template class from a URL. */
private final Resolver resolver = new Resolver();
// construction --------------------------------------
/** The default constructor that servlet containers need. */
public OrangeServlet() {}
// public methods ----------
/** Finds a template from the URL and renders the template.
* If cannot find the template: 404.
* Any exception in template rendering becomes 500.
* @param request the request
* @param response the response */
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
setContentType(response);
try{
Template t = null;
try {
t = template(request, response);//ClassNotFoundException
}
// Can not find a template class: 404
// OrangeServlet translates not finding the template class to 404.
catch (ClassNotFoundException e) {
error(request, 404, e);
response.sendError(404);
return;
}
t.render(); // Exception, may be anything from the Java-islands
timber(response);
}
catch (Exception e) {
error(request, 500, e);
response.sendError(500);
}
}
/** For POST, do the same as for GET.
* The html can discriminate and react. */
@Override protected void doPost(HttpServletRequest request, HttpServletResponse response)throws IOException {
doGet(request, response);
}
// helpers ---------------------------------------------------------
/** Always sets text/html.
* (All templates are html.) */
private void setContentType(HttpServletResponse response) {
response.setContentType("text/html; charset=utf-8");
}
/** Find a template class and instantiate it.
* @param request the request
* @param response the response
* @throws ClassNotFoundException if the template can't be found. That's 404.
* @throws NoSuchMethodException Template class lacks constructor. Orange maven plugin is broken.
* @throws InstantiationException Template instantiation failed. Orange maven plugin is broken.
* @throws IllegalAccessException Template instantiation failed. Orange maven plugin is broken.
* @throws InvocationTargetException Template instantiation failed. Orange maven plugin is broken.
* */
Template template(HttpServletRequest request, HttpServletResponse response) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
// TODO Is it necessary to get reflection out of request time?
String fqcn = fully(request);
ServletPageContext pc = new ServletPageContext(this, request, response);
Class extends Template>c = Class.forName(fqcn).asSubclass(Template.class);//ClassNotFoundException
Constructor extends Template> cons = c.getConstructor(PageContext.class);
return cons.newInstance(pc);
}
/** An exception has occurred. Puts some attributes into the request.
*
* Spec Servlet 6.0.
* */
private void error(HttpServletRequest request, int status, Throwable e){
request.setAttribute(ERROR_STATUS_CODE, status);
request.setAttribute(ERROR_EXCEPTION_TYPE, e.getClass());
request.setAttribute(ERROR_MESSAGE, e.getMessage());
request.setAttribute(ERROR_EXCEPTION, e);
request.setAttribute(ERROR_REQUEST_URI, request.getRequestURI());
request.setAttribute(ERROR_SERVLET_NAME, getServletName());
}
/** Makes full java class name from request path.
* Example: GET /index.html --> cat.inspiracio.orange.index,java */
private String fully(HttpServletRequest request){
String contextPath = request.getContextPath();
String uri = request.getRequestURI();
if(contextPath!=null && uri.startsWith(contextPath))
uri = uri.substring(contextPath.length());
// Tomcat has directed to welcome file, even though request.getRequestURI() == "/".
if("/".equals(uri))
uri = request.getServletPath();// "/index.html"
return resolver.fqcn(uri);
}
/** Maybe write timber output to page.
* Only if it's .html and there is something to write.
* @throws IOException */
private void timber(HttpServletResponse response) throws IOException{
String type = response.getContentType(); //text/html;charset=utf-8
boolean isHTML = type!=null && type.startsWith("text/html");
if(isHTML) {
String timber = Timber.string();
if(!timber.isEmpty())
response.getWriter().append("");
}
}
}