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 }