001    /**
002     *
003     * Copyright 2003-2004 The Apache Software Foundation
004     *
005     *  Licensed under the Apache License, Version 2.0 (the "License");
006     *  you may not use this file except in compliance with the License.
007     *  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    package org.apache.geronimo.system.jmx;
018    
019    import java.io.ObjectInputStream;
020    import java.util.HashSet;
021    import java.util.Iterator;
022    import java.util.Set;
023    import java.util.HashMap;
024    import java.util.Collections;
025    import java.util.LinkedHashSet;
026    import javax.management.Attribute;
027    import javax.management.AttributeList;
028    import javax.management.AttributeNotFoundException;
029    import javax.management.InstanceAlreadyExistsException;
030    import javax.management.InstanceNotFoundException;
031    import javax.management.ListenerNotFoundException;
032    import javax.management.MBeanException;
033    import javax.management.MBeanInfo;
034    import javax.management.MBeanRegistrationException;
035    import javax.management.MBeanServer;
036    import javax.management.NotCompliantMBeanException;
037    import javax.management.NotificationFilter;
038    import javax.management.NotificationListener;
039    import javax.management.ObjectInstance;
040    import javax.management.ObjectName;
041    import javax.management.OperationsException;
042    import javax.management.QueryExp;
043    import javax.management.ReflectionException;
044    import javax.management.MalformedObjectNameException;
045    import javax.management.loading.ClassLoaderRepository;
046    
047    import org.apache.geronimo.gbean.GBeanInfo;
048    import org.apache.geronimo.gbean.AbstractNameQuery;
049    import org.apache.geronimo.gbean.AbstractName;
050    import org.apache.geronimo.kernel.GBeanNotFoundException;
051    import org.apache.geronimo.kernel.InternalKernelException;
052    import org.apache.geronimo.kernel.NoSuchAttributeException;
053    import org.apache.geronimo.kernel.NoSuchOperationException;
054    import org.apache.geronimo.kernel.Kernel;
055    import org.apache.geronimo.kernel.lifecycle.LifecycleAdapter;
056    
057    /**
058     * A fake MBeanServer that delegates to a Kernel.
059     * @version $Rev: 396619 $ $Date: 2006-04-24 10:44:00 -0700 (Mon, 24 Apr 2006) $
060     */
061    public class KernelMBeanServer implements MBeanServer {
062        private static final AbstractNameQuery ALL = new AbstractNameQuery(null, Collections.EMPTY_MAP, Collections.EMPTY_SET);
063    
064        private final HashMap objetNameToAbstractName = new HashMap();
065        private final Kernel kernel;
066    
067        public KernelMBeanServer(Kernel kernel) {
068            this.kernel = kernel;
069        }
070    
071        public void doStart() {
072            kernel.getLifecycleMonitor().addLifecycleListener(new GBeanRegistrationListener(), ALL);
073    
074            Set allNames = kernel.listGBeans(ALL);
075            for (Iterator iterator = allNames.iterator(); iterator.hasNext();) {
076                AbstractName abstractName = (AbstractName) iterator.next();
077                register(abstractName);
078            }
079        }
080    
081        public synchronized AbstractName getAbstractNameFor(ObjectName objectName) {
082            return (AbstractName) objetNameToAbstractName.get(objectName);
083        }
084    
085        private synchronized void register(AbstractName abstractName) {
086            objetNameToAbstractName.put(abstractName.getObjectName(), abstractName);
087        }
088    
089        private synchronized void unregister(AbstractName abstractName) {
090            objetNameToAbstractName.remove(abstractName.getObjectName());
091        }
092    
093        public void doFail() {
094            doStop();
095        }
096    
097        public synchronized void doStop() {
098            objetNameToAbstractName.clear();
099        }
100    
101        private class GBeanRegistrationListener extends LifecycleAdapter {
102            public void loaded(AbstractName abstractName) {
103                register(abstractName);
104            }
105    
106            public void unloaded(AbstractName abstractName) {
107                unregister(abstractName);
108            }
109        }
110    
111        public AbstractName toAbstractName(ObjectName objectName) throws InstanceNotFoundException{
112            AbstractName abstractName = getAbstractNameFor(objectName);
113            if (abstractName == null) {
114                throw new InstanceNotFoundException(objectName.getCanonicalName());
115            }
116            return abstractName;
117        }
118    
119        public Object getAttribute(ObjectName name, String attribute) throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException {
120            AbstractName abstractName = toAbstractName(name);
121            try {
122                return kernel.getAttribute(abstractName, attribute);
123            } catch (NoSuchAttributeException e) {
124                throw new AttributeNotFoundException(attribute);
125            } catch (GBeanNotFoundException e) {
126                throw new InstanceNotFoundException(name.getCanonicalName());
127            } catch (InternalKernelException e) {
128                throw new MBeanException(unwrapInternalKernelException(e));
129            } catch (Exception e) {
130                throw new MBeanException(e);
131            }
132        }
133    
134        public AttributeList getAttributes(ObjectName name, String[] attributes) throws InstanceNotFoundException, ReflectionException {
135            AbstractName abstractName = toAbstractName(name);
136            AttributeList attributeList = new AttributeList(attributes.length);
137            for (int i = 0; i < attributes.length; i++) {
138                String attribute = attributes[i];
139                try {
140                    Object value = kernel.getAttribute(abstractName, attribute);
141                    attributeList.add(i, new Attribute(attribute, value));
142                } catch (NoSuchAttributeException e) {
143                    // ignored - caller will simply find no value
144                } catch (GBeanNotFoundException e) {
145                    throw new InstanceNotFoundException(name.getCanonicalName());
146                } catch (InternalKernelException e) {
147                    throw new ReflectionException(unwrapInternalKernelException(e));
148                } catch (Exception e) {
149                    // ignored - caller will simply find no value
150                }
151            }
152            return attributeList;
153        }
154    
155        public String getDefaultDomain() {
156            return kernel.getKernelName();
157        }
158    
159        public Integer getMBeanCount() {
160            return new Integer(kernel.listGBeans((AbstractNameQuery)null).size());
161        }
162    
163        public MBeanInfo getMBeanInfo(ObjectName name) throws InstanceNotFoundException, ReflectionException {
164            AbstractName abstractName = toAbstractName(name);
165            GBeanInfo gbeanInfo;
166            try {
167                gbeanInfo = kernel.getGBeanInfo(abstractName);
168            } catch (GBeanNotFoundException e) {
169                throw new InstanceNotFoundException(name.getCanonicalName());
170            } catch (InternalKernelException e) {
171                throw new ReflectionException(unwrapInternalKernelException(e));
172            }
173            return JMXUtil.toMBeanInfo(gbeanInfo);
174        }
175    
176        public Object invoke(ObjectName name, String operationName, Object[] params, String[] signature) throws InstanceNotFoundException, MBeanException, ReflectionException {
177            AbstractName abstractName = toAbstractName(name);
178            try {
179                return kernel.invoke(abstractName, operationName, params, signature);
180            } catch (NoSuchOperationException e) {
181                throw new ReflectionException(new NoSuchMethodException(e.getMessage()));
182            } catch (GBeanNotFoundException e) {
183                if(name.equals(e.getGBeanName())) {
184                    throw new InstanceNotFoundException(name.getCanonicalName());
185                }
186                throw new MBeanException(e);
187            } catch (InternalKernelException e) {
188                throw new MBeanException(unwrapInternalKernelException(e));
189            } catch (Exception e) {
190                throw new MBeanException(e);
191            }
192        }
193    
194        public boolean isRegistered(ObjectName name) {
195            AbstractName abstractName = getAbstractNameFor(name);
196            if (abstractName == null) {
197                return false;
198            }
199            return kernel.isLoaded(abstractName);
200        }
201    
202        public Set queryNames(ObjectName pattern, QueryExp query) {
203            // normalize the name
204            if (pattern != null && pattern.getDomain().length() == 0) {
205                try {
206                    pattern = new ObjectName(kernel.getKernelName(), pattern.getKeyPropertyList());
207                } catch (MalformedObjectNameException e) {
208                    throw new AssertionError(e);
209                }
210            }
211    
212            Set names;
213            synchronized (this) {
214                names = new LinkedHashSet(objetNameToAbstractName.keySet());
215            }
216    
217            // fairly dumb implementation that iterates the list of all registered GBeans
218            Set result = new HashSet(names.size());
219            for (Iterator iterator = names.iterator(); iterator.hasNext();) {
220                ObjectName name = (ObjectName) iterator.next();
221                if (pattern == null || pattern.apply(name)) {
222                    if (query != null) {
223                        query.setMBeanServer(this);
224    
225                        try {
226                            if (query.apply(name)) {
227                                result.add(name);
228                            }
229                        } catch (Exception e) {
230                            // reject any name that threw an exception
231                        }
232                    } else {
233                        result.add(name);
234                    }
235                }
236            }
237    
238            return result;
239        }
240    
241        public Set queryMBeans(ObjectName pattern, QueryExp query) {
242            Set names = queryNames(pattern, query);
243            Set objectInstances = new HashSet(names.size());
244            for (Iterator iterator = names.iterator(); iterator.hasNext();) {
245                ObjectName name = (ObjectName) iterator.next();
246                try {
247                    objectInstances.add(getObjectInstance(name));
248                } catch (InstanceNotFoundException e) {
249                    // ignore
250                }
251            }
252            return objectInstances;
253        }
254    
255        public void setAttribute(ObjectName name, Attribute attribute) throws InstanceNotFoundException, AttributeNotFoundException, MBeanException {
256            AbstractName abstractName = toAbstractName(name);
257            String attributeName = attribute.getName();
258            Object attributeValue = attribute.getValue();
259            try {
260                kernel.setAttribute(abstractName, attributeName, attributeValue);
261            } catch (NoSuchAttributeException e) {
262                throw new AttributeNotFoundException(attributeName);
263            } catch (GBeanNotFoundException e) {
264                throw new InstanceNotFoundException(name.getCanonicalName());
265            } catch (InternalKernelException e) {
266                throw new MBeanException(unwrapInternalKernelException(e));
267            } catch (Exception e) {
268                throw new MBeanException(e);
269            }
270        }
271    
272        public AttributeList setAttributes(ObjectName name, AttributeList attributes) throws InstanceNotFoundException, ReflectionException {
273            AbstractName abstractName = toAbstractName(name);
274            AttributeList set = new AttributeList(attributes.size());
275            for (Iterator iterator = attributes.iterator(); iterator.hasNext();) {
276                Attribute attribute = (Attribute) iterator.next();
277                String attributeName = attribute.getName();
278                Object attributeValue = attribute.getValue();
279                try {
280                    kernel.setAttribute(abstractName, attributeName, attributeValue);
281                    set.add(attribute);
282                } catch (NoSuchAttributeException e) {
283                    // ignored - caller will see value was not set because this attribute will not be in the attribute list
284                } catch (GBeanNotFoundException e) {
285                    throw new InstanceNotFoundException(name.getCanonicalName());
286                } catch (InternalKernelException e) {
287                    throw new ReflectionException(unwrapInternalKernelException(e));
288                } catch (Exception e) {
289                    // ignored - caller will see value was not set because this attribute will not be in the attribute list
290                }
291            }
292            return set;
293        }
294    
295        public String[] getDomains() {
296            Set domains = new HashSet();
297            Set names = kernel.listGBeans((AbstractNameQuery)null);
298            for (Iterator iterator = names.iterator(); iterator.hasNext();) {
299                ObjectName objectName = (ObjectName) iterator.next();
300                domains.add(objectName.getDomain());
301            }
302            return (String[]) domains.toArray(new String[domains.size()]);
303        }
304    
305        public ObjectInstance getObjectInstance(ObjectName objectName) throws InstanceNotFoundException {
306            AbstractName abstractName = toAbstractName(objectName);
307            try {
308                GBeanInfo gbeanInfo = kernel.getGBeanInfo(abstractName);
309                return new ObjectInstance(objectName, gbeanInfo.getClassName());
310            } catch (GBeanNotFoundException e) {
311                throw new InstanceNotFoundException(objectName.getCanonicalName());
312            }
313        }
314    
315        public ClassLoader getClassLoaderFor(ObjectName objectName) throws InstanceNotFoundException {
316            AbstractName abstractName = toAbstractName(objectName);
317            try {
318                return kernel.getClassLoaderFor(abstractName);
319            } catch (GBeanNotFoundException e) {
320                throw new InstanceNotFoundException(objectName.getCanonicalName());
321            }
322        }
323    
324        private static Exception unwrapInternalKernelException(InternalKernelException e) {
325            if (e.getCause() instanceof Exception) {
326                return (Exception) e.getCause();
327            }
328            return e;
329        }
330    
331        //////////////////////////////////////////////
332        //
333        // NOT ALLOWED
334        //
335        //////////////////////////////////////////////
336    
337        public void addNotificationListener(ObjectName objectName, NotificationListener notificationListener, NotificationFilter notificationFilter, Object o) throws InstanceNotFoundException {
338            throw new SecurityException("Operation not allowed");
339        }
340    
341        public void addNotificationListener(ObjectName objectName, ObjectName objectName1, NotificationFilter notificationFilter, Object o) throws InstanceNotFoundException {
342            throw new SecurityException("Operation not allowed");
343        }
344    
345        public void removeNotificationListener(ObjectName objectName, ObjectName objectName1) throws InstanceNotFoundException, ListenerNotFoundException {
346            throw new SecurityException("Operation not allowed");
347        }
348    
349        public void removeNotificationListener(ObjectName objectName, NotificationListener notificationListener) throws InstanceNotFoundException, ListenerNotFoundException {
350            throw new SecurityException("Operation not allowed");
351        }
352    
353        public void removeNotificationListener(ObjectName objectName, ObjectName objectName1, NotificationFilter notificationFilter, Object o) throws InstanceNotFoundException, ListenerNotFoundException {
354            throw new SecurityException("Operation not allowed");
355        }
356    
357        public void removeNotificationListener(ObjectName objectName, NotificationListener notificationListener, NotificationFilter notificationFilter, Object o) throws InstanceNotFoundException, ListenerNotFoundException {
358            throw new SecurityException("Operation not allowed");
359        }
360    
361        public boolean isInstanceOf(ObjectName objectName, String s) throws InstanceNotFoundException {
362            throw new SecurityException("Operation not allowed");
363        }
364    
365        public ObjectInstance createMBean(String s, ObjectName objectName) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException {
366            throw new SecurityException("Operation not allowed");
367        }
368    
369        public ObjectInstance createMBean(String s, ObjectName objectName, ObjectName objectName1) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException {
370            throw new SecurityException("Operation not allowed");
371        }
372    
373        public ObjectInstance createMBean(String s, ObjectName objectName, Object[] objects, String[] strings) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException {
374            throw new SecurityException("Operation not allowed");
375        }
376    
377        public ObjectInstance createMBean(String s, ObjectName objectName, ObjectName objectName1, Object[] objects, String[] strings) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException {
378            throw new SecurityException("Operation not allowed");
379        }
380    
381        public Object instantiate(String s) throws ReflectionException, MBeanException {
382            throw new SecurityException("Operation not allowed");
383        }
384    
385        public Object instantiate(String s, ObjectName objectName) throws ReflectionException, MBeanException, InstanceNotFoundException {
386            throw new SecurityException("Operation not allowed");
387        }
388    
389        public Object instantiate(String s, Object[] objects, String[] strings) throws ReflectionException, MBeanException {
390            throw new SecurityException("Operation not allowed");
391        }
392    
393        public Object instantiate(String s, ObjectName objectName, Object[] objects, String[] strings) throws ReflectionException, MBeanException, InstanceNotFoundException {
394            throw new SecurityException("Operation not allowed");
395        }
396    
397        public ObjectInstance registerMBean(Object o, ObjectName objectName) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
398            throw new SecurityException("Operation not allowed");
399        }
400    
401        public ObjectInputStream deserialize(String s, ObjectName objectName, byte[] bytes) throws InstanceNotFoundException, OperationsException, ReflectionException {
402            throw new SecurityException("Operation not allowed");
403        }
404    
405        public ObjectInputStream deserialize(String s, byte[] bytes) throws OperationsException, ReflectionException {
406            throw new SecurityException("Operation not allowed");
407        }
408    
409        public ObjectInputStream deserialize(ObjectName objectName, byte[] bytes) throws InstanceNotFoundException, OperationsException {
410            throw new SecurityException("Operation not allowed");
411        }
412    
413        public ClassLoader getClassLoader(ObjectName objectName) throws InstanceNotFoundException {
414            throw new SecurityException("Operation not allowed");
415        }
416    
417        public ClassLoaderRepository getClassLoaderRepository() {
418            return new ClassLoaderRepository() {
419                public Class loadClass(String className) throws ClassNotFoundException {
420                    throw new ClassNotFoundException(className);
421                }
422    
423                public Class loadClassWithout(ClassLoader loader, String className) throws ClassNotFoundException {
424                    throw new ClassNotFoundException(className);
425                }
426    
427                public Class loadClassBefore(ClassLoader loader, String className) throws ClassNotFoundException {
428                    throw new ClassNotFoundException(className);
429                }
430            };
431        }
432    
433        public void unregisterMBean(ObjectName objectName) throws InstanceNotFoundException, MBeanRegistrationException {
434            throw new SecurityException("Operation not allowed");
435        }
436    }