View Javadoc
1   /*
2    * Copyright (c) 2011, 2012, 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 com.sun.management.GarbageCollectionNotificationInfo;
29  import com.sun.management.GcInfo;
30  import java.lang.reflect.Method;
31  import javax.management.openmbean.CompositeData;
32  import javax.management.openmbean.CompositeType;
33  import javax.management.openmbean.CompositeDataSupport;
34  import javax.management.openmbean.OpenDataException;
35  import javax.management.openmbean.OpenType;
36  import javax.management.openmbean.SimpleType;
37  import java.security.AccessController;
38  import java.security.PrivilegedAction;
39  import java.lang.reflect.Field;
40  import java.util.HashMap;
41  
42  /**
43   * A CompositeData for GarbageCollectionNotificationInfo for the local management support.
44   * This class avoids the performance penalty paid to the
45   * construction of a CompositeData use in the local case.
46   */
47  public class GarbageCollectionNotifInfoCompositeData extends LazyCompositeData {
48      private final GarbageCollectionNotificationInfo gcNotifInfo;
49  
50      public GarbageCollectionNotifInfoCompositeData(GarbageCollectionNotificationInfo info) {
51          this.gcNotifInfo = info;
52      }
53  
54      public GarbageCollectionNotificationInfo getGarbageCollectionNotifInfo() {
55          return gcNotifInfo;
56      }
57  
58      public static CompositeData toCompositeData(GarbageCollectionNotificationInfo info) {
59          GarbageCollectionNotifInfoCompositeData gcnicd =
60              new GarbageCollectionNotifInfoCompositeData(info);
61          return gcnicd.getCompositeData();
62      }
63  
64      private CompositeType getCompositeTypeByBuilder() {
65          final GcInfoBuilder builder = AccessController.doPrivileged (new PrivilegedAction<GcInfoBuilder>() {
66                  public GcInfoBuilder run() {
67                      try {
68                          Class cl = Class.forName("com.sun.management.GcInfo");
69                          Field f = cl.getDeclaredField("builder");
70                          f.setAccessible(true);
71                          return (GcInfoBuilder)f.get(gcNotifInfo.getGcInfo());
72                      } catch(ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
73                          return null;
74                      }
75                  }
76              });
77          CompositeType gict = null;
78          synchronized(compositeTypeByBuilder) {
79              gict = compositeTypeByBuilder.get(builder);
80              if(gict == null) {
81                  OpenType<?>[] gcNotifInfoItemTypes = new OpenType<?>[] {
82                      SimpleType.STRING,
83                      SimpleType.STRING,
84                      SimpleType.STRING,
85                      builder.getGcInfoCompositeType(),
86                  };
87                  try {
88                      final String typeName =
89                          "sun.management.GarbageCollectionNotifInfoCompositeType";
90                      gict = new CompositeType(typeName,
91                                               "CompositeType for GC notification info",
92                                               gcNotifInfoItemNames,
93                                               gcNotifInfoItemNames,
94                                               gcNotifInfoItemTypes);
95                      compositeTypeByBuilder.put(builder,gict);
96                  } catch (OpenDataException e) {
97                      // shouldn't reach here
98                      throw Util.newException(e);
99                  }
100             }
101         }
102         return gict;
103     }
104 
105     protected CompositeData getCompositeData() {
106         // CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH
107         // gcNotifInfoItemNames!
108         final Object[] gcNotifInfoItemValues;
109         gcNotifInfoItemValues = new Object[] {
110             gcNotifInfo.getGcName(),
111             gcNotifInfo.getGcAction(),
112             gcNotifInfo.getGcCause(),
113             GcInfoCompositeData.toCompositeData(gcNotifInfo.getGcInfo())
114         };
115 
116         CompositeType gict = getCompositeTypeByBuilder();
117 
118         try {
119             return new CompositeDataSupport(gict,
120                                             gcNotifInfoItemNames,
121                                             gcNotifInfoItemValues);
122         } catch (OpenDataException e) {
123             // Should never reach here
124             throw new AssertionError(e);
125         }
126     }
127 
128     //    private static MappedMXBeanType gcInfoMapType;
129     private static final String GC_NAME = "gcName";
130     private static final String GC_ACTION = "gcAction";
131     private static final String GC_CAUSE = "gcCause";
132     private static final String GC_INFO     = "gcInfo";
133     private static final String[] gcNotifInfoItemNames = {
134         GC_NAME,
135         GC_ACTION,
136         GC_CAUSE,
137         GC_INFO
138     };
139     private static HashMap<GcInfoBuilder,CompositeType> compositeTypeByBuilder =
140         new HashMap<>();
141 
142     public static String getGcName(CompositeData cd) {
143         String gcname = getString(cd, GC_NAME);
144         if (gcname == null) {
145             throw new IllegalArgumentException("Invalid composite data: " +
146                 "Attribute " + GC_NAME + " has null value");
147         }
148         return gcname;
149     }
150 
151     public static String getGcAction(CompositeData cd) {
152         String gcaction = getString(cd, GC_ACTION);
153         if (gcaction == null) {
154             throw new IllegalArgumentException("Invalid composite data: " +
155                 "Attribute " + GC_ACTION + " has null value");
156         }
157         return gcaction;
158     }
159 
160     public static String getGcCause(CompositeData cd) {
161         String gccause = getString(cd, GC_CAUSE);
162         if (gccause == null) {
163             throw new IllegalArgumentException("Invalid composite data: " +
164                 "Attribute " + GC_CAUSE + " has null value");
165         }
166         return gccause;
167     }
168 
169     public static GcInfo getGcInfo(CompositeData cd) {
170         CompositeData gcInfoData = (CompositeData) cd.get(GC_INFO);
171         return GcInfo.from(gcInfoData);
172     }
173 
174     /** Validate if the input CompositeData has the expected
175      * CompositeType (i.e. contain all attributes with expected
176      * names and types).
177      */
178     public static void validateCompositeData(CompositeData cd) {
179         if (cd == null) {
180             throw new NullPointerException("Null CompositeData");
181         }
182 
183         if (!isTypeMatched( getBaseGcNotifInfoCompositeType(), cd.getCompositeType())) {
184             throw new IllegalArgumentException(
185                 "Unexpected composite type for GarbageCollectionNotificationInfo");
186         }
187     }
188 
189     // This is only used for validation.
190     private static CompositeType baseGcNotifInfoCompositeType = null;
191     private static synchronized CompositeType getBaseGcNotifInfoCompositeType() {
192         if (baseGcNotifInfoCompositeType == null) {
193             try {
194                 OpenType<?>[] baseGcNotifInfoItemTypes = new OpenType<?>[] {
195                     SimpleType.STRING,
196                     SimpleType.STRING,
197                     SimpleType.STRING,
198                     GcInfoCompositeData.getBaseGcInfoCompositeType()
199                 };
200                 baseGcNotifInfoCompositeType =
201                     new CompositeType("sun.management.BaseGarbageCollectionNotifInfoCompositeType",
202                                       "CompositeType for Base GarbageCollectionNotificationInfo",
203                                       gcNotifInfoItemNames,
204                                       gcNotifInfoItemNames,
205                                       baseGcNotifInfoItemTypes);
206             } catch (OpenDataException e) {
207                 // shouldn't reach here
208                 throw Util.newException(e);
209             }
210         }
211         return baseGcNotifInfoCompositeType;
212     }
213 
214     private static final long serialVersionUID = -1805123446483771292L;
215 }