001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    
019    package org.apache.commons.modeler;
020    
021    
022    import java.util.ArrayList;
023    import java.util.Iterator;
024    import java.util.List;
025    
026    import javax.management.Descriptor;
027    import javax.management.InstanceNotFoundException;
028    import javax.management.MBeanException;
029    import javax.management.RuntimeOperationsException;
030    import javax.management.modelmbean.InvalidTargetObjectTypeException;
031    import javax.management.modelmbean.ModelMBean;
032    import javax.management.modelmbean.ModelMBeanAttributeInfo;
033    import javax.management.modelmbean.ModelMBeanConstructorInfo;
034    import javax.management.modelmbean.ModelMBeanInfo;
035    import javax.management.modelmbean.ModelMBeanInfoSupport;
036    import javax.management.modelmbean.ModelMBeanNotificationInfo;
037    import javax.management.modelmbean.ModelMBeanOperationInfo;
038    
039    
040    /**
041     * <p>Internal configuration information for a managed bean (MBean)
042     * descriptor.</p>
043     *
044     * @author Craig R. McClanahan
045     * @version $Revision: 480402 $ $Date: 2006-11-29 05:43:23 +0100 (Wed, 29 Nov 2006) $
046     */
047    
048    public class ManagedBean implements java.io.Serializable
049    {
050        // ----------------------------------------------------- Instance Variables
051    
052    
053        /**
054         * The <code>ModelMBeanInfo</code> object that corresponds
055         * to this <code>ManagedBean</code> instance.
056         */
057        transient ModelMBeanInfo info = null;
058        protected AttributeInfo attributes[] = new AttributeInfo[0];
059        protected String className =
060                "org.apache.commons.modeler.BaseModelMBean";
061        protected ConstructorInfo constructors[] = new ConstructorInfo[0];
062        protected String description = null;
063        protected String domain = null;
064        protected String group = null;
065        protected String name = null;
066    
067        protected List fields = new ArrayList();
068        protected NotificationInfo notifications[] = new NotificationInfo[0];
069        protected OperationInfo operations[] = new OperationInfo[0];
070        protected String type = null;
071    
072        /** Constructor. Will add default attributes. 
073         *  
074         */ 
075        public ManagedBean() {
076            AttributeInfo ai=new AttributeInfo();
077            ai.setName("modelerType");
078            ai.setDescription("Type of the modeled resource. Can be set only once");
079            ai.setType("java.lang.String");
080            ai.setWriteable(false);
081            addAttribute(ai);
082        }
083        
084        // ------------------------------------------------------------- Properties
085    
086    
087        /**
088         * The collection of attributes for this MBean.
089         */
090        public AttributeInfo[] getAttributes() {
091            return (this.attributes);
092        }
093    
094    
095        /**
096         * The fully qualified name of the Java class of the MBean
097         * described by this descriptor.  If not specified, the standard JMX
098         * class (<code>javax.management.modelmbean.RequiredModeLMBean</code>)
099         * will be utilized.
100         */
101        public String getClassName() {
102            return (this.className);
103        }
104    
105        public void setClassName(String className) {
106            this.className = className;
107            this.info = null;
108        }
109    
110    
111        /**
112         * The collection of constructors for this MBean.
113         */
114        public ConstructorInfo[] getConstructors() {
115            return (this.constructors);
116        }
117    
118    
119        /**
120         * The human-readable description of this MBean.
121         */
122        public String getDescription() {
123            return (this.description);
124        }
125    
126        public void setDescription(String description) {
127            this.description = description;
128            this.info = null;
129        }
130    
131    
132        /**
133         * The (optional) <code>ObjectName</code> domain in which this MBean
134         * should be registered in the MBeanServer.
135         */
136        public String getDomain() {
137            return (this.domain);
138        }
139    
140        public void setDomain(String domain) {
141            this.domain = domain;
142        }
143    
144    
145        /**
146         * <p>Return a <code>List</code> of the {@link FieldInfo} objects for
147         * the name/value pairs that should be
148         * added to the Descriptor created from this metadata.</p>
149         */
150        public List getFields() {
151            return (this.fields);
152        }
153    
154    
155        /**
156         * The (optional) group to which this MBean belongs.
157         */
158        public String getGroup() {
159            return (this.group);
160        }
161    
162        public void setGroup(String group) {
163            this.group = group;
164        }
165    
166    
167        /**
168         * The name of this managed bean, which must be unique among all
169         * MBeans managed by a particular MBeans server.
170         */
171        public String getName() {
172            return (this.name);
173        }
174    
175        public void setName(String name) {
176            this.name = name;
177            this.info = null;
178        }
179    
180    
181        /**
182         * The collection of notifications for this MBean.
183         */
184        public NotificationInfo[] getNotifications() {
185            return (this.notifications);
186        }
187    
188    
189        /**
190         * The collection of operations for this MBean.
191         */
192        public OperationInfo[] getOperations() {
193            return (this.operations);
194        }
195    
196    
197        /**
198         * The fully qualified name of the Java class of the resource
199         * implementation class described by the managed bean described
200         * by this descriptor.
201         */
202        public String getType() {
203            return (this.type);
204        }
205    
206        public void setType(String type) {
207            this.type = type;
208            this.info = null;
209        }
210    
211    
212        // --------------------------------------------------------- Public Methods
213    
214    
215        /**
216         * Add a new attribute to the set of attributes for this MBean.
217         *
218         * @param attribute The new attribute descriptor
219         */
220        public void addAttribute(AttributeInfo attribute) {
221    
222            synchronized (attributes) {
223                AttributeInfo results[] =
224                    new AttributeInfo[attributes.length + 1];
225                System.arraycopy(attributes, 0, results, 0, attributes.length);
226                results[attributes.length] = attribute;
227                attributes = results;
228                this.info = null;
229            }
230    
231        }
232    
233    
234        /**
235         * Add a new constructor to the set of constructors for this MBean.
236         *
237         * @param constructor The new constructor descriptor
238         */
239        public void addConstructor(ConstructorInfo constructor) {
240    
241            synchronized (constructors) {
242                ConstructorInfo results[] =
243                    new ConstructorInfo[constructors.length + 1];
244                System.arraycopy(constructors, 0, results, 0, constructors.length);
245                results[constructors.length] = constructor;
246                constructors = results;
247                this.info = null;
248            }
249    
250        }
251    
252    
253        /**
254         * <p>Add a new field to the fields associated with the
255         * Descriptor that will be created from this metadata.</p>
256         *
257         * @param field The field to be added
258         */
259        public void addField(FieldInfo field) {
260            fields.add(field);
261        }
262    
263    
264        /**
265         * Add a new notification to the set of notifications for this MBean.
266         *
267         * @param notification The new notification descriptor
268         */
269        public void addNotification(NotificationInfo notification) {
270    
271            synchronized (notifications) {
272                NotificationInfo results[] =
273                    new NotificationInfo[notifications.length + 1];
274                System.arraycopy(notifications, 0, results, 0,
275                                 notifications.length);
276                results[notifications.length] = notification;
277                notifications = results;
278                this.info = null;
279            }
280    
281        }
282    
283    
284        /**
285         * Add a new operation to the set of operations for this MBean.
286         *
287         * @param operation The new operation descriptor
288         */
289        public void addOperation(OperationInfo operation) {
290            synchronized (operations) {
291                OperationInfo results[] =
292                    new OperationInfo[operations.length + 1];
293                System.arraycopy(operations, 0, results, 0, operations.length);
294                results[operations.length] = operation;
295                operations = results;
296                this.info = null;
297            }
298    
299        }
300    
301    
302        /**
303         * Create and return a <code>ModelMBean</code> that has been
304         * preconfigured with the <code>ModelMBeanInfo</code> information
305         * for this managed bean, but is not associated with any particular
306         * managed resource.  The returned <code>ModelMBean</code> will
307         * <strong>NOT</strong> have been registered with our
308         * <code>MBeanServer</code>.
309         *
310         * @exception InstanceNotFoundException if the managed resource
311         *  object cannot be found
312         * @exception InvalidTargetObjectTypeException if our MBean cannot
313         *  handle object references (should never happen)
314         * @exception MBeanException if a problem occurs instantiating the
315         *  <code>ModelMBean</code> instance
316         * @exception RuntimeOperationsException if a JMX runtime error occurs
317         */
318        public ModelMBean createMBean()
319            throws InstanceNotFoundException,
320            InvalidTargetObjectTypeException,
321            MBeanException, RuntimeOperationsException {
322    
323            return (createMBean(null));
324    
325        }
326    
327    
328        /**
329         * Create and return a <code>ModelMBean</code> that has been
330         * preconfigured with the <code>ModelMBeanInfo</code> information
331         * for this managed bean, and is associated with the specified
332         * managed object instance.  The returned <code>ModelMBean</code>
333         * will <strong>NOT</strong> have been registered with our
334         * <code>MBeanServer</code>.
335         *
336         * @param instance Instanced of the managed object, or <code>null</code>
337         *  for no associated instance
338         *
339         * @exception InstanceNotFoundException if the managed resource
340         *  object cannot be found
341         * @exception InvalidTargetObjectTypeException if our MBean cannot
342         *  handle object references (should never happen)
343         * @exception MBeanException if a problem occurs instantiating the
344         *  <code>ModelMBean</code> instance
345         * @exception RuntimeOperationsException if a JMX runtime error occurs
346         */
347        public ModelMBean createMBean(Object instance)
348            throws InstanceNotFoundException,
349            InvalidTargetObjectTypeException,
350            MBeanException, RuntimeOperationsException {
351    
352            // Load the ModelMBean implementation class
353            Class clazz = null;
354            Exception ex = null;
355            try {
356                clazz = Class.forName(getClassName());
357            } catch (Exception e) {
358            }
359          
360            if( clazz==null ) {  
361                try {
362                    ClassLoader cl= Thread.currentThread().getContextClassLoader();
363                    if ( cl != null)
364                        clazz= cl.loadClass(getClassName());
365                } catch (Exception e) {
366                    ex=e;
367                }
368            }
369    
370            if( clazz==null) { 
371                throw new MBeanException
372                    (ex, "Cannot load ModelMBean class " + getClassName());
373            }
374    
375            // Create a new ModelMBean instance
376            ModelMBean mbean = null;
377            try {
378                mbean = (ModelMBean) clazz.newInstance();
379                mbean.setModelMBeanInfo(createMBeanInfo());
380            } catch (MBeanException e) {
381                throw e;
382            } catch (RuntimeOperationsException e) {
383                throw e;
384            } catch (Exception e) {
385                throw new MBeanException
386                    (e, "Cannot instantiate ModelMBean of class " +
387                     getClassName());
388            }
389    
390            // Set the managed resource (if any)
391            try {
392                if (instance != null)
393                    mbean.setManagedResource(instance, "ObjectReference");
394            } catch (InstanceNotFoundException e) {
395                throw e;
396            } catch (InvalidTargetObjectTypeException e) {
397                throw e;
398            }
399            return (mbean);
400    
401        }
402    
403    
404        /**
405         * Create and return a <code>ModelMBeanInfo</code> object that
406         * describes this entire managed bean.
407         */
408        public ModelMBeanInfo createMBeanInfo() {
409    
410            // Return our cached information (if any)
411            if (info != null)
412                return (info);
413    
414            // Create subordinate information descriptors as required
415            AttributeInfo attrs[] = getAttributes();
416            ModelMBeanAttributeInfo attributes[] =
417                new ModelMBeanAttributeInfo[attrs.length];
418            for (int i = 0; i < attrs.length; i++)
419                attributes[i] = attrs[i].createAttributeInfo();
420            
421            ConstructorInfo consts[] = getConstructors();
422            ModelMBeanConstructorInfo constructors[] =
423                new ModelMBeanConstructorInfo[consts.length];
424            for (int i = 0; i < consts.length; i++)
425                constructors[i] = consts[i].createConstructorInfo();
426            NotificationInfo notifs[] = getNotifications();
427            ModelMBeanNotificationInfo notifications[] =
428                new ModelMBeanNotificationInfo[notifs.length];
429            for (int i = 0; i < notifs.length; i++)
430                notifications[i] = notifs[i].createNotificationInfo();
431            OperationInfo opers[] = getOperations();
432            ModelMBeanOperationInfo operations[] =
433                new ModelMBeanOperationInfo[opers.length];
434            for (int i = 0; i < opers.length; i++)
435                operations[i] = opers[i].createOperationInfo();
436    
437            /*
438            // Add operations for attribute getters and setters as needed
439            ArrayList list = new ArrayList();
440            for (int i = 0; i < operations.length; i++)
441                list.add(operations[i]);
442            for (int i = 0; i < attributes.length; i++) {
443                Descriptor descriptor = attributes[i].getDescriptor();
444                String getMethod = (String) descriptor.getFieldValue("getMethod");
445                if (getMethod != null) {
446                    OperationInfo oper =
447                        new OperationInfo(getMethod, true,
448                                          attributes[i].getType());
449                    list.add(oper.createOperationInfo());
450                }
451                String setMethod = (String) descriptor.getFieldValue("setMethod");
452                if (setMethod != null) {
453                    OperationInfo oper =
454                        new OperationInfo(setMethod, false,
455                                          attributes[i].getType());
456                    list.add(oper.createOperationInfo());
457                }
458            }
459            if (list.size() > operations.length)
460                operations =
461                    (ModelMBeanOperationInfo[]) list.toArray(operations);
462            */
463            
464            // Construct and return a new ModelMBeanInfo object
465            info = new ModelMBeanInfoSupport
466                (getClassName(), getDescription(),
467                 attributes, constructors, operations, notifications);
468            try {
469                Descriptor descriptor = info.getMBeanDescriptor();
470                Iterator fields = getFields().iterator();
471                while (fields.hasNext()) {
472                    FieldInfo field = (FieldInfo) fields.next();
473                    descriptor.setField(field.getName(), field.getValue());
474                }
475                info.setMBeanDescriptor(descriptor);
476            } catch (MBeanException e) {
477                ;
478            }
479    
480            return (info);
481    
482        }
483    
484    
485        /**
486         * Return a string representation of this managed bean.
487         */
488        public String toString() {
489    
490            StringBuffer sb = new StringBuffer("ManagedBean[");
491            sb.append("name=");
492            sb.append(name);
493            sb.append(", className=");
494            sb.append(className);
495            sb.append(", description=");
496            sb.append(description);
497            if (group != null) {
498                sb.append(", group=");
499                sb.append(group);
500            }
501            sb.append(", type=");
502            sb.append(type);
503            sb.append("]");
504            return (sb.toString());
505    
506        }
507    
508    
509    }