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 }