View Javadoc

1   /**
2    *
3    * Copyright 2006 The Apache Software Foundation
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package org.apache.geronimo.upgrade;
19  
20  import java.io.InputStream;
21  import java.io.IOException;
22  import java.io.Writer;
23  import java.util.Map;
24  import java.util.HashMap;
25  import java.util.ArrayList;
26  import java.util.Collection;
27  
28  import javax.xml.namespace.QName;
29  import javax.management.ObjectName;
30  import javax.management.MalformedObjectNameException;
31  
32  import org.apache.xmlbeans.XmlObject;
33  import org.apache.xmlbeans.XmlException;
34  import org.apache.xmlbeans.XmlOptions;
35  import org.apache.xmlbeans.XmlCursor;
36  import org.apache.geronimo.kernel.repository.Artifact;
37  import org.apache.geronimo.kernel.repository.Environment;
38  import org.apache.geronimo.kernel.repository.ImportType;
39  import org.apache.geronimo.deployment.xbeans.EnvironmentType;
40  import org.apache.geronimo.deployment.service.EnvironmentBuilder;
41  
42  /**
43   * @version $Rev: 432510 $ $Date: 2006-08-18 00:44:04 -0700 (Fri, 18 Aug 2006) $
44   */
45  public class Upgrade1_0To1_1 {
46  
47      private static final Map NAMESPACE_UPDATES = new HashMap();
48  
49      static {
50          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-client", "http://geronimo.apache.org/xml/ns/j2ee/application-client-1.2");
51          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-client-1.0", "http://geronimo.apache.org/xml/ns/j2ee/application-client-1.2");
52          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-client-1.1", "http://geronimo.apache.org/xml/ns/j2ee/application-client-1.2");
53          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application", "http://geronimo.apache.org/xml/ns/j2ee/application-1.2");
54          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-1.0", "http://geronimo.apache.org/xml/ns/j2ee/application-1.2");
55          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-1.1", "http://geronimo.apache.org/xml/ns/j2ee/application-1.2");
56          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/deployment", "http://geronimo.apache.org/xml/ns/deployment-1.2");
57          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/deployment-1.0", "http://geronimo.apache.org/xml/ns/deployment-1.2");
58          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/deployment-1.1", "http://geronimo.apache.org/xml/ns/deployment-1.2");
59          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/connector", "http://geronimo.apache.org/xml/ns/j2ee/connector-1.2");
60          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/connector-1.0", "http://geronimo.apache.org/xml/ns/j2ee/connector-1.2");
61          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/connector-1.1", "http://geronimo.apache.org/xml/ns/j2ee/connector-1.2");
62          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/deployment/javabean", "http://geronimo.apache.org/xml/ns/deployment/javabean-1.0");
63          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/loginconfig", "http://geronimo.apache.org/xml/ns/loginconfig-1.0");
64          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/loginconfig-1.0", "http://geronimo.apache.org/xml/ns/loginconfig-1.0");
65          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/loginconfig-1.1", "http://geronimo.apache.org/xml/ns/loginconfig-1.0");
66          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/naming", "http://geronimo.apache.org/xml/ns/naming-1.2");
67          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/naming-1.0", "http://geronimo.apache.org/xml/ns/naming-1.2");
68          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/naming-1.1", "http://geronimo.apache.org/xml/ns/naming-1.2");
69          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/security", "http://geronimo.apache.org/xml/ns/security-1.2");
70          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/security-1.0", "http://geronimo.apache.org/xml/ns/security-1.2");
71          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/security-1.1", "http://geronimo.apache.org/xml/ns/security-1.2");
72          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web", "http://geronimo.apache.org/xml/ns/j2ee/web-1.2");
73          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web-1.0", "http://geronimo.apache.org/xml/ns/j2ee/web-1.2");
74          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web-1.1", "http://geronimo.apache.org/xml/ns/j2ee/web-1.2");
75          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web-1.0", "http://geronimo.apache.org/xml/ns/j2ee/web-1.2");
76          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/jetty", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.2");
77          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/jetty-1.0", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.2");
78          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.0", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.2");
79          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.1", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.2");
80          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/jetty/config", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty/config-1.0");
81          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/tomcat", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.2");
82          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/tomcat-1.0", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.2");
83          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.0", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.2");
84          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.1", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.2");
85          NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/tomcat/config", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat/config-1.0");
86          NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/openejb-jar", "http://www.openejb.org/xml/ns/openejb-jar-2.2");
87          NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/openejb-jar-2.0", "http://www.openejb.org/xml/ns/openejb-jar-2.2");
88          NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/openejb-jar-2.1", "http://www.openejb.org/xml/ns/openejb-jar-2.2");
89          NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/pkgen", "http://www.openejb.org/xml/ns/pkgen-2.0");
90          NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/corba-css-config_1_0", "http://www.openejb.org/xml/ns/corba-css-config-2.0");
91          NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/corba-tss-config_1_0", "http://www.openejb.org/xml/ns/corba-tss-config-2.0");
92      }
93  
94      private static final QName ENVIRONMENT_QNAME = new QName("http://geronimo.apache.org/xml/ns/deployment-1.2", "environment");
95      private static final String DEFAULT_GROUPID = "default";
96      private static final String DEFAULT_VERSION = "1-default";
97      private static final QName CLIENT_ENVIRONMENT_QNAME = new QName("http://geronimo.apache.org/xml/ns/deployment-1.2", "client-environment");
98      private static final QName SERVER_ENVIRONMENT_QNAME = new QName("http://geronimo.apache.org/xml/ns/deployment-1.2", "server-environment");
99      private static final QName PATTERN_QNAME = new QName("http://geronimo.apache.org/xml/ns/naming-1.2", "pattern");
100     private static final QName GROUP_QNAME = new QName("http://geronimo.apache.org/xml/ns/naming-1.2", "groupId");
101     private static final QName ARTIFACT_QNAME = new QName("http://geronimo.apache.org/xml/ns/naming-1.2", "artifactId");
102     private static final QName MODULE_QNAME = new QName("http://geronimo.apache.org/xml/ns/naming-1.2", "module");
103     private static final QName NAME_QNAME = new QName("http://geronimo.apache.org/xml/ns/naming-1.2", "name");
104     private static final QName NAME_QNAME2 = new QName("http://geronimo.apache.org/xml/ns/deployment-1.2", "name");
105     private static final QName GBEAN_NAME_QNAME = new QName(null, "gbeanName");
106 
107     public void upgrade(InputStream source, Writer target) throws IOException, XmlException {
108         XmlObject xmlObject = parse(source);
109         xmlObject = upgrade(xmlObject);
110 
111         XmlOptions xmlOptions = new XmlOptions();
112         xmlOptions.setSavePrettyPrint();
113         xmlObject.save(target, xmlOptions);
114 
115     }
116 
117     public XmlObject upgrade(XmlObject xmlObject) throws XmlException {
118         XmlCursor cursor = xmlObject.newCursor();
119         XmlCursor.TokenType token;
120         while ((token = cursor.toNextToken()) != XmlCursor.TokenType.ENDDOC) {
121             if (token == XmlCursor.TokenType.START) {
122                 Artifact configId = extractArtifact("configId", cursor);
123                 Artifact parentId = extractArtifact("parentId", cursor);
124                 Artifact clientConfigId = extractArtifact("clientConfigId", cursor);
125                 Artifact clientParentId = extractArtifact("clientParentId", cursor);
126                 boolean suppressDefaultEnvironment = extractSuppressDefaultEnvironment(cursor);
127                 if (clientConfigId != null) {
128 
129                     insertEnvironment(clientConfigId, clientParentId, cursor, CLIENT_ENVIRONMENT_QNAME, suppressDefaultEnvironment);
130 
131                     insertEnvironment(configId, parentId, cursor, SERVER_ENVIRONMENT_QNAME, false);
132 
133                 } else if (configId != null) {
134 
135                     insertEnvironment(configId, parentId, cursor, ENVIRONMENT_QNAME, suppressDefaultEnvironment);
136                 } else {
137                     cleanContextPriorityClassLoader(cursor);
138                     cleanRef(cursor);
139                 }
140                 checkInvalid(cursor);
141             }
142         }
143         return xmlObject;
144     }
145 
146     private void cleanContextPriorityClassLoader(XmlCursor cursor) {
147         String localName = getLocalName(cursor);
148         if ("context-priority-classloader".equals(localName)) {
149             String value = cursor.getTextValue();
150             if ("false".equals(value)) {
151                 cursor.removeXml();
152             } else if ("true".equals("true")) {
153                 cursor.removeXml();
154                 cursor.insertComment("YOU MUST INSERT THE ELEMENT <inverse-classloading/> INTO THE ENVIRONMENT ELEMENT FOR THIS MODULE");
155             }
156         }
157     }
158 
159     private static void checkInvalid(XmlCursor cursor) throws XmlException {
160         String localName = getLocalName(cursor);
161         if ("gbean".equals(localName)) {
162             if (cursor.getAttributeText(GBEAN_NAME_QNAME) != null) {
163                 throw new XmlException("You must replace the gbeanName attribute manually: " + cursor.getAttributeText(GBEAN_NAME_QNAME));
164             }
165         }
166     }
167 
168     private static void cleanRef(XmlCursor cursor) throws XmlException {
169         String localName = getLocalName(cursor);
170         if ("ejb-ref".equals(localName)) {
171             cursor.toFirstChild();
172             String application = null;
173             String module = null;
174             String name = null;
175             while (cursor.getName() != null) {
176                 localName = cursor.getName().getLocalPart();
177                 if ("ref-name".equals(localName)) {
178 //                    cursor.toNextSibling();
179                 } else if ("domain".equals(localName)) {
180                     cursor.removeXml();
181                 } else if ("server".equals(localName)) {
182                     cursor.removeXml();
183                 } else if ("application".equals(localName)) {
184                     application = cursor.getTextValue();
185                     if ("null".equals(application)) {
186                         application = null;
187                     }
188                     cursor.removeXml();
189                 } else if ("module".equals(localName)) {
190                     if (application == null) {
191                         //this is a configuration name
192                         application = cursor.getTextValue();
193                     } else {
194                         module = cursor.getTextValue();
195                     }
196                     cursor.removeXml();
197                 } else if ("type".equals(localName)) {
198                     cursor.removeXml();
199                 } else if ("name".equals(localName)) {
200                     name = cursor.getTextValue();
201                     cursor.removeXml();
202                 } else if ("ejb-link".equals(localName)) {
203                     break;
204                 } else if ("target-name".equals(localName)) {
205                     ObjectName targetName = extractObjectName(cursor);
206                     name = targetName.getKeyProperty("name");
207                     application = targetName.getKeyProperty("J2EEApplication");
208                     if ("null".equals(application)) {
209                         application = targetName.getKeyProperty("EJBModule");
210                     } else {
211                         module = targetName.getKeyProperty("EJBModule");
212                     }
213 
214                 } else if ("ns-corbaloc".equals(localName)) {
215                     cursor.toNextSibling();
216 //                    cursor.toNextSibling();
217                 } else if ("css".equals(localName)) {
218                     //TODO fix this
219 //                    cursor.toNextSibling();
220                 } else if ("css-link".equals(localName)) {
221 //                    cursor.toNextSibling();
222                 } else if ("css-name".equals(localName)) {
223 //                    cursor.toNextSibling();
224                 } else {
225                     throw new IllegalStateException("unrecognized element: " + cursor.getTextValue());
226                 }
227                 if (!cursor.toNextSibling()) {
228                     break;
229                 }
230             }
231             if (name != null) {
232                 cursor.beginElement(PATTERN_QNAME);
233                 if (application != null) {
234                     try {
235                         Artifact artifact = Artifact.create(application);
236                         cursor.insertElementWithText(GROUP_QNAME, artifact.getGroupId());
237                         cursor.insertElementWithText(ARTIFACT_QNAME, artifact.getArtifactId());
238                     } catch (Exception e) {
239                         cursor.insertElementWithText(ARTIFACT_QNAME, application.replace('/', '_'));
240                     }
241 //                    cursor.insertElementWithText(VERSION_QNAME, artifact.getVersion().toString());
242                 }
243                 if (module != null) {
244                     cursor.insertElementWithText(MODULE_QNAME, module);
245                 }
246                 cursor.insertElementWithText(NAME_QNAME, name);
247                 cursor.toNextToken();
248             }
249         } else if ("gbean-name".equals(localName)) {
250             ObjectName targetName = extractObjectName(cursor);
251             String name = targetName.getKeyProperty("name");
252             cursor.insertComment("CHECK THAT THE TARGET GBEAN IS IN THE ANCESTOR SET OF THIS MODULE AND THAT THE NAME UNIQUELY IDENTIFIES IT");
253             cursor.insertElementWithText(NAME_QNAME2, name);
254         }
255     }
256 
257     private static ObjectName extractObjectName(XmlCursor cursor) throws XmlException {
258         String targetNameString = cursor.getTextValue();
259         cursor.removeXml();
260         ObjectName targetName;
261         try {
262             targetName = ObjectName.getInstance(targetNameString);
263         } catch (MalformedObjectNameException e) {
264             throw new XmlException("Invalid object name: " + targetNameString);
265         }
266         return targetName;
267     }
268 
269     private static String getLocalName(XmlCursor cursor) {
270         QName name = cursor.getName();
271         return name == null ? null : name.getLocalPart();
272     }
273 
274     private static void insertEnvironment(Artifact configId, Artifact parentId, XmlCursor cursor, QName environmentQname, boolean suppressDefaultEnvironment) {
275         positionEnvironment(cursor);
276         Environment environment = new Environment();
277         environment.setConfigId(configId);
278         if (parentId != null) {
279             environment.addDependency(parentId, ImportType.ALL);
280         }
281         environment.setSuppressDefaultEnvironment(suppressDefaultEnvironment);
282         extractDependencies(cursor, environment);
283         EnvironmentType environmentType = EnvironmentBuilder.buildEnvironmentType(environment);
284         cursor.beginElement(environmentQname);
285         XmlCursor element = environmentType.newCursor();
286         try {
287             element.copyXmlContents(cursor);
288         } finally {
289             element.dispose();
290         }
291     }
292 
293     private static void extractDependencies(XmlCursor cursor, Environment environment) {
294         if (cursor.getName() == null) {
295             //no dependencies, do nothing
296             return;
297         }
298         do {
299             String localPart = getLocalName(cursor);
300             if (localPart.equals("dependency") || localPart.equals("import")) {
301                 extractDependency(cursor, environment);
302             } else {
303                 break;
304             }
305         } while (cursor.toNextSibling());
306     }
307 
308     private static void extractDependency(XmlCursor cursor, Environment environment) {
309         cursor.push();
310         cursor.toFirstChild();
311         Artifact artifact;
312         if (cursor.getName().getLocalPart().equals("uri")) {
313             String uri = cursor.getTextValue();
314             artifact = toArtifact(uri);
315         } else {
316             checkName(cursor, "groupId");
317             String groupId = cursor.getTextValue();
318             cursor.toNextSibling();
319             String type = "jar";
320             if (cursor.getName().getLocalPart().equals("type")) {
321                 type = cursor.getTextValue();
322                 cursor.toNextSibling();
323             }
324             checkName(cursor, "artifactId");
325             String artifactId = cursor.getTextValue();
326             cursor.toNextSibling();
327             checkName(cursor, "version");
328             String version = cursor.getTextValue();
329             artifact = new Artifact(groupId, artifactId, version, type);
330         }
331         environment.addDependency(artifact, ImportType.ALL);
332         cursor.pop();
333         cursor.removeXml();
334     }
335 
336     private static void checkName(XmlCursor cursor, String localName) {
337         if (!cursor.getName().getLocalPart().equals(localName)) {
338             throw new IllegalArgumentException("Expected element: " + localName + " but actually: " + cursor.getName().getLocalPart());
339         }
340 
341     }
342 
343     private static void positionEnvironment(XmlCursor cursor) {
344         XmlCursor.TokenType token;
345         while ((token = cursor.toNextToken()) != XmlCursor.TokenType.START && token != XmlCursor.TokenType.END) {
346             //keep going
347         }
348     }
349 
350     private static Artifact extractArtifact(String attrName, XmlCursor cursor) {
351         String attrValue;
352         QName attrQName = new QName(null, attrName);
353         if ((attrValue = cursor.getAttributeText(attrQName)) != null) {
354             cursor.removeAttribute(attrQName);
355             return toArtifact(attrValue);
356         }
357         return null;
358     }
359 
360     private static Artifact toArtifact(String attrValue) {
361         try {
362             return Artifact.create(attrValue);
363         } catch (Exception e) {
364             return new Artifact(DEFAULT_GROUPID, attrValue.replace('/', '_'), DEFAULT_VERSION, "car");
365         }
366     }
367 
368     private static boolean extractSuppressDefaultEnvironment(XmlCursor cursor) {
369         String attrValue;
370         QName attrQName = new QName(null, "suppressDefaultParentId");
371         if ((attrValue = cursor.getAttributeText(attrQName)) != null) {
372             cursor.removeAttribute(attrQName);
373             return Boolean.valueOf(attrValue).booleanValue();
374         }
375         return false;
376     }
377 
378     public static XmlObject parse(InputStream is) throws IOException, XmlException {
379         ArrayList errors = new ArrayList();
380         XmlObject parsed = XmlObject.Factory.parse(is, createXmlOptions(errors));
381         if (errors.size() != 0) {
382             throw new XmlException(errors.toArray().toString());
383         }
384         return parsed;
385     }
386 
387     public static XmlOptions createXmlOptions(Collection errors) {
388         XmlOptions options = new XmlOptions();
389         options.setLoadLineNumbers();
390         options.setErrorListener(errors);
391         options.setLoadSubstituteNamespaces(NAMESPACE_UPDATES);
392         return options;
393     }
394 
395 }