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 }