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 }