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.deployment.xmlbeans;
019    
020    import java.util.Map;
021    import java.util.HashMap;
022    import java.util.ArrayList;
023    import java.util.Collection;
024    import java.util.Iterator;
025    import java.util.List;
026    import java.io.File;
027    import java.io.IOException;
028    import java.io.InputStream;
029    import java.net.URL;
030    
031    import javax.xml.namespace.QName;
032    
033    import org.w3c.dom.Element;
034    import org.apache.xmlbeans.XmlOptions;
035    import org.apache.xmlbeans.XmlException;
036    import org.apache.xmlbeans.XmlObject;
037    import org.apache.xmlbeans.SchemaTypeLoader;
038    import org.apache.xmlbeans.SchemaType;
039    import org.apache.xmlbeans.QNameSet;
040    import org.apache.xmlbeans.XmlValidationError;
041    
042    /**
043     * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
044     */
045    public class XmlBeansUtil {
046        private static final Map NAMESPACE_UPDATES = new HashMap();
047        //TODO thread safe? conncurrentReaderMap?
048        private static final Map substitutionGroups = new HashMap();
049        private static final XmlObject[] NO_ELEMENTS = new XmlObject[]{};
050    
051        static {
052            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-client", "http://geronimo.apache.org/xml/ns/j2ee/application-client-1.2");
053            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-client-1.1", "http://geronimo.apache.org/xml/ns/j2ee/application-client-1.2");
054            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application", "http://geronimo.apache.org/xml/ns/j2ee/application-1.2");
055            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-1.1", "http://geronimo.apache.org/xml/ns/j2ee/application-1.2");
056            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/deployment", "http://geronimo.apache.org/xml/ns/deployment-1.2");
057            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/deployment-1.1", "http://geronimo.apache.org/xml/ns/deployment-1.2");
058            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/connector", "http://geronimo.apache.org/xml/ns/j2ee/connector-1.2");
059            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/connector-1.1", "http://geronimo.apache.org/xml/ns/j2ee/connector-1.2");
060            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/deployment/javabean", "http://geronimo.apache.org/xml/ns/deployment/javabean-1.0");
061            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/loginconfig", "http://geronimo.apache.org/xml/ns/loginconfig-1.2");
062            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/loginconfig-1.1", "http://geronimo.apache.org/xml/ns/loginconfig-1.2");
063            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/naming", "http://geronimo.apache.org/xml/ns/naming-1.2");
064            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/naming-1.1", "http://geronimo.apache.org/xml/ns/naming-1.2");
065            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/security", "http://geronimo.apache.org/xml/ns/security-1.2");
066            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/security-1.1", "http://geronimo.apache.org/xml/ns/security-1.2");
067            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web", "http://geronimo.apache.org/xml/ns/j2ee/web-1.2");
068            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web-1.1", "http://geronimo.apache.org/xml/ns/j2ee/web-1.2");
069            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/jetty", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.2");
070            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.1", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.2");
071            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/jetty/config", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty/config-1.0");
072            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/tomcat", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.2");
073            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.1", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.2");
074            NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/tomcat/config", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat/config-1.0");
075            NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/openejb-jar", "http://openejb.apache.org/xml/ns/openejb-jar-2.2");
076            NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/openejb-jar-2.1", "http://openejb.apache.org/xml/ns/openejb-jar-2.2");
077            NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/openejb-jar-2.2", "http://openejb.apache.org/xml/ns/openejb-jar-2.2");
078            NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/pkgen", "http://openejb.apache.org/xml/ns/pkgen-2.1");
079            NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/pkgen-2.0", "http://openejb.apache.org/xml/ns/pkgen-2.1");
080            NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/corba-css-config_1_0", "http://openejb.apache.org/xml/ns/corba-css-config-2.1");
081            NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/corba-css-config-2.0", "http://openejb.apache.org/xml/ns/corba-css-config-2.1");
082            NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/corba-tss-config_1_0", "http://openejb.apache.org/xml/ns/corba-tss-config-2.1");
083            NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/corba-tss-config-2.0", "http://openejb.apache.org/xml/ns/corba-tss-config-2.1");
084            NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/corba-tss-config-2.1", "http://openejb.apache.org/xml/ns/corba-tss-config-2.1");
085        }
086    
087        private XmlBeansUtil() {
088        }
089    
090    
091        public static XmlObject parse(File file) throws IOException, XmlException {
092            ArrayList errors = new ArrayList();
093            XmlObject parsed = XmlObject.Factory.parse(file, createXmlOptions(errors));
094            if (errors.size() != 0) {
095                throw new XmlException(errors.toArray().toString());
096            }
097            return parsed;
098        }
099    
100        public static XmlObject parse(URL url, ClassLoader cl) throws IOException, XmlException {
101            ArrayList errors = new ArrayList();
102            Thread currentThread = Thread.currentThread();
103            ClassLoader oldcl = currentThread.getContextClassLoader();
104            currentThread.setContextClassLoader(cl);
105            XmlObject parsed;
106            try {
107                parsed = XmlObject.Factory.parse(url, createXmlOptions(errors));
108            } finally {
109                currentThread.setContextClassLoader(oldcl);
110            }
111            if (errors.size() != 0) {
112                throw new XmlException(errors.toArray().toString());
113            }
114            return parsed;
115        }
116    
117        public static XmlObject parse(InputStream is) throws IOException, XmlException {
118            ArrayList errors = new ArrayList();
119            XmlObject parsed = XmlObject.Factory.parse(is, createXmlOptions(errors));
120            if (errors.size() != 0) {
121                throw new XmlException(errors.toArray().toString());
122            }
123            return parsed;
124        }
125    
126        public static XmlObject parse(String xml) throws XmlException {
127            ArrayList errors = new ArrayList();
128            XmlObject parsed = XmlObject.Factory.parse(xml, createXmlOptions(errors));
129            if (errors.size() != 0) {
130                throw new XmlException(errors.toArray().toString());
131            }
132            return parsed;
133        }
134    
135        public static XmlObject parse(Element element) throws XmlException {
136            ArrayList errors = new ArrayList();
137            XmlObject parsed = XmlObject.Factory.parse(element, createXmlOptions(errors));
138            if (errors.size() != 0) {
139                throw new XmlException(errors.toArray().toString());
140            }
141            return parsed;
142        }
143    
144        public static XmlOptions createXmlOptions(Collection errors) {
145            XmlOptions options = new XmlOptions();
146            options.setLoadLineNumbers();
147            options.setErrorListener(errors);
148            options.setLoadSubstituteNamespaces(NAMESPACE_UPDATES);
149            return options;
150        }
151    
152        public static void registerSubstitutionGroupElements(QName substitutionGroup, QNameSet substitutions) {
153            QNameSet oldSubstitutions = (QNameSet) substitutionGroups.get(substitutionGroup);
154            if (oldSubstitutions != null) {
155                substitutions = oldSubstitutions.union(substitutions);
156            }
157            substitutionGroups.put(substitutionGroup, substitutions);
158        }
159    
160        public static void unregisterSubstitutionGroupElements(QName substitutionGroup, QNameSet substitutions) {
161            QNameSet oldSubstitutions = (QNameSet) substitutionGroups.get(substitutionGroup);
162            if (oldSubstitutions != null && substitutions != null) {
163                QNameSet difference = oldSubstitutions.intersect(substitutions.inverse());
164                substitutionGroups.put(substitutionGroup, difference);
165            }
166        }
167    
168        public static QNameSet getQNameSetForSubstitutionGroup(QName substitutionGroup) {
169            return (QNameSet) substitutionGroups.get(substitutionGroup);
170        }
171    
172        public static XmlObject[] selectSubstitutionGroupElements(QName substitutionGroup, XmlObject container) {
173            QNameSet substitutionGroupMembers = getQNameSetForSubstitutionGroup(substitutionGroup);
174            if (substitutionGroupMembers == null) {
175                return NO_ELEMENTS;
176            }
177            return container.selectChildren(substitutionGroupMembers);
178        }
179    
180        public static void validateDD(XmlObject dd) throws XmlException {
181            XmlOptions xmlOptions = new XmlOptions();
182            xmlOptions.setLoadLineNumbers();
183            Collection errors = new ArrayList();
184            xmlOptions.setErrorListener(errors);
185            try {
186                if (!dd.validate(xmlOptions)) {
187    
188                    for (Iterator iterator = errors.iterator(); iterator.hasNext();) {
189                        Object o = iterator.next();
190                        if (o instanceof XmlValidationError) {
191                            XmlValidationError validationError = (XmlValidationError) o;
192                            List expected = validationError.getExpectedQNames();
193                            QName actual = validationError.getOffendingQName();
194                            if (expected != null) {
195                                for (Iterator iterator1 = expected.iterator(); iterator1.hasNext();) {
196                                    QName expectedQName = (QName) iterator1.next();
197                                    QNameSet substitutions = getQNameSetForSubstitutionGroup(expectedQName);
198                                    if (substitutions != null && substitutions.contains(actual)) {
199                                        iterator.remove();
200                                        break;
201                                    }
202                                }
203                            }
204                        }
205                    }
206    
207                    if (!errors.isEmpty()) {
208                        throw new XmlException("Invalid deployment descriptor: " + errors + "\nDescriptor: " + dd.toString(), null, errors);
209                    }
210                }
211            } catch (NullPointerException e) {
212                //ignore
213            }
214    //        System.out.println("descriptor: " + dd.toString());
215        }
216    }