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