1 /*
2  * Copyright (c) 2005, 2018, 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.management;
27 
28 import javax.management.openmbean.CompositeType;
29 import javax.management.openmbean.CompositeData;
30 import javax.management.openmbean.CompositeDataSupport;
31 import javax.management.openmbean.OpenDataException;
32 import javax.management.openmbean.OpenType;
33 import java.util.Arrays;
34 import java.util.HashMap;
35 import java.util.Map;
36 import java.util.stream.Stream;
37 
38 /**
39  * A CompositeData for StackTraceElement for the local management support.
40  * This class avoids the performance penalty paid to the
41  * construction of a CompositeData use in the local case.
42  */
43 public class StackTraceElementCompositeData extends LazyCompositeData {
44     private final StackTraceElement ste;
45 
StackTraceElementCompositeData(StackTraceElement ste)46     private StackTraceElementCompositeData(StackTraceElement ste) {
47         this.ste = ste;
48     }
49 
getStackTraceElement()50     public StackTraceElement getStackTraceElement() {
51         return ste;
52     }
53 
from(CompositeData cd)54     public static StackTraceElement from(CompositeData cd) {
55         validateCompositeData(cd);
56 
57         if (STACK_TRACE_ELEMENT_COMPOSITE_TYPE.equals(cd.getCompositeType())) {
58             return new StackTraceElement(getString(cd, CLASS_LOADER_NAME),
59                                          getString(cd, MODULE_NAME),
60                                          getString(cd, MODULE_VERSION),
61                                          getString(cd, CLASS_NAME),
62                                          getString(cd, METHOD_NAME),
63                                          getString(cd, FILE_NAME),
64                                          getInt(cd, LINE_NUMBER));
65         } else {
66             return new StackTraceElement(getString(cd, CLASS_NAME),
67                                          getString(cd, METHOD_NAME),
68                                          getString(cd, FILE_NAME),
69                                          getInt(cd, LINE_NUMBER));
70 
71         }
72     }
73 
toCompositeData(StackTraceElement ste)74     public static CompositeData toCompositeData(StackTraceElement ste) {
75         StackTraceElementCompositeData cd = new StackTraceElementCompositeData(ste);
76         return cd.getCompositeData();
77     }
78 
getCompositeData()79     protected CompositeData getCompositeData() {
80         // values may be null; so can't use Map.of
81         Map<String,Object> items = new HashMap<>();
82         items.put(CLASS_LOADER_NAME, ste.getClassLoaderName());
83         items.put(MODULE_NAME,       ste.getModuleName());
84         items.put(MODULE_VERSION,    ste.getModuleVersion());
85         items.put(CLASS_NAME,        ste.getClassName());
86         items.put(METHOD_NAME,       ste.getMethodName());
87         items.put(FILE_NAME,         ste.getFileName());
88         items.put(LINE_NUMBER,       ste.getLineNumber());
89         items.put(NATIVE_METHOD,     ste.isNativeMethod());
90 
91         try {
92             return new CompositeDataSupport(STACK_TRACE_ELEMENT_COMPOSITE_TYPE, items);
93         } catch (OpenDataException e) {
94             // Should never reach here
95             throw new AssertionError(e);
96         }
97     }
98 
99     // Attribute names
100     private static final String CLASS_LOADER_NAME = "classLoaderName";
101     private static final String MODULE_NAME       = "moduleName";
102     private static final String MODULE_VERSION    = "moduleVersion";
103     private static final String CLASS_NAME        = "className";
104     private static final String METHOD_NAME       = "methodName";
105     private static final String FILE_NAME         = "fileName";
106     private static final String LINE_NUMBER       = "lineNumber";
107     private static final String NATIVE_METHOD     = "nativeMethod";
108 
109     private static final String[] V5_ATTRIBUTES = {
110         CLASS_NAME,
111         METHOD_NAME,
112         FILE_NAME,
113         LINE_NUMBER,
114         NATIVE_METHOD,
115     };
116 
117     private static final String[] V9_ATTRIBUTES = {
118         CLASS_LOADER_NAME,
119         MODULE_NAME,
120         MODULE_VERSION,
121     };
122 
123     private static final CompositeType STACK_TRACE_ELEMENT_COMPOSITE_TYPE;
124     private static final CompositeType V5_COMPOSITE_TYPE;
125     static {
126         try {
127             STACK_TRACE_ELEMENT_COMPOSITE_TYPE = (CompositeType)
128                 MappedMXBeanType.toOpenType(StackTraceElement.class);
129 
130             OpenType<?>[] types = new OpenType<?>[V5_ATTRIBUTES.length];
131             for (int i=0; i < V5_ATTRIBUTES.length; i++) {
132                 String name = V5_ATTRIBUTES[i];
133                 types[i] = STACK_TRACE_ELEMENT_COMPOSITE_TYPE.getType(name);
134             }
135             V5_COMPOSITE_TYPE = new CompositeType("StackTraceElement",
136                                                   "JDK 5 StackTraceElement",
137                                                   V5_ATTRIBUTES,
138                                                   V5_ATTRIBUTES,
139                                                   types);
140         } catch (OpenDataException e) {
141             // Should never reach here
142             throw new AssertionError(e);
143         }
144     }
145 
v5CompositeType()146     static CompositeType v5CompositeType() {
147         return V5_COMPOSITE_TYPE;
148     }
149 
150     /**
151      * Validate if the input CompositeData has the expected
152      * CompositeType (i.e. contain all attributes with expected
153      * names and types).
154      */
validateCompositeData(CompositeData cd)155     public static void validateCompositeData(CompositeData cd) {
156         if (cd == null) {
157             throw new NullPointerException("Null CompositeData");
158         }
159 
160         CompositeType ct = cd.getCompositeType();
161         if (!isTypeMatched(STACK_TRACE_ELEMENT_COMPOSITE_TYPE, ct) &&
162             !isTypeMatched(V5_COMPOSITE_TYPE, ct)) {
163             throw new IllegalArgumentException(
164                 "Unexpected composite type for StackTraceElement");
165         }
166     }
167     private static final long serialVersionUID = -2704607706598396827L;
168 }
169