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: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 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 String message = e.getMessage(); 081 StringBuffer buf = new StringBuffer("Could not load gbean class ").append(className).append(" due to NoClassDefFoundError\n"); 082 if (message != null) { 083 message = message.replace('/', '.'); 084 buf.append(" problematic class ").append(message); 085 try { 086 Class hardToLoad = classLoader.loadClass(message); 087 buf.append(" can be loaded in supplied classloader ").append(classLoader).append("\n"); 088 buf.append(" and is found in ").append(hardToLoad.getClassLoader()); 089 } catch (ClassNotFoundException e1) { 090 buf.append(" cannot be loaded in supplied classloader ").append(classLoader).append("\n"); 091 } 092 } 093 throw new InvalidConfigurationException(buf.toString(), e); 094 } 095 try { 096 return (GBeanInfo) method.invoke(null, new Object[]{}); 097 } catch (Exception e) { 098 throw new InvalidConfigurationException("Could not get GBeanInfo from class: " + className, e); 099 } 100 } 101 102 private final String sourceClass; 103 private final String name; 104 private final String className; 105 private final String j2eeType; 106 private final Set<GAttributeInfo> attributes; 107 private final Map attributesByName; 108 private final GConstructorInfo constructor; 109 private final Set operations; 110 private final Set notifications; 111 private final Set references; 112 private final Map referencesByName; 113 private final Set interfaces; 114 private int priority; 115 116 /** 117 * @deprecated use GBeanInfoBuilder 118 */ 119 public GBeanInfo(String name, String className, String j2eeType, Collection attributes, GConstructorInfo constructor, Collection operations, Set references, Set interfaces) { 120 this(null, name, className, j2eeType, attributes, constructor, operations, references, interfaces, DEFAULT_NOTIFICATIONS, PRIORITY_NORMAL); 121 } 122 123 /** 124 * @deprecated use GBeanInfoBuilder 125 */ 126 public GBeanInfo(String className, String j2eeType, Collection attributes, GConstructorInfo constructor, Collection operations, Set references, Set interfaces) { 127 this(null, className, className, j2eeType, attributes, constructor, operations, references, interfaces, DEFAULT_NOTIFICATIONS, PRIORITY_NORMAL); 128 } 129 130 /** 131 * @deprecated use GBeanInfoBuilder 132 */ 133 public GBeanInfo(String className, String j2eeType, Collection attributes, GConstructorInfo constructor, Collection operations, Set references, Set interfaces, Set notifications) { 134 this(null, className, className, j2eeType, attributes, constructor, operations, references, interfaces, notifications, PRIORITY_NORMAL); 135 } 136 137 /** 138 * @deprecated use GBeanInfoBuilder 139 */ 140 public GBeanInfo(String name, String className, String j2eeType, Collection attributes, GConstructorInfo constructor, Collection operations, Set references, Set interfaces, Set notifications) { 141 this(null, name, className, j2eeType, attributes, constructor, operations, references, interfaces, notifications, PRIORITY_NORMAL); 142 } 143 144 GBeanInfo(String sourceClass, String name, String className, String j2eeType, Collection attributes, GConstructorInfo constructor, Collection operations, Set references, Set interfaces, int priority) { 145 this(sourceClass, name, className, j2eeType, attributes, constructor, operations, references, interfaces, DEFAULT_NOTIFICATIONS, priority); 146 } 147 148 GBeanInfo(String sourceClass, String name, String className, String j2eeType, Collection attributes, GConstructorInfo constructor, Collection operations, Set references, Set interfaces, Set notifications, int priority) { 149 this.sourceClass = sourceClass; 150 this.name = name; 151 this.className = className; 152 this.j2eeType = j2eeType; 153 if (attributes == null) { 154 this.attributes = Collections.EMPTY_SET; 155 this.attributesByName = Collections.EMPTY_MAP; 156 } else { 157 Map map = new HashMap(); 158 for (Iterator iterator = attributes.iterator(); iterator.hasNext();) { 159 GAttributeInfo attribute = (GAttributeInfo) iterator.next(); 160 map.put(attribute.getName(), attribute); 161 } 162 this.attributesByName = Collections.unmodifiableMap(map); 163 this.attributes = Collections.unmodifiableSet(new HashSet(map.values())); 164 } 165 if (constructor == null) { 166 this.constructor = new GConstructorInfo(Collections.EMPTY_LIST); 167 } else { 168 this.constructor = constructor; 169 } 170 if (operations == null) { 171 this.operations = Collections.EMPTY_SET; 172 } else { 173 this.operations = Collections.unmodifiableSet(new HashSet(operations)); 174 } 175 if (references == null) { 176 this.references = Collections.EMPTY_SET; 177 this.referencesByName = Collections.EMPTY_MAP; 178 } else { 179 Map map = new HashMap(); 180 for (Iterator iterator = references.iterator(); iterator.hasNext();) { 181 GReferenceInfo reference = (GReferenceInfo) iterator.next(); 182 map.put(reference.getName(), reference); 183 } 184 this.referencesByName = Collections.unmodifiableMap(map); 185 this.references = Collections.unmodifiableSet(new HashSet(references)); 186 } 187 if (interfaces == null) { 188 this.interfaces = Collections.EMPTY_SET; 189 } else { 190 this.interfaces = Collections.unmodifiableSet(new HashSet(interfaces)); 191 } 192 if (notifications == null) { 193 this.notifications = Collections.EMPTY_SET; 194 } else { 195 this.notifications = Collections.unmodifiableSet(new HashSet(notifications)); 196 } 197 this.priority = priority; 198 } 199 200 /** 201 * Gets the source class from which this GBeanInfo can be retrieved using GBeanInfo.getGBeanInfo(className, classLoader). 202 * A null source class means the gbean info was dynamically generated. 203 * 204 * @return the source of this GBeanInfo, or null if it was dynamically generated 205 */ 206 public String getSourceClass() { 207 return sourceClass; 208 } 209 210 public String getName() { 211 return name; 212 } 213 214 public String getClassName() { 215 return className; 216 } 217 218 public String getJ2eeType() { 219 return j2eeType; 220 } 221 222 /** 223 * Gets the info for the specified attribute, or null if there is no such 224 * attribute. Note that the attribute may have a getter or setter or both; 225 * being an attribute does not imply that both methods are available. 226 */ 227 public GAttributeInfo getAttribute(String name) { 228 return (GAttributeInfo) attributesByName.get(name); 229 } 230 231 /** 232 * Returns a Set where the elements are type GAttributeInfo 233 */ 234 public Set<GAttributeInfo> getAttributes() { 235 return attributes; 236 } 237 238 /** 239 * Returns a list where the elements are type GAttributeInfo 240 */ 241 public List getPersistentAttributes() { 242 List attrs = new ArrayList(); 243 for (Iterator i = attributes.iterator(); i.hasNext();) { 244 GAttributeInfo info = (GAttributeInfo) i.next(); 245 if (info.isPersistent()) { 246 attrs.add(info); 247 } 248 } 249 return attrs; 250 } 251 252 /** 253 * Returns a list where the elements are type GAttributeInfo 254 */ 255 public List getManageableAttributes() { 256 List attrs = new ArrayList(); 257 for (Iterator i = attributes.iterator(); i.hasNext();) { 258 GAttributeInfo info = (GAttributeInfo) i.next(); 259 if (info.isManageable()) { 260 attrs.add(info); 261 } 262 } 263 return attrs; 264 } 265 266 public GConstructorInfo getConstructor() { 267 return constructor; 268 } 269 270 public Set getOperations() { 271 return operations; 272 } 273 274 public Set getNotifications() { 275 return notifications; 276 } 277 278 public Set getReferences() { 279 return references; 280 } 281 282 public GReferenceInfo getReference(String name) { 283 return (GReferenceInfo) referencesByName.get(name); 284 } 285 286 public Set getInterfaces() { 287 return interfaces; 288 } 289 290 public int getPriority() { 291 return priority; 292 } 293 294 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 295 priority = GBeanInfo.PRIORITY_NORMAL; 296 in.defaultReadObject(); 297 } 298 299 public String toString() { 300 StringBuffer result = new StringBuffer("[GBeanInfo:"); 301 result.append(" id=").append(super.toString()); 302 result.append(" sourceClass=").append(sourceClass); 303 result.append(" name=").append(name); 304 for (Iterator iterator = attributes.iterator(); iterator.hasNext();) { 305 GAttributeInfo geronimoAttributeInfo = (GAttributeInfo) iterator.next(); 306 result.append("\n attribute: ").append(geronimoAttributeInfo); 307 } 308 for (Iterator iterator = operations.iterator(); iterator.hasNext();) { 309 GOperationInfo geronimoOperationInfo = (GOperationInfo) iterator.next(); 310 result.append("\n operation: ").append(geronimoOperationInfo); 311 } 312 for (Iterator iterator = references.iterator(); iterator.hasNext();) { 313 GReferenceInfo referenceInfo = (GReferenceInfo) iterator.next(); 314 result.append("\n reference: ").append(referenceInfo); 315 } 316 result.append("]"); 317 return result.toString(); 318 } 319 320 public String toXML(AbstractName abstractName) { 321 StringBuilder xml = new StringBuilder(); 322 323 xml.append("<gBeanInfo "); 324 xml.append("id='" + super.toString() + "' "); 325 xml.append("sourceClass='" + sourceClass + "' "); 326 xml.append("name='" + name + "' "); 327 xml.append("className='" + className + "' "); 328 xml.append("type='" + j2eeType + "' "); 329 xml.append("priority='" + priority + "' "); 330 xml.append(">"); 331 332 xml.append("<attributes>"); 333 334 for (Iterator loop = attributes.iterator(); loop.hasNext(); ) { 335 xml.append(((GAttributeInfo) loop.next()).toXML(abstractName)); 336 } 337 338 xml.append("</attributes>"); 339 340 xml.append(constructor.toXML()); 341 342 xml.append("<operations>"); 343 344 for (Iterator loop = operations.iterator(); loop.hasNext(); ) { 345 xml.append(((GOperationInfo) loop.next()).toXML()); 346 } 347 348 xml.append("</operations>"); 349 350 xml.append("<notifications>"); 351 352 // I had expected this to be a set of GNotification Objects 353 // but it was just strings 354 for (Iterator loop = notifications.iterator(); loop.hasNext(); ) { 355 Object note = loop.next(); 356 357 xml.append("<notification>" + note + "</notification>"); 358 } 359 360 xml.append("</notifications>"); 361 362 xml.append("<references>"); 363 364 for (Iterator loop = references.iterator(); loop.hasNext(); ) { 365 xml.append(((GReferenceInfo) loop.next()).toXML()); 366 } 367 368 xml.append("</references>"); 369 370 xml.append("</gBeanInfo>"); 371 372 return xml.toString(); 373 } 374 }