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.web.deployment;
018
019 import java.util.ArrayList;
020 import java.util.HashMap;
021 import java.util.List;
022 import java.util.Map;
023
024 import javax.xml.namespace.QName;
025
026 import org.apache.geronimo.common.DeploymentException;
027 import org.apache.geronimo.deployment.xbeans.ModuleDocument;
028 import org.apache.geronimo.schema.SchemaConversionUtils;
029 import org.apache.geronimo.xbeans.geronimo.security.GerSecurityDocument;
030 import org.apache.geronimo.xbeans.geronimo.web.GerWebAppDocument;
031 import org.apache.xmlbeans.XmlCursor;
032 import org.apache.xmlbeans.XmlObject;
033
034 /**
035 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
036 */
037 public class GenericToSpecificPlanConverter {
038
039 private static final QName GENERIC_QNAME = GerWebAppDocument.type.getDocumentElementName();
040 private static final String GENERIC_NAMESPACE = GENERIC_QNAME.getNamespaceURI();
041 private static final String OLD_GENERIC_NAMESPACE = "http://geronimo.apache.org/xml/ns/web";
042
043 private static final QName GENERIC_CONFIG_QNAME = new QName(GENERIC_NAMESPACE, "container-config");
044 private static final QName OLD_GENERIC_CONFIG_QNAME = new QName(OLD_GENERIC_NAMESPACE, "container-config");
045 private static final String SYSTEM_NAMESPACE = ModuleDocument.type.getDocumentElementName().getNamespaceURI();
046 private static final QName SECURITY_QNAME = GerSecurityDocument.type.getDocumentElementName();
047 private final String configNamespace;
048 private final String namespace;
049 private final String element;
050
051 public GenericToSpecificPlanConverter(String configNamespace, String namespace, String element) {
052 this.configNamespace = configNamespace;
053 this.namespace = namespace;
054 this.element = element;
055 }
056
057 public XmlObject convertToSpecificPlan(XmlObject plan) throws DeploymentException {
058 XmlCursor rawCursor = plan.newCursor();
059 try {
060 if (SchemaConversionUtils.findNestedElement(rawCursor, "web-app")) {
061 XmlCursor temp = rawCursor.newCursor();
062 String namespace = temp.getName().getNamespaceURI();
063 temp.dispose();
064 if(!namespace.equals(GENERIC_NAMESPACE) && !namespace.equals(this.namespace) && !namespace.equals(OLD_GENERIC_NAMESPACE)) {
065 throw new DeploymentException("Cannot handle web plan with namespace "+namespace+" -- expecting "+GENERIC_NAMESPACE+" or "+this.namespace);
066 }
067
068 XmlObject webPlan = rawCursor.getObject().copy();
069
070 XmlCursor cursor = webPlan.newCursor();
071 XmlCursor end = cursor.newCursor();
072 try {
073 cursor.push();
074 if (cursor.toChild(GENERIC_CONFIG_QNAME) || cursor.toChild(OLD_GENERIC_CONFIG_QNAME)) {
075 XmlCursor source = cursor.newCursor();
076 cursor.push();
077 cursor.toEndToken();
078 cursor.toNextToken();
079 try {
080 if (source.toChild(configNamespace, element)) {
081 source.copyXmlContents(cursor);
082 }
083
084 } finally {
085 source.dispose();
086 }
087 cursor.pop();
088 cursor.removeXml();
089 }
090 cursor.pop();
091
092 cursor.push();
093 while (cursor.hasNextToken()) {
094 if (cursor.isStart()) {
095 if (!SchemaConversionUtils.convertSingleElementToGeronimoSubSchemas(cursor, end)
096 && !this.namespace.equals(cursor.getName().getNamespaceURI())) {
097 cursor.setName(new QName(this.namespace, cursor.getName().getLocalPart()));
098 }
099 }
100 cursor.toNextToken();
101 }
102 cursor.pop();
103
104 cursor.push();
105 Map<Object, List<XmlCursor>> map = createElementMap(cursor);
106 cursor.pop();
107
108 moveToBottom(cursor, map.get("security-realm-name"));
109 moveToBottom(cursor, map.get("security"));
110 moveToBottom(cursor, map.get("gbean"));
111 moveToBottom(cursor, map.get("persistence"));
112
113 clearElementMap(map);
114
115 return webPlan;
116 } finally {
117 cursor.dispose();
118 end.dispose();
119 }
120 } else {
121 throw new DeploymentException("No web-app element");
122 }
123 } finally {
124 rawCursor.dispose();
125 }
126 }
127
128 private static Map<Object, List<XmlCursor>> createElementMap(XmlCursor cursor) {
129 Map<Object, List<XmlCursor>> map = new HashMap<Object, List<XmlCursor>>();
130 cursor.toStartDoc();
131 if (cursor.toFirstChild()) {
132 do {
133 QName name = cursor.getName();
134 List<XmlCursor> locations = map.get(name);
135 if (locations == null) {
136 locations = new ArrayList<XmlCursor>();
137 map.put(name, locations);
138 map.put(name.getLocalPart(), locations);
139 }
140 locations.add(cursor.newCursor());
141 } while(cursor.toNextSibling());
142 }
143 return map;
144 }
145
146 private static void clearElementMap(Map<Object, List<XmlCursor>> map) {
147 for (Map.Entry<Object, List<XmlCursor>> entry : map.entrySet()) {
148 for (XmlCursor cursor : entry.getValue()) {
149 cursor.dispose();
150 }
151 }
152 map.clear();
153 }
154
155 private static void moveToBottom(XmlCursor cursor, List<XmlCursor> locations) {
156 if (locations != null) {
157 for (XmlCursor location : locations) {
158 cursor.toEndDoc();
159 location.moveXml(cursor);
160 }
161 }
162 }
163
164 }