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    }