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.connector.deployment; 019 020 import java.lang.reflect.Field; 021 import java.lang.reflect.Method; 022 import java.util.HashMap; 023 import java.util.List; 024 import java.util.Map; 025 026 import javax.annotation.Resource; 027 import javax.naming.Reference; 028 import javax.xml.namespace.QName; 029 030 import org.apache.commons.logging.Log; 031 import org.apache.commons.logging.LogFactory; 032 import org.apache.geronimo.common.DeploymentException; 033 import org.apache.geronimo.common.UnresolvedReferenceException; 034 import org.apache.geronimo.gbean.AbstractNameQuery; 035 import org.apache.geronimo.gbean.GBeanInfo; 036 import org.apache.geronimo.gbean.GBeanInfoBuilder; 037 import org.apache.geronimo.j2ee.deployment.Module; 038 import org.apache.geronimo.j2ee.deployment.EARContext; 039 import org.apache.geronimo.j2ee.deployment.annotation.AnnotatedApp; 040 import org.apache.geronimo.j2ee.deployment.annotation.ResourceAnnotationHelper; 041 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 042 import org.apache.geronimo.kernel.GBeanNotFoundException; 043 import org.apache.geronimo.kernel.config.Configuration; 044 import org.apache.geronimo.kernel.repository.Environment; 045 import org.apache.geronimo.naming.deployment.AbstractNamingBuilder; 046 import org.apache.geronimo.naming.reference.ResourceReference; 047 import org.apache.geronimo.naming.reference.UserTransactionReference; 048 import org.apache.geronimo.xbeans.geronimo.naming.GerMessageDestinationDocument; 049 import org.apache.geronimo.xbeans.geronimo.naming.GerMessageDestinationType; 050 import org.apache.geronimo.xbeans.geronimo.naming.GerPatternType; 051 import org.apache.geronimo.xbeans.geronimo.naming.GerResourceEnvRefDocument; 052 import org.apache.geronimo.xbeans.geronimo.naming.GerResourceEnvRefType; 053 import org.apache.geronimo.xbeans.javaee.DescriptionType; 054 import org.apache.geronimo.xbeans.javaee.FullyQualifiedClassType; 055 import org.apache.geronimo.xbeans.javaee.InjectionTargetType; 056 import org.apache.geronimo.xbeans.javaee.JndiNameType; 057 import org.apache.geronimo.xbeans.javaee.MessageDestinationRefType; 058 import org.apache.geronimo.xbeans.javaee.MessageDestinationType; 059 import org.apache.geronimo.xbeans.javaee.MessageDestinationTypeType; 060 import org.apache.geronimo.xbeans.javaee.ResourceEnvRefType; 061 import org.apache.geronimo.xbeans.javaee.XsdStringType; 062 import org.apache.xmlbeans.QNameSet; 063 import org.apache.xmlbeans.XmlObject; 064 065 /** 066 * @version $Rev: 547737 $ $Date: 2007-06-15 12:47:19 -0400 (Fri, 15 Jun 2007) $ 067 */ 068 public class AdminObjectRefBuilder extends AbstractNamingBuilder { 069 private final static Log log = LogFactory.getLog(AdminObjectRefBuilder.class); 070 private final QNameSet adminOjbectRefQNameSet; 071 private final QNameSet messageDestinationQNameSet; 072 private final QNameSet messageDestinationRefQNameSet; 073 074 private static final QName GER_ADMIN_OBJECT_REF_QNAME = GerResourceEnvRefDocument.type.getDocumentElementName(); 075 private static final QNameSet GER_ADMIN_OBJECT_REF_QNAME_SET = QNameSet.singleton(GER_ADMIN_OBJECT_REF_QNAME); 076 private static final QName GER_MESSAGE_DESTINATION_QNAME = GerMessageDestinationDocument.type.getDocumentElementName(); 077 private static final QNameSet GER_MESSAGE_DESTINATION_QNAME_SET = QNameSet.singleton(GER_MESSAGE_DESTINATION_QNAME); 078 079 public AdminObjectRefBuilder(Environment defaultEnvironment, String[] eeNamespaces) { 080 super(defaultEnvironment); 081 adminOjbectRefQNameSet = buildQNameSet(eeNamespaces, "resource-env-ref"); 082 messageDestinationQNameSet = buildQNameSet(eeNamespaces, "message-destination"); 083 messageDestinationRefQNameSet = buildQNameSet(eeNamespaces, "message-destination-ref"); 084 } 085 086 protected boolean willMergeEnvironment(XmlObject specDD, XmlObject plan) { 087 return specDD.selectChildren(adminOjbectRefQNameSet).length > 0 || specDD.selectChildren(messageDestinationRefQNameSet).length > 0; 088 } 089 090 public void initContext(XmlObject specDD, XmlObject plan, Module module) throws DeploymentException { 091 List<MessageDestinationType> specDestinations = convert(specDD.selectChildren(messageDestinationQNameSet), JEE_CONVERTER, MessageDestinationType.class, MessageDestinationType.type); 092 XmlObject[] gerDestinations = plan.selectChildren(GER_MESSAGE_DESTINATION_QNAME_SET); 093 Map<String, GerMessageDestinationType> nameMap = new HashMap<String, GerMessageDestinationType>(); 094 for (XmlObject gerDestination : gerDestinations) { 095 GerMessageDestinationType destination = (GerMessageDestinationType) gerDestination.copy().changeType(GerMessageDestinationType.type); 096 String name = destination.getMessageDestinationName().trim(); 097 nameMap.put(name, destination); 098 boolean found = false; 099 for (MessageDestinationType specDestination : specDestinations) { 100 if (specDestination.getMessageDestinationName().getStringValue().trim().equals(name)) { 101 found = true; 102 break; 103 } 104 } 105 if (!found) { 106 throw new DeploymentException("No spec DD message-destination for " + name); 107 } 108 } 109 module.getRootEarContext().registerMessageDestionations(module.getName(), nameMap); 110 } 111 112 113 public void buildNaming(XmlObject specDD, XmlObject plan, Module module, Map componentContext) throws DeploymentException { 114 XmlObject[] gerResourceEnvRefsUntyped = plan == null ? NO_REFS : plan.selectChildren(GER_ADMIN_OBJECT_REF_QNAME_SET); 115 Map<String, GerResourceEnvRefType> refMap = mapResourceEnvRefs(gerResourceEnvRefsUntyped); 116 Map<String, Map<String, GerMessageDestinationType>> messageDestinations = module.getRootEarContext().getMessageDestinations(); 117 118 // Discover and process any @Resource annotations (if !metadata-complete) 119 if (module.getClassFinder() != null) { 120 121 // Process all the annotations for this naming builder type 122 try { 123 ResourceAnnotationHelper.processAnnotations(module.getAnnotatedApp(), module.getClassFinder(), new AdminObjectRefProcessor(refMap, messageDestinations, module.getEarContext())); 124 } 125 catch (Exception e) { 126 log.warn("Unable to process @Resource annotations for module" + module.getName(), e); 127 } 128 } 129 130 List<ResourceEnvRefType> resourceEnvRefsUntyped = convert(specDD.selectChildren(adminOjbectRefQNameSet), JEE_CONVERTER, ResourceEnvRefType.class, ResourceEnvRefType.type); 131 ClassLoader cl = module.getEarContext().getClassLoader(); 132 for (ResourceEnvRefType resourceEnvRef : resourceEnvRefsUntyped) { 133 String name = resourceEnvRef.getResourceEnvRefName().getStringValue().trim(); 134 addInjections(name, resourceEnvRef.getInjectionTargetArray(), componentContext); 135 String type = resourceEnvRef.getResourceEnvRefType().getStringValue().trim(); 136 Class iface; 137 try { 138 iface = cl.loadClass(type); 139 } catch (ClassNotFoundException e) { 140 throw new DeploymentException("could not load class " + type, e); 141 } 142 GerResourceEnvRefType gerResourceEnvRef = refMap.get(name); 143 refMap.remove(name); 144 try { 145 String refType = getStringValue(resourceEnvRef.getResourceEnvRefType()); 146 if (refType.equals("javax.transaction.UserTransaction")) { 147 Reference ref = new UserTransactionReference(); 148 getJndiContextMap(componentContext).put(ENV + name, ref); 149 } else { 150 AbstractNameQuery containerId = getAdminObjectContainerId(name, gerResourceEnvRef); 151 Reference ref = buildAdminObjectReference(module, containerId, iface); 152 getJndiContextMap(componentContext).put(ENV + name, ref); 153 } 154 } catch (UnresolvedReferenceException e) { 155 throw new DeploymentException("Unable to resolve resource env reference '" + name + "' (" + (e.isMultiple() ? "found multiple matching resources" : "no matching resources found") + ")", e); 156 } 157 } 158 159 if (refMap.size() > 0) { 160 log.warn("Failed to build reference to Admin object reference "+refMap.keySet()+" defined in plan file, reason - corresponding entry in deployment descriptor missing."); 161 } 162 163 //message-destination-refs 164 List<MessageDestinationRefType> messageDestinationRefsUntyped = convert(specDD.selectChildren(messageDestinationRefQNameSet), JEE_CONVERTER, MessageDestinationRefType.class, MessageDestinationRefType.type); 165 166 for (MessageDestinationRefType messageDestinationRef : messageDestinationRefsUntyped) { 167 String name = getStringValue(messageDestinationRef.getMessageDestinationRefName()); 168 addInjections(name, messageDestinationRef.getInjectionTargetArray(), componentContext); 169 String linkName = getStringValue(messageDestinationRef.getMessageDestinationLink()); 170 //TODO figure out something better to do here! 171 if (linkName == null) { 172 linkName = name; 173 } 174 String type = getStringValue(messageDestinationRef.getMessageDestinationType()); 175 if (type == null) { 176 //must have an injection target to determine type EE5.8.1.3 177 InjectionTargetType[] targets = messageDestinationRef.getInjectionTargetArray(); 178 if (targets.length == 0) { 179 throw new DeploymentException("No type for message-destination-ref can be determined from explicit specification or injection target: " + messageDestinationRef); 180 } 181 type = getStringValue(targets[0].getInjectionTargetClass()); 182 if (type == null) { 183 throw new DeploymentException("no type for message destination ref in injection target: " + targets[0]); 184 } 185 } 186 Class iface; 187 try { 188 iface = cl.loadClass(type); 189 } catch (ClassNotFoundException e) { 190 throw new DeploymentException("could not load class " + type, e); 191 } 192 String moduleURI = null; 193 GerMessageDestinationType destination = getMessageDestination(linkName, messageDestinations); 194 if (destination != null) { 195 if (destination.isSetAdminObjectLink()) { 196 if (destination.isSetAdminObjectModule()) { 197 moduleURI = destination.getAdminObjectModule().trim(); 198 } 199 linkName = destination.getAdminObjectLink().trim(); 200 } 201 } else { 202 //well, we know for sure an admin object is not going to be defined in a modules that can have a message-destination 203 int pos = linkName.indexOf('#'); 204 if (pos > -1) { 205 //AMM -- the following line causes blowups; e.g. to look in DayTrader EJB module for a RA -- why is that?!? 206 //moduleURI = linkName.substring(0, pos); 207 linkName = linkName.substring(pos + 1); 208 } 209 } 210 211 //try to resolve ref based only matching resource-ref-name 212 //throws exception if it can't locate ref. 213 AbstractNameQuery containerId = buildAbstractNameQuery(null, moduleURI, linkName, NameFactory.JCA_ADMIN_OBJECT, NameFactory.RESOURCE_ADAPTER_MODULE); 214 Reference ref = buildAdminObjectReference(module, containerId, iface); 215 getJndiContextMap(componentContext).put(ENV + name, ref); 216 217 } 218 219 } 220 221 public static GerMessageDestinationType getMessageDestination(String messageDestinationLink, Map<String, Map<String, GerMessageDestinationType>> messageDestinations) throws DeploymentException { 222 GerMessageDestinationType destination = null; 223 int pos = messageDestinationLink.indexOf('#'); 224 if (pos > -1) { 225 String targetModule = messageDestinationLink.substring(0, pos); 226 Map<String, GerMessageDestinationType> destinations = messageDestinations.get(targetModule); 227 // Hmmm...if we don't find the module then something is wrong in the deployment. 228 if (destinations == null) { 229 StringBuffer sb = new StringBuffer(); 230 for (Object o : messageDestinations.keySet()) { 231 sb.append(o).append("\n"); 232 } 233 throw new DeploymentException("Unknown module " + targetModule + " when processing message destination " + messageDestinationLink + 234 "\nKnown modules in deployable unit are:\n" + sb.toString()); 235 } 236 messageDestinationLink = messageDestinationLink.substring(pos + 1); 237 destination = destinations.get(messageDestinationLink); 238 } else { 239 for (Map<String, GerMessageDestinationType> destinations : messageDestinations.values()) { 240 GerMessageDestinationType destinationTest = destinations.get(messageDestinationLink); 241 if (destinationTest != null) { 242 if (destination != null) { 243 throw new DeploymentException("Duplicate message destination " + messageDestinationLink + " accessed from a message-destination-link without a module"); 244 } 245 destination = destinationTest; 246 } 247 } 248 } 249 return destination; 250 } 251 252 253 private Reference buildAdminObjectReference(Module module, AbstractNameQuery containerId, Class iface) throws DeploymentException { 254 Configuration localConfiguration = module.getEarContext().getConfiguration(); 255 try { 256 localConfiguration.findGBean(containerId); 257 } catch (GBeanNotFoundException e) { 258 throw new DeploymentException("Can not resolve admin object ref " + containerId + " in configuration " + localConfiguration.getId(), e); 259 } 260 return new ResourceReference(module.getConfigId(), containerId, iface); 261 } 262 263 private static AbstractNameQuery getAdminObjectContainerId(String name, GerResourceEnvRefType gerResourceEnvRef) { 264 AbstractNameQuery containerId; 265 if (gerResourceEnvRef == null) { 266 containerId = buildAbstractNameQuery(null, null, name, NameFactory.JCA_ADMIN_OBJECT, NameFactory.RESOURCE_ADAPTER_MODULE); 267 } else if (gerResourceEnvRef.isSetMessageDestinationLink()) { 268 containerId = buildAbstractNameQuery(null, null, gerResourceEnvRef.getMessageDestinationLink().trim(), NameFactory.JCA_ADMIN_OBJECT, NameFactory.RESOURCE_ADAPTER_MODULE); 269 } else if (gerResourceEnvRef.isSetAdminObjectLink()) { 270 String moduleURI = null; 271 if (gerResourceEnvRef.isSetAdminObjectModule()) { 272 moduleURI = gerResourceEnvRef.getAdminObjectModule().trim(); 273 } 274 containerId = buildAbstractNameQuery(null, moduleURI, gerResourceEnvRef.getAdminObjectLink().trim(), NameFactory.JCA_ADMIN_OBJECT, NameFactory.RESOURCE_ADAPTER_MODULE); 275 } else { 276 //construct name from components 277 GerPatternType patternType = gerResourceEnvRef.getPattern(); 278 containerId = buildAbstractNameQuery(patternType, NameFactory.JCA_ADMIN_OBJECT, NameFactory.RESOURCE_ADAPTER_MODULE, null); 279 } 280 return containerId; 281 } 282 283 private static Map<String, GerResourceEnvRefType> mapResourceEnvRefs(XmlObject[] refs) { 284 Map<String, GerResourceEnvRefType> refMap = new HashMap<String, GerResourceEnvRefType>(); 285 if (refs != null) { 286 for (XmlObject ref1 : refs) { 287 GerResourceEnvRefType ref = (GerResourceEnvRefType) ref1.copy().changeType(GerResourceEnvRefType.type); 288 refMap.put(ref.getRefName().trim(), ref); 289 } 290 } 291 return refMap; 292 } 293 294 public QNameSet getSpecQNameSet() { 295 return adminOjbectRefQNameSet; 296 } 297 298 public QNameSet getPlanQNameSet() { 299 return GER_ADMIN_OBJECT_REF_QNAME_SET; 300 } 301 302 public static class AdminObjectRefProcessor extends ResourceAnnotationHelper.ResourceProcessor { 303 private final EARContext earContext; 304 private final Map<String, GerResourceEnvRefType> refMap; 305 private final Map<String, Map<String, GerMessageDestinationType>> messageDestinations; 306 307 public AdminObjectRefProcessor(Map<String, GerResourceEnvRefType> refMap, Map<String, Map<String, GerMessageDestinationType>> messageDestinations, EARContext earContext) { 308 this.refMap = refMap; 309 this.messageDestinations = messageDestinations; 310 this.earContext = earContext; 311 } 312 313 public boolean processResource(AnnotatedApp annotatedApp, Resource annotation, Class cls, Method method, Field field) throws DeploymentException { 314 String resourceName = getResourceName(annotation, method, field); 315 String resourceType = getResourceType(annotation, method, field); 316 317 if (resourceType.equals("javax.ejb.SessionContext")) return true; 318 if (resourceType.equals("javax.ejb.MessageDrivenContext")) return true; 319 if (resourceType.equals("javax.ejb.EntityContext")) return true; 320 321 //If it already exists in xml as a message-destination-ref or resource-env-ref, we are done. 322 MessageDestinationRefType[] messageDestinationRefs = annotatedApp.getMessageDestinationRefArray(); 323 for (MessageDestinationRefType messageDestinationRef : messageDestinationRefs) { 324 if (messageDestinationRef.getMessageDestinationRefName().getStringValue().trim().equals(resourceName)) { 325 if (method != null || field != null) { 326 InjectionTargetType[] targets = messageDestinationRef.getInjectionTargetArray(); 327 if (!hasTarget(method, field, targets)) { 328 configureInjectionTarget(messageDestinationRef.addNewInjectionTarget(), method, field); 329 } 330 } 331 return true; 332 } 333 } 334 ResourceEnvRefType[] ResourceEnvRefs = annotatedApp.getResourceEnvRefArray(); 335 for (ResourceEnvRefType resourceEnvRefType : ResourceEnvRefs) { 336 if (resourceEnvRefType.getResourceEnvRefName().getStringValue().trim().equals(resourceName)) { 337 if (method != null || field != null) { 338 InjectionTargetType[] targets = resourceEnvRefType.getInjectionTargetArray(); 339 if (!hasTarget(method, field, targets)) { 340 configureInjectionTarget(resourceEnvRefType.addNewInjectionTarget(), method, field); 341 } 342 } 343 return true; 344 } 345 } 346 347 //if it maps to a message-destination in the geronimo plan, it's a message-destination. 348 GerMessageDestinationType gerMessageDestinationType = getMessageDestination(resourceName, messageDestinations); 349 if (gerMessageDestinationType != null) { 350 addMethodDestinationRef(annotatedApp, resourceName, resourceType, method, field, annotation); 351 return true; 352 } else { 353 //if it maps to a resource-env-ref in the geronimo plan, it's a resource-ref 354 GerResourceEnvRefType resourceEnvRefType = refMap.get(resourceName); 355 if (resourceEnvRefType != null || resourceType.equals("javax.transaction.UserTransaction")) { 356 //mapped resource-env-ref 357 addResourceEnvRef(annotatedApp, resourceName, resourceType, method, field, annotation); 358 return true; 359 } else { 360 //look for an JCAAdminObject gbean with the right name 361 AbstractNameQuery containerId = buildAbstractNameQuery(null, null, resourceName, NameFactory.JCA_ADMIN_OBJECT, NameFactory.RESOURCE_ADAPTER_MODULE); 362 try { 363 earContext.findGBean(containerId); 364 } catch (GBeanNotFoundException e) { 365 //not identifiable as an admin object ref 366 return false; 367 } 368 addResourceEnvRef(annotatedApp, resourceName, resourceType, method, field, annotation); 369 return true; 370 } 371 } 372 } 373 374 private void addResourceEnvRef(AnnotatedApp annotatedApp, String resourceName, String resourceType, Method method, Field field, Resource annotation) { 375 ResourceEnvRefType resourceEnvRef = annotatedApp.addNewResourceEnvRef(); 376 377 //------------------------------------------------------------------------------ 378 // <resource-env-ref> required elements: 379 //------------------------------------------------------------------------------ 380 381 // resource-env-ref-name 382 JndiNameType resourceEnvRefName = resourceEnvRef.addNewResourceEnvRefName(); 383 resourceEnvRefName.setStringValue(resourceName); 384 resourceEnvRef.setResourceEnvRefName(resourceEnvRefName); 385 386 if (!resourceType.equals("")) { 387 // resource-env-ref-type 388 FullyQualifiedClassType qualifiedClass = resourceEnvRef.addNewResourceEnvRefType(); 389 qualifiedClass.setStringValue(resourceType); 390 resourceEnvRef.setResourceEnvRefType(qualifiedClass); 391 } 392 if (method != null || field != null) { 393 // injectionTarget 394 InjectionTargetType injectionTarget = resourceEnvRef.addNewInjectionTarget(); 395 configureInjectionTarget(injectionTarget, method, field); 396 } 397 398 //------------------------------------------------------------------------------ 399 // <resource-env-ref> optional elements: 400 //------------------------------------------------------------------------------ 401 402 // description 403 String descriptionAnnotation = annotation.description(); 404 if (!descriptionAnnotation.equals("")) { 405 DescriptionType description = resourceEnvRef.addNewDescription(); 406 description.setStringValue(descriptionAnnotation); 407 } 408 409 // mappedName 410 String mappdedNameAnnotation = annotation.mappedName(); 411 if (!mappdedNameAnnotation.equals("")) { 412 XsdStringType mappedName = resourceEnvRef.addNewMappedName(); 413 mappedName.setStringValue(mappdedNameAnnotation); 414 resourceEnvRef.setMappedName(mappedName); 415 } 416 } 417 418 private void addMethodDestinationRef(AnnotatedApp annotatedApp, String resourceName, String resourceType, Method method, Field field, Resource annotation) { 419 MessageDestinationRefType messageDestinationRef = annotatedApp.addNewMessageDestinationRef(); 420 421 //------------------------------------------------------------------------------ 422 // <message-destination-ref> required elements: 423 //------------------------------------------------------------------------------ 424 425 // message-destination-ref-name 426 JndiNameType messageDestinationRefName = messageDestinationRef.addNewMessageDestinationRefName(); 427 messageDestinationRefName.setStringValue(resourceName); 428 messageDestinationRef.setMessageDestinationRefName(messageDestinationRefName); 429 430 if (!resourceType.equals("")) { 431 // message-destination-ref-type 432 MessageDestinationTypeType msgDestType = messageDestinationRef.addNewMessageDestinationType(); 433 msgDestType.setStringValue(resourceType); 434 messageDestinationRef.setMessageDestinationType(msgDestType); 435 } 436 if (method != null || field != null) { 437 // injectionTarget 438 InjectionTargetType injectionTarget = messageDestinationRef.addNewInjectionTarget(); 439 configureInjectionTarget(injectionTarget, method, field); 440 } 441 442 //------------------------------------------------------------------------------ 443 // <message-destination-ref> optional elements: 444 //------------------------------------------------------------------------------ 445 446 // description 447 String descriptionAnnotation = annotation.description(); 448 if (!descriptionAnnotation.equals("")) { 449 DescriptionType description = messageDestinationRef.addNewDescription(); 450 description.setStringValue(descriptionAnnotation); 451 } 452 453 // mappedName 454 String mappdedNameAnnotation = annotation.mappedName(); 455 if (!mappdedNameAnnotation.equals("")) { 456 XsdStringType mappedName = messageDestinationRef.addNewMappedName(); 457 mappedName.setStringValue(mappdedNameAnnotation); 458 messageDestinationRef.setMappedName(mappedName); 459 } 460 } 461 } 462 463 public static final GBeanInfo GBEAN_INFO; 464 465 static { 466 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(AdminObjectRefBuilder.class, NameFactory.MODULE_BUILDER); 467 infoBuilder.addAttribute("eeNamespaces", String[].class, true, true); 468 infoBuilder.addAttribute("defaultEnvironment", Environment.class, true, true); 469 470 infoBuilder.setConstructor(new String[]{"defaultEnvironment", "eeNamespaces"}); 471 472 GBEAN_INFO = infoBuilder.getBeanInfo(); 473 } 474 475 public static GBeanInfo getGBeanInfo 476 () { 477 return GBEAN_INFO; 478 } 479 480 }