/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * 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.pentaho.di.trans.steps.webservices.wsdl; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import javax.wsdl.Definition; import javax.wsdl.Types; import javax.wsdl.extensions.ExtensibilityElement; import javax.wsdl.extensions.schema.Schema; import javax.xml.namespace.QName; import org.pentaho.di.core.exception.KettleStepException; import org.pentaho.di.i18n.BaseMessages; import org.w3c.dom.Element; /** * WsdlTypes provides utilities for getting information about the <types> section of the WSDL. */ public final class WsdlTypes implements Serializable { private static Class<?> PKG = WsdlTypes.class; // for i18n purposes, needed by Translator2!! private static final long serialVersionUID = 1L; private final String _targetNamespace; private final Types _types; private HashSet<String> _elementFormQualifiedNamespaces; private Map<String, String> _prefixMappings; private WsdlComplexTypes _namedComplexTypes; /** * Create a new for WsdlTypes instance for the specified WSDL definition. * * @param wsdlDefinition * The WSDL definition. */ @SuppressWarnings( "unchecked" ) protected WsdlTypes( Definition wsdlDefinition ) { _types = wsdlDefinition.getTypes(); _targetNamespace = wsdlDefinition.getTargetNamespace(); _prefixMappings = wsdlDefinition.getNamespaces(); _elementFormQualifiedNamespaces = new HashSet<String>( getElementFormQualifiedNamespaces() ); _namedComplexTypes = new WsdlComplexTypes( this ); } /** * Find a named <element> in the types section of the WSDL. * * @param elementName * Name of element to find. * @return The element node. * @throws KettleStepException * If schema or element in schema can't be found for the given element name */ protected Element findNamedElement( QName elementName ) throws KettleStepException { Element namedElement = null; Schema s = getSchema( elementName.getNamespaceURI() ); if ( s == null ) { throw new KettleStepException( BaseMessages .getString( PKG, "Wsdl.Error.MissingSchemaException", elementName ) ); } Element schemaRoot = s.getElement(); List<Element> elements = DomUtils.getChildElementsByName( schemaRoot, WsdlUtils.ELEMENT_NAME ); for ( Element e : elements ) { String schemaElementName = e.getAttribute( WsdlUtils.NAME_ATTR ); if ( elementName.getLocalPart().equals( schemaElementName ) ) { namedElement = e; break; } } if ( namedElement == null ) { throw new KettleStepException( BaseMessages.getString( PKG, "Wsdl.Error.ElementMissingException", elementName ) ); } return namedElement; } /** * Find a named <complexType> or <simpleType> in the types section of the WSDL. * * @param typeName * Name of the type to find. * @return null if type not found. */ protected Element findNamedType( QName typeName ) { Schema s = getSchema( typeName.getNamespaceURI() ); if ( s == null ) { return null; } Element schemaRoot = s.getElement(); // get all simple and complex types defined at the top-level. // List<Element> types = DomUtils.getChildElementsByName( schemaRoot, WsdlUtils.COMPLEX_TYPE_NAME ); types.addAll( DomUtils.getChildElementsByName( schemaRoot, WsdlUtils.SIMPLE_TYPE_NAME ) ); Element namedType = null; for ( Element t : types ) { String schemaTypeName = t.getAttribute( WsdlUtils.NAME_ATTR ); if ( typeName.getLocalPart().equals( schemaTypeName ) ) { namedType = t; break; } } return namedType; } /** * Get the map of named complex types defined in the WSDL. * * @return Wsdl's named complex types. */ protected WsdlComplexTypes getNamedComplexTypes() { return _namedComplexTypes; } /** * Get the target namespace of the wsdl. * * @return String contianing the target namespace. */ protected String getTargetNamespace() { return _targetNamespace; } /** * Get the type qname for the type parameter. Resolve namespace references if present, if a namespace prefix is not * found the WSDL's target namespace will be used. * * @param type * Name of type. * @return A QName for the type name. */ protected QName getTypeQName( String type ) { if ( type.indexOf( ':' ) > -1 ) { String prefix = type.substring( 0, type.indexOf( ':' ) ); type = type.substring( type.indexOf( ':' ) + 1 ); return new QName( _prefixMappings.get( prefix ), type ); } else { return new QName( _targetNamespace, type ); } } /** * Return a list of of all schemas defined by the WSDL definition. * * @return A list of javax.wsdl.extension.schema.Schema elements. */ protected List<ExtensibilityElement> getSchemas() { if ( _types == null ) { return Collections.emptyList(); } return WsdlUtils.findExtensibilityElements( _types, WsdlUtils.SCHEMA_ELEMENT_NAME ); } /** * Determine if the namespace URI is element form qualifed. * * @param namespaceURI * Namespace URI string. * @return true If element form is qualified. */ public boolean isElementFormQualified( String namespaceURI ) { return _elementFormQualifiedNamespaces.contains( namespaceURI ); } /** * Build a list of schema target name spaces which are element form qualified. * * @return All target name spaces for schemas defined in the WSDL which are element form qualified. */ private List<String> getElementFormQualifiedNamespaces() { List<String> namespaces = new ArrayList<String>(); List<ExtensibilityElement> schemas = getSchemas(); for ( ExtensibilityElement schema : schemas ) { Element schemaElement = ( (Schema) schema ).getElement(); if ( schemaElement.hasAttribute( WsdlUtils.ELEMENT_FORM_DEFAULT_ATTR ) ) { String v = schemaElement.getAttribute( WsdlUtils.ELEMENT_FORM_DEFAULT_ATTR ); if ( WsdlUtils.ELEMENT_FORM_QUALIFIED.equalsIgnoreCase( v ) ) { namespaces.add( schemaElement.getAttribute( WsdlUtils.TARGET_NAMESPACE_ATTR ) ); } } } return namespaces; } /** * Get the schema with the specified target namespace. * * @param targetNamespace * target namespace of the schema to get. * @return null if not found. */ private Schema getSchema( String targetNamespace ) { if ( _types == null ) { return null; } List<ExtensibilityElement> schemas = WsdlUtils.findExtensibilityElements( _types, "schema" ); for ( ExtensibilityElement e : schemas ) { Element schemaRoot = ( (Schema) e ).getElement(); String tns = schemaRoot.getAttribute( "targetNamespace" ); if ( targetNamespace.equals( tns ) ) { return (Schema) e; } } return null; } }