/*
* 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.WsdlUtils;
import org.apache.ws.util.WsrfWsdlUtils;
import javax.wsdl.Definition;
import javax.wsdl.Import;
import javax.wsdl.Operation;
import javax.wsdl.PortType;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.net.URL;
import java.net.MalformedURLException;
/**
* 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;
/**
* 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;
m_baseUrl = baseURL;
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();
}
}
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." );
}
}
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." );
}
}
}
}
public boolean hasProperties()
{
return m_propNames != null;
}
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] );
}
public Map getImplementedResourceCapabilities()
{
return m_implementedResourceDefs;
}
/**
* 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 PortType getPortType()
{
return m_portType;
}
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 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] );
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public QName[] getPropertyNames()
{
return m_propNames;
}
/**
* 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();
}
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 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()
{
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 );
if ( !isInheritedOperation( inheritedOps, op ) )
{
customOpNames.add( op.getName() );
}
}
m_customOpNames = (String[]) customOpNames.toArray( new String[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 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 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 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;
}
/**
* 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\\hermes-1.0-beta1\\webapps\\hermes\\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() );
}
public boolean implementsResourceCapability( QName capabilityName )
{
return m_implementedResourceDefs.containsKey( capabilityName );
}
public QName getPropertiesDocumentName()
{
return m_propsDocName;
}
public QName getMetadataDescriptorName()
{
return m_metadataDescName;
}
public String getMetadataDescriptorLocation()
{
return m_metadataDescLocation;
}
}