001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.jaxb;
019:
020: import java.lang.reflect.Field;
021: import java.util.Iterator;
022:
023: import javax.xml.namespace.QName;
024:
025: import com.sun.xml.bind.v2.runtime.JAXBContextImpl;
026: import com.sun.xml.bind.v2.runtime.JaxBeanInfo;
027:
028: import org.apache.cxf.service.ServiceModelVisitor;
029: import org.apache.cxf.service.model.FaultInfo;
030: import org.apache.cxf.service.model.MessagePartInfo;
031: import org.apache.cxf.service.model.SchemaInfo;
032: import org.apache.cxf.service.model.ServiceInfo;
033: import org.apache.cxf.wsdl.WSDLConstants;
034: import org.apache.ws.commons.schema.XmlSchema;
035: import org.apache.ws.commons.schema.XmlSchemaCollection;
036: import org.apache.ws.commons.schema.XmlSchemaComplexType;
037: import org.apache.ws.commons.schema.XmlSchemaElement;
038: import org.apache.ws.commons.schema.XmlSchemaForm;
039: import org.apache.ws.commons.schema.XmlSchemaObject;
040: import org.apache.ws.commons.schema.XmlSchemaSequence;
041: import org.apache.ws.commons.schema.utils.NamespaceMap;
042:
043: /**
044: * Walks the service model and sets up the element/type names.
045: */
046: class JAXBSchemaInitializer extends ServiceModelVisitor {
047:
048: private XmlSchemaCollection schemas;
049: private JAXBContextImpl context;
050:
051: public JAXBSchemaInitializer(ServiceInfo serviceInfo,
052: XmlSchemaCollection col, JAXBContextImpl context) {
053: super (serviceInfo);
054: schemas = col;
055: this .context = context;
056: }
057:
058: @Override
059: public void begin(MessagePartInfo part) {
060: // Check to see if the WSDL information has been filled in for us.
061: if (part.getTypeQName() != null
062: || part.getElementQName() != null) {
063: checkForExistence(part);
064: return;
065: }
066:
067: Class<?> clazz = part.getTypeClass();
068: if (clazz == null) {
069: return;
070: }
071:
072: boolean isFromWrapper = part.getMessageInfo().getOperation()
073: .isUnwrapped();
074: if (isFromWrapper && clazz.isArray()
075: && !Byte.TYPE.equals(clazz.getComponentType())) {
076: clazz = clazz.getComponentType();
077: }
078:
079: JaxBeanInfo<?> beanInfo = context.getBeanInfo(clazz);
080: if (beanInfo == null) {
081: if (Exception.class.isAssignableFrom(clazz)) {
082: QName name = (QName) part.getMessageInfo().getProperty(
083: "elementName");
084: part.setElementQName(name);
085: buildExceptionType(part, clazz);
086: }
087: return;
088: }
089:
090: boolean isElement = beanInfo.isElement();
091:
092: part.setElement(isElement);
093:
094: if (isElement) {
095: QName name = new QName(beanInfo
096: .getElementNamespaceURI(null), beanInfo
097: .getElementLocalName(null));
098: XmlSchemaElement el = schemas.getElementByQName(name);
099: if (el != null && el.getRefName() != null) {
100: part.setTypeQName(el.getRefName());
101: } else {
102: part.setElementQName(name);
103: }
104: part.setXmlSchema(el);
105: } else {
106: QName typeName = getTypeName(beanInfo);
107: if (typeName != null) {
108: part.setTypeQName(typeName);
109: part.setXmlSchema(schemas.getTypeByQName(typeName));
110: }
111: }
112: }
113:
114: private QName getTypeName(JaxBeanInfo<?> beanInfo) {
115: Iterator<QName> itr = beanInfo.getTypeNames().iterator();
116: if (!itr.hasNext()) {
117: return null;
118: }
119:
120: return itr.next();
121: }
122:
123: public void checkForExistence(MessagePartInfo part) {
124: QName qn = part.getElementQName();
125: if (qn != null) {
126: XmlSchemaElement el = schemas.getElementByQName(qn);
127: if (el == null) {
128: Class<?> clazz = part.getTypeClass();
129: if (clazz == null) {
130: return;
131: }
132:
133: boolean isFromWrapper = part.getMessageInfo()
134: .getOperation().isUnwrapped();
135: if (isFromWrapper && clazz.isArray()
136: && !Byte.TYPE.equals(clazz.getComponentType())) {
137: clazz = clazz.getComponentType();
138: }
139: JaxBeanInfo<?> beanInfo = context.getBeanInfo(clazz);
140: if (beanInfo == null) {
141: if (Exception.class.isAssignableFrom(clazz)) {
142: QName name = (QName) part.getMessageInfo()
143: .getProperty("elementName");
144: part.setElementQName(name);
145: buildExceptionType(part, clazz);
146: }
147: return;
148: }
149:
150: QName typeName = getTypeName(beanInfo);
151:
152: createBridgeXsElement(part, qn, typeName);
153: }
154: }
155: }
156:
157: private void createBridgeXsElement(MessagePartInfo part, QName qn,
158: QName typeName) {
159: XmlSchemaElement el = null;
160: SchemaInfo schemaInfo = null;
161: for (SchemaInfo s : serviceInfo.getSchemas()) {
162: if (s.getNamespaceURI().equals(qn.getNamespaceURI())) {
163: schemaInfo = s;
164:
165: el = createXsElement(part, typeName, schemaInfo);
166:
167: schemaInfo.getSchema().getItems().add(el);
168:
169: return;
170: }
171: }
172:
173: schemaInfo = new SchemaInfo(serviceInfo, qn.getNamespaceURI());
174: el = createXsElement(part, typeName, schemaInfo);
175:
176: XmlSchema schema = new XmlSchema(qn.getNamespaceURI(), schemas);
177: schemaInfo.setSchema(schema);
178: schema.getItems().add(el);
179:
180: NamespaceMap nsMap = new NamespaceMap();
181: nsMap.add(WSDLConstants.NP_SCHEMA_XSD,
182: WSDLConstants.NU_SCHEMA_XSD);
183: schema.setNamespaceContext(nsMap);
184:
185: serviceInfo.addSchema(schemaInfo);
186: }
187:
188: private XmlSchemaElement createXsElement(MessagePartInfo part,
189: QName typeName, SchemaInfo schemaInfo) {
190: XmlSchemaElement el = new XmlSchemaElement();
191: el.setQName(part.getElementQName());
192: el.setName(part.getElementQName().getLocalPart());
193: el.setNillable(true);
194: el.setSchemaTypeName(typeName);
195: part.setXmlSchema(el);
196: return el;
197: }
198:
199: public void end(FaultInfo fault) {
200: MessagePartInfo part = fault.getMessageParts().get(0);
201: Class<?> cls = part.getTypeClass();
202: Class<?> cl2 = (Class) fault.getProperty(Class.class.getName());
203: if (cls != cl2) {
204: QName name = (QName) fault.getProperty("elementName");
205: part.setElementQName(name);
206: JaxBeanInfo<?> beanInfo = context.getBeanInfo(cls);
207: SchemaInfo schemaInfo = null;
208: for (SchemaInfo s : serviceInfo.getSchemas()) {
209: if (s.getNamespaceURI().equals(
210: part.getElementQName().getNamespaceURI())) {
211: schemaInfo = s;
212:
213: XmlSchemaElement el = new XmlSchemaElement();
214: el.setQName(part.getElementQName());
215: el.setName(part.getElementQName().getLocalPart());
216: el.setNillable(true);
217:
218: if (!isExistSchemaElement(schemaInfo.getSchema(),
219: part.getElementQName())) {
220: schemaInfo.getSchema().getItems().add(el);
221: }
222:
223: Iterator<QName> itr = beanInfo.getTypeNames()
224: .iterator();
225: if (!itr.hasNext()) {
226: continue;
227: }
228: QName typeName = itr.next();
229: el.setSchemaTypeName(typeName);
230:
231: return;
232: }
233: }
234: }
235: }
236:
237: private void buildExceptionType(MessagePartInfo part, Class cls) {
238: SchemaInfo schemaInfo = null;
239: for (SchemaInfo s : serviceInfo.getSchemas()) {
240: if (s.getNamespaceURI().equals(
241: part.getElementQName().getNamespaceURI())) {
242: schemaInfo = s;
243: break;
244: }
245: }
246: XmlSchema schema;
247: if (schemaInfo == null) {
248: schema = new XmlSchema(part.getElementQName()
249: .getNamespaceURI(), schemas);
250: schema.setElementFormDefault(new XmlSchemaForm(
251: XmlSchemaForm.QUALIFIED));
252:
253: NamespaceMap nsMap = new NamespaceMap();
254: nsMap.add(WSDLConstants.NP_SCHEMA_XSD,
255: WSDLConstants.NU_SCHEMA_XSD);
256: schema.setNamespaceContext(nsMap);
257:
258: schemaInfo = new SchemaInfo(serviceInfo, part
259: .getElementQName().getNamespaceURI());
260: schemaInfo.setSchema(schema);
261: serviceInfo.addSchema(schemaInfo);
262: } else {
263: schema = schemaInfo.getSchema();
264: }
265:
266: XmlSchemaComplexType ct = new XmlSchemaComplexType(schema);
267: ct.setName(part.getElementQName().getLocalPart());
268: // Before updating everything, make sure we haven't added this
269: // type yet. Multiple methods that throw the same exception
270: // types will cause duplicates.
271: if (schema.getTypeByName(ct.getQName()) != null) {
272: return;
273: }
274:
275: XmlSchemaElement el = new XmlSchemaElement();
276: el.setQName(part.getElementQName());
277: el.setName(part.getElementQName().getLocalPart());
278: schema.getItems().add(el);
279:
280: schema.getItems().add(ct);
281: schema.addType(ct);
282: el.setSchemaTypeName(part.getElementQName());
283:
284: XmlSchemaSequence seq = new XmlSchemaSequence();
285: ct.setParticle(seq);
286: String namespace = part.getElementQName().getNamespaceURI();
287: for (Field f : cls.getDeclaredFields()) {
288: JaxBeanInfo<?> beanInfo = context.getBeanInfo(f.getType());
289: if (beanInfo != null) {
290: el = new XmlSchemaElement();
291: el.setName(f.getName());
292: el.setQName(new QName(namespace, f.getName()));
293:
294: el.setMinOccurs(1);
295: el.setMaxOccurs(1);
296: el.setNillable(true);
297:
298: if (beanInfo.isElement()) {
299: QName name = new QName(beanInfo
300: .getElementNamespaceURI(null), beanInfo
301: .getElementLocalName(null));
302: XmlSchemaElement el2 = schemas
303: .getElementByQName(name);
304: el.setRefName(el2.getRefName());
305: } else {
306: Iterator<QName> itr = beanInfo.getTypeNames()
307: .iterator();
308: if (!itr.hasNext()) {
309: continue;
310: }
311: QName typeName = itr.next();
312: el.setSchemaTypeName(typeName);
313: }
314:
315: seq.getItems().add(el);
316: }
317: }
318: JaxBeanInfo<?> beanInfo = context.getBeanInfo(String.class);
319: el = new XmlSchemaElement();
320: el.setName("message");
321: el.setQName(new QName(namespace, "message"));
322:
323: el.setMinOccurs(1);
324: el.setMaxOccurs(1);
325: el.setNillable(true);
326:
327: if (beanInfo.isElement()) {
328: el.setRefName(beanInfo.getTypeName(null));
329: } else {
330: el.setSchemaTypeName(beanInfo.getTypeName(null));
331: }
332: seq.getItems().add(el);
333: }
334:
335: private boolean isExistSchemaElement(XmlSchema schema, QName qn) {
336: boolean isExist = false;
337: for (Iterator ite = schema.getItems().getIterator(); ite
338: .hasNext();) {
339: XmlSchemaObject obj = (XmlSchemaObject) ite.next();
340: if (obj instanceof XmlSchemaElement) {
341: XmlSchemaElement xsEle = (XmlSchemaElement) obj;
342: if (xsEle.getQName().equals(qn)) {
343: isExist = true;
344: break;
345: }
346: }
347: }
348: return isExist;
349: }
350: }
|