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    package org.apache.geronimo.gbean;
019    
020    import java.io.IOException;
021    import java.io.ObjectInputStream;
022    import java.io.Serializable;
023    import java.lang.reflect.Method;
024    import java.util.ArrayList;
025    import java.util.Arrays;
026    import java.util.Collection;
027    import java.util.Collections;
028    import java.util.HashMap;
029    import java.util.HashSet;
030    import java.util.Iterator;
031    import java.util.List;
032    import java.util.Map;
033    import java.util.Set;
034    
035    import org.apache.geronimo.kernel.management.NotificationType;
036    
037    /**
038     * Describes a GBean.  This class should never be constructed directly.  Insted use GBeanInfoBuilder.
039     *
040     * @version $Rev: 487175 $ $Date: 2006-12-14 03:10:31 -0800 (Thu, 14 Dec 2006) $
041     */
042    public final class GBeanInfo implements Serializable {
043        private static final long serialVersionUID = -6198804067155550221L;
044        
045        public static final int PRIORITY_CLASSLOADER = 1;
046        public static final int PRIORITY_NORMAL = 5;
047    
048        private static final Set DEFAULT_NOTIFICATIONS = Collections.unmodifiableSet(new HashSet(Arrays.asList(NotificationType.TYPES)));
049    
050        /**
051         * Static helper to try to get the GBeanInfo from the class supplied.
052         *
053         * @param className   name of the class to get the GBeanInfo from
054         * @param classLoader the class loader use to load the specifiec class
055         * @return GBeanInfo generated by supplied class
056         * @throws InvalidConfigurationException
057         *          if there is a problem getting the GBeanInfo from the class
058         */
059        public static GBeanInfo getGBeanInfo(String className, ClassLoader classLoader) throws InvalidConfigurationException {
060            Class clazz;
061            try {
062                clazz = classLoader.loadClass(className);
063            } catch (ClassNotFoundException e) {
064                throw new InvalidConfigurationException("Could not load class " + className, e);
065            } catch (NoClassDefFoundError e) {
066                throw new InvalidConfigurationException("Could not load class " + className, e);
067            }
068            Method method;
069            try {
070                method = clazz.getDeclaredMethod("getGBeanInfo", new Class[]{});
071            } catch (NoSuchMethodException e) {
072                try {
073                    // try to get the info from ${className}GBean
074                    clazz = classLoader.loadClass(className + "GBean");
075                    method = clazz.getDeclaredMethod("getGBeanInfo", new Class[]{});
076                } catch (Exception ignored) {
077                    throw new InvalidConfigurationException("Class does not have a getGBeanInfo() method: " + className);
078                }
079            } catch (NoClassDefFoundError e) {
080                throw new InvalidConfigurationException("Could not find getGBeanInfo method on " + className, e);
081            }
082            try {
083                return (GBeanInfo) method.invoke(null, new Object[]{});
084            } catch (Exception e) {
085                throw new InvalidConfigurationException("Could not get GBeanInfo from class: " + className, e);
086            }
087        }
088    
089        private final String sourceClass;
090        private final String name;
091        private final String className;
092        private final String j2eeType;
093        private final Set attributes;
094        private final Map attributesByName;
095        private final GConstructorInfo constructor;
096        private final Set operations;
097        private final Set notifications;
098        private final Set references;
099        private final Map referencesByName;
100        private final Set interfaces;
101        private int priority;
102    
103        /**
104         * @deprecated use GBeanInfoBuilder
105         */
106        public GBeanInfo(String name, String className, String j2eeType, Collection attributes, GConstructorInfo constructor, Collection operations, Set references, Set interfaces) {
107            this(null, name, className, j2eeType, attributes, constructor, operations, references, interfaces, DEFAULT_NOTIFICATIONS, PRIORITY_NORMAL);
108        }
109    
110        /**
111         * @deprecated use GBeanInfoBuilder
112         */
113        public GBeanInfo(String className, String j2eeType, Collection attributes, GConstructorInfo constructor, Collection operations, Set references, Set interfaces) {
114            this(null, className, className, j2eeType, attributes, constructor, operations, references, interfaces, DEFAULT_NOTIFICATIONS, PRIORITY_NORMAL);
115        }
116    
117        /**
118         * @deprecated use GBeanInfoBuilder
119         */
120        public GBeanInfo(String className, String j2eeType, Collection attributes, GConstructorInfo constructor, Collection operations, Set references, Set interfaces, Set notifications) {
121            this(null, className, className, j2eeType, attributes, constructor, operations, references, interfaces, notifications, PRIORITY_NORMAL);
122        }
123    
124        /**
125         * @deprecated use GBeanInfoBuilder
126         */
127        public GBeanInfo(String name, String className, String j2eeType, Collection attributes, GConstructorInfo constructor, Collection operations, Set references, Set interfaces, Set notifications) {
128            this(null, name, className, j2eeType, attributes, constructor, operations, references, interfaces, notifications, PRIORITY_NORMAL);
129        }
130    
131        GBeanInfo(String sourceClass, String name, String className, String j2eeType, Collection attributes, GConstructorInfo constructor, Collection operations, Set references, Set interfaces, int priority) {
132            this(sourceClass, name, className, j2eeType, attributes, constructor, operations, references, interfaces, DEFAULT_NOTIFICATIONS, priority);
133        }
134    
135        GBeanInfo(String sourceClass, String name, String className, String j2eeType, Collection attributes, GConstructorInfo constructor, Collection operations, Set references, Set interfaces, Set notifications, int priority) {
136            this.sourceClass = sourceClass;
137            this.name = name;
138            this.className = className;
139            this.j2eeType = j2eeType;
140            if (attributes == null) {
141                this.attributes = Collections.EMPTY_SET;
142                this.attributesByName = Collections.EMPTY_MAP;
143            } else {
144                Map map = new HashMap();
145                for (Iterator iterator = attributes.iterator(); iterator.hasNext();) {
146                    GAttributeInfo attribute = (GAttributeInfo) iterator.next();
147                    map.put(attribute.getName(), attribute);
148                }
149                this.attributesByName = Collections.unmodifiableMap(map);
150                this.attributes = Collections.unmodifiableSet(new HashSet(map.values()));
151            }
152            if (constructor == null) {
153                this.constructor = new GConstructorInfo(Collections.EMPTY_LIST);
154            } else {
155                this.constructor = constructor;
156            }
157            if (operations == null) {
158                this.operations = Collections.EMPTY_SET;
159            } else {
160                this.operations = Collections.unmodifiableSet(new HashSet(operations));
161            }
162            if (references == null) {
163                this.references = Collections.EMPTY_SET;
164                this.referencesByName = Collections.EMPTY_MAP;
165            } else {
166                Map map = new HashMap();
167                for (Iterator iterator = references.iterator(); iterator.hasNext();) {
168                    GReferenceInfo reference = (GReferenceInfo) iterator.next();
169                    map.put(reference.getName(), reference);
170                }
171                this.referencesByName = Collections.unmodifiableMap(map);
172                this.references = Collections.unmodifiableSet(new HashSet(references));
173            }
174            if (interfaces == null) {
175                this.interfaces = Collections.EMPTY_SET;
176            } else {
177                this.interfaces = Collections.unmodifiableSet(new HashSet(interfaces));
178            }
179            if (notifications == null) {
180                this.notifications = Collections.EMPTY_SET;
181            } else {
182                this.notifications = Collections.unmodifiableSet(new HashSet(notifications));
183            }
184            this.priority = priority;
185        }
186    
187        /**
188         * Gets the source class from which this GBeanInfo can be retrieved using GBeanInfo.getGBeanInfo(className, classLoader).
189         * A null source class means the gbean info was dynamically generated.
190         *
191         * @return the source of this GBeanInfo, or null if it was dynamically generated
192         */
193        public String getSourceClass() {
194            return sourceClass;
195        }
196    
197        public String getName() {
198            return name;
199        }
200    
201        public String getClassName() {
202            return className;
203        }
204    
205        public String getJ2eeType() {
206            return j2eeType;
207        }
208    
209        /**
210         * Gets the info for the specified attribute, or null if there is no such
211         * attribute.  Note that the attribute may have a getter or setter or both;
212         * being an attribute does not imply that both methods are available.
213         */
214        public GAttributeInfo getAttribute(String name) {
215            return (GAttributeInfo) attributesByName.get(name);
216        }
217    
218        /**
219         * Returns a Set where the elements are type GAttributeInfo
220         */
221        public Set getAttributes() {
222            return attributes;
223        }
224    
225        /**
226         * Returns a list where the elements are type GAttributeInfo
227         */
228        public List getPersistentAttributes() {
229            List attrs = new ArrayList();
230            for (Iterator i = attributes.iterator(); i.hasNext();) {
231                GAttributeInfo info = (GAttributeInfo) i.next();
232                if (info.isPersistent()) {
233                    attrs.add(info);
234                }
235            }
236            return attrs;
237        }
238    
239        /**
240         * Returns a list where the elements are type GAttributeInfo
241         */
242        public List getManageableAttributes() {
243            List attrs = new ArrayList();
244            for (Iterator i = attributes.iterator(); i.hasNext();) {
245                GAttributeInfo info = (GAttributeInfo) i.next();
246                if (info.isManageable()) {
247                    attrs.add(info);
248                }
249            }
250            return attrs;
251        }
252    
253        public GConstructorInfo getConstructor() {
254            return constructor;
255        }
256    
257        public Set getOperations() {
258            return operations;
259        }
260    
261        public Set getNotifications() {
262            return notifications;
263        }
264    
265        public Set getReferences() {
266            return references;
267        }
268    
269        public GReferenceInfo getReference(String name) {
270            return (GReferenceInfo) referencesByName.get(name);
271        }
272    
273        public Set getInterfaces() {
274            return interfaces;
275        }
276    
277        public int getPriority() {
278            return priority;
279        }
280    
281        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
282            priority = GBeanInfo.PRIORITY_NORMAL;
283            in.defaultReadObject();
284        }
285        
286        public String toString() {
287            StringBuffer result = new StringBuffer("[GBeanInfo:");
288            result.append(" id=").append(super.toString());
289            result.append(" sourceClass=").append(sourceClass);
290            result.append(" name=").append(name);
291            for (Iterator iterator = attributes.iterator(); iterator.hasNext();) {
292                GAttributeInfo geronimoAttributeInfo = (GAttributeInfo) iterator.next();
293                result.append("\n    attribute: ").append(geronimoAttributeInfo);
294            }
295            for (Iterator iterator = operations.iterator(); iterator.hasNext();) {
296                GOperationInfo geronimoOperationInfo = (GOperationInfo) iterator.next();
297                result.append("\n    operation: ").append(geronimoOperationInfo);
298            }
299            for (Iterator iterator = references.iterator(); iterator.hasNext();) {
300                GReferenceInfo referenceInfo = (GReferenceInfo) iterator.next();
301                result.append("\n    reference: ").append(referenceInfo);
302            }
303            result.append("]");
304            return result.toString();
305        }
306    }