001    /**
002     *
003     *  Licensed to the Apache Software Foundation (ASF) under one or more
004     *  contributor license agreements.  See the NOTICE file distributed with
005     *  this work for additional information regarding copyright ownership.
006     *  The ASF licenses this file to You under the Apache License, Version 2.0
007     *  (the "License"); you may not use this file except in compliance with
008     *  the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     *  Unless required by applicable law or agreed to in writing, software
013     *  distributed under the License is distributed on an "AS IS" BASIS,
014     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     *  See the License for the specific language governing permissions and
016     *  limitations under the License.
017     */
018    package org.apache.geronimo.j2ee.deployment;
019    
020    import org.apache.geronimo.common.DeploymentException;
021    import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
022    import org.apache.geronimo.deployment.ModuleIDBuilder;
023    import org.apache.geronimo.gbean.GBeanInfo;
024    import org.apache.geronimo.gbean.GBeanInfoBuilder;
025    import org.apache.geronimo.gbean.ReferenceCollection;
026    import org.apache.geronimo.gbean.ReferenceCollectionEvent;
027    import org.apache.geronimo.gbean.ReferenceCollectionListener;
028    import org.apache.geronimo.gbean.AbstractName;
029    import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
030    import org.apache.geronimo.kernel.repository.Environment;
031    import org.apache.geronimo.kernel.Naming;
032    import org.apache.geronimo.kernel.config.ConfigurationStore;
033    import org.apache.xmlbeans.XmlCursor;
034    import org.apache.xmlbeans.XmlException;
035    import org.apache.xmlbeans.XmlObject;
036    
037    import java.io.File;
038    import java.io.IOException;
039    import java.net.URL;
040    import java.util.Collection;
041    import java.util.HashMap;
042    import java.util.Iterator;
043    import java.util.Map;
044    import java.util.jar.JarFile;
045    
046    /**
047     * @version $Rev:386276 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
048     */
049    public class SwitchingModuleBuilder implements ModuleBuilder {
050    
051        private final Map namespaceToBuilderMap = new HashMap();
052    
053        private String defaultNamespace;
054    
055        public SwitchingModuleBuilder(Collection builders) {
056            ReferenceCollection buildersCollection = (ReferenceCollection) builders;
057            buildersCollection.addReferenceCollectionListener(new ReferenceCollectionListener() {
058                public void memberAdded(ReferenceCollectionEvent event) {
059                    ModuleBuilder builder = (ModuleBuilder) event.getMember();
060                    String namespace = builder.getSchemaNamespace();
061                    namespaceToBuilderMap.put(namespace, builder);
062                }
063    
064                public void memberRemoved(ReferenceCollectionEvent event) {
065                    ModuleBuilder builder = (ModuleBuilder) event.getMember();
066                    String namespace =  builder.getSchemaNamespace();
067                    namespaceToBuilderMap.remove(namespace);
068                }
069            });
070            for (Iterator iterator = builders.iterator(); iterator.hasNext();) {
071                ModuleBuilder builder = (ModuleBuilder) iterator.next();
072                String namespace =  builder.getSchemaNamespace();
073                namespaceToBuilderMap.put(namespace, builder);
074            }
075    
076        }
077    
078        public String getDefaultNamespace() {
079            return defaultNamespace;
080        }
081    
082        public void setDefaultNamespace(String defaultNamespace) {
083            this.defaultNamespace = defaultNamespace;
084        }
085    
086        public Module createModule(File plan, JarFile moduleFile, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
087            String namespace;
088            if (plan == null) {
089                namespace = defaultNamespace;
090            } else {
091                namespace = getNamespaceFromPlan(plan);
092            }
093            ModuleBuilder builder = getBuilderFromNamespace(namespace);
094            if (builder != null) {
095                return builder.createModule(plan, moduleFile, naming, idBuilder);
096            } else {
097                return null;
098            }
099        }
100    
101        private String getNamespaceFromPlan(Object plan) throws DeploymentException {
102            XmlObject xmlObject;
103            if (plan instanceof File) {
104                try {
105                    xmlObject = XmlBeansUtil.parse(((File) plan).toURL(), getClass().getClassLoader());
106                } catch (IOException e) {
107                    throw new DeploymentException("Could not read plan file", e);
108                } catch (XmlException e) {
109                    throw new DeploymentException("Plan file does not contain well formed xml", e);
110                }
111            } else if (plan instanceof XmlObject) {
112                xmlObject = (XmlObject) plan;
113            } else {
114                return defaultNamespace;
115            }
116            XmlCursor cursor = xmlObject.newCursor();
117            try {
118                while (cursor.hasNextToken()){
119                    if (cursor.isStart()) {
120                        return cursor.getName().getNamespaceURI();
121                    }
122                    cursor.toNextToken();
123                }
124            } finally {
125                cursor.dispose();
126            }
127            throw new DeploymentException("Cannot find namespace in xmlObject: " + xmlObject.xmlText());
128        }
129    
130        private ModuleBuilder getBuilderFromNamespace(String namespace) {
131            ModuleBuilder builder = (ModuleBuilder) namespaceToBuilderMap.get(namespace);
132            if (builder == null) {
133                builder = (ModuleBuilder) namespaceToBuilderMap.get(defaultNamespace);
134            }
135            return builder;
136        }
137    
138        public Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, Environment environment, Object moduleContextInfo, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
139            String namespace = getNamespaceFromPlan(plan);
140            ModuleBuilder builder = getBuilderFromNamespace(namespace);
141            if (builder != null) {
142                return builder.createModule(plan, moduleFile, targetPath, specDDUrl, environment, moduleContextInfo, earName, naming, idBuilder);
143            } else {
144                return null;
145            }
146        }
147    
148        public void installModule(JarFile earFile, EARContext earContext, Module module, Collection configurationStores, ConfigurationStore targetConfigurationStore, Collection repositories) throws DeploymentException {
149            String namespace = module.getNamespace();
150            ModuleBuilder builder = getBuilderFromNamespace(namespace);
151            builder.installModule(earFile, earContext, module, configurationStores, targetConfigurationStore, repositories);
152        }
153    
154        public void initContext(EARContext earContext, Module module, ClassLoader cl) throws DeploymentException {
155            String namespace = module.getNamespace();
156            ModuleBuilder builder = getBuilderFromNamespace(namespace);
157            builder.initContext(earContext, module, cl);
158        }
159    
160        public void addGBeans(EARContext earContext, Module module, ClassLoader cl, Collection repositories) throws DeploymentException {
161            String namespace = module.getNamespace();
162            ModuleBuilder builder = getBuilderFromNamespace(namespace);
163            builder.addGBeans(earContext, module, cl, repositories);
164        }
165    
166        public String getSchemaNamespace() {
167            return null;
168        }
169    
170        public static final GBeanInfo GBEAN_INFO;
171    
172        static {
173            GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(SwitchingModuleBuilder.class, NameFactory.MODULE_BUILDER);
174            infoBuilder.addAttribute("defaultNamespace", String.class, true, true);
175            infoBuilder.addReference("ModuleBuilders", ModuleBuilder.class, NameFactory.MODULE_BUILDER);
176            infoBuilder.addInterface(ModuleBuilder.class);
177    
178            infoBuilder.setConstructor(new String[] {"ModuleBuilders"});
179            GBEAN_INFO = infoBuilder.getBeanInfo();
180        }
181    
182        public static GBeanInfo getGBeanInfo() {
183            return GBEAN_INFO;
184        }
185    }