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: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 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 private XmlBeansUtil() { 050 } 051 052 public static void registerNamespaceUpdates(Map<String, String> updates) { 053 NAMESPACE_UPDATES.putAll(updates); 054 } 055 056 public static void unregisterNamespaceUpdates(Map<String, String> updates) { 057 NAMESPACE_UPDATES.entrySet().removeAll(updates.entrySet()); 058 } 059 060 public static XmlObject parse(File file) throws IOException, XmlException { 061 ArrayList errors = new ArrayList(); 062 XmlObject parsed = XmlObject.Factory.parse(file, createXmlOptions(errors)); 063 if (errors.size() != 0) { 064 throw new XmlException(errors.toArray().toString()); 065 } 066 return parsed; 067 } 068 069 public static XmlObject parse(URL url, ClassLoader cl) throws IOException, XmlException { 070 ArrayList errors = new ArrayList(); 071 Thread currentThread = Thread.currentThread(); 072 ClassLoader oldcl = currentThread.getContextClassLoader(); 073 currentThread.setContextClassLoader(cl); 074 XmlObject parsed; 075 try { 076 parsed = XmlObject.Factory.parse(url, createXmlOptions(errors)); 077 } finally { 078 currentThread.setContextClassLoader(oldcl); 079 } 080 if (errors.size() != 0) { 081 throw new XmlException(errors.toArray().toString()); 082 } 083 return parsed; 084 } 085 086 public static XmlObject parse(InputStream is) throws IOException, XmlException { 087 ArrayList errors = new ArrayList(); 088 XmlObject parsed = XmlObject.Factory.parse(is, createXmlOptions(errors)); 089 if (errors.size() != 0) { 090 throw new XmlException(errors.toArray().toString()); 091 } 092 return parsed; 093 } 094 095 public static XmlObject parse(String xml) throws XmlException { 096 ArrayList errors = new ArrayList(); 097 XmlObject parsed = XmlObject.Factory.parse(xml, createXmlOptions(errors)); 098 if (errors.size() != 0) { 099 throw new XmlException(errors.toArray().toString()); 100 } 101 return parsed; 102 } 103 104 public static XmlObject parse(Element element) throws XmlException { 105 ArrayList errors = new ArrayList(); 106 XmlObject parsed = XmlObject.Factory.parse(element, createXmlOptions(errors)); 107 if (errors.size() != 0) { 108 throw new XmlException(errors.toArray().toString()); 109 } 110 return parsed; 111 } 112 113 public static XmlOptions createXmlOptions(Collection errors) { 114 XmlOptions options = new XmlOptions(); 115 options.setLoadLineNumbers(); 116 options.setErrorListener(errors); 117 options.setLoadSubstituteNamespaces(NAMESPACE_UPDATES); 118 return options; 119 } 120 121 public static void registerSubstitutionGroupElements(QName substitutionGroup, QNameSet substitutions) { 122 QNameSet oldSubstitutions = substitutionGroups.get(substitutionGroup); 123 if (oldSubstitutions != null) { 124 substitutions = oldSubstitutions.union(substitutions); 125 } 126 substitutionGroups.put(substitutionGroup, substitutions); 127 } 128 129 public static void unregisterSubstitutionGroupElements(QName substitutionGroup, QNameSet substitutions) { 130 QNameSet oldSubstitutions = substitutionGroups.get(substitutionGroup); 131 if (oldSubstitutions != null && substitutions != null) { 132 QNameSet difference = oldSubstitutions.intersect(substitutions.inverse()); 133 substitutionGroups.put(substitutionGroup, difference); 134 } 135 } 136 137 public static QNameSet getQNameSetForSubstitutionGroup(QName substitutionGroup) { 138 return substitutionGroups.get(substitutionGroup); 139 } 140 141 public static XmlObject[] selectSubstitutionGroupElements(QName substitutionGroup, XmlObject container) { 142 QNameSet substitutionGroupMembers = getQNameSetForSubstitutionGroup(substitutionGroup); 143 if (substitutionGroupMembers == null) { 144 return NO_ELEMENTS; 145 } 146 return container.selectChildren(substitutionGroupMembers); 147 } 148 149 public static XmlObject typedCopy(XmlObject in, SchemaType type) throws XmlException { 150 XmlObject out = in.copy().changeType(type); 151 validateDD(out); 152 return out; 153 } 154 155 public static void validateDD(XmlObject dd) throws XmlException { 156 XmlOptions xmlOptions = new XmlOptions(); 157 xmlOptions.setLoadLineNumbers(); 158 Collection errors = new ArrayList(); 159 xmlOptions.setErrorListener(errors); 160 try { 161 if (!dd.validate(xmlOptions)) { 162 163 for (Iterator iterator = errors.iterator(); iterator.hasNext();) { 164 Object o = iterator.next(); 165 if (o instanceof XmlValidationError) { 166 XmlValidationError validationError = (XmlValidationError) o; 167 List<QName> expected = validationError.getExpectedQNames(); 168 QName actual = validationError.getOffendingQName(); 169 if (expected != null) { 170 for (QName expectedQName : expected) { 171 QNameSet substitutions = getQNameSetForSubstitutionGroup(expectedQName); 172 if (substitutions != null && substitutions.contains(actual)) { 173 iterator.remove(); 174 break; 175 } 176 } 177 } 178 } 179 } 180 181 if (!errors.isEmpty()) { 182 StringBuffer buf = new StringBuffer("Invalid deployment descriptor: errors:\n\n"); 183 for (Object o: errors) { 184 buf.append(o).append("\n\n"); 185 } 186 buf.append("Descriptor:\n").append(dd.toString()).append("\n"); 187 throw new XmlException(buf.toString(), null, errors); 188 } 189 } 190 } catch (NullPointerException e) { 191 //ignore 192 } catch (AssertionError e) { 193 //ignore. Would be the NPE above if assertions were turned off 194 } 195 // System.out.println("descriptor: " + dd.toString()); 196 } 197 }