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