View Javadoc

1   /**
2    *
3    *  Licensed to the Apache Software Foundation (ASF) under one or more
4    *  contributor license agreements.  See the NOTICE file distributed with
5    *  this work for additional information regarding copyright ownership.
6    *  The ASF licenses this file to You under the Apache License, Version 2.0
7    *  (the "License"); you may not use this file except in compliance with
8    *  the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  
19  package org.apache.geronimo.schema;
20  
21  import java.util.HashMap;
22  import java.util.Map;
23  
24  import javax.xml.namespace.QName;
25  
26  import org.apache.geronimo.xbeans.j2ee.ApplicationClientDocument;
27  import org.apache.geronimo.xbeans.j2ee.ApplicationDocument;
28  import org.apache.geronimo.xbeans.j2ee.ConnectorDocument;
29  import org.apache.geronimo.xbeans.j2ee.EjbJarDocument;
30  import org.apache.geronimo.xbeans.j2ee.WebAppDocument;
31  import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
32  import org.apache.xmlbeans.SchemaType;
33  import org.apache.xmlbeans.XmlCursor;
34  import org.apache.xmlbeans.XmlDocumentProperties;
35  import org.apache.xmlbeans.XmlException;
36  import org.apache.xmlbeans.XmlObject;
37  
38  /**
39   * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
40   */
41  public class SchemaConversionUtils {
42      public static final String J2EE_NAMESPACE = "http://java.sun.com/xml/ns/j2ee";
43      public static final String JAVAEE_NAMESPACE = "http://java.sun.com/xml/ns/javaee";
44  
45      static final String GERONIMO_NAMING_NAMESPACE = "http://geronimo.apache.org/xml/ns/naming-1.2";
46      private static final String GERONIMO_SECURITY_NAMESPACE = "http://geronimo.apache.org/xml/ns/security-1.2";
47      private static final String GERONIMO_SERVICE_NAMESPACE = "http://geronimo.apache.org/xml/ns/deployment-1.2";
48  
49      private static final Map GERONIMO_SCHEMA_CONVERSIONS = new HashMap();
50  
51      static {
52  
53          GERONIMO_SCHEMA_CONVERSIONS.put("gbean-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
54          GERONIMO_SCHEMA_CONVERSIONS.put("ejb-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
55          GERONIMO_SCHEMA_CONVERSIONS.put("ejb-local-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
56          GERONIMO_SCHEMA_CONVERSIONS.put("service-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
57          GERONIMO_SCHEMA_CONVERSIONS.put("resource-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
58          GERONIMO_SCHEMA_CONVERSIONS.put("resource-env-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
59          GERONIMO_SCHEMA_CONVERSIONS.put("message-destination", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
60          GERONIMO_SCHEMA_CONVERSIONS.put("cmp-connection-factory", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
61          GERONIMO_SCHEMA_CONVERSIONS.put("workmanager", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
62          GERONIMO_SCHEMA_CONVERSIONS.put("resource-adapter", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
63          GERONIMO_SCHEMA_CONVERSIONS.put("web-container", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
64  
65          GERONIMO_SCHEMA_CONVERSIONS.put("security", new SecurityElementConverter());
66          GERONIMO_SCHEMA_CONVERSIONS.put("default-principal", new NamespaceElementConverter(GERONIMO_SECURITY_NAMESPACE));
67  
68          GERONIMO_SCHEMA_CONVERSIONS.put("gbean", new GBeanElementConverter());
69          GERONIMO_SCHEMA_CONVERSIONS.put("environment", new NamespaceElementConverter(GERONIMO_SERVICE_NAMESPACE));
70          GERONIMO_SCHEMA_CONVERSIONS.put("client-environment", new NamespaceElementConverter(GERONIMO_SERVICE_NAMESPACE));
71          GERONIMO_SCHEMA_CONVERSIONS.put("server-environment", new NamespaceElementConverter(GERONIMO_SERVICE_NAMESPACE));
72      }
73  
74      private SchemaConversionUtils() {
75      }
76  
77      public static void registerNamespaceConversions(Map conversions) {
78          GERONIMO_SCHEMA_CONVERSIONS.putAll(conversions);
79      }
80  
81      public static void convertToGeronimoSubSchemas(XmlCursor cursor) {
82          cursor.toStartDoc();
83          XmlCursor end = cursor.newCursor();
84          try {
85              while (cursor.hasNextToken()) {
86                  convertSingleElementToGeronimoSubSchemas(cursor, end);
87                  cursor.toNextToken();
88              }
89          } finally {
90              end.dispose();
91          }
92      }
93  
94      public static boolean convertSingleElementToGeronimoSubSchemas(XmlCursor cursor, XmlCursor end) {
95          if (cursor.isStart()) {
96              String localName = cursor.getName().getLocalPart();
97              ElementConverter converter = (ElementConverter) GERONIMO_SCHEMA_CONVERSIONS.get(localName);
98              if (converter != null) {
99                  converter.convertElement(cursor, end);
100                 return true;
101             }
102             return false;
103         }
104         //you should only call this method at a start token
105         return false;
106     }
107 
108     public static XmlObject fixGeronimoSchema(XmlObject rawPlan, QName desiredElement, SchemaType desiredType) throws XmlException {
109         XmlCursor cursor = rawPlan.newCursor();
110         try {
111             if (findNestedElement(cursor, desiredElement)) {
112                 cursor.push();
113                 convertToGeronimoSubSchemas(cursor);
114                 cursor.pop();
115                 XmlObject temp = cursor.getObject();
116 
117                 XmlObject result = temp.changeType(desiredType);
118                 if (result == null || result.schemaType() != desiredType) {
119                     result = temp.copy().changeType(desiredType);
120                 }
121                 XmlBeansUtil.validateDD(result);
122                 return result;
123             } else {
124                 return null;
125             }
126         } finally {
127             cursor.dispose();
128         }
129     }
130 
131     public static XmlObject getNestedObject(XmlObject xmlObject, QName desiredElement) {
132         XmlCursor cursor = xmlObject.newCursor();
133         try {
134             if (findNestedElement(cursor, desiredElement)) {
135                 XmlObject child = cursor.getObject();
136                 //The copy seems to be needed to make the type change work for some documents!
137                 return child.copy();
138             }
139         } finally {
140             cursor.dispose();
141         }
142         throw new IllegalArgumentException("xmlobject did not have desired element: " + desiredElement + "/n" + xmlObject);
143     }
144 
145     public static boolean findNestedElement(XmlCursor cursor, QName desiredElement) {
146         while (cursor.hasNextToken()) {
147             if (cursor.isStart()) {
148                 QName element = cursor.getName();
149                 if (element.equals(desiredElement)) {
150                     return true;
151                 }
152             }
153             cursor.toNextToken();
154         }
155         return false;
156     }
157 
158     public static boolean findNestedElement(XmlCursor cursor, String desiredElement) {
159         while (cursor.hasNextToken()) {
160             if (cursor.isStart()) {
161                 String element = cursor.getName().getLocalPart();
162                 if (element.equals(desiredElement)) {
163                     return true;
164                 }
165             }
166             cursor.toNextToken();
167         }
168         return false;
169     }
170 
171     public static XmlObject getNestedObjectAsType(XmlObject xmlObject, QName desiredElement, SchemaType type) {
172         XmlCursor cursor = xmlObject.newCursor();
173         try {
174             if (findNestedElement(cursor, desiredElement)) {
175                 XmlObject child = cursor.getObject();
176                 //The copy seems to be needed to make the type change work for some documents!
177                 XmlObject result = child.copy().changeType(type);
178                 assert result.schemaType() == type;
179                 return result;
180             }
181         } finally {
182             cursor.dispose();
183         }
184         throw new IllegalArgumentException("xmlobject did not have desired element: " + desiredElement + "\n" + xmlObject);
185     }
186 
187 
188     public static boolean convertToSchema(XmlCursor cursor, String namespace, String schemaLocationURL, String version) {
189         //remove dtd
190         XmlDocumentProperties xmlDocumentProperties = cursor.documentProperties();
191         xmlDocumentProperties.remove(XmlDocumentProperties.DOCTYPE_NAME);
192         xmlDocumentProperties.remove(XmlDocumentProperties.DOCTYPE_PUBLIC_ID);
193         xmlDocumentProperties.remove(XmlDocumentProperties.DOCTYPE_SYSTEM_ID);
194         //convert namespace
195         boolean isFirstStart = true;
196         while (cursor.hasNextToken()) {
197             if (cursor.isStart()) {
198                 if (namespace.equals(cursor.getName().getNamespaceURI())) {
199                     //already has correct schema, exit
200                     return false;
201                 }
202                 cursor.setName(new QName(namespace, cursor.getName().getLocalPart()));
203                 cursor.toNextToken();
204                 if (isFirstStart) {
205                     cursor.insertNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
206                     cursor.insertAttributeWithValue(new QName("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation", "xsi"), namespace + schemaLocationURL);
207                     cursor.insertAttributeWithValue(new QName("version"), version);
208                     isFirstStart = false;
209                 }
210             } else {
211                 cursor.toNextToken();
212             }
213         }
214         return true;
215     }
216 
217     public static boolean convertSchemaVersion (XmlCursor cursor, String namespace, String schemaLocationURL, String version) {
218         boolean isFirstStart = true;
219 
220 
221         while (cursor.hasNextToken()) {
222             if (cursor.isStart()) {
223                 //convert namespace of each starting element
224                 cursor.setName(new QName(namespace, cursor.getName().getLocalPart()));
225                 if (isFirstStart) {
226                     //if we are at the first element in the document, reset the version number ...
227                     cursor.setAttributeText(new QName("version"), version);
228                     //... and also set the xsi:schemaLocation
229                     cursor.setAttributeText(new QName("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation", "xsi"), namespace + "  "+schemaLocationURL);
230                     isFirstStart = false;
231                 }
232                 cursor.toNextToken();
233 
234             } else {
235                 cursor.toNextToken();
236             }
237         }
238 
239 
240         return true;
241     }
242 
243     /**
244      * Reorders elements to match descriptionGroup
245      *
246      * @param namespace
247      * @param cursor XmlCursor positioned at first element of "group" to be reordered
248      */
249     public static void convertToDescriptionGroup(String namespace, XmlCursor cursor, XmlCursor moveable) {
250         moveable.toCursor(cursor);
251         moveElements("description", namespace, moveable, cursor);
252         moveElements("display-name", namespace, moveable, cursor);
253         moveElements("icon", namespace, moveable, cursor);
254     }
255 
256     public static void convertToJNDIEnvironmentRefsGroup(String namespace, XmlCursor cursor, XmlCursor moveable) {
257         moveElements("env-entry", namespace, moveable, cursor);
258         moveElements("ejb-ref", namespace, moveable, cursor);
259         moveElements("ejb-local-ref", namespace, moveable, cursor);
260         moveElements("resource-ref", namespace, moveable, cursor);
261         moveElements("resource-env-ref", namespace, moveable, cursor);
262         moveElements("message-destination-ref", namespace, moveable, cursor);
263         if (cursor.toPrevSibling()) {
264             do {
265                 String name = cursor.getName().getLocalPart();
266                 if ("env-entry".equals(name)) {
267                     cursor.push();
268                     cursor.toFirstChild();
269                     convertToDescriptionGroup(namespace, cursor, moveable);
270                     convertToEnvEntryGroup(namespace, cursor, moveable);
271                     cursor.pop();
272                 }
273             } while (cursor.toPrevSibling());
274         }
275     }
276 
277     public static void convertToEnvEntryGroup(String namespace, XmlCursor cursor, XmlCursor moveable) {
278         moveElements("env-entry-name", namespace, moveable, cursor);
279         moveElements("env-entry-type", namespace, moveable, cursor);
280         moveElements("env-entry-value", namespace, moveable, cursor);
281     }
282 
283     private static void moveElements(String localName, String namespace, XmlCursor moveable, XmlCursor toHere) {
284         QName name = new QName(namespace, localName);
285         //skip elements already in the correct order.
286         while (name.equals(toHere.getName()) && toHere.toNextSibling()) {
287         }
288         moveable.toCursor(toHere);
289         while (moveable.toNextSibling(name)) {
290             moveable.moveXml(toHere);
291         }
292     }
293 
294 }