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