/**
*
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.geronimo.schema;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.xml.namespace.QName;
import org.apache.geronimo.xbeans.j2ee.ApplicationClientDocument;
import org.apache.geronimo.xbeans.j2ee.ApplicationDocument;
import org.apache.geronimo.xbeans.j2ee.ConnectorDocument;
import org.apache.geronimo.xbeans.j2ee.EjbJarDocument;
import org.apache.geronimo.xbeans.j2ee.WebAppDocument;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlDocumentProperties;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
/**
* @version $Rev$ $Date$
*/
public class SchemaConversionUtils {
static final String J2EE_NAMESPACE = "http://java.sun.com/xml/ns/j2ee";
static final String GERONIMO_NAMING_NAMESPACE = "http://geronimo.apache.org/xml/ns/naming-1.0";
private static final String GERONIMO_SECURITY_NAMESPACE = "http://geronimo.apache.org/xml/ns/security-1.1";
private static final String GERONIMO_SERVICE_NAMESPACE = "http://geronimo.apache.org/xml/ns/deployment-1.0";
private static final QName RESOURCE_ADAPTER_VERSION = new QName(J2EE_NAMESPACE, "resourceadapter-version");
private static final QName TAGLIB = new QName(J2EE_NAMESPACE, "taglib");
private static final QName CMP_VERSION = new QName(J2EE_NAMESPACE, "cmp-version");
private static final Map GERONIMO_SCHEMA_CONVERSIONS = new HashMap();
static {
GERONIMO_SCHEMA_CONVERSIONS.put("ejb-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
GERONIMO_SCHEMA_CONVERSIONS.put("ejb-local-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
GERONIMO_SCHEMA_CONVERSIONS.put("service-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
GERONIMO_SCHEMA_CONVERSIONS.put("resource-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
GERONIMO_SCHEMA_CONVERSIONS.put("resource-env-ref", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
GERONIMO_SCHEMA_CONVERSIONS.put("cmp-connection-factory", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
GERONIMO_SCHEMA_CONVERSIONS.put("workmanager", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
GERONIMO_SCHEMA_CONVERSIONS.put("resource-adapter", new NamespaceElementConverter(GERONIMO_NAMING_NAMESPACE));
GERONIMO_SCHEMA_CONVERSIONS.put("security", new SecurityElementConverter());
GERONIMO_SCHEMA_CONVERSIONS.put("default-principal", new NamespaceElementConverter(GERONIMO_SECURITY_NAMESPACE));
GERONIMO_SCHEMA_CONVERSIONS.put("gbean", new GBeanElementConverter());
GERONIMO_SCHEMA_CONVERSIONS.put("import", new NamespaceElementConverter(GERONIMO_SERVICE_NAMESPACE));
GERONIMO_SCHEMA_CONVERSIONS.put("hidden-classes", new NamespaceElementConverter(GERONIMO_SERVICE_NAMESPACE));
GERONIMO_SCHEMA_CONVERSIONS.put("non-overridable-classes", new NamespaceElementConverter(GERONIMO_SERVICE_NAMESPACE));
GERONIMO_SCHEMA_CONVERSIONS.put("dependency", new NamespaceElementConverter(GERONIMO_SERVICE_NAMESPACE));
GERONIMO_SCHEMA_CONVERSIONS.put("include", new NamespaceElementConverter(GERONIMO_SERVICE_NAMESPACE));
}
private SchemaConversionUtils() {
}
public static void registerNamespaceConversions(Map conversions) {
GERONIMO_SCHEMA_CONVERSIONS.putAll(conversions);
}
public static ApplicationDocument convertToApplicationSchema(XmlObject xmlObject) throws XmlException {
if (ApplicationDocument.type.equals(xmlObject.schemaType())) {
validateDD(xmlObject);
return (ApplicationDocument) xmlObject;
}
XmlCursor cursor = xmlObject.newCursor();
XmlCursor moveable = xmlObject.newCursor();
String schemaLocationURL = "http://java.sun.com/xml/ns/j2ee/application_1_4.xsd";
String version = "1.4";
try {
convertToSchema(cursor, J2EE_NAMESPACE, schemaLocationURL, version);
cursor.toStartDoc();
cursor.toChild(J2EE_NAMESPACE, "application");
cursor.toFirstChild();
convertToDescriptionGroup(cursor, moveable);
} finally {
cursor.dispose();
moveable.dispose();
}
XmlObject result = xmlObject.changeType(ApplicationDocument.type);
if (result != null) {
validateDD(result);
return (ApplicationDocument) result;
}
validateDD(xmlObject);
return (ApplicationDocument) xmlObject;
}
public static ApplicationClientDocument convertToApplicationClientSchema(XmlObject xmlObject) throws XmlException {
if (ApplicationClientDocument.type.equals(xmlObject.schemaType())) {
validateDD(xmlObject);
return (ApplicationClientDocument) xmlObject;
}
XmlCursor cursor = xmlObject.newCursor();
XmlCursor moveable = xmlObject.newCursor();
String schemaLocationURL = "http://java.sun.com/xml/ns/j2ee/application-client_1_4.xsd";
String version = "1.4";
try {
convertToSchema(cursor, J2EE_NAMESPACE, schemaLocationURL, version);
cursor.toStartDoc();
cursor.toChild(J2EE_NAMESPACE, "application-client");
cursor.toFirstChild();
convertToDescriptionGroup(cursor, moveable);
} finally {
cursor.dispose();
moveable.dispose();
}
XmlObject result = xmlObject.changeType(ApplicationClientDocument.type);
if (result != null) {
validateDD(result);
return (ApplicationClientDocument) result;
}
validateDD(xmlObject);
return (ApplicationClientDocument) xmlObject;
}
public static ConnectorDocument convertToConnectorSchema(XmlObject xmlObject) throws XmlException {
if (ConnectorDocument.type.equals(xmlObject.schemaType())) {
validateDD(xmlObject);
return (ConnectorDocument) xmlObject;
}
XmlCursor cursor = xmlObject.newCursor();
XmlDocumentProperties xmlDocumentProperties = cursor.documentProperties();
String publicId = xmlDocumentProperties.getDoctypePublicId();
try {
if ("-//Sun Microsystems, Inc.//DTD Connector 1.0//EN".equals(publicId)) {
XmlCursor moveable = xmlObject.newCursor();
try {
String schemaLocationURL = "http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd";
String version = "1.5";
convertToSchema(cursor, J2EE_NAMESPACE, schemaLocationURL, version);
cursor.toStartDoc();
cursor.toChild(J2EE_NAMESPACE, "connector");
cursor.toFirstChild();
convertToDescriptionGroup(cursor, moveable);
cursor.toNextSibling(J2EE_NAMESPACE, "spec-version");
cursor.removeXml();
cursor.toNextSibling(J2EE_NAMESPACE, "version");
cursor.setName(RESOURCE_ADAPTER_VERSION);
cursor.toNextSibling(J2EE_NAMESPACE, "resourceadapter");
moveable.toCursor(cursor);
cursor.toFirstChild();
cursor.beginElement("outbound-resourceadapter", J2EE_NAMESPACE);
cursor.beginElement("connection-definition", J2EE_NAMESPACE);
moveable.toChild(J2EE_NAMESPACE, "managedconnectionfactory-class");
moveable.push();
//from moveable to cursor
moveable.moveXml(cursor);
while (moveable.toNextSibling(J2EE_NAMESPACE, "config-property")) {
moveable.moveXml(cursor);
}
moveable.pop();
moveable.toNextSibling(J2EE_NAMESPACE, "connectionfactory-interface");
moveable.moveXml(cursor);
moveable.toNextSibling(J2EE_NAMESPACE, "connectionfactory-impl-class");
moveable.moveXml(cursor);
moveable.toNextSibling(J2EE_NAMESPACE, "connection-interface");
moveable.moveXml(cursor);
moveable.toNextSibling(J2EE_NAMESPACE, "connection-impl-class");
moveable.moveXml(cursor);
//get out of connection-definition element
cursor.toNextToken();
moveable.toNextSibling(J2EE_NAMESPACE, "transaction-support");
moveable.moveXml(cursor);
while (moveable.toNextSibling(J2EE_NAMESPACE, "authentication-mechanism")) {
moveable.moveXml(cursor);
}
moveable.toNextSibling(J2EE_NAMESPACE, "reauthentication-support");
moveable.moveXml(cursor);
} finally {
moveable.dispose();
}
}
} finally {
cursor.dispose();
}
XmlObject result = xmlObject.changeType(ConnectorDocument.type);
if (result != null) {
validateDD(result);
return (ConnectorDocument) result;
}
validateDD(xmlObject);
return (ConnectorDocument) xmlObject;
}
public static EjbJarDocument convertToEJBSchema(XmlObject xmlObject) throws XmlException {
if (EjbJarDocument.type.equals(xmlObject.schemaType())) {
validateDD(xmlObject);
return (EjbJarDocument) xmlObject;
}
XmlCursor cursor = xmlObject.newCursor();
XmlCursor moveable = xmlObject.newCursor();
//cursor is intially located before the logical STARTDOC token
try {
cursor.toFirstChild();
if ("http://java.sun.com/xml/ns/j2ee".equals(cursor.getName().getNamespaceURI())) {
XmlObject result = xmlObject.changeType(EjbJarDocument.type);
validateDD(result);
return (EjbJarDocument) result;
}
// deployment descriptor is probably in EJB 1.1 or 2.0 format
XmlDocumentProperties xmlDocumentProperties = cursor.documentProperties();
String publicId = xmlDocumentProperties.getDoctypePublicId();
String cmpVersion;
if ("-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN".equals(publicId)) {
cmpVersion = "1.x";
} else if ("-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN".equals(publicId)) {
cmpVersion = null;//2.x is the default "2.x";
} else {
throw new XmlException("Unrecognized document type: " + publicId);
}
String schemaLocationURL = "http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd";
String version = "2.1";
convertToSchema(cursor, J2EE_NAMESPACE, schemaLocationURL, version);
//play with message-driven
cursor.toStartDoc();
convertBeans(cursor, moveable, cmpVersion);
} finally {
cursor.dispose();
moveable.dispose();
}
XmlObject result = xmlObject.changeType(EjbJarDocument.type);
if (result != null) {
validateDD(result);
return (EjbJarDocument) result;
}
validateDD(xmlObject);
return (EjbJarDocument) xmlObject;
}
public static WebAppDocument convertToServletSchema(XmlObject xmlObject) throws XmlException {
if (WebAppDocument.type.equals(xmlObject.schemaType())) {
validateDD(xmlObject);
return (WebAppDocument) xmlObject;
}
XmlCursor cursor = xmlObject.newCursor();
try {
cursor.toStartDoc();
cursor.toFirstChild();
if ("http://java.sun.com/xml/ns/j2ee".equals(cursor.getName().getNamespaceURI())) {
XmlObject result = xmlObject.changeType(WebAppDocument.type);
validateDD(result);
return (WebAppDocument) result;
}
XmlDocumentProperties xmlDocumentProperties = cursor.documentProperties();
String publicId = xmlDocumentProperties.getDoctypePublicId();
if ("-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN".equals(publicId) ||
"-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN".equals(publicId)) {
XmlCursor moveable = xmlObject.newCursor();
try {
moveable.toStartDoc();
moveable.toFirstChild();
String schemaLocationURL = "http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd";
String version = "2.4";
convertToSchema(cursor, J2EE_NAMESPACE, schemaLocationURL, version);
cursor.toStartDoc();
cursor.toChild(J2EE_NAMESPACE, "web-app");
cursor.toFirstChild();
convertToDescriptionGroup(cursor, moveable);
convertToJNDIEnvironmentRefsGroup(cursor, moveable);
cursor.push();
if (cursor.toNextSibling(TAGLIB)) {
cursor.toPrevSibling();
moveable.toCursor(cursor);
cursor.beginElement("jsp-config", J2EE_NAMESPACE);
while (moveable.toNextSibling(TAGLIB)) {
moveable.moveXml(cursor);
}
}
cursor.pop();
do {
String name = cursor.getName().getLocalPart();
if ("filter".equals(name) || "servlet".equals(name)) {
cursor.push();
cursor.toFirstChild();
convertToDescriptionGroup(cursor, moveable);
if (cursor.toNextSibling(J2EE_NAMESPACE, "init-param")) {
cursor.toFirstChild();
convertToDescriptionGroup(cursor, moveable);
}
cursor.pop();
}
} while (cursor.toNextSibling());
} finally {
moveable.dispose();
}
}
} finally {
cursor.dispose();
}
XmlObject result = xmlObject.changeType(WebAppDocument.type);
if (result != null) {
validateDD(result);
return (WebAppDocument) result;
}
validateDD(xmlObject);
return (WebAppDocument) xmlObject;
}
public static void convertToGeronimoSubSchemas(XmlCursor cursor) {
cursor.toStartDoc();
XmlCursor end = cursor.newCursor();
try {
while (cursor.hasNextToken()) {
convertSingleElementToGeronimoSubSchemas(cursor, end);
cursor.toNextToken();
}
} finally {
end.dispose();
}
}
public static boolean convertSingleElementToGeronimoSubSchemas(XmlCursor cursor, XmlCursor end) {
if (cursor.isStart()) {
String localName = cursor.getName().getLocalPart();
ElementConverter converter = (ElementConverter) GERONIMO_SCHEMA_CONVERSIONS.get(localName);
if (converter != null) {
converter.convertElement(cursor, end);
return true;
}
return false;
}
//you should only call this method at a start token
return false;
}
public static XmlObject fixGeronimoSchema(XmlObject rawPlan, QName desiredElement, SchemaType desiredType) throws XmlException {
XmlCursor cursor = rawPlan.newCursor();
try {
if (findNestedElement(cursor, desiredElement)) {
cursor.push();
convertToGeronimoSubSchemas(cursor);
cursor.pop();
XmlObject temp = cursor.getObject();
XmlObject result = temp.changeType(desiredType);
if (result == null || result.schemaType() != desiredType) {
result = temp.copy().changeType(desiredType);
}
validateDD(result);
return result;
} else {
return null;
}
} finally {
cursor.dispose();
}
}
public static XmlObject getNestedObject(XmlObject xmlObject, QName desiredElement) {
XmlCursor cursor = xmlObject.newCursor();
try {
if (findNestedElement(cursor, desiredElement)) {
XmlObject child = cursor.getObject();
//The copy seems to be needed to make the type change work for some documents!
return child.copy();
}
} finally {
cursor.dispose();
}
throw new IllegalArgumentException("xmlobject did not have desired element: " + desiredElement + "/n" + xmlObject);
}
public static boolean findNestedElement(XmlCursor cursor, QName desiredElement) {
while (cursor.hasNextToken()) {
if (cursor.isStart()) {
QName element = cursor.getName();
if (element.equals(desiredElement)) {
return true;
}
}
cursor.toNextToken();
}
return false;
}
public static boolean findNestedElement(XmlCursor cursor, String desiredElement) {
while (cursor.hasNextToken()) {
if (cursor.isStart()) {
String element = cursor.getName().getLocalPart();
if (element.equals(desiredElement)) {
return true;
}
}
cursor.toNextToken();
}
return false;
}
public static XmlObject getNestedObjectAsType(XmlObject xmlObject, QName desiredElement, SchemaType type) {
XmlCursor cursor = xmlObject.newCursor();
try {
if (findNestedElement(cursor, desiredElement)) {
XmlObject child = cursor.getObject();
//The copy seems to be needed to make the type change work for some documents!
XmlObject result = child.copy().changeType(type);
assert result.schemaType() == type;
return result;
}
} finally {
cursor.dispose();
}
throw new IllegalArgumentException("xmlobject did not have desired element: " + desiredElement + "/n" + xmlObject);
}
public static boolean convertToSchema(XmlCursor cursor, String namespace, String schemaLocationURL, String version) {
//remove dtd
XmlDocumentProperties xmlDocumentProperties = cursor.documentProperties();
xmlDocumentProperties.remove(XmlDocumentProperties.DOCTYPE_NAME);
xmlDocumentProperties.remove(XmlDocumentProperties.DOCTYPE_PUBLIC_ID);
xmlDocumentProperties.remove(XmlDocumentProperties.DOCTYPE_SYSTEM_ID);
//convert namespace
boolean isFirstStart = true;
while (cursor.hasNextToken()) {
if (cursor.isStart()) {
if (namespace.equals(cursor.getName().getNamespaceURI())) {
//already has correct schema, exit
return false;
}
cursor.setName(new QName(namespace, cursor.getName().getLocalPart()));
cursor.toNextToken();
if (isFirstStart) {
cursor.insertNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
cursor.insertAttributeWithValue(new QName("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation", "xsi"), namespace + schemaLocationURL);
cursor.insertAttributeWithValue(new QName("version"), version);
isFirstStart = false;
}
} else {
cursor.toNextToken();
}
}
return true;
}
public static void convertBeans(XmlCursor cursor, XmlCursor moveable, String cmpVersion) {
cursor.toChild(J2EE_NAMESPACE, "ejb-jar");
cursor.toChild(J2EE_NAMESPACE, "enterprise-beans");
if (cursor.toFirstChild()) {
//there's at least one ejb...
do {
cursor.push();
String type = cursor.getName().getLocalPart();
if ("session".equals(type)) {
cursor.toChild(J2EE_NAMESPACE, "transaction-type");
cursor.toNextSibling();
convertToJNDIEnvironmentRefsGroup(cursor, moveable);
} else if ("entity".equals(type)) {
cursor.toChild(J2EE_NAMESPACE, "persistence-type");
String persistenceType = cursor.getTextValue();
//reentrant is the last required tag before jndiEnvironmentRefsGroup
cursor.toNextSibling(J2EE_NAMESPACE, "reentrant");
//Convert 2.0 True/False to true/false for 2.1
cursor.setTextValue(cursor.getTextValue().toLowerCase());
if (cmpVersion != null && !cursor.toNextSibling(CMP_VERSION) && "Container".equals(persistenceType)) {
cursor.toNextSibling();
cursor.insertElementWithText(CMP_VERSION, cmpVersion);
}
cursor.toNextSibling(J2EE_NAMESPACE, "abstract-schema-name");
while (cursor.toNextSibling(J2EE_NAMESPACE, "cmp-field")) {
;
}
cursor.toNextSibling(J2EE_NAMESPACE, "primkey-field");
cursor.toNextSibling();
convertToJNDIEnvironmentRefsGroup(cursor, moveable);
} else if ("message-driven".equals(type)) {
cursor.toFirstChild();
if (cursor.toNextSibling(J2EE_NAMESPACE, "messaging-type")) {
cursor.toNextSibling(J2EE_NAMESPACE, "transaction-type");
} else {
cursor.toNextSibling(J2EE_NAMESPACE, "transaction-type");
//insert messaging-type (introduced in EJB 2.1 spec) before transaction-type
cursor.insertElementWithText("messaging-type", J2EE_NAMESPACE, "javax.jms.MessageListener");
//cursor still on transaction-type
}
if (!cursor.toNextSibling(J2EE_NAMESPACE, "activation-config")) {
boolean hasProperties = false;
//skip transaction-type
cursor.toNextSibling();
//convert EJB 2.0 elements to activation-config-properties.
moveable.toCursor(cursor);
cursor.push();
cursor.beginElement("activation-config", J2EE_NAMESPACE);
hasProperties |= addActivationConfigProperty(moveable, cursor, "message-selector", "messageSelector");
hasProperties |= addActivationConfigProperty(moveable, cursor, "acknowledge-mode", "acknowledgeMode");
if (new QName(J2EE_NAMESPACE, "message-driven-destination").equals(moveable.getName()) ||
moveable.toNextSibling(J2EE_NAMESPACE, "message-driven-destination")) {
moveable.push();
moveable.toFirstChild();
hasProperties |= addActivationConfigProperty(moveable, cursor, "destination-type", "destinationType");
hasProperties |= addActivationConfigProperty(moveable, cursor, "subscription-durability", "subscriptionDurability");
moveable.pop();
moveable.removeXml();
}
cursor.pop();
if (!hasProperties) {
//the activation-config element that we created is empty so delete it
cursor.toPrevSibling();
cursor.removeXml();
//cursor should now be at first element in JNDIEnvironmentRefsGroup
}
} else {
//cursor pointing at activation-config
cursor.toNextSibling();
//cursor should now be at first element in JNDIEnvironmentRefsGroup
}
convertToJNDIEnvironmentRefsGroup(cursor, moveable);
}
cursor.pop();
} while (cursor.toNextSibling());
}
}
private static boolean addActivationConfigProperty(XmlCursor moveable, XmlCursor cursor, String elementName, String propertyName) {
QName name = new QName(J2EE_NAMESPACE, elementName);
if (name.equals(moveable.getName()) || moveable.toNextSibling(name)) {
cursor.push();
cursor.beginElement("activation-config-property", J2EE_NAMESPACE);
cursor.insertElementWithText("activation-config-property-name", J2EE_NAMESPACE, propertyName);
cursor.insertElementWithText("activation-config-property-value", J2EE_NAMESPACE, moveable.getTextValue());
moveable.removeXml();
cursor.pop();
cursor.toNextSibling();
return true;
}
return false;
}
/**
* Reorders elements to match descriptionGroup
*
* @param cursor XmlCursor positioned at first element of "group" to be reordered
*/
public static void convertToDescriptionGroup(XmlCursor cursor, XmlCursor moveable) {
moveable.toCursor(cursor);
moveElements("description", moveable, cursor);
moveElements("display-name", moveable, cursor);
moveElements("icon", moveable, cursor);
}
public static void convertToJNDIEnvironmentRefsGroup(XmlCursor cursor, XmlCursor moveable) {
moveElements("env-entry", moveable, cursor);
moveElements("ejb-ref", moveable, cursor);
moveElements("ejb-local-ref", moveable, cursor);
moveElements("resource-ref", moveable, cursor);
moveElements("resource-env-ref", moveable, cursor);
moveElements("message-destination-ref", moveable, cursor);
if (cursor.toPrevSibling()) {
do {
String name = cursor.getName().getLocalPart();
if ("env-entry".equals(name)) {
cursor.push();
cursor.toFirstChild();
convertToDescriptionGroup(cursor, moveable);
convertToEnvEntryGroup(cursor, moveable);
cursor.pop();
}
} while (cursor.toPrevSibling());
}
}
public static void convertToEnvEntryGroup(XmlCursor cursor, XmlCursor moveable) {
moveElements("env-entry-name", moveable, cursor);
moveElements("env-entry-type", moveable, cursor);
moveElements("env-entry-value", moveable, cursor);
}
public static void validateDD(XmlObject dd) throws XmlException {
XmlOptions xmlOptions = new XmlOptions();
xmlOptions.setLoadLineNumbers();
Collection errors = new ArrayList();
xmlOptions.setErrorListener(errors);
if (!dd.validate(xmlOptions)) {
throw new XmlException("Invalid deployment descriptor: " + errors + "\nDescriptor: " + dd.toString(), null, errors);
}
// System.out.println("descriptor: " + dd.toString());
}
private static void moveElements(String localName, XmlCursor moveable, XmlCursor toHere) {
QName name = new QName(J2EE_NAMESPACE, localName);
//skip elements already in the correct order.
while (name.equals(toHere.getName()) && toHere.toNextSibling()) {
}
moveable.toCursor(toHere);
while (moveable.toNextSibling(name)) {
moveable.moveXml(toHere);
}
}
}