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 018 package org.apache.geronimo.schema; 019 020 import java.util.HashMap; 021 import java.util.Map; 022 023 import javax.xml.namespace.QName; 024 025 import org.apache.geronimo.xbeans.javaee.ApplicationClientDocument; 026 import org.apache.geronimo.xbeans.javaee.ApplicationDocument; 027 //import org.apache.geronimo.xbeans.javaee.ConnectorDocument; 028 import org.apache.geronimo.xbeans.javaee.EjbJarDocument; 029 import org.apache.geronimo.xbeans.javaee.WebAppDocument; 030 import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil; 031 import org.apache.xmlbeans.SchemaType; 032 import org.apache.xmlbeans.XmlCursor; 033 import org.apache.xmlbeans.XmlDocumentProperties; 034 import org.apache.xmlbeans.XmlException; 035 import org.apache.xmlbeans.XmlObject; 036 037 /** 038 * @version $Rev: 557762 $ $Date: 2007-07-19 16:18:13 -0400 (Thu, 19 Jul 2007) $ 039 */ 040 public class SchemaConversionUtils { 041 public static final String J2EE_NAMESPACE = "http://java.sun.com/xml/ns/j2ee"; 042 public static final String JAVAEE_NAMESPACE = "http://java.sun.com/xml/ns/javaee"; 043 044 static final String GERONIMO_NAMING_NAMESPACE = "http://geronimo.apache.org/xml/ns/naming-1.2"; 045 private static final String GERONIMO_SECURITY_NAMESPACE = "http://geronimo.apache.org/xml/ns/security-2.0"; 046 private static final String GERONIMO_SERVICE_NAMESPACE = "http://geronimo.apache.org/xml/ns/deployment-1.2"; 047 private static final String JPA_PERSISTENCE_NAMESPACE = "http://java.sun.com/xml/ns/persistence"; 048 049 private static final Map<String, ElementConverter> GERONIMO_SCHEMA_CONVERSIONS = new HashMap<String, ElementConverter>(); 050 051 static { 052 053 GERONIMO_SCHEMA_CONVERSIONS.put("gbean-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE)); 054 GERONIMO_SCHEMA_CONVERSIONS.put("ejb-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE)); 055 GERONIMO_SCHEMA_CONVERSIONS.put("ejb-local-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE)); 056 GERONIMO_SCHEMA_CONVERSIONS.put("service-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE)); 057 GERONIMO_SCHEMA_CONVERSIONS.put("resource-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE)); 058 GERONIMO_SCHEMA_CONVERSIONS.put("resource-env-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE)); 059 GERONIMO_SCHEMA_CONVERSIONS.put("message-destination", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE)); 060 GERONIMO_SCHEMA_CONVERSIONS.put("cmp-connection-factory", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE)); 061 GERONIMO_SCHEMA_CONVERSIONS.put("workmanager", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE)); 062 GERONIMO_SCHEMA_CONVERSIONS.put("resource-adapter", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE)); 063 GERONIMO_SCHEMA_CONVERSIONS.put("web-container", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE)); 064 065 GERONIMO_SCHEMA_CONVERSIONS.put("security", new SecurityElementConverter()); 066 GERONIMO_SCHEMA_CONVERSIONS.put("default-subject", new NamespaceElementConverter(GERONIMO_SECURITY_NAMESPACE)); 067 068 GERONIMO_SCHEMA_CONVERSIONS.put("gbean", new GBeanElementConverter()); 069 GERONIMO_SCHEMA_CONVERSIONS.put("environment", new NamespaceElementConverter(GERONIMO_SERVICE_NAMESPACE)); 070 GERONIMO_SCHEMA_CONVERSIONS.put("client-environment", new NamespaceElementConverter(GERONIMO_SERVICE_NAMESPACE)); 071 GERONIMO_SCHEMA_CONVERSIONS.put("server-environment", new NamespaceElementConverter(GERONIMO_SERVICE_NAMESPACE)); 072 GERONIMO_SCHEMA_CONVERSIONS.put("persistence", new NamespaceElementConverter(JPA_PERSISTENCE_NAMESPACE)); 073 } 074 075 private SchemaConversionUtils() { 076 } 077 078 public static void registerNamespaceConversions(Map conversions) { 079 GERONIMO_SCHEMA_CONVERSIONS.putAll(conversions); 080 } 081 082 public static void convertToGeronimoSubSchemas(XmlCursor cursor) { 083 cursor.toStartDoc(); 084 XmlCursor end = cursor.newCursor(); 085 try { 086 while (cursor.hasNextToken()) { 087 convertSingleElementToGeronimoSubSchemas(cursor, end); 088 cursor.toNextToken(); 089 } 090 } finally { 091 end.dispose(); 092 } 093 } 094 095 public static boolean convertSingleElementToGeronimoSubSchemas(XmlCursor cursor, XmlCursor end) { 096 if (cursor.isStart()) { 097 String localName = cursor.getName().getLocalPart(); 098 ElementConverter converter = (ElementConverter) GERONIMO_SCHEMA_CONVERSIONS.get(localName); 099 if (converter != null) { 100 converter.convertElement(cursor, end); 101 return true; 102 } 103 return false; 104 } 105 //you should only call this method at a start token 106 return false; 107 } 108 109 public static XmlObject fixGeronimoSchema(XmlObject rawPlan, QName desiredElement, SchemaType desiredType) throws XmlException { 110 XmlCursor cursor = rawPlan.newCursor(); 111 try { 112 if (findNestedElement(cursor, desiredElement)) { 113 cursor.push(); 114 convertToGeronimoSubSchemas(cursor); 115 cursor.pop(); 116 XmlObject temp = cursor.getObject(); 117 118 XmlObject result = temp.changeType(desiredType); 119 if (result == null || result.schemaType() != desiredType) { 120 result = temp.copy().changeType(desiredType); 121 } 122 XmlBeansUtil.validateDD(result); 123 return result; 124 } else { 125 return null; 126 } 127 } finally { 128 cursor.dispose(); 129 } 130 } 131 132 public static XmlObject getNestedObject(XmlObject xmlObject, QName desiredElement) { 133 XmlCursor cursor = xmlObject.newCursor(); 134 try { 135 if (findNestedElement(cursor, desiredElement)) { 136 XmlObject child = cursor.getObject(); 137 //The copy seems to be needed to make the type change work for some documents! 138 return child.copy(); 139 } 140 } finally { 141 cursor.dispose(); 142 } 143 throw new IllegalArgumentException("xmlobject did not have desired element: " + desiredElement + "/n" + xmlObject); 144 } 145 146 public static boolean findNestedElement(XmlCursor cursor, QName desiredElement) { 147 while (cursor.hasNextToken()) { 148 if (cursor.isStart()) { 149 QName element = cursor.getName(); 150 if (element.equals(desiredElement)) { 151 return true; 152 } 153 } 154 cursor.toNextToken(); 155 } 156 return false; 157 } 158 159 public static boolean findNestedElement(XmlCursor cursor, String desiredElement) { 160 while (cursor.hasNextToken()) { 161 if (cursor.isStart()) { 162 String element = cursor.getName().getLocalPart(); 163 if (element.equals(desiredElement)) { 164 return true; 165 } 166 } 167 cursor.toNextToken(); 168 } 169 return false; 170 } 171 172 public static XmlObject getNestedObjectAsType(XmlObject xmlObject, QName desiredElement, SchemaType type) { 173 XmlCursor cursor = xmlObject.newCursor(); 174 try { 175 if (findNestedElement(cursor, desiredElement)) { 176 XmlObject child = cursor.getObject(); 177 //The copy seems to be needed to make the type change work for some documents! 178 XmlObject result = child.copy().changeType(type); 179 assert result.schemaType() == type; 180 return result; 181 } 182 } finally { 183 cursor.dispose(); 184 } 185 throw new IllegalArgumentException("xmlobject did not have desired element: " + desiredElement + "\n" + xmlObject); 186 } 187 188 189 public static boolean convertToSchema(XmlCursor cursor, String namespace, String schemaLocationURL, String version) { 190 //remove dtd 191 XmlDocumentProperties xmlDocumentProperties = cursor.documentProperties(); 192 xmlDocumentProperties.remove(XmlDocumentProperties.DOCTYPE_NAME); 193 xmlDocumentProperties.remove(XmlDocumentProperties.DOCTYPE_PUBLIC_ID); 194 xmlDocumentProperties.remove(XmlDocumentProperties.DOCTYPE_SYSTEM_ID); 195 //convert namespace 196 boolean isFirstStart = true; 197 while (cursor.hasNextToken()) { 198 if (cursor.isStart()) { 199 if (namespace.equals(cursor.getName().getNamespaceURI())) { 200 //already has correct schema, exit 201 return false; 202 } 203 cursor.setName(new QName(namespace, cursor.getName().getLocalPart())); 204 cursor.toNextToken(); 205 if (isFirstStart) { 206 cursor.insertNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); 207 cursor.insertAttributeWithValue(new QName("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation", "xsi"), namespace + " " + schemaLocationURL); 208 cursor.insertAttributeWithValue(new QName("version"), version); 209 isFirstStart = false; 210 } 211 } else { 212 cursor.toNextToken(); 213 } 214 } 215 return true; 216 } 217 218 public static boolean convertSchemaVersion (XmlCursor cursor, String namespace, String schemaLocationURL, String version) { 219 boolean isFirstStart = true; 220 221 222 while (cursor.hasNextToken()) { 223 if (cursor.isStart()) { 224 if (isFirstStart) { 225 //HACK to work around digester's difficulty with namespaces 226 if (cursor.getAttributeText(new QName("xmlns")) != null) { 227 cursor.removeAttribute(new QName("xmlns")); 228 } 229 //if we are at the first element in the document, reset the version number ... 230 cursor.setAttributeText(new QName("version"), version); 231 //... and also set the xsi:schemaLocation 232 cursor.setAttributeText(new QName("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation", "xsi"), namespace + " "+schemaLocationURL); 233 isFirstStart = false; 234 } 235 //convert namespace of each starting element 236 cursor.setName(new QName(namespace, cursor.getName().getLocalPart())); 237 cursor.toNextToken(); 238 239 } else { 240 cursor.toNextToken(); 241 } 242 } 243 244 245 return true; 246 } 247 248 /** 249 * Reorders elements to match descriptionGroup 250 * 251 * @param namespace 252 * @param cursor XmlCursor positioned at first element of "group" to be reordered 253 */ 254 public static void convertToDescriptionGroup(String namespace, XmlCursor cursor, XmlCursor moveable) { 255 moveable.toCursor(cursor); 256 moveElements("description", namespace, moveable, cursor); 257 moveElements("display-name", namespace, moveable, cursor); 258 moveElements("icon", namespace, moveable, cursor); 259 } 260 261 public static void convertToTldTag(String namespace, XmlCursor cursor, XmlCursor moveable) { 262 moveable.toCursor(cursor); 263 moveElements("description", namespace, moveable, cursor); 264 moveElements("display-name", namespace, moveable, cursor); 265 moveElements("icon", namespace, moveable, cursor); 266 moveElements("name", namespace, moveable, cursor); 267 moveElements("tag-class", namespace, moveable, cursor); 268 moveElements("tei-class", namespace, moveable, cursor); 269 moveElements("body-content", namespace, moveable, cursor); 270 moveElements("variable", namespace, moveable, cursor); 271 moveElements("attribute", namespace, moveable, cursor); 272 moveElements("dynamic-attributes", namespace, moveable, cursor); 273 moveElements("example", namespace, moveable, cursor); 274 moveElements("tag-extension", namespace, moveable, cursor); 275 } 276 277 public static void convertToTldAttribute(String namespace, XmlCursor cursor, XmlCursor moveable) { 278 moveable.toCursor(cursor); 279 moveElements("description", namespace, moveable, cursor); 280 moveElements("name", namespace, moveable, cursor); 281 moveElements("required", namespace, moveable, cursor); 282 moveElements("rtexprvalue", namespace, moveable, cursor); 283 moveElements("type", namespace, moveable, cursor); 284 moveElements("fragment", namespace, moveable, cursor); 285 } 286 287 public static void convertToTldInitParam(String namespace, XmlCursor cursor, XmlCursor moveable) { 288 moveable.toCursor(cursor); 289 moveElements("description", namespace, moveable, cursor); 290 moveElements("param-name", namespace, moveable, cursor); 291 moveElements("param-value", namespace, moveable, cursor); 292 } 293 294 public static void convertToTldValidator(String namespace, XmlCursor cursor, XmlCursor moveable) { 295 moveable.toCursor(cursor); 296 moveElements("description", namespace, moveable, cursor); 297 moveElements("validator-class", namespace, moveable, cursor); 298 moveElements("init-param", namespace, moveable, cursor); 299 } 300 301 public static void convertToTldVariable(String namespace, XmlCursor cursor, XmlCursor moveable) { 302 moveable.toCursor(cursor); 303 moveElements("description", namespace, moveable, cursor); 304 moveElements("name-given", namespace, moveable, cursor); 305 moveElements("name-from-attribute", namespace, moveable, cursor); 306 moveElements("variable-class", namespace, moveable, cursor); 307 moveElements("declare", namespace, moveable, cursor); 308 moveElements("scope", namespace, moveable, cursor); 309 } 310 311 public static void convertToJNDIEnvironmentRefsGroup(String namespace, XmlCursor cursor, XmlCursor moveable) { 312 moveElements("env-entry", namespace, moveable, cursor); 313 moveElements("ejb-ref", namespace, moveable, cursor); 314 moveElements("ejb-local-ref", namespace, moveable, cursor); 315 moveElements("resource-ref", namespace, moveable, cursor); 316 moveElements("resource-env-ref", namespace, moveable, cursor); 317 moveElements("message-destination-ref", namespace, moveable, cursor); 318 if (cursor.toPrevSibling()) { 319 do { 320 String name = cursor.getName().getLocalPart(); 321 if ("env-entry".equals(name)) { 322 cursor.push(); 323 cursor.toFirstChild(); 324 convertToDescriptionGroup(namespace, cursor, moveable); 325 convertToEnvEntryGroup(namespace, cursor, moveable); 326 cursor.pop(); 327 } 328 } while (cursor.toPrevSibling()); 329 } 330 } 331 332 public static void convertToEnvEntryGroup(String namespace, XmlCursor cursor, XmlCursor moveable) { 333 moveElements("env-entry-name", namespace, moveable, cursor); 334 moveElements("env-entry-type", namespace, moveable, cursor); 335 moveElements("env-entry-value", namespace, moveable, cursor); 336 } 337 338 private static void moveElements(String localName, String namespace, XmlCursor moveable, XmlCursor toHere) { 339 QName name = new QName(namespace, localName); 340 //skip elements already in the correct order. 341 while (name.equals(toHere.getName()) && toHere.toNextSibling()) { 342 } 343 moveable.toCursor(toHere); 344 while (moveable.toNextSibling(name)) { 345 moveable.moveXml(toHere); 346 } 347 } 348 349 }