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.logging;
018
019import java.util.*;
020
021/**
022 * Logger-name normalization for resource classes.
023 *
024 * <p>
025 * Walks up known proxy class names and returns the first non-proxy superclass so default logger naming is
026 * stable across common runtime-generated proxies while preserving ordinary nested-class names.
027 *
028 * @since 10.0.0
029 */
030public final class LoggerNaming {
031
032   private static final List<String> KNOWN_PROXY_INFIXES = List.of(
033      "$$SpringCGLIB$$",
034      "$$EnhancerBySpringCGLIB$$",
035      "$$EnhancerByCGLIB$$",
036      "$$FastClassBySpringCGLIB$$",
037      "$ByteBuddy$",
038      "$Proxy",
039      "$HibernateProxy$",
040      "$MockitoMock$"
041   );
042
043   private LoggerNaming() {}
044
045   /**
046    * Returns the user-class binary name for a class used in default logger derivation.
047    *
048    * <p>
049    * If the supplied class name contains a known proxy infix, this walks superclasses until it finds a
050    * class name without a known proxy infix. Ordinary nested classes are returned unchanged.
051    *
052    * @param c The class to normalize. Must not be <jk>null</jk>.
053    * @return The normalized binary class name.
054    */
055   public static String userClassName(Class<?> c) {
056      var original = c;
057      while (c != null && containsKnownProxyInfix(c.getName()))
058         c = c.getSuperclass();
059      return (c != null ? c : original).getName();
060   }
061
062   private static boolean containsKnownProxyInfix(String className) {
063      for (var infix : KNOWN_PROXY_INFIXES)
064         if (className.contains(infix))
065            return true;
066      return false;
067   }
068}