/*=============================================================================*
* 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.notification.base.v2004_06.porttype.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.XmlObjectWrapper;
import org.apache.ws.addressing.EndpointReference;
import org.apache.ws.addressing.XmlBeansEndpointReference;
import org.apache.ws.notification.base.NotificationProducerResource;
import org.apache.ws.notification.base.Subscription;
import org.apache.ws.notification.base.WsnNamespaceVersionHolder;
import org.apache.ws.notification.base.faults.InvalidTopicExpressionFaultException;
import org.apache.ws.notification.base.faults.NoCurrentMessageOnTopicFaultException;
import org.apache.ws.notification.base.faults.SubscribeCreationFailedFaultException;
import org.apache.ws.notification.base.faults.TopicPathDialectUnknownFaultException;
import org.apache.ws.notification.base.impl.XmlBeansTopicExpression;
import org.apache.ws.notification.base.v2004_06.impl.SubscriptionHome;
import org.apache.ws.notification.base.v2004_06.impl.SubscriptionResource;
import org.apache.ws.notification.base.v2004_06.impl.WsnNamespaceVersionHolderImpl;
import org.apache.ws.notification.base.v2004_06.porttype.NotificationProducerPortType;
import org.apache.ws.notification.topics.Topic;
import org.apache.ws.notification.topics.TopicSpaceSet;
import org.apache.ws.notification.topics.expression.InvalidTopicExpressionException;
import org.apache.ws.notification.topics.expression.TopicExpression;
import org.apache.ws.notification.topics.expression.TopicExpressionException;
import org.apache.ws.notification.topics.expression.TopicPathDialectUnknownException;
import org.apache.ws.notification.topics.impl.SubscriptionTopicListener;
import org.apache.ws.resource.ResourceContext;
import org.apache.ws.resource.faults.BaseFaultException;
import org.apache.ws.resource.impl.AbstractResourceContext;
import org.apache.ws.resource.properties.NamespaceVersionHolder;
import org.apache.ws.resource.properties.impl.AbstractResourcePropertiesPortType;
import org.apache.ws.resource.properties.query.QueryExpression;
import org.apache.ws.resource.properties.query.impl.XmlBeansQueryExpression;
import org.apache.ws.util.XmlBeanUtils;
import org.apache.xmlbeans.XmlObject;
import org.oasisOpen.docs.wsn.x2004.x06.wsnWSBaseNotification12Draft01.GetCurrentMessageDocument;
import org.oasisOpen.docs.wsn.x2004.x06.wsnWSBaseNotification12Draft01.GetCurrentMessageResponseDocument;
import org.oasisOpen.docs.wsn.x2004.x06.wsnWSBaseNotification12Draft01.SubscribeDocument;
import org.oasisOpen.docs.wsn.x2004.x06.wsnWSBaseNotification12Draft01.SubscribeResponseDocument;
import org.oasisOpen.docs.wsn.x2004.x06.wsnWSBaseNotification12Draft01.TopicExpressionType;
import org.xmlsoap.schemas.ws.x2003.x03.addressing.EndpointReferenceType;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Calendar;
/**
* An implementation of the WS-BaseNotification NotificationProducer portType.
*
* @author Ian Springer (ian DOT springer AT hp DOT com)
*/
public class NotificationProducerPortTypeImpl
extends AbstractResourcePropertiesPortType
implements NotificationProducerPortType
{
private static final Log LOG =
LogFactory.getLog( NotificationProducerPortTypeImpl.class.getName( ) );
private static final WsnNamespaceVersionHolder NAMESPACE_SET = new WsnNamespaceVersionHolderImpl( );
/**
* Creates a new {@link NotificationProducerPortTypeImpl} object.
*
* @param resourceContext DOCUMENT_ME
*/
public NotificationProducerPortTypeImpl( ResourceContext resourceContext )
{
super( resourceContext );
}
/**
* @see NotificationProducerPortType#getCurrentMessage(org.oasisOpen.docs.wsn.x2004.x06.wsnWSBaseNotification12Draft01.GetCurrentMessageDocument)
*/
public GetCurrentMessageResponseDocument getCurrentMessage( GetCurrentMessageDocument requestDoc )
{
GetCurrentMessageDocument.GetCurrentMessage request = requestDoc.getGetCurrentMessage( );
TopicExpression topicExpr = getTopicExpression( request.getTopic( ) );
Topic[] topics = evaluateTopicExpression( topicExpr );
if ( topics.length == 0 )
{
throw new InvalidTopicExpressionFaultException( NAMESPACE_SET,
"Given TopicExpression did not match any Topics supported by this NotificationProducer - the WS-BaseN spec mandates that it match exactly one." );
}
if ( topics.length > 1 )
{
throw new InvalidTopicExpressionFaultException( NAMESPACE_SET,
"Given TopicExpression matched more than one Topic supported by this NotificationProducer - the WS-BaseN spec mandates that it match exactly one." );
}
Topic topic = topics[0];
XmlObject currentMsg = (XmlObject) topic.getCurrentMessage( );
if ( currentMsg == null )
{
throw new NoCurrentMessageOnTopicFaultException( NAMESPACE_SET );
}
GetCurrentMessageResponseDocument responseDoc =
GetCurrentMessageResponseDocument.Factory.newInstance( );
GetCurrentMessageResponseDocument.GetCurrentMessageResponse response =
responseDoc.addNewGetCurrentMessageResponse( );
XmlBeanUtils.addChildElement( response, currentMsg );
return responseDoc;
}
/**
* @see NotificationProducerPortType#subscribe(org.oasisOpen.docs.wsn.x2004.x06.wsnWSBaseNotification12Draft01.SubscribeDocument)
*/
public SubscribeResponseDocument subscribe( SubscribeDocument requestDoc )
{
SubscribeDocument.Subscribe request = requestDoc.getSubscribe( );
TopicExpression topicExpr = getTopicExpression( request.getTopicExpression( ) );
Topic[] topics = evaluateTopicExpression( topicExpr );
if ( topics.length == 0 )
{
throw new InvalidTopicExpressionFaultException( NAMESPACE_SET,
"Given TopicExpression did not match any Topics supported by this NotificationProducer - the WS-BaseN spec mandates that it match at least one." );
}
Calendar initialTerminationTime = null;
if ( request.isSetInitialTerminationTime( ) )
{
initialTerminationTime = request.getInitialTerminationTime( );
}
QueryExpression precondition = null;
if ( request.isSetPrecondition( ) )
{
precondition = new XmlBeansQueryExpression( request.getPrecondition( ) );
}
QueryExpression selector = null;
if ( request.isSetSelector( ) )
{
selector = new XmlBeansQueryExpression( request.getSelector( ) );
}
XmlObject subPolicy = null;
if ( request.isSetSubscriptionPolicy( ) )
{
subPolicy = request.getSubscriptionPolicy( );
}
EndpointReferenceType subscriptionEPR = null;
boolean useNotify = request.isSetUseNotify( ) ? request.getUseNotify( ) : true; // NOTE: we must set the default value ourselves, as XMLBeans does NOT do this for us
EndpointReference producerEPR = getResource( ).getEndpointReference( );
SubscriptionHome subscriptionHome = null;
try
{
subscriptionHome = (SubscriptionHome) new InitialContext( ).lookup( SubscriptionHome.HOME_LOCATION );
}
catch ( NamingException ne )
{
LOG.error( "Subscribe failed due to internal error: " + ne );
throw new BaseFaultException( NAMESPACE_SET, "Subscribe failed due to internal server error." );
}
Subscription subscription = null;
try
{
subscription =
subscriptionHome.create( SubscriptionResource.class,
new XmlBeansEndpointReference( request.getConsumerReference( ) ),
producerEPR,
initialTerminationTime,
subPolicy,
precondition,
selector,
getResource( ).getID( ),
( (AbstractResourceContext) getResourceContext( ) ).getResourceHomeLocation( ),
topicExpr,
useNotify,
(WsnNamespaceVersionHolder) getNamespaceSet( ) );
}
catch ( Exception e )
{
LOG.error( "Subscribe failed due to internal error: " + e );
if ( LOG.isDebugEnabled( ) )
{
e.printStackTrace( );
}
throw new SubscribeCreationFailedFaultException( NAMESPACE_SET );
}
SubscriptionTopicListener subscriptionTopicListener = new SubscriptionTopicListener( subscription );
for ( int i = 0; i < topics.length; i++ )
{
topics[i].addTopicListener( subscriptionTopicListener );
}
SubscribeResponseDocument subscribeResponseDoc =
SubscribeResponseDocument.Factory.newInstance( );
SubscribeResponseDocument.SubscribeResponse subscribeResponse =
subscribeResponseDoc.addNewSubscribeResponse( );
subscriptionEPR =
(EndpointReferenceType) ( (XmlObjectWrapper) subscription.getEndpointReference( ) ).getXmlObject( );
subscribeResponse.setSubscriptionReference( subscriptionEPR );
return subscribeResponseDoc;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
protected NamespaceVersionHolder getNamespaceSet( )
{
return NAMESPACE_SET;
}
private TopicExpression getTopicExpression( TopicExpressionType topicExpressionType )
{
TopicExpression topicExpr = null;
try
{
topicExpr = new XmlBeansTopicExpression( topicExpressionType );
}
catch ( InvalidTopicExpressionException ite )
{
throw new InvalidTopicExpressionFaultException( NAMESPACE_SET,
ite.getLocalizedMessage( ) );
}
return topicExpr;
}
private Topic[] evaluateTopicExpression( TopicExpression topicExpr )
{
try
{
NotificationProducerResource resource = (NotificationProducerResource) getResource( );
TopicSpaceSet topicSpaceSet = resource.getTopicSpaceSet( );
return topicSpaceSet.evaluateTopicExpression( topicExpr );
}
catch ( TopicPathDialectUnknownException tpdue )
{
throw new TopicPathDialectUnknownFaultException( NAMESPACE_SET,
tpdue.getLocalizedMessage( ) );
}
catch ( TopicExpressionException tee )
{
throw new BaseFaultException( NAMESPACE_SET,
tee.getLocalizedMessage( ) );
}
}
}