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 gmbal Show documentation
Show all versions of gmbal Show documentation
GlassFish MBean Annotation Library (Implementation)
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2007-2011 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 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.pfl.basic.facet.FacetAccessor;
import org.glassfish.pfl.basic.facet.FacetAccessorImpl;
import org.glassfish.pfl.basic.logex.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.isEmpty()) {
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
© 2015 - 2024 Weber Informatics LLC | Privacy Policy