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    package org.apache.geronimo.j2ee.deployment;
018    
019    import org.apache.geronimo.common.DeploymentException;
020    import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
021    import org.apache.geronimo.deployment.ModuleIDBuilder;
022    import org.apache.geronimo.gbean.GBeanInfo;
023    import org.apache.geronimo.gbean.GBeanInfoBuilder;
024    import org.apache.geronimo.gbean.ReferenceCollection;
025    import org.apache.geronimo.gbean.ReferenceCollectionEvent;
026    import org.apache.geronimo.gbean.ReferenceCollectionListener;
027    import org.apache.geronimo.gbean.AbstractName;
028    import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
029    import org.apache.geronimo.kernel.repository.Environment;
030    import org.apache.geronimo.kernel.Naming;
031    import org.apache.geronimo.kernel.config.ConfigurationStore;
032    import org.apache.xmlbeans.XmlCursor;
033    import org.apache.xmlbeans.XmlException;
034    import org.apache.xmlbeans.XmlObject;
035    
036    import java.io.File;
037    import java.io.IOException;
038    import java.net.URL;
039    import java.util.Collection;
040    import java.util.HashMap;
041    import java.util.Iterator;
042    import java.util.Map;
043    import java.util.jar.JarFile;
044    
045    /**
046     * @version $Rev:386276 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $
047     */
048    public class SwitchingModuleBuilder implements ModuleBuilder {
049    
050        private final Map namespaceToBuilderMap = new HashMap();
051    
052        private String defaultNamespace;
053    
054        public SwitchingModuleBuilder(Collection builders) {
055            ReferenceCollection buildersCollection = (ReferenceCollection) builders;
056            buildersCollection.addReferenceCollectionListener(new ReferenceCollectionListener() {
057                public void memberAdded(ReferenceCollectionEvent event) {
058                    ModuleBuilder builder = (ModuleBuilder) event.getMember();
059                    String namespace = builder.getSchemaNamespace();
060                    namespaceToBuilderMap.put(namespace, builder);
061                }
062    
063                public void memberRemoved(ReferenceCollectionEvent event) {
064                    ModuleBuilder builder = (ModuleBuilder) event.getMember();
065                    String namespace =  builder.getSchemaNamespace();
066                    namespaceToBuilderMap.remove(namespace);
067                }
068            });
069            for (Iterator iterator = builders.iterator(); iterator.hasNext();) {
070                ModuleBuilder builder = (ModuleBuilder) iterator.next();
071                String namespace =  builder.getSchemaNamespace();
072                namespaceToBuilderMap.put(namespace, builder);
073            }
074    
075        }
076    
077        public String getDefaultNamespace() {
078            return defaultNamespace;
079        }
080    
081        public void setDefaultNamespace(String defaultNamespace) {
082            this.defaultNamespace = defaultNamespace;
083        }
084    
085        public Module createModule(File plan, JarFile moduleFile, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
086            String namespace;
087            if (plan == null) {
088                namespace = defaultNamespace;
089            } else {
090                namespace = getNamespaceFromPlan(plan);
091            }
092            ModuleBuilder builder = getBuilderFromNamespace(namespace);
093            if (builder != null) {
094                return builder.createModule(plan, moduleFile, naming, idBuilder);
095            } else {
096                return null;
097            }
098        }
099    
100        private String getNamespaceFromPlan(Object plan) throws DeploymentException {
101            XmlObject xmlObject;
102            if (plan instanceof File) {
103                try {
104                    xmlObject = XmlBeansUtil.parse(((File) plan).toURL(), getClass().getClassLoader());
105                } catch (IOException e) {
106                    throw new DeploymentException("Could not read plan file", e);
107                } catch (XmlException e) {
108                    throw new DeploymentException("Plan file does not contain well formed xml", e);
109                }
110            } else if (plan instanceof XmlObject) {
111                xmlObject = (XmlObject) plan;
112            } else {
113                return defaultNamespace;
114            }
115            XmlCursor cursor = xmlObject.newCursor();
116            try {
117                while (cursor.hasNextToken()){
118                    if (cursor.isStart()) {
119                        return cursor.getName().getNamespaceURI();
120                    }
121                    cursor.toNextToken();
122                }
123            } finally {
124                cursor.dispose();
125            }
126            throw new DeploymentException("Cannot find namespace in xmlObject: " + xmlObject.xmlText());
127        }
128    
129        private ModuleBuilder getBuilderFromNamespace(String namespace) {
130            ModuleBuilder builder = (ModuleBuilder) namespaceToBuilderMap.get(namespace);
131            if (builder == null) {
132                builder = (ModuleBuilder) namespaceToBuilderMap.get(defaultNamespace);
133            }
134            if (builder == null && namespaceToBuilderMap.size() == 1) {
135                builder = (ModuleBuilder) namespaceToBuilderMap.values().iterator().next();
136            }
137            return builder;
138        }
139    
140        public Module createModule(Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, Environment environment, Object moduleContextInfo, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
141            String namespace = getNamespaceFromPlan(plan);
142            ModuleBuilder builder = getBuilderFromNamespace(namespace);
143            if (builder != null) {
144                return builder.createModule(plan, moduleFile, targetPath, specDDUrl, environment, moduleContextInfo, earName, naming, idBuilder);
145            } else {
146                return null;
147            }
148        }
149    
150        public void installModule(JarFile earFile, EARContext earContext, Module module, Collection configurationStores, ConfigurationStore targetConfigurationStore, Collection repositories) throws DeploymentException {
151            String namespace = module.getNamespace();
152            ModuleBuilder builder = getBuilderFromNamespace(namespace);
153            builder.installModule(earFile, earContext, module, configurationStores, targetConfigurationStore, repositories);
154        }
155    
156        public void initContext(EARContext earContext, Module module, ClassLoader cl) throws DeploymentException {
157            String namespace = module.getNamespace();
158            ModuleBuilder builder = getBuilderFromNamespace(namespace);
159            builder.initContext(earContext, module, cl);
160        }
161    
162        public void addGBeans(EARContext earContext, Module module, ClassLoader cl, Collection repositories) throws DeploymentException {
163            String namespace = module.getNamespace();
164            ModuleBuilder builder = getBuilderFromNamespace(namespace);
165            builder.addGBeans(earContext, module, cl, repositories);
166        }
167    
168        public String getSchemaNamespace() {
169            return null;
170        }
171    
172        public static final GBeanInfo GBEAN_INFO;
173    
174        static {
175            GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(SwitchingModuleBuilder.class, NameFactory.MODULE_BUILDER);
176            infoBuilder.addAttribute("defaultNamespace", String.class, true, true);
177            infoBuilder.addReference("ModuleBuilders", ModuleBuilder.class, NameFactory.MODULE_BUILDER);
178            infoBuilder.addInterface(ModuleBuilder.class);
179    
180            infoBuilder.setConstructor(new String[] {"ModuleBuilders"});
181            GBEAN_INFO = infoBuilder.getBeanInfo();
182        }
183    
184        public static GBeanInfo getGBeanInfo() {
185            return GBEAN_INFO;
186        }
187    }