001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.util; 020 021import java.util.regex.Matcher; 022import java.util.regex.Pattern; 023 024/** 025 * Return Caller's short class name, method and line number 026 */ 027public class Caller { 028 /** Utility class; instances carry no state. */ 029 public Caller() {} 030 private static String JAVA_ID_PATTERN = "(\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)\\.*"; 031 private static Pattern FQCN = Pattern.compile(JAVA_ID_PATTERN + "(\\." + JAVA_ID_PATTERN + ")*"); 032 /** 033 * Returns information for the immediate caller of the method that calls this helper. 034 * 035 * @return abbreviated {@code class.method:line} string 036 */ 037 public static String info() { 038 return info(1); 039 } 040 041 /** 042 * Returns information for the caller {@code pos} frames above the immediate caller. 043 * 044 * @param pos additional stack frames to skip past the immediate caller 045 * @return abbreviated {@code class.method:line} string 046 */ 047 public static String info(int pos) { 048 return info (Thread.currentThread().getStackTrace()[2+pos]); 049 } 050 051 /** 052 * Formats a stack trace element as {@code abbreviatedClass.method:line}. 053 * 054 * @param st stack frame to format 055 * @return abbreviated {@code class.method:line} string 056 */ 057 public static String info (StackTraceElement st) { 058 String clazz = st.getClassName(); 059 Matcher matcher = FQCN.matcher(clazz); 060 StringBuilder sb = new StringBuilder(); 061 while (matcher.find()) { 062 sb.append(matcher.hitEnd() ? matcher.group(1) : matcher.group(1).charAt(0)); 063 sb.append('.'); 064 } 065 return sb.append(st.getMethodName()) 066 .append(':') 067 .append(st.getLineNumber()) 068 .toString(); 069 } 070 071 072 /** 073 * Abbreviates a fully-qualified class name by collapsing every package segment 074 * to its first character (e.g. {@code o.j.u.Caller}). 075 * 076 * @param clazz fully-qualified class name 077 * @return the abbreviated class name 078 */ 079 public static String shortClassName(String clazz) { 080 Matcher matcher = FQCN.matcher(clazz); 081 StringBuilder sb = new StringBuilder(); 082 while (matcher.find()) { 083 if (matcher.hitEnd()) { 084 sb.append(matcher.group(1)); 085 break; 086 } 087 else { 088 sb.append(matcher.group(1).charAt(0)); 089 sb.append('.'); 090 } 091 } 092 return sb.toString(); 093 } 094}