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 package org.apache.geronimo.upgrade;
018
019 import java.io.InputStream;
020 import java.io.IOException;
021 import java.io.Writer;
022 import java.util.Map;
023 import java.util.HashMap;
024 import java.util.ArrayList;
025 import java.util.Collection;
026
027 import javax.xml.namespace.QName;
028 import javax.management.ObjectName;
029 import javax.management.MalformedObjectNameException;
030
031 import org.apache.xmlbeans.XmlObject;
032 import org.apache.xmlbeans.XmlException;
033 import org.apache.xmlbeans.XmlOptions;
034 import org.apache.xmlbeans.XmlCursor;
035 import org.apache.geronimo.kernel.repository.Artifact;
036 import org.apache.geronimo.kernel.repository.Environment;
037 import org.apache.geronimo.kernel.repository.ImportType;
038 import org.apache.geronimo.deployment.xbeans.EnvironmentType;
039 import org.apache.geronimo.deployment.service.EnvironmentBuilder;
040
041 /**
042 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
043 */
044 public class Upgrade1_0To1_1 {
045
046 private static final Map NAMESPACE_UPDATES = new HashMap();
047
048 static {
049 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-client", "http://geronimo.apache.org/xml/ns/j2ee/application-client-2.0");
050 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-client-1.1", "http://geronimo.apache.org/xml/ns/j2ee/application-client-2.0");
051 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-client-1.2", "http://geronimo.apache.org/xml/ns/j2ee/application-client-2.0");
052 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application", "http://geronimo.apache.org/xml/ns/j2ee/application-2.0");
053 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-1.1", "http://geronimo.apache.org/xml/ns/j2ee/application-2.0");
054 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-1.2", "http://geronimo.apache.org/xml/ns/j2ee/application-2.0");
055 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/deployment", "http://geronimo.apache.org/xml/ns/deployment-1.2");
056 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/deployment-1.0", "http://geronimo.apache.org/xml/ns/deployment-1.2");
057 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/deployment-1.1", "http://geronimo.apache.org/xml/ns/deployment-1.2");
058 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/connector", "http://geronimo.apache.org/xml/ns/j2ee/connector-1.2");
059 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/connector-1.0", "http://geronimo.apache.org/xml/ns/j2ee/connector-1.2");
060 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/connector-1.1", "http://geronimo.apache.org/xml/ns/j2ee/connector-1.2");
061 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/deployment/javabean", "http://geronimo.apache.org/xml/ns/deployment/javabean-1.0");
062 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/loginconfig", "http://geronimo.apache.org/xml/ns/loginconfig-1.0");
063 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/loginconfig-1.0", "http://geronimo.apache.org/xml/ns/loginconfig-1.0");
064 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/loginconfig-1.1", "http://geronimo.apache.org/xml/ns/loginconfig-1.0");
065 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/naming", "http://geronimo.apache.org/xml/ns/naming-1.2");
066 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/naming-1.0", "http://geronimo.apache.org/xml/ns/naming-1.2");
067 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/naming-1.1", "http://geronimo.apache.org/xml/ns/naming-1.2");
068 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/security", "http://geronimo.apache.org/xml/ns/security-1.2");
069 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/security-1.0", "http://geronimo.apache.org/xml/ns/security-1.2");
070 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/security-1.1", "http://geronimo.apache.org/xml/ns/security-1.2");
071 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web", "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
072 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web-1.0", "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
073 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web-1.1", "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
074 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web-1.2", "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
075 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web-2.0", "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
076 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web-1.0", "http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1");
077 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/jetty", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.1");
078 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/jetty-1.0", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.1");
079 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.0", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.1");
080 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.1", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.1");
081 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/jetty-1.2", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.1");
082 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty-2.0.1");
083 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/jetty/config", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty/config-1.0");
084 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/tomcat", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1");
085 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/tomcat-1.0", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1");
086 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.0", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1");
087 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.1", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1");
088 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.2", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1");
089 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-2.0.1");
090 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/tomcat/config", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat/config-1.0");
091 NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/openejb-jar", "http://www.openejb.org/xml/ns/openejb-jar-2.3");
092 NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/openejb-jar-2.0", "http://www.openejb.org/xml/ns/openejb-jar-2.3");
093 NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/openejb-jar-2.1", "http://www.openejb.org/xml/ns/openejb-jar-2.3");
094 NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/openejb-jar-2.2", "http://www.openejb.org/xml/ns/openejb-jar-2.3");
095 NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/pkgen", "http://www.openejb.org/xml/ns/pkgen-2.0");
096 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");
097 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");
098 }
099
100 private static final QName ENVIRONMENT_QNAME = new QName("http://geronimo.apache.org/xml/ns/deployment-1.2", "environment");
101 private static final String DEFAULT_GROUPID = "default";
102 private static final String DEFAULT_VERSION = "1-default";
103 private static final QName CLIENT_ENVIRONMENT_QNAME = new QName("http://geronimo.apache.org/xml/ns/deployment-1.2", "client-environment");
104 private static final QName SERVER_ENVIRONMENT_QNAME = new QName("http://geronimo.apache.org/xml/ns/deployment-1.2", "server-environment");
105 private static final QName PATTERN_QNAME = new QName("http://geronimo.apache.org/xml/ns/naming-1.2", "pattern");
106 private static final QName GROUP_QNAME = new QName("http://geronimo.apache.org/xml/ns/naming-1.2", "groupId");
107 private static final QName ARTIFACT_QNAME = new QName("http://geronimo.apache.org/xml/ns/naming-1.2", "artifactId");
108 private static final QName MODULE_QNAME = new QName("http://geronimo.apache.org/xml/ns/naming-1.2", "module");
109 private static final QName NAME_QNAME = new QName("http://geronimo.apache.org/xml/ns/naming-1.2", "name");
110 private static final QName NAME_QNAME2 = new QName("http://geronimo.apache.org/xml/ns/deployment-1.2", "name");
111 private static final QName GBEAN_NAME_QNAME = new QName(null, "gbeanName");
112
113 public void upgrade(InputStream source, Writer target) throws IOException, XmlException {
114 XmlObject xmlObject = parse(source);
115 xmlObject = upgrade(xmlObject);
116
117 XmlOptions xmlOptions = new XmlOptions();
118 xmlOptions.setSavePrettyPrint();
119 xmlObject.save(target, xmlOptions);
120
121 }
122
123 public XmlObject upgrade(XmlObject xmlObject) throws XmlException {
124 XmlCursor cursor = xmlObject.newCursor();
125 XmlCursor.TokenType token;
126 while ((token = cursor.toNextToken()) != XmlCursor.TokenType.ENDDOC) {
127 if (token == XmlCursor.TokenType.START) {
128 Artifact configId = extractArtifact("configId", cursor);
129 Artifact parentId = extractArtifact("parentId", cursor);
130 Artifact clientConfigId = extractArtifact("clientConfigId", cursor);
131 Artifact clientParentId = extractArtifact("clientParentId", cursor);
132 boolean suppressDefaultEnvironment = extractSuppressDefaultEnvironment(cursor);
133 if (clientConfigId != null) {
134
135 insertEnvironment(clientConfigId, clientParentId, cursor, CLIENT_ENVIRONMENT_QNAME, suppressDefaultEnvironment);
136
137 insertEnvironment(configId, parentId, cursor, SERVER_ENVIRONMENT_QNAME, false);
138
139 } else if (configId != null) {
140
141 insertEnvironment(configId, parentId, cursor, ENVIRONMENT_QNAME, suppressDefaultEnvironment);
142 } else {
143 cleanContextPriorityClassLoader(cursor);
144 cleanRef(cursor);
145 }
146 checkInvalid(cursor);
147 }
148 }
149 return xmlObject;
150 }
151
152 private void cleanContextPriorityClassLoader(XmlCursor cursor) {
153 String localName = getLocalName(cursor);
154 if ("context-priority-classloader".equals(localName)) {
155 String value = cursor.getTextValue();
156 if ("false".equals(value)) {
157 cursor.removeXml();
158 } else if ("true".equals("true")) {
159 cursor.removeXml();
160 cursor.insertComment("YOU MUST INSERT THE ELEMENT <inverse-classloading/> INTO THE ENVIRONMENT ELEMENT FOR THIS MODULE");
161 }
162 }
163 }
164
165 private static void checkInvalid(XmlCursor cursor) throws XmlException {
166 String localName = getLocalName(cursor);
167 if ("gbean".equals(localName)) {
168 if (cursor.getAttributeText(GBEAN_NAME_QNAME) != null) {
169 throw new XmlException("You must replace the gbeanName attribute manually: " + cursor.getAttributeText(GBEAN_NAME_QNAME));
170 }
171 }
172 }
173
174 private static void cleanRef(XmlCursor cursor) throws XmlException {
175 String localName = getLocalName(cursor);
176 if ("ejb-ref".equals(localName)) {
177 cursor.toFirstChild();
178 String application = null;
179 String module = null;
180 String name = null;
181 while (cursor.getName() != null) {
182 localName = cursor.getName().getLocalPart();
183 if ("ref-name".equals(localName)) {
184 // cursor.toNextSibling();
185 } else if ("domain".equals(localName)) {
186 cursor.removeXml();
187 } else if ("server".equals(localName)) {
188 cursor.removeXml();
189 } else if ("application".equals(localName)) {
190 application = cursor.getTextValue();
191 if ("null".equals(application)) {
192 application = null;
193 }
194 cursor.removeXml();
195 } else if ("module".equals(localName)) {
196 if (application == null) {
197 //this is a configuration name
198 application = cursor.getTextValue();
199 } else {
200 module = cursor.getTextValue();
201 }
202 cursor.removeXml();
203 } else if ("type".equals(localName)) {
204 cursor.removeXml();
205 } else if ("name".equals(localName)) {
206 name = cursor.getTextValue();
207 cursor.removeXml();
208 } else if ("ejb-link".equals(localName)) {
209 break;
210 } else if ("target-name".equals(localName)) {
211 ObjectName targetName = extractObjectName(cursor);
212 name = targetName.getKeyProperty("name");
213 application = targetName.getKeyProperty("J2EEApplication");
214 if ("null".equals(application)) {
215 application = targetName.getKeyProperty("EJBModule");
216 } else {
217 module = targetName.getKeyProperty("EJBModule");
218 }
219
220 } else if ("ns-corbaloc".equals(localName)) {
221 cursor.toNextSibling();
222 // cursor.toNextSibling();
223 } else if ("css".equals(localName)) {
224 //TODO fix this
225 // cursor.toNextSibling();
226 } else if ("css-link".equals(localName)) {
227 // cursor.toNextSibling();
228 } else if ("css-name".equals(localName)) {
229 // cursor.toNextSibling();
230 } else {
231 throw new IllegalStateException("unrecognized element: " + cursor.getTextValue());
232 }
233 if (!cursor.toNextSibling()) {
234 break;
235 }
236 }
237 if (name != null) {
238 cursor.beginElement(PATTERN_QNAME);
239 if (application != null) {
240 try {
241 Artifact artifact = Artifact.create(application);
242 cursor.insertElementWithText(GROUP_QNAME, artifact.getGroupId());
243 cursor.insertElementWithText(ARTIFACT_QNAME, artifact.getArtifactId());
244 } catch (Exception e) {
245 cursor.insertElementWithText(ARTIFACT_QNAME, application.replace('/', '_'));
246 }
247 // cursor.insertElementWithText(VERSION_QNAME, artifact.getVersion().toString());
248 }
249 if (module != null) {
250 cursor.insertElementWithText(MODULE_QNAME, module);
251 }
252 cursor.insertElementWithText(NAME_QNAME, name);
253 cursor.toNextToken();
254 }
255 } else if ("gbean-name".equals(localName)) {
256 ObjectName targetName = extractObjectName(cursor);
257 String name = targetName.getKeyProperty("name");
258 cursor.insertComment("CHECK THAT THE TARGET GBEAN IS IN THE ANCESTOR SET OF THIS MODULE AND THAT THE NAME UNIQUELY IDENTIFIES IT");
259 cursor.insertElementWithText(NAME_QNAME2, name);
260 }
261 }
262
263 private static ObjectName extractObjectName(XmlCursor cursor) throws XmlException {
264 String targetNameString = cursor.getTextValue();
265 cursor.removeXml();
266 ObjectName targetName;
267 try {
268 targetName = ObjectName.getInstance(targetNameString);
269 } catch (MalformedObjectNameException e) {
270 throw (XmlException)new XmlException("Invalid object name: " + targetNameString).initCause(e);
271 }
272 return targetName;
273 }
274
275 private static String getLocalName(XmlCursor cursor) {
276 QName name = cursor.getName();
277 return name == null ? null : name.getLocalPart();
278 }
279
280 private static void insertEnvironment(Artifact configId, Artifact parentId, XmlCursor cursor, QName environmentQname, boolean suppressDefaultEnvironment) {
281 positionEnvironment(cursor);
282 Environment environment = new Environment();
283 environment.setConfigId(configId);
284 if (parentId != null) {
285 environment.addDependency(parentId, ImportType.ALL);
286 }
287 environment.setSuppressDefaultEnvironment(suppressDefaultEnvironment);
288 extractDependencies(cursor, environment);
289 EnvironmentType environmentType = EnvironmentBuilder.buildEnvironmentType(environment);
290 cursor.beginElement(environmentQname);
291 XmlCursor element = environmentType.newCursor();
292 try {
293 element.copyXmlContents(cursor);
294 } finally {
295 element.dispose();
296 }
297 }
298
299 private static void extractDependencies(XmlCursor cursor, Environment environment) {
300 if (cursor.getName() == null) {
301 //no dependencies, do nothing
302 return;
303 }
304 do {
305 String localPart = getLocalName(cursor);
306 if (localPart.equals("dependency") || localPart.equals("import")) {
307 extractDependency(cursor, environment);
308 } else {
309 break;
310 }
311 } while (cursor.toNextSibling());
312 }
313
314 private static void extractDependency(XmlCursor cursor, Environment environment) {
315 cursor.push();
316 cursor.toFirstChild();
317 Artifact artifact;
318 if (cursor.getName().getLocalPart().equals("uri")) {
319 String uri = cursor.getTextValue();
320 artifact = toArtifact(uri);
321 } else {
322 checkName(cursor, "groupId");
323 String groupId = cursor.getTextValue();
324 cursor.toNextSibling();
325 String type = "jar";
326 if (cursor.getName().getLocalPart().equals("type")) {
327 type = cursor.getTextValue();
328 cursor.toNextSibling();
329 }
330 checkName(cursor, "artifactId");
331 String artifactId = cursor.getTextValue();
332 cursor.toNextSibling();
333 checkName(cursor, "version");
334 String version = cursor.getTextValue();
335 artifact = new Artifact(groupId, artifactId, version, type);
336 }
337 environment.addDependency(artifact, ImportType.ALL);
338 cursor.pop();
339 cursor.removeXml();
340 }
341
342 private static void checkName(XmlCursor cursor, String localName) {
343 if (!cursor.getName().getLocalPart().equals(localName)) {
344 throw new IllegalArgumentException("Expected element: " + localName + " but actually: " + cursor.getName().getLocalPart());
345 }
346
347 }
348
349 private static void positionEnvironment(XmlCursor cursor) {
350 XmlCursor.TokenType token;
351 while ((token = cursor.toNextToken()) != XmlCursor.TokenType.START && token != XmlCursor.TokenType.END) {
352 //keep going
353 }
354 }
355
356 private static Artifact extractArtifact(String attrName, XmlCursor cursor) {
357 String attrValue;
358 QName attrQName = new QName(null, attrName);
359 if ((attrValue = cursor.getAttributeText(attrQName)) != null) {
360 cursor.removeAttribute(attrQName);
361 return toArtifact(attrValue);
362 }
363 return null;
364 }
365
366 private static Artifact toArtifact(String attrValue) {
367 try {
368 return Artifact.create(attrValue);
369 } catch (Exception e) {
370 return new Artifact(DEFAULT_GROUPID, attrValue.replace('/', '_'), DEFAULT_VERSION, "car");
371 }
372 }
373
374 private static boolean extractSuppressDefaultEnvironment(XmlCursor cursor) {
375 String attrValue;
376 QName attrQName = new QName(null, "suppressDefaultParentId");
377 if ((attrValue = cursor.getAttributeText(attrQName)) != null) {
378 cursor.removeAttribute(attrQName);
379 return Boolean.valueOf(attrValue).booleanValue();
380 }
381 return false;
382 }
383
384 public static XmlObject parse(InputStream is) throws IOException, XmlException {
385 ArrayList errors = new ArrayList();
386 XmlObject parsed = XmlObject.Factory.parse(is, createXmlOptions(errors));
387 if (errors.size() != 0) {
388 throw new XmlException(errors.toArray().toString());
389 }
390 return parsed;
391 }
392
393 public static XmlOptions createXmlOptions(Collection errors) {
394 XmlOptions options = new XmlOptions();
395 options.setLoadLineNumbers();
396 options.setErrorListener(errors);
397 options.setLoadSubstituteNamespaces(NAMESPACE_UPDATES);
398 return options;
399 }
400
401 }