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.deployment.service;
019    
020    import java.beans.PropertyEditor;
021    import java.util.Collections;
022    import java.util.HashMap;
023    import java.util.HashSet;
024    import java.util.Iterator;
025    import java.util.Map;
026    import java.util.Set;
027    
028    import org.apache.geronimo.common.DeploymentException;
029    import org.apache.geronimo.common.propertyeditor.PropertyEditors;
030    import org.apache.geronimo.deployment.DeploymentContext;
031    import org.apache.geronimo.deployment.xbeans.PatternType;
032    import org.apache.geronimo.deployment.xbeans.ReferenceType;
033    import org.apache.geronimo.gbean.AbstractName;
034    import org.apache.geronimo.gbean.AbstractNameQuery;
035    import org.apache.geronimo.gbean.GAttributeInfo;
036    import org.apache.geronimo.gbean.GBeanData;
037    import org.apache.geronimo.gbean.GBeanInfo;
038    import org.apache.geronimo.gbean.GReferenceInfo;
039    import org.apache.geronimo.gbean.ReferencePatterns;
040    import org.apache.geronimo.kernel.repository.Artifact;
041    import org.apache.xmlbeans.XmlObject;
042    
043    /**
044     * @version $Rev: 549098 $ $Date: 2007-06-20 08:58:51 -0400 (Wed, 20 Jun 2007) $
045     */
046    public class SingleGBeanBuilder {
047        private final GBeanData gbean;
048        private final ClassLoader classLoader;
049        private final DeploymentContext context;
050        private final AbstractName moduleName;
051        private final Map xmlAttributeBuilderMap;
052        private final Map xmlReferenceBuilderMap;
053    
054        SingleGBeanBuilder(AbstractName abstractName, GBeanInfo gBeanInfo, ClassLoader classLoader, DeploymentContext context, AbstractName moduleName, Map xmlAttributeBuilderMap, Map xmlReferenceBuilderMap) {
055    
056            this.classLoader = classLoader;
057            this.context = context;
058            this.moduleName = moduleName;
059            this.gbean = new GBeanData(abstractName, gBeanInfo);
060            this.xmlAttributeBuilderMap = xmlAttributeBuilderMap;
061            this.xmlReferenceBuilderMap = xmlReferenceBuilderMap;
062        }
063    
064        public void setAttribute(String name, String type, String text) throws DeploymentException {
065            if (text != null) {
066                text = text.trim(); // avoid formatting errors due to extra whitespace in XML configuration file
067            }
068            try {
069                // @todo we should not need all of common just for this
070                if (type == null) {
071                    GAttributeInfo attribute = gbean.getGBeanInfo().getAttribute(name);
072                    if (attribute == null) {
073                        throw new DeploymentException("Unknown attribute " + name + " on " + gbean.getAbstractName());
074                    }
075                    type = attribute.getType();
076                }
077    
078                PropertyEditor editor = PropertyEditors.findEditor(type, classLoader);
079                if (editor == null) {
080                    throw new DeploymentException("Unable to find PropertyEditor for " + type);
081                }
082                editor.setAsText(text);
083                Object value = editor.getValue();
084                gbean.setAttribute(name, value);
085            } catch (DeploymentException e) {
086                throw e;
087            } catch (ClassNotFoundException e) {
088                throw new DeploymentException("Unable to find PropertyEditor for " + type, e);
089            } catch (Exception e) {
090                throw new DeploymentException("Unable to set attribute " + name + " to " + text, e);
091            }
092        }
093    
094        public void setXmlAttribute(String name, XmlObject xmlObject) throws DeploymentException {
095            String namespace = xmlObject.getDomNode().getNamespaceURI();
096            XmlAttributeBuilder builder = (XmlAttributeBuilder) xmlAttributeBuilderMap.get(namespace);
097            if (builder == null) {
098                throw new DeploymentException("No attribute builder deployed for namespace: " + namespace);
099            }
100            GAttributeInfo attribute = gbean.getGBeanInfo().getAttribute(name);
101            if (attribute == null) {
102                throw new DeploymentException("Unknown attribute " + name + " on " + gbean.getAbstractName());
103            }
104            String type = attribute.getType();
105            Object value = builder.getValue(xmlObject, type, classLoader);
106            gbean.setAttribute(name, value);
107        }
108    
109        public void setXmlReference(String name, XmlObject xmlObject) throws DeploymentException {
110            String namespace = xmlObject.getDomNode().getNamespaceURI();
111            XmlReferenceBuilder builder = (XmlReferenceBuilder) xmlReferenceBuilderMap.get(namespace);
112            if (builder == null) {
113                throw new DeploymentException("No reference builder deployed for namespace: " + namespace);
114            }
115            ReferencePatterns references = builder.getReferences(xmlObject, context, moduleName, classLoader);
116            if (references != null) {
117                gbean.setReferencePatterns(name, references);
118            }
119        }
120    
121        public void setReference(String name, ReferenceType pattern, AbstractName parentName) throws DeploymentException {
122            setReference(name, new PatternType[]{pattern}, parentName);
123        }
124    
125        public void setReference(String name, PatternType[] patterns, AbstractName parentName) throws DeploymentException {
126            Set patternNames = new HashSet(patterns.length);
127            for (int i = 0; i < patterns.length; i++) {
128                patternNames.add(buildAbstractNameQuery(name, patterns[i]));
129            }
130            gbean.setReferencePatterns(name, patternNames);
131        }
132    
133        public void addDependency(PatternType patternType) throws DeploymentException {
134            AbstractNameQuery refInfo = buildAbstractNameQuery(patternType, null);
135            gbean.addDependency(refInfo);
136        }
137    
138        private AbstractNameQuery buildAbstractNameQuery(String refName, PatternType pattern) throws DeploymentException {
139    //        if (refName == null) {
140    //            throw new DeploymentException("No type specified in dependency pattern " + pattern + " for gbean " + gbean.getName());
141    //        }
142            assert refName != null;
143            GReferenceInfo referenceInfo = null;
144            Set referenceInfos = gbean.getGBeanInfo().getReferences();
145            for (Iterator iterator = referenceInfos.iterator(); iterator.hasNext();) {
146                GReferenceInfo testReferenceInfo = (GReferenceInfo) iterator.next();
147                String testRefName = testReferenceInfo.getName();
148                if (testRefName.equals(refName)) {
149                    referenceInfo = testReferenceInfo;
150                }
151            }
152            if (referenceInfo == null) {
153                throw new DeploymentException("No reference named " + refName + " in gbean " + gbean.getAbstractName());
154            }
155    
156            return buildAbstractNameQuery(pattern, referenceInfo);
157        }
158    
159        public static AbstractNameQuery buildAbstractNameQuery(PatternType pattern, GReferenceInfo referenceInfo) {
160            String nameTypeName = referenceInfo == null? null: referenceInfo.getNameTypeName();
161            Set interfaceTypes = referenceInfo == null? null: Collections.singleton(referenceInfo.getReferenceType());
162            return buildAbstractNameQuery(pattern, nameTypeName, interfaceTypes);
163        }
164    
165        public static AbstractNameQuery buildAbstractNameQuery(PatternType pattern, String nameTypeName, Set interfaceTypes) {
166            String groupId = pattern.isSetGroupId() ? pattern.getGroupId().trim() : null;
167            String artifactid = pattern.isSetArtifactId() ? pattern.getArtifactId().trim() : null;
168            String version = pattern.isSetVersion() ? pattern.getVersion().trim() : null;
169            String module = pattern.isSetModule() ? pattern.getModule().trim() : null;
170            String type = pattern.isSetType() ? pattern.getType().trim() : null;
171            String name = pattern.isSetName() ? pattern.getName().trim() : null;
172    
173            Artifact artifact = artifactid != null? new Artifact(groupId, artifactid, version, "car"): null;
174            //get the type from the gbean info if not supplied explicitly
175            if (type == null) {
176                type = nameTypeName;
177            }
178            Map nameMap = new HashMap();
179            if (name != null) {
180                nameMap.put("name", name);
181            }
182            if (type != null) {
183                nameMap.put("j2eeType", type);
184            }
185            if (module != null) {
186                nameMap.put("J2EEModule", module);
187            }
188            return new AbstractNameQuery(artifact, nameMap, interfaceTypes);
189        }
190    
191        public GBeanData getGBeanData() {
192            return gbean;
193        }
194    
195    }