001 /** 002 * 003 * Copyright 2006 The Apache Software Foundation 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * 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 018 package org.apache.geronimo.upgrade; 019 020 import java.io.InputStream; 021 import java.io.IOException; 022 import java.io.Writer; 023 import java.util.Map; 024 import java.util.HashMap; 025 import java.util.ArrayList; 026 import java.util.Collection; 027 028 import javax.xml.namespace.QName; 029 import javax.management.ObjectName; 030 import javax.management.MalformedObjectNameException; 031 032 import org.apache.xmlbeans.XmlObject; 033 import org.apache.xmlbeans.XmlException; 034 import org.apache.xmlbeans.XmlOptions; 035 import org.apache.xmlbeans.XmlCursor; 036 import org.apache.geronimo.kernel.repository.Artifact; 037 import org.apache.geronimo.kernel.repository.Environment; 038 import org.apache.geronimo.kernel.repository.ImportType; 039 import org.apache.geronimo.deployment.xbeans.EnvironmentType; 040 import org.apache.geronimo.deployment.service.EnvironmentBuilder; 041 042 /** 043 * @version $Rev: 432510 $ $Date: 2006-08-18 00:44:04 -0700 (Fri, 18 Aug 2006) $ 044 */ 045 public class Upgrade1_0To1_1 { 046 047 private static final Map NAMESPACE_UPDATES = new HashMap(); 048 049 static { 050 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-client", "http://geronimo.apache.org/xml/ns/j2ee/application-client-1.2"); 051 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"); 052 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"); 053 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application", "http://geronimo.apache.org/xml/ns/j2ee/application-1.2"); 054 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-1.0", "http://geronimo.apache.org/xml/ns/j2ee/application-1.2"); 055 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/application-1.1", "http://geronimo.apache.org/xml/ns/j2ee/application-1.2"); 056 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/deployment", "http://geronimo.apache.org/xml/ns/deployment-1.2"); 057 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/deployment-1.0", "http://geronimo.apache.org/xml/ns/deployment-1.2"); 058 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/deployment-1.1", "http://geronimo.apache.org/xml/ns/deployment-1.2"); 059 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/connector", "http://geronimo.apache.org/xml/ns/j2ee/connector-1.2"); 060 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/connector-1.0", "http://geronimo.apache.org/xml/ns/j2ee/connector-1.2"); 061 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/connector-1.1", "http://geronimo.apache.org/xml/ns/j2ee/connector-1.2"); 062 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/deployment/javabean", "http://geronimo.apache.org/xml/ns/deployment/javabean-1.0"); 063 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/loginconfig", "http://geronimo.apache.org/xml/ns/loginconfig-1.0"); 064 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/loginconfig-1.0", "http://geronimo.apache.org/xml/ns/loginconfig-1.0"); 065 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/loginconfig-1.1", "http://geronimo.apache.org/xml/ns/loginconfig-1.0"); 066 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/naming", "http://geronimo.apache.org/xml/ns/naming-1.2"); 067 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/naming-1.0", "http://geronimo.apache.org/xml/ns/naming-1.2"); 068 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/naming-1.1", "http://geronimo.apache.org/xml/ns/naming-1.2"); 069 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/security", "http://geronimo.apache.org/xml/ns/security-1.2"); 070 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/security-1.0", "http://geronimo.apache.org/xml/ns/security-1.2"); 071 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/security-1.1", "http://geronimo.apache.org/xml/ns/security-1.2"); 072 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web", "http://geronimo.apache.org/xml/ns/j2ee/web-1.2"); 073 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web-1.0", "http://geronimo.apache.org/xml/ns/j2ee/web-1.2"); 074 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/j2ee/web-1.1", "http://geronimo.apache.org/xml/ns/j2ee/web-1.2"); 075 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web-1.0", "http://geronimo.apache.org/xml/ns/j2ee/web-1.2"); 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-1.2"); 078 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"); 079 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"); 080 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/jetty/config", "http://geronimo.apache.org/xml/ns/j2ee/web/jetty/config-1.0"); 081 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/tomcat", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.2"); 082 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/tomcat-1.0", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat-1.2"); 083 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"); 084 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"); 085 NAMESPACE_UPDATES.put("http://geronimo.apache.org/xml/ns/web/tomcat/config", "http://geronimo.apache.org/xml/ns/j2ee/web/tomcat/config-1.0"); 086 NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/openejb-jar", "http://www.openejb.org/xml/ns/openejb-jar-2.2"); 087 NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/openejb-jar-2.0", "http://www.openejb.org/xml/ns/openejb-jar-2.2"); 088 NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/openejb-jar-2.1", "http://www.openejb.org/xml/ns/openejb-jar-2.2"); 089 NAMESPACE_UPDATES.put("http://www.openejb.org/xml/ns/pkgen", "http://www.openejb.org/xml/ns/pkgen-2.0"); 090 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"); 091 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"); 092 } 093 094 private static final QName ENVIRONMENT_QNAME = new QName("http://geronimo.apache.org/xml/ns/deployment-1.2", "environment"); 095 private static final String DEFAULT_GROUPID = "default"; 096 private static final String DEFAULT_VERSION = "1-default"; 097 private static final QName CLIENT_ENVIRONMENT_QNAME = new QName("http://geronimo.apache.org/xml/ns/deployment-1.2", "client-environment"); 098 private static final QName SERVER_ENVIRONMENT_QNAME = new QName("http://geronimo.apache.org/xml/ns/deployment-1.2", "server-environment"); 099 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 }