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
24package com.app;
25
26import java.lang.StackWalker.StackFrame;
27import java.lang.module.ModuleDescriptor;
28import java.util.Objects;
29
30public class Utils {
31    public static void verify(Class<?> caller, String loaderName,
32                              String methodname, String filename) {
33        StackTraceElement[] stes = Thread.currentThread().getStackTrace();
34        StackWalker.StackFrame[] frames = new StackFrame[] {
35            makeStackFrame(Utils.class, "verify", "Utils.java"),
36            makeStackFrame(caller, methodname, filename)
37        };
38
39        checkFrame("app", frames[0], stes[1]);
40        checkFrame(loaderName, frames[1], stes[2]);
41    }
42
43    public static StackFrame makeStackFrame(Class<?> c, String methodname, String filename) {
44        return new StackFrame() {
45            @Override
46            public String getClassName() {
47                return c.getName();
48            }
49            @Override
50            public String getMethodName() {
51                return methodname;
52            }
53            @Override
54            public Class<?> getDeclaringClass() {
55                return c;
56            }
57            @Override
58            public int getByteCodeIndex() {
59                return 0;
60            }
61            @Override
62            public String getFileName() {
63                return filename;
64            }
65
66            @Override
67            public int getLineNumber() {
68                return 0;
69            }
70            @Override
71            public boolean isNativeMethod() {
72                return false;
73            }
74            @Override
75            public StackTraceElement toStackTraceElement() {
76                return null;
77            }
78
79            private String getClassLoaderName(Class<?> c) {
80                ClassLoader loader = c.getClassLoader();
81                String name = "";
82                if (loader == null) {
83                    name = "boot";
84                } else if (loader.getName() != null) {
85                    name = loader.getName();
86                }
87                return name;
88            }
89
90            @Override
91            public String toString() {
92                String mid = getClassLoaderName(c);
93                Module module = c.getModule();
94                if (module.isNamed()) {
95                    ModuleDescriptor md = module.getDescriptor();
96                    mid = md.name();
97                    if (md.version().isPresent())
98                        mid += "@" + md.version().get().toString();
99                    mid += "/";
100                }
101                String fileName = getFileName();
102                int lineNumber = getLineNumber();
103                String sourceinfo = "Unknown Source";
104                if (isNativeMethod()) {
105                    sourceinfo = "Native Method";
106                } else if (fileName != null && lineNumber >= 0) {
107                    sourceinfo = fileName + ":" + lineNumber;
108                }
109                return String.format("%s/%s.%s(%s)", mid, getClassName(), getMethodName(),
110                                     sourceinfo);
111
112            }
113        };
114    }
115
116    public static void checkFrame(String loaderName, StackFrame frame,
117                                  StackTraceElement ste) {
118        System.err.println("checking " + ste.toString() + " expected: " + frame.toString());
119        Class<?> c = frame.getDeclaringClass();
120        Module module = c.getModule();
121        assertEquals(ste.getModuleName(), module.getName(), "module name");
122        assertEquals(ste.getClassLoaderName(), loaderName, "class loader name");
123        assertEquals(ste.getClassLoaderName(), c.getClassLoader().getName(),
124                     "class loader name");
125        assertEquals(ste.getClassName(), c.getName(), "class name");
126        assertEquals(ste.getMethodName(), frame.getMethodName(), "method name");
127        assertEquals(ste.getFileName(), frame.getFileName(), "file name");
128
129    }
130    private static void assertEquals(String actual, String expected, String msg) {
131        if (!Objects.equals(actual, expected))
132            throw new AssertionError("Actual: " + actual + " Excepted: " +
133                expected + " mismatched " + msg);
134    }
135}
136