1/*
2 * Copyright (c) 2007, 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
27
28package com.sun.org.glassfish.gmbal;
29
30import java.io.IOException;
31import java.util.HashMap;
32import java.util.Map;
33import javax.management.Attribute;
34import javax.management.AttributeList;
35import javax.management.AttributeNotFoundException;
36import javax.management.Descriptor;
37import javax.management.InstanceNotFoundException;
38import javax.management.IntrospectionException;
39import javax.management.InvalidAttributeValueException;
40import javax.management.JMException;
41import javax.management.MBeanException;
42import javax.management.MBeanInfo;
43import javax.management.MBeanServerConnection;
44import javax.management.MalformedObjectNameException;
45import javax.management.ObjectName;
46import javax.management.ReflectionException;
47import javax.management.RuntimeOperationsException;
48import javax.management.modelmbean.ModelMBeanInfo;
49
50
51/** This class implements a generic AMXMBeanInterface MBean which is connected to a possibly
52 * remote MBeanServerConnection (note that MBeanServer isA MBeanServerConnection,
53 * so we can actually create an AMXClientImpl simply by using the MBeanServer
54 * from the mom: this is useful for testing).
55 * <P>
56 * Note that this version of the AMXMBeanInterface API provides a generic get/set API that
57 * is identical to DynamicMBean, except that it only throws unchecked exceptions.
58 * This is far more convenient in practice than the JMX-standard checked exceptions.
59 *
60 * @author ken
61 */
62public class AMXClient implements AMXMBeanInterface {
63    private static ObjectName makeObjectName( String str ) {
64        try {
65            return new ObjectName(str);
66        } catch (MalformedObjectNameException ex) {
67            return null ;
68        }
69    }
70
71    /** Special object name used to represent a NULL objectName result.
72     */
73    public static final ObjectName NULL_OBJECTNAME = makeObjectName(
74        "null:type=Null,name=Null" ) ;
75
76    private MBeanServerConnection server ;
77    private ObjectName oname ;
78
79    @Override
80    public boolean equals( Object obj ) {
81        if (this == obj) {
82            return true ;
83        }
84
85        if (!(obj instanceof AMXClient)) {
86            return false ;
87        }
88
89        AMXClient other = (AMXClient)obj ;
90
91        return oname.equals( other.oname ) ;
92    }
93
94    @Override
95    public int hashCode() {
96        int hash = 5;
97        hash = 47 * hash + (this.oname != null ? this.oname.hashCode() : 0);
98        return hash;
99    }
100
101    @Override
102    public String toString() {
103        return "AMXClient[" + oname + "]" ;
104    }
105
106    private <T> T fetchAttribute( String name, Class<T> type ) {
107        try {
108            Object obj = server.getAttribute( oname, name ) ;
109            if (NULL_OBJECTNAME.equals( obj )) {
110                return null ;
111            } else {
112                return type.cast( obj ) ;
113            }
114        } catch (JMException exc) {
115            throw new GmbalException( "Exception in fetchAttribute", exc ) ;
116        } catch (IOException exc) {
117            throw new GmbalException( "Exception in fetchAttribute", exc ) ;
118        }
119    }
120
121    public AMXClient( MBeanServerConnection server,
122        ObjectName oname ) {
123        this.server = server ;
124        this.oname = oname ;
125    }
126
127    private AMXClient makeAMX( ObjectName on ) {
128        if (on == null) {
129            return null ;
130        }
131        return new AMXClient( this.server, on ) ;
132    }
133
134    public String getName() {
135        return fetchAttribute( "Name", String.class )  ;
136    }
137
138    public Map<String,?> getMeta() {
139        try {
140            ModelMBeanInfo mbi = (ModelMBeanInfo) server.getMBeanInfo( oname );
141            Descriptor desc = mbi.getMBeanDescriptor() ;
142            Map<String,Object> result = new HashMap<String,Object>() ;
143            for (String str : desc.getFieldNames()) {
144                result.put( str, desc.getFieldValue( str )) ;
145            }
146            return result ;
147        } catch (MBeanException ex) {
148            throw new GmbalException( "Exception in getMeta", ex ) ;
149        } catch (RuntimeOperationsException ex) {
150            throw new GmbalException( "Exception in getMeta", ex ) ;
151        } catch (InstanceNotFoundException ex) {
152            throw new GmbalException( "Exception in getMeta", ex ) ;
153        } catch (IntrospectionException ex) {
154            throw new GmbalException( "Exception in getMeta", ex ) ;
155        } catch (ReflectionException ex) {
156            throw new GmbalException( "Exception in getMeta", ex ) ;
157        } catch (IOException ex) {
158            throw new GmbalException( "Exception in getMeta", ex ) ;
159        }
160    }
161
162    public AMXClient getParent() {
163        ObjectName res  = fetchAttribute( "Parent", ObjectName.class ) ;
164        return makeAMX( res ) ;
165    }
166
167    public AMXClient[] getChildren() {
168        ObjectName[] onames = fetchAttribute( "Children",
169            ObjectName[].class ) ;
170        return makeAMXArray( onames ) ;
171    }
172
173    private AMXClient[] makeAMXArray( ObjectName[] onames ) {
174        AMXClient[] result = new AMXClient[onames.length] ;
175        int ctr=0 ;
176        for (ObjectName on : onames ) {
177            result[ctr++] = makeAMX( on ) ;
178        }
179
180        return result ;
181    }
182
183    public Object getAttribute(String attribute) {
184        try {
185            return server.getAttribute(oname, attribute);
186        } catch (MBeanException ex) {
187            throw new GmbalException( "Exception in getAttribute", ex ) ;
188        } catch (AttributeNotFoundException ex) {
189            throw new GmbalException( "Exception in getAttribute", ex ) ;
190        } catch (ReflectionException ex) {
191            throw new GmbalException( "Exception in getAttribute", ex ) ;
192        } catch (InstanceNotFoundException ex) {
193            throw new GmbalException( "Exception in getAttribute", ex ) ;
194        } catch (IOException ex) {
195            throw new GmbalException( "Exception in getAttribute", ex ) ;
196        }
197    }
198
199    public void setAttribute(String name, Object value ) {
200        Attribute attr = new Attribute( name, value ) ;
201        setAttribute( attr ) ;
202    }
203
204    public void setAttribute(Attribute attribute) {
205        try {
206            server.setAttribute(oname, attribute);
207        } catch (InstanceNotFoundException ex) {
208            throw new GmbalException( "Exception in setAttribute", ex ) ;
209        } catch (AttributeNotFoundException ex) {
210            throw new GmbalException( "Exception in setAttribute", ex ) ;
211        } catch (InvalidAttributeValueException ex) {
212            throw new GmbalException( "Exception in setAttribute", ex ) ;
213        } catch (MBeanException ex) {
214            throw new GmbalException( "Exception in setAttribute", ex ) ;
215        } catch (ReflectionException ex) {
216            throw new GmbalException( "Exception in setAttribute", ex ) ;
217        } catch (IOException ex) {
218            throw new GmbalException( "Exception in setAttribute", ex ) ;
219        }
220    }
221
222    public AttributeList getAttributes(String[] attributes) {
223        try {
224            return server.getAttributes(oname, attributes);
225        } catch (InstanceNotFoundException ex) {
226            throw new GmbalException( "Exception in getAttributes", ex ) ;
227        } catch (ReflectionException ex) {
228            throw new GmbalException( "Exception in getAttributes", ex ) ;
229        } catch (IOException ex) {
230            throw new GmbalException( "Exception in getAttributes", ex ) ;
231        }
232    }
233
234    public AttributeList setAttributes(AttributeList attributes) {
235        try {
236            return server.setAttributes(oname, attributes);
237        } catch (InstanceNotFoundException ex) {
238            throw new GmbalException( "Exception in setAttributes", ex ) ;
239        } catch (ReflectionException ex) {
240            throw new GmbalException( "Exception in setAttributes", ex ) ;
241        } catch (IOException ex) {
242            throw new GmbalException( "Exception in setAttributes", ex ) ;
243        }
244    }
245
246    public Object invoke(String actionName, Object[] params, String[] signature)
247        throws MBeanException, ReflectionException {
248        try {
249            return server.invoke(oname, actionName, params, signature);
250        } catch (InstanceNotFoundException ex) {
251            throw new GmbalException( "Exception in invoke", ex ) ;
252        } catch (IOException ex) {
253            throw new GmbalException( "Exception in invoke", ex ) ;
254        }
255    }
256
257    public MBeanInfo getMBeanInfo() {
258        try {
259            return server.getMBeanInfo(oname);
260        } catch (InstanceNotFoundException ex) {
261            throw new GmbalException( "Exception in invoke", ex ) ;
262        } catch (IntrospectionException ex) {
263            throw new GmbalException( "Exception in invoke", ex ) ;
264        } catch (ReflectionException ex) {
265            throw new GmbalException( "Exception in invoke", ex ) ;
266        } catch (IOException ex) {
267            throw new GmbalException( "Exception in invoke", ex ) ;
268        }
269    }
270
271    public ObjectName objectName() {
272        return oname ;
273    }
274}
275