1 /*
   2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package com.app;
  25 
  26 import java.lang.StackWalker.StackFrame;
  27 import java.lang.module.ModuleDescriptor;
  28 import java.lang.reflect.Module;
  29 import java.util.Objects;
  30 
  31 public class Utils {
  32     public static void verify(Class<?> caller, String loaderName,
  33                               String methodname, String filename) {
  34         StackTraceElement[] stes = Thread.currentThread().getStackTrace();
  35         StackWalker.StackFrame[] frames = new StackFrame[] {
  36             makeStackFrame(Utils.class, "verify", "Utils.java"),
  37             makeStackFrame(caller, methodname, filename)
  38         };
  39 
  40         checkFrame("app", frames[0], stes[1]);
  41         checkFrame(loaderName, frames[1], stes[2]);
  42     }
  43 
  44     public static StackFrame makeStackFrame(Class<?> c, String methodname, String filename) {
  45         return new StackFrame() {
  46             @Override
  47             public String getClassName() {
  48                 return c.getName();
  49             }
  50             @Override
  51             public String getMethodName() {
  52                 return methodname;
  53             }
  54             @Override
  55             public Class<?> getDeclaringClass() {
  56                 return c;
  57             }
  58             @Override
  59             public int getByteCodeIndex() {
  60                 return 0;
  61             }
  62             @Override
  63             public String getFileName() {
  64                 return filename;
  65             }
  66 
  67             @Override
  68             public int getLineNumber() {
  69                 return 0;
  70             }
  71             @Override
  72             public boolean isNativeMethod() {
  73                 return false;
  74             }
  75             @Override
  76             public StackTraceElement toStackTraceElement() {
  77                 return null;
  78             }
  79 
  80             private String getClassLoaderName(Class<?> c) {
  81                 ClassLoader loader = c.getClassLoader();
  82                 String name = "";
  83                 if (loader == null) {
  84                     name = "boot";
  85                 } else if (loader.getName() != null) {
  86                     name = loader.getName();
  87                 }
  88                 return name;
  89             }
  90 
  91             @Override
  92             public String toString() {
  93                 String mid = getClassLoaderName(c);
  94                 Module module = c.getModule();
  95                 if (module.isNamed()) {
  96                     ModuleDescriptor md = module.getDescriptor();
  97                     mid = md.name();
  98                     if (md.version().isPresent())
  99                         mid += "@" + md.version().get().toString();
 100                     mid += "/";
 101                 }
 102                 String fileName = getFileName();
 103                 int lineNumber = getLineNumber();
 104                 String sourceinfo = "Unknown Source";
 105                 if (isNativeMethod()) {
 106                     sourceinfo = "Native Method";
 107                 } else if (fileName != null && lineNumber >= 0) {
 108                     sourceinfo = fileName + ":" + lineNumber;
 109                 }
 110                 return String.format("%s/%s.%s(%s)", mid, getClassName(), getMethodName(),
 111                                      sourceinfo);
 112 
 113             }
 114         };
 115     }
 116 
 117     public static void checkFrame(String loaderName, StackFrame frame,
 118                                   StackTraceElement ste) {
 119         System.err.println("checking " + ste.toString() + " expected: " + frame.toString());
 120         Class<?> c = frame.getDeclaringClass();
 121         Module module = c.getModule();
 122         assertEquals(ste.getModuleName(), module.getName(), "module name");
 123         assertEquals(ste.getClassLoaderName(), loaderName, "class loader name");
 124         assertEquals(ste.getClassLoaderName(), c.getClassLoader().getName(),
 125                      "class loader name");
 126         assertEquals(ste.getClassName(), c.getName(), "class name");
 127         assertEquals(ste.getMethodName(), frame.getMethodName(), "method name");
 128         assertEquals(ste.getFileName(), frame.getFileName(), "file name");
 129 
 130     }
 131     private static void assertEquals(String actual, String expected, String msg) {
 132         if (!Objects.equals(actual, expected))
 133             throw new AssertionError("Actual: " + actual + " Excepted: " +
 134                 expected + " mismatched " + msg);
 135     }
 136 }