org.glassfish.gmbal.impl.MBeanImpl 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 java.lang.reflect.Field;
import org.glassfish.gmbal.generic.FacetAccessor;
import org.glassfish.gmbal.generic.FacetAccessorImpl;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import javax.management.Attribute ;
import javax.management.AttributeList ;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException ;
import javax.management.InvalidAttributeValueException ;
import javax.management.AttributeNotFoundException ;
import javax.management.MBeanRegistrationException;
import javax.management.NotCompliantMBeanException;
import javax.management.ReflectionException ;
import javax.management.MBeanInfo ;
import javax.management.NotificationBroadcasterSupport ;
import javax.management.MBeanNotificationInfo ;
import javax.management.AttributeChangeNotification ;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.security.AccessController ;
import java.security.PrivilegedExceptionAction ;
import java.security.PrivilegedActionException ;
import java.util.Map ;
import java.util.HashMap ;
import java.util.HashSet;
import java.util.Set;
import org.glassfish.external.amx.AMX;
import org.glassfish.gmbal.GmbalMBean;
import org.glassfish.gmbal.generic.OperationTracer;
public class MBeanImpl extends NotificationBroadcasterSupport
implements FacetAccessor, GmbalMBean {
private boolean registered ;
private final MBeanSkeleton skel ;
private final String type ;
private String name ;
private ObjectName oname ;
private MBeanImpl parent ;
private final Set subTypes ; // Null if not used: don't create empty
// sets if not used.
// First index is type, second is name.
private Map> children ;
private Object target ;
private MBeanServer server ;
private String parentPathForObjectName;
private boolean suspended;
public MBeanImpl( final MBeanSkeleton skel,
final Object obj, final MBeanServer server,
final String type ) {
this.registered = false ;
this.skel = skel ;
this.type = type ;
this.name = "" ;
this.oname = null ;
this.parent = null ;
this.children = new HashMap>() ;
this.target = obj ;
String[] stypes = skel.getMBeanType().subTypes() ;
if (stypes.length > 0) {
this.subTypes = new HashSet( Arrays.asList(stypes)) ;
} else {
this.subTypes = null ;
}
addFacet( obj ) ;
addFacet( new AMXImpl( this ) ) ;
// Note that the construction of an MBean skeleton and
// facet registration must stay in sync. The code is currently separated into
// two places (here and call to new MBeanSkeleton( skel, skel )).
// This will also be important for dealing with multiple upper bounds.
this.server = server ;
this.parentPathForObjectName = null ;
this.suspended = false ;
}
@Override
public synchronized boolean equals( Object obj ) {
if (this == obj) {
return true ;
}
if (!(obj instanceof MBeanImpl)) {
return false ;
}
MBeanImpl other = (MBeanImpl)obj ;
return parent == other.parent() &&
name.equals( other.name() ) &&
type.equals( other.type() ) ;
}
@Override
public synchronized int hashCode() {
if (parent == null) {
return name.hashCode() ^ type.hashCode() ;
} else {
return name.hashCode() ^ type.hashCode() ^ parent.hashCode() ;
}
}
@Override
public String toString() {
return "MBeanImpl[type=" + type + ",name=" + name
+ ",oname=" + oname + "]" ;
}
public MBeanSkeleton skeleton() {
return skel ;
}
public String type() {
return type ;
}
public Object target() {
return target ;
}
public synchronized String name() {
return name ;
}
public synchronized void name( String str ) {
name = str ;
}
public synchronized ObjectName objectName() {
return oname ;
}
public synchronized void objectName( ObjectName oname ) {
this.oname = oname ;
}
public synchronized MBeanImpl parent() {
return parent ;
}
public synchronized void parent( MBeanImpl entity ) {
if (parent == null) {
parent = entity ;
} else {
throw Exceptions.self.nodeAlreadyHasParent(entity) ;
}
}
public synchronized Map> children() {
// Make a copy to avoid problems with concurrent modification.
Map> result = new
HashMap>() ;
for (Map.Entry> entry
: children.entrySet()) {
result.put( entry.getKey(),
Collections.unmodifiableMap(
new HashMap( entry.getValue() ) ) ) ;
}
return Collections.unmodifiableMap( result ) ;
}
public synchronized void addChild( MBeanImpl child ) {
child.parent( this ) ;
// XXX Add test case!
if (subTypes != null && !subTypes.contains(child.type())) {
throw Exceptions.self.invalidSubtypeOfParent( this.oname,
this.subTypes, child.objectName(), child.type() ) ;
}
Map map = children.get( child.type() ) ;
if (map == null) {
map = new HashMap() ;
children.put( child.type(), map ) ;
}
// XXX add test case!
boolean isSingleton = child.skeleton().getMBeanType().isSingleton() ;
if (isSingleton && map.size() > 0) {
throw Exceptions.self.childMustBeSingleton( this.oname,
child.type(), child.objectName() ) ;
}
map.put( child.name(), child) ;
}
public synchronized void removeChild( MBeanImpl child ) {
Map map = children.get( child.type() ) ;
if (map != null) {
map.remove( child.name() ) ;
if (map.size() == 0) {
children.remove( child.type() ) ;
}
}
}
private void restNameHelper( StringBuilder sb ) {
if (parent() != null) {
parent().restNameHelper( sb ) ;
sb.append( '/' ) ;
}
sb.append( type() ) ;
if (!name.equals("")) {
sb.append( '[' ) ;
sb.append( name ) ;
sb.append( ']' ) ;
}
}
private synchronized String restName() {
StringBuilder sb = new StringBuilder( 60 ) ;
restNameHelper( sb ) ;
return sb.toString() ;
}
public synchronized String getParentPathPart( String rootParentPrefix ) {
if (parentPathForObjectName == null) {
StringBuilder result = new StringBuilder() ;
result.append( AMX.PARENT_PATH_KEY ) ;
result.append( "=" ) ;
String qname ;
if (rootParentPrefix == null) {
qname = "/" + restName() ;
} else {
qname = rootParentPrefix + "/" + restName() ;
}
result.append( MBeanTree.getQuotedName( qname ) ) ;
// Note that the "/" MUST be passed to getQuotedName, or we
// can get things like /"...", which is wrong.
result.append( ',' ) ;
parentPathForObjectName = result.toString() ;
}
return parentPathForObjectName ;
}
public synchronized boolean suspended() {
return suspended ;
}
public synchronized void suspended( boolean flag ) {
suspended = flag ;
}
public synchronized void register() throws InstanceAlreadyExistsException,
MBeanRegistrationException, NotCompliantMBeanException {
if (!registered) {
if (skeleton().mom().jmxRegistrationDebug()) {
Exceptions.self.registeringMBean( oname ) ;
}
try {
AccessController.doPrivileged(
new PrivilegedExceptionAction