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.common.utils; 018 019import static org.apache.juneau.commons.utils.Shorts.*; 020 021import java.lang.reflect.*; 022 023/** 024 * HTTP utilities. 025 * 026 */ 027@SuppressWarnings({ 028 "java:S3776" // detectHttpMethod and detectHttpPath branch over the do/get/put/... name-prefix conventions 029}) 030public class HttpUtils { 031 032 /** 033 * Prevents instantiation. 034 */ 035 private HttpUtils() {} 036 037 private static final String[] LC_METHODS = { "get", "put", "post", "delete", "options", "head", "connect", "trace", "patch" }; 038 private static final String[] UC_METHODS = { "GET", "PUT", "POST", "DELETE", "OPTIONS", "HEAD", "CONNECT", "TRACE", "PATCH" }; 039 040 /** 041 * Given a method name, infers the REST method name. 042 * 043 * @param m The Java method. Must not be <jk>null</jk>. 044 * @param detectMethod Whether we should auto-detect the HTTP method name from the Java method name. 045 * @param def The default HTTP method if not detected. Can be <jk>null</jk>. 046 * @return The REST method name, or <c>def</c> (which can be <jk>null</jk>) if not detected. 047 */ 048 public static String detectHttpMethod(Method m, boolean detectMethod, String def) { 049 String n = m.getName(); 050 if (detectMethod) { 051 if (n.startsWith("do") && n.length() > 2) { 052 String n2 = ucr(n.substring(2)); 053 for (var t : UC_METHODS) 054 if (eq(n2, t)) 055 return n2; 056 } 057 for (var t : LC_METHODS) 058 if (n.startsWith(t) && (n.length() == t.length() || Character.isUpperCase(n.charAt(t.length())))) 059 return ucr(t); 060 } 061 return def; 062 } 063 064 /** 065 * Given a Java method, infers the REST path. 066 * 067 * @param m The Java method. Must not be <jk>null</jk>. 068 * @param method The HTTP method name if it's known. Can be <jk>null</jk>, in which case the path is inferred from Java method naming conventions. 069 * @return The REST path. Never <jk>null</jk> (falls back to <c>'/' + methodName</c> when no convention matches). 070 */ 071 public static String detectHttpPath(Method m, String method) { 072 String n = m.getName(); 073 if (method == null) { 074 if (n.startsWith("do") && n.length() > 2) { 075 String n2 = ucr(n.substring(2)); 076 for (var t : UC_METHODS) 077 if (eq(n2, t)) 078 return "/"; 079 } 080 for (var t : LC_METHODS) { 081 if (n.startsWith(t) && (n.length() == t.length() || Character.isUpperCase(n.charAt(t.length())))) { 082 return '/' + java.beans.Introspector.decapitalize(n.substring(t.length())); 083 } 084 } 085 } else { 086 if (eqic(n, method) || eqa(n, "do", "_")) 087 return "/"; 088 if (n.startsWith(method) && (n.length() == method.length() || Character.isUpperCase(n.charAt(method.length())))) { 089 return '/' + java.beans.Introspector.decapitalize(n.substring(method.length())); 090 } 091 } 092 return '/' + n; 093 } 094}