org.glassfish.gmbal.impl.MBeanSkeleton Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of webservices-rt Show documentation
Show all versions of webservices-rt Show documentation
This module contains the Metro runtime code.
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2007-2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.glassfish.gmbal.impl;
import org.glassfish.gmbal.AMXMetadata;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicLong;
import java.lang.reflect.Method;
import java.lang.reflect.ReflectPermission;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.MBeanException;
import javax.management.InvalidAttributeValueException;
import javax.management.AttributeNotFoundException;
import javax.management.ReflectionException;
import javax.management.MBeanParameterInfo;
import javax.management.NotificationBroadcasterSupport;
import javax.management.AttributeChangeNotification;
import org.glassfish.gmbal.generic.BinaryFunction;
import org.glassfish.gmbal.NameValue;
import org.glassfish.gmbal.ManagedOperation;
import org.glassfish.gmbal.ParameterNames;
import org.glassfish.gmbal.generic.DumpIgnore;
import org.glassfish.gmbal.generic.Pair;
import org.glassfish.gmbal.generic.DumpToString;
import org.glassfish.gmbal.generic.FacetAccessor;
import javax.management.Descriptor;
import javax.management.JMException;
import javax.management.modelmbean.ModelMBeanAttributeInfo;
import javax.management.modelmbean.ModelMBeanInfoSupport;
import javax.management.modelmbean.ModelMBeanOperationInfo;
import javax.management.openmbean.OpenMBeanParameterInfoSupport;
import org.glassfish.gmbal.generic.Algorithms;
import org.glassfish.gmbal.generic.MethodMonitor;
import org.glassfish.gmbal.generic.MethodMonitorFactory;
import org.glassfish.gmbal.typelib.EvaluatedClassAnalyzer;
import org.glassfish.gmbal.typelib.EvaluatedClassDeclaration;
import org.glassfish.gmbal.typelib.EvaluatedFieldDeclaration;
import org.glassfish.gmbal.typelib.EvaluatedMethodDeclaration;
import org.glassfish.gmbal.typelib.EvaluatedType;
public class MBeanSkeleton {
private static Descriptor DEFAULT_AMX_DESCRIPTOR =
DescriptorIntrospector.descriptorForElement( null,
ManagedObjectManagerImpl.DefaultAMXMetadataHolder.class ) ;
public interface Operation
extends BinaryFunction, Object> {
};
private AMXMetadata mbeanType;
private final String type;
private Descriptor descriptor;
@DumpToString
private final AtomicLong sequenceNumber;
@DumpToString
private final ManagedObjectManagerInternal mom;
@DumpIgnore
private final MethodMonitor mm;
private final Map setters;
private final Map getters;
private AttributeDescriptor nameAttributeDescriptor;
private final Map, Operation>> operations;
private final List mbeanAttributeInfoList;
private final List mbeanOperationInfoList;
private final ModelMBeanInfoSupport mbInfo;
private void addToCompoundMap(
Map> source, Map> dest) {
for (Map.Entry> entry : source.entrySet()) {
Map dmap = dest.get(entry.getKey());
if (dmap == null) {
dmap = new HashMap();
dest.put(entry.getKey(), dmap);
}
dmap.putAll(entry.getValue());
}
}
public MBeanSkeleton(final EvaluatedClassDeclaration annotatedClass,
final EvaluatedClassAnalyzer ca,
final ManagedObjectManagerInternal mom) {
boolean isDefaultAMXMetadata = false ;
mbeanType = mom.getFirstAnnotationOnClass(annotatedClass, AMXMetadata.class);
if (mbeanType == null) {
isDefaultAMXMetadata = true ;
mbeanType = mom.getDefaultAMXMetadata() ;
}
type = mom.getTypeName(annotatedClass.cls(), "AMX_TYPE",
mbeanType.type());
Descriptor ldesc = DescriptorIntrospector.descriptorForElement( mom,
annotatedClass.cls() ) ;
if (isDefaultAMXMetadata) {
// We didn't have an @AMXMetadata annotation on annotatedClass,
// so we need to construct a new Descriptor that contains the
// default AMXMetadata values, as well as any other values that
// may be present from other metadata annotations.
ldesc = DescriptorUtility.union( DEFAULT_AMX_DESCRIPTOR, ldesc ) ;
}
// Now fix up the descriptor so that the ModelMBean code won't
// complain.
descriptor = makeValidDescriptor( ldesc, DescriptorType.mbean, type);
sequenceNumber = new AtomicLong();
this.mom = mom;
mm = MethodMonitorFactory.makeStandard(getClass());
setters = new HashMap();
getters = new HashMap();
operations = new HashMap, Operation>>();
mbeanAttributeInfoList = new ArrayList();
mbeanOperationInfoList = new ArrayList();
analyzeAttributes(ca);
analyzeOperations(ca);
analyzeObjectNameKeys(ca);
mbInfo = makeMbInfo(mom.getDescription(annotatedClass));
}
// In case of conflicts, always prefer second over first.
private MBeanSkeleton(MBeanSkeleton first, MBeanSkeleton second) {
mbeanType = second.mbeanType;
type = second.type;
descriptor = DescriptorUtility.union(first.descriptor,
second.descriptor);
sequenceNumber = new AtomicLong();
mom = second.mom;
mm = MethodMonitorFactory.makeStandard(getClass());
setters = new HashMap();
setters.putAll(first.setters);
setters.putAll(second.setters);
getters = new HashMap();
getters.putAll(first.getters);
getters.putAll(second.getters);
nameAttributeDescriptor = second.nameAttributeDescriptor;
operations = new HashMap, Operation>>();
addToCompoundMap(first.operations, operations);
addToCompoundMap(second.operations, operations);
mbeanAttributeInfoList = new ArrayList();
mbeanAttributeInfoList.addAll(first.mbeanAttributeInfoList);
mbeanAttributeInfoList.addAll(second.mbeanAttributeInfoList);
mbeanOperationInfoList = new ArrayList();
mbeanOperationInfoList.addAll(first.mbeanOperationInfoList);
mbeanOperationInfoList.addAll(second.mbeanOperationInfoList);
// This must go last, because it depends on some of the
// preceding initializations.
mbInfo = makeMbInfo(second.mbInfo.getDescription());
}
private ModelMBeanInfoSupport makeMbInfo(String description) {
ModelMBeanAttributeInfo[] attrInfos = mbeanAttributeInfoList.toArray(
new ModelMBeanAttributeInfo[mbeanAttributeInfoList.size()]);
ModelMBeanOperationInfo[] operInfos = mbeanOperationInfoList.toArray(
new ModelMBeanOperationInfo[mbeanOperationInfoList.size()]);
return new ModelMBeanInfoSupport( type, description, attrInfos, null,
operInfos, null, descriptor);
}
/** Create a new MBeanSkeleton that is the composition of this one
* and skel. Note that, if this and skel contain the same attribute,
* the version from skel will appear in the composition.
*/
public MBeanSkeleton compose(MBeanSkeleton skel) {
return new MBeanSkeleton(this, skel);
}
private enum DescriptorType { mbean, attribute, operation }
// Create a valid descriptor so that ModelMBinfoSupport won't throw
// an exception.
Descriptor makeValidDescriptor(Descriptor desc, DescriptorType dtype,
String dname) {
Map map = new HashMap();
String[] names = desc.getFieldNames();
Object[] values = desc.getFieldValues((String[]) null);
for (int ctr = 0; ctr < names.length; ctr++) {
map.put(names[ctr], values[ctr]);
}
map.put("descriptorType", dtype.toString());
if (dtype == DescriptorType.operation) {
map.put("role", "operation");
map.put("targetType", "ObjectReference");
} else if (dtype == DescriptorType.mbean) {
map.put("persistPolicy", "never");
map.put("log", "F");
map.put("visibility", "1");
}
map.put("name", dname);
map.put("displayName", dname);
return DescriptorUtility.makeDescriptor(map);
}
@Override
public String toString() {
return "DynamicMBeanSkeleton[type" + type + "]";
}
// This method should only be called when getter.id.equals( setter.id )
private void processAttribute(AttributeDescriptor getter,
AttributeDescriptor setter) {
mm.enter(mom.registrationFineDebug(), "processAttribute", getter,
setter);
try {
if ((setter == null) && (getter == null)) {
throw Exceptions.self.notBothNull();
}
if ((setter != null) && (getter != null)
&& !setter.type().equals(getter.type())) {
throw Exceptions.self.typesMustMatch();
}
AttributeDescriptor nonNullDescriptor =
(getter != null) ? getter : setter;
String name = nonNullDescriptor.id();
String description = nonNullDescriptor.description();
Descriptor desc = DescriptorUtility.EMPTY_DESCRIPTOR;
if (getter != null) {
desc = DescriptorUtility.union(desc,
DescriptorIntrospector.descriptorForElement( mom,
getter.accessible()));
}
if (setter != null) {
desc = DescriptorUtility.union(desc,
DescriptorIntrospector.descriptorForElement( mom,
setter.accessible()));
}
desc = makeValidDescriptor(desc, DescriptorType.attribute, name);
mm.info( mom.registrationFineDebug(), name, description, desc );
TypeConverter tc = mom.getTypeConverter(nonNullDescriptor.type());
ModelMBeanAttributeInfo ainfo = new ModelMBeanAttributeInfo(name,
tc.getManagedType().getClassName(), description,
getter != null, setter != null, false, desc);
mm.info( mom.registrationFineDebug(), ainfo);
mbeanAttributeInfoList.add(ainfo);
} finally {
mm.exit( mom.registrationFineDebug() );
}
}
private void analyzeAttributes(EvaluatedClassAnalyzer ca) {
mm.enter( mom.registrationFineDebug(), "analyzeAttributes", ca);
try {
Pair