/*=============================================================================*
* 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.ws.resource.impl;
import org.apache.ws.resource.InvalidWsrfWsdlException;
import org.apache.ws.resource.ResourceCapability;
import org.apache.ws.util.OperationInfo;
import org.apache.ws.util.WsdlUtils;
import org.apache.ws.util.WsrfWsdlUtils;
import javax.wsdl.Binding;
import javax.wsdl.Definition;
import javax.wsdl.Fault;
import javax.wsdl.Import;
import javax.wsdl.Input;
import javax.wsdl.Message;
import javax.wsdl.Operation;
import javax.wsdl.Output;
import javax.wsdl.PortType;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* A {@link ResourceCapability} implementation.
*
* @author Ian Springer (ian DOT springer AT hp DOT com)
*/
public class ResourceCapabilityImpl
implements ResourceCapability
{
private Definition m_def;
private PortType m_portType;
private Map m_implementedResourceDefs;
private QName[] m_propNames;
private String[] m_customOpNames;
private QName[] m_customPropNames;
private QName m_propsDocName;
private String m_metadataDescLocation;
private QName m_metadataDescName;
private URL m_baseUrl;
private QName m_bindingName;
/**
* Creates a new {@link ResourceCapabilityImpl} based on the specified JWSDL definition and portType.
*
* @param def a JWSDL definition
* @param baseURL
*/
public ResourceCapabilityImpl( Definition def,
PortType portType,
URL baseURL )
throws InvalidWsrfWsdlException
{
m_def = def;
m_portType = portType;
if ( m_portType.isUndefined( ) )
{
throw new InvalidWsrfWsdlException( "The portType: " + m_portType.getQName( )
+ " is undefined in your WSDL. Please check the name of your wsdl:portType and its reference in the wsdl:binding." );
}
m_baseUrl = baseURL;
m_bindingName = getBindingName( def,
m_portType.getQName( ) );
initImplementedPortTypes( );
initCustomOperations( );
initPropertyNames( );
m_metadataDescName = WsrfWsdlUtils.getMetadataDescriptorName( m_portType );
m_metadataDescLocation = WsrfWsdlUtils.getMetadataDescriptorLocation( m_portType );
if ( !m_def.getTargetNamespace( ).startsWith( "http://docs.oasis-open.org/" ) )
{
validateOperations( );
validateProperties( );
}
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public Map getAllOperations( )
{
Map opMap = new HashMap( );
List operations = m_portType.getOperations( );
for ( int i = 0; i < operations.size( ); i++ )
{
Operation o = (Operation) operations.get( i );
//does this work??
OperationInfo opInfo = new OperationInfo( o,
m_portType.getQName( ).getNamespaceURI( ) );
opMap.put( o.getName( ),
opInfo );
}
return opMap;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public QName getBindingName( )
{
return m_bindingName;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public String[] getCustomOperationNames( )
{
return m_customOpNames;
}
/**
* @return
*/
public QName[] getCustomPropertyNames( )
{
return m_customPropNames;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public Definition getDefinition( )
{
return m_def;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public Map getImplementedResourceCapabilities( )
{
return m_implementedResourceDefs;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public PortType getPortType( )
{
return m_portType;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public QName[] getPropertyNames( )
{
return m_propNames;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public boolean hasProperties( )
{
return m_propNames != null;
}
/**
* DOCUMENT_ME
*
* @param args DOCUMENT_ME
*
* @throws Exception DOCUMENT_ME
*/
public static void main( String[] args )
throws Exception
{
WSDLReader wsdlReader = WSDLFactory.newInstance( ).newWSDLReader( );
String wsdlPath = "C:\\opt\\pubscribe-1.0-beta1\\webapps\\pubscribe\\wsdl\\FileSystem.wsdl";
Definition def = wsdlReader.readWSDL( wsdlPath );
PortType portType = (PortType) def.getPortTypes( ).values( ).toArray( )[0];
ResourceCapability wsResourceDef = null;
try
{
wsResourceDef = new ResourceCapabilityImpl( def, portType, null );
}
catch ( InvalidWsrfWsdlException iwwe )
{
System.err.println( iwwe );
System.exit( 1 );
}
System.out.println( wsResourceDef );
Map implementedResourceDefs = wsResourceDef.getImplementedResourceCapabilities( );
Iterator specDefs = implementedResourceDefs.values( ).iterator( );
while ( specDefs.hasNext( ) )
{
System.out.println( (ResourceCapability) specDefs.next( ) );
}
System.out.println( wsResourceDef.getMetadataDescriptorName( ) );
System.out.println( wsResourceDef.getMetadataDescriptorLocation( ) );
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public String getMetadataDescriptorLocation( )
{
return m_metadataDescLocation;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public QName getMetadataDescriptorName( )
{
return m_metadataDescName;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public QName getPropertiesDocumentName( )
{
return m_propsDocName;
}
/**
* DOCUMENT_ME
*
* @param capabilityName DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public boolean implementsResourceCapability( QName capabilityName )
{
return m_implementedResourceDefs.containsKey( capabilityName );
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public String toString( )
{
StringBuffer strBuf = new StringBuffer( );
strBuf.append( "=== WS-Resource Definition defined via portType " + m_portType.getQName( ) + " ===\n" );
strBuf.append( "Implemented PortTypes:\n" );
if ( m_implementedResourceDefs.isEmpty( ) )
{
strBuf.append( "\t<NONE>\n" );
}
else
{
Iterator implementedPortTypeNameIter = m_implementedResourceDefs.keySet( ).iterator( );
while ( implementedPortTypeNameIter.hasNext( ) )
{
QName portTypeName = (QName) implementedPortTypeNameIter.next( );
strBuf.append( "\t" + portTypeName + "\n" );
}
}
strBuf.append( "Custom Operations:\n" );
if ( m_customOpNames.length == 0 )
{
strBuf.append( "\t<NONE>\n" );
}
else
{
for ( int i = 0; i < m_customOpNames.length; i++ )
{
strBuf.append( "\t" + m_customOpNames[i] + "\n" );
}
}
strBuf.append( "Custom Properties:\n" );
if ( !hasProperties( ) )
{
strBuf.append( "\t<NONE>\n" );
}
else
{
for ( int i = 0; i < m_customPropNames.length; i++ )
{
strBuf.append( "\t" + m_customPropNames[i] + "\n" );
}
}
return strBuf.toString( );
}
/**
* DOCUMENT_ME
*
* @throws InvalidWsrfWsdlException DOCUMENT_ME
*/
protected void validateOperations( )
throws InvalidWsrfWsdlException
{
if ( hasProperties( ) )
{
if ( !m_implementedResourceDefs.containsKey( org.apache.ws.resource.properties.v2004_11.porttype.GetResourcePropertyPortType.NAME )
&& !m_implementedResourceDefs.containsKey( org.apache.ws.resource.properties.v2004_06.porttype.GetResourcePropertyPortType.NAME ) )
{
throw new InvalidWsrfWsdlException( "PortType " + m_portType.getQName( )
+ " defines a wsrp:ResourceProperties attribute but does not implement the WSRF-RP GetResourceProperty portType." );
}
}
else
{
Iterator resourceDefNames = m_implementedResourceDefs.keySet( ).iterator( );
while ( resourceDefNames.hasNext( ) )
{
QName resourceDefName = (QName) resourceDefNames.next( );
if ( resourceDefName.getNamespaceURI( ).equals( org.apache.ws.resource.properties.v2004_11.ResourcePropertiesConstants.NSURI_WSRP_WSDL )
|| resourceDefName.getNamespaceURI( ).equals( org.apache.ws.resource.properties.v2004_06.ResourcePropertiesConstants.NSURI_WSRP_WSDL ) )
{
throw new InvalidWsrfWsdlException( "PortType " + m_portType.getQName( )
+ " does not define a wsrp:ResourceProperties attribute but implements one or more WSRF-RP portTypes." );
}
}
}
}
/**
* DOCUMENT_ME
*
* @throws InvalidWsrfWsdlException DOCUMENT_ME
*/
protected void validateProperties( )
throws InvalidWsrfWsdlException
{
boolean isValid = true;
List propNameList;
if ( m_propNames != null ) //avoid a null pointer if m_propNames are null (i.e. no props defined)
{
propNameList = Arrays.asList( m_propNames );
}
else
{
propNameList = new ArrayList( ); //no properties were defined....
} //continue checking if implemented defs had props that the user didn't implement
Iterator defIter = m_implementedResourceDefs.values( ).iterator( );
while ( defIter.hasNext( ) )
{
ResourceCapability def = (ResourceCapability) defIter.next( );
if ( def.hasProperties( ) )
{
QName[] propNames = def.getPropertyNames( );
Set missingPropNames = new HashSet( );
for ( int i = 0; i < propNames.length; i++ )
{
if ( !propNameList.contains( propNames[i] ) )
{
missingPropNames.add( propNames[i] );
}
}
if ( !missingPropNames.isEmpty( ) )
{
System.err.println( "PortType implements the operations from the "
+ def.getPortType( ).getQName( )
+ " portType but does not define the following required properties: "
+ missingPropNames );
isValid = false;
}
}
}
if ( !isValid )
{
throw new InvalidWsrfWsdlException( "PortType " + m_portType.getQName( )
+ " does not define one or more properties required by the portTypes it implements." );
}
}
private QName getBindingName( Definition def,
QName portTypeQName )
{
Map bindings = def.getBindings( );
Iterator iterator = bindings.values( ).iterator( );
while ( iterator.hasNext( ) )
{
Binding binding = (Binding) iterator.next( );
if ( binding.getPortType( ).getQName( ).equals( portTypeQName ) )
{
return binding.getQName( );
}
}
return null;
}
private ResourceCapability[] getImportedResourceDefinitions( )
throws InvalidWsrfWsdlException
{
List importedResourceDefs = new ArrayList( );
Import[] imports = getImports( m_def );
for ( int i = 0; i < imports.length; i++ )
{
Definition def = imports[i].getDefinition( );
Map portTypes = def.getPortTypes( );
Iterator portTypeIter = portTypes.values( ).iterator( );
while ( portTypeIter.hasNext( ) )
{
PortType portType = (PortType) portTypeIter.next( );
URL baseUrl = null;
try
{
baseUrl = new URL( m_baseUrl,
imports[i].getLocationURI( ) );
}
catch ( MalformedURLException e )
{
throw new InvalidWsrfWsdlException( "Invalid import location " + imports[i].getLocationURI( ) );
}
importedResourceDefs.add( new ResourceCapabilityImpl( def, portType, baseUrl ) );
}
}
return (ResourceCapability[]) importedResourceDefs.toArray( new ResourceCapability[0] );
}
private Import[] getImports( Definition def )
{
Set importSet = new HashSet( );
Map importMap = def.getImports( );
Iterator iter = importMap.keySet( ).iterator( );
while ( iter.hasNext( ) )
{
String nsURI = (String) iter.next( );
Iterator importsIter = ( (List) importMap.get( nsURI ) ).iterator( );
while ( importsIter.hasNext( ) )
{
Import anImport = (Import) importsIter.next( );
Import[] importDefImports = getImports( anImport.getDefinition( ) );
List imports = new ArrayList( );
imports.add( anImport );
imports.addAll( Arrays.asList( importDefImports ) );
for ( int i = 0; i < imports.size( ); i++ )
{
Import importToCheck = (Import) imports.get( i );
if ( !importIsRedundant( importSet, importToCheck ) )
{
importSet.add( anImport );
}
}
}
}
return (Import[]) importSet.toArray( new Import[0] );
}
private boolean isInheritedOperation( Set inheritedOps,
Operation op )
{
boolean isInheritedOp = false;
Iterator inheritedOpIter = inheritedOps.iterator( );
while ( inheritedOpIter.hasNext( ) )
{
Operation inheritedOp = (Operation) inheritedOpIter.next( );
if ( WsdlUtils.equals( op, inheritedOp ) )
{
isInheritedOp = true;
break;
}
}
return isInheritedOp;
}
private Set getInheritedOperations( )
{
Set specOps = new HashSet( );
Iterator defIter = m_implementedResourceDefs.values( ).iterator( );
while ( defIter.hasNext( ) )
{
ResourceCapability def = (ResourceCapability) defIter.next( );
List ops = def.getPortType( ).getOperations( );
for ( int i = 0; i < ops.size( ); i++ )
{
specOps.add( (Operation) ops.get( i ) );
}
}
return specOps;
}
private boolean isInheritedProperty( Set inheritedPropNames,
QName propName )
{
boolean isInheritedProp = false;
Iterator inheritedPropNameIter = inheritedPropNames.iterator( );
while ( inheritedPropNameIter.hasNext( ) )
{
QName inheritedPropName = (QName) inheritedPropNameIter.next( );
if ( inheritedPropName.equals( propName ) )
{
isInheritedProp = true;
break;
}
}
return isInheritedProp;
}
private Set getInheritedPropertyNames( )
{
Set inheritedPropNames = new HashSet( );
Iterator defIter = m_implementedResourceDefs.values( ).iterator( );
while ( defIter.hasNext( ) )
{
ResourceCapability def = (ResourceCapability) defIter.next( );
if ( def.hasProperties( ) )
{
QName[] propNames = def.getPropertyNames( );
for ( int i = 0; i < propNames.length; i++ )
{
inheritedPropNames.add( propNames[i] );
}
}
}
return inheritedPropNames;
}
private boolean importIsRedundant( Set imports,
Import anImport )
{
boolean importIsRedundant = false;
Iterator importIter = imports.iterator( );
while ( importIter.hasNext( ) )
{
Import anotherImport = (Import) importIter.next( );
if ( WsdlUtils.equals( anImport, anotherImport ) )
{
importIsRedundant = true;
break;
}
}
return importIsRedundant;
}
private void initCustomOperations( ) throws InvalidWsrfWsdlException
{
Set customOpNames = new HashSet( );
Set inheritedOps = getInheritedOperations( );
List ops = m_portType.getOperations( );
for ( int i = 0; i < ops.size( ); i++ )
{
Operation op = (Operation) ops.get( i );
validateOperationIsDefined(op);
if ( !isInheritedOperation( inheritedOps, op ) )
{
customOpNames.add( op.getName( ) );
}
}
m_customOpNames = (String[]) customOpNames.toArray( new String[0] );
}
/**
* Determines if the given Operation's messages, and its fault's messages, are defined, thereby ruling out
* missing WSDL imports and avoiding potential generation issues.
*
* @param op
* @throws InvalidWsrfWsdlException
*/
private void validateOperationIsDefined(Operation op) throws InvalidWsrfWsdlException {
Input input = op.getInput();
if(input != null)
{
Message message = input.getMessage();
determineIfMessageIsUndefined(op, message);
}
Output output = op.getOutput();
if(output != null)
{
Message message = output.getMessage();
determineIfMessageIsUndefined(op, message);
}
Iterator iterator = op.getFaults().values().iterator();
while (iterator.hasNext()) {
Fault fault = (Fault) iterator.next();
if(fault.getMessage().isUndefined() == true)
{
throw new InvalidWsrfWsdlException("The import for the namespace: " + op.getInput().getMessage().getQName().getNamespaceURI() + " was either undefined or is invalid. Please check your WSDL imports.");
}
}
}
/**
* @param op
* @param message
* @throws InvalidWsrfWsdlException
*/
private void determineIfMessageIsUndefined(Operation op, Message message) throws InvalidWsrfWsdlException {
if(message.isUndefined() == true)
{
throw new InvalidWsrfWsdlException("The import for the namespace: " + op.getInput().getMessage().getQName().getNamespaceURI() + " was either undefined or is invalid. Please check your WSDL imports.");
}
}
private void initImplementedPortTypes( )
throws InvalidWsrfWsdlException
{
m_implementedResourceDefs = new HashMap( );
ResourceCapability[] importedResourceDefs = getImportedResourceDefinitions( );
for ( int i = 0; i < importedResourceDefs.length; i++ )
{
PortType importedPortType = importedResourceDefs[i].getPortType( );
if ( WsrfWsdlUtils.implementsPortType( m_portType, importedPortType ) )
{
m_implementedResourceDefs.put( importedPortType.getQName( ),
importedResourceDefs[i] );
}
}
}
private void initPropertyNames( )
throws InvalidWsrfWsdlException
{
m_propsDocName = WsrfWsdlUtils.getResourcePropertiesDocumentName( m_portType );
m_propNames = WsrfWsdlUtils.getResourcePropertyNames( m_propsDocName, m_def, m_baseUrl );
Set customPropNames = new HashSet( );
if ( hasProperties( ) )
{
Set inheritedPropNames = getInheritedPropertyNames( );
for ( int i = 0; i < m_propNames.length; i++ )
{
if ( !isInheritedProperty( inheritedPropNames, m_propNames[i] ) )
{
customPropNames.add( m_propNames[i] );
}
}
}
m_customPropNames = (QName[]) customPropNames.toArray( new QName[0] );
}
}