/*******************************************************************************
* Copyright (c) 2009 MATERNA Information & Communications. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html. For further
* project-related information visit http://www.ws4d.org. The most recent
* version of the JMEDS framework can be obtained from
* http://sourceforge.net/projects/ws4d-javame.
******************************************************************************/
package org.ws4d.java.service;
import org.ws4d.java.communication.ProtocolInfo;
import org.ws4d.java.constants.WSEConstants;
import org.ws4d.java.eventing.EventSink;
import org.ws4d.java.eventing.EventingException;
import org.ws4d.java.message.Message;
import org.ws4d.java.message.SOAPException;
import org.ws4d.java.schema.SchemaUtil;
import org.ws4d.java.structures.EmptyStructures;
import org.ws4d.java.structures.Iterator;
import org.ws4d.java.structures.ReadOnlyIterator;
import org.ws4d.java.types.EndpointReference;
import org.ws4d.java.types.EprInfo;
import org.ws4d.java.types.LocalizedString;
import org.ws4d.java.types.URI;
import org.ws4d.java.types.URISet;
/**
* Instances of this class hold essential information about an event
* subscription as seen from the server-side. These include the
* {@link #getNotifyTo() endpoint reference} to which events are to be
* delivered, the {@link #getFilterActions() actions} the subscription
* addresses, its {@link #getExpirationTime() expiration time} and the optional
* endpoint to which the server-initiated end of the subscription should be
* announced.
*/
public class ServiceSubscription {
private static final long MAX_EXPIRATION_DURATION = SchemaUtil.MILLIS_PER_YEAR;
private static final String FAULT_REASON_INVALID_EXIRATION_TIME = "The expiration time requested is invalid.";
private static final String FAULT_REASON_UNSUPPORTED_EXIRATION_TYPE = "Only expiration durations are supported.";
// -------------- VAR ------------------
// milliseconds from the epoch
long expirationTime; // in
/** remote client subscription id */
EprInfo notifyTo;
EprInfo endTo;
String communicationManagerId;
URISet filterActions;
/** Local event sink needed for local client */
EventSink sink = null;
/** Local client subscription */
String clientSubscriptionId = null;
EndpointReference subscriptionManager;
final ProtocolInfo pInfo;
public ServiceSubscription(ProtocolInfo pInfo) {
this.pInfo = pInfo;
}
void setExpiration(String expires, Message msg) throws SOAPException {
if (expires == null || (expires = expires.trim()).length() == 0) {
expirationTime = System.currentTimeMillis() + MAX_EXPIRATION_DURATION;
return;
}
if (expires.charAt(0) == 'P') {
// _positive_ duration
long duration = SchemaUtil.parseDuration(expires);
if (duration <= 0L) {
// Fault wse:InvalidExpirationTime
throw DefaultSubscriptionManager.createFault(msg, WSEConstants.WSE_FAULT_INVALID_EXPIRATION_TIME, new LocalizedString(FAULT_REASON_INVALID_EXIRATION_TIME, LocalizedString.DEFAULT_LANG));
}
expirationTime = System.currentTimeMillis() + duration;
} else {
// we currently don't support dateTime
// long expTime = parseDateTime(expires);
// if (expTime <= System.currentTimeMillis()) {
// return false;
// }
// expirationTime = expTime;
// Fault wse:UnsupportedExpirationType
// TODO add supported expiration types within fault detail
throw DefaultSubscriptionManager.createFault(msg, WSEConstants.WSE_FAULT_UNSUPPORTED_EXPIRATION_TYPE, new LocalizedString(FAULT_REASON_UNSUPPORTED_EXIRATION_TYPE, LocalizedString.DEFAULT_LANG));
}
}
/**
* Sets expiration for local client subscription.
*
* @param duration
*/
void setExpiration(long duration) throws EventingException {
if (duration == 0) {
expirationTime = System.currentTimeMillis() + MAX_EXPIRATION_DURATION;
return;
} else if (duration > 0) {
expirationTime = System.currentTimeMillis() + duration;
} else {
/*
* negative duration, throw exception
*/
throw new EventingException(WSEConstants.WSE_FAULT_INVALID_EXPIRATION_TIME, FAULT_REASON_INVALID_EXIRATION_TIME);
}
}
/**
* Sets EPR of subscription manager for this service subscription instance.
*
* @param subscriptionManager
*/
void setSubscriptionManager(EndpointReference subscriptionManager) {
this.subscriptionManager = subscriptionManager;
}
/**
* Returns the expiration time of this subscription in milliseconds from the
* epoch.
*
* @return the expiration time
*/
public long getExpirationTime() {
return expirationTime;
}
/**
* Returns the EprInfo to which notifications matching this
* subscription shall be sent.
* <P>
* Be aware that the xAddress of the returned <code>EprInfo</code> may be
* <code>null</code> if the endpoint reference is not a transport address
* </P>
* @return the <code>EprInfo</code> to which to send notifications
*/
public EprInfo getNotifyTo() {
return notifyTo;
}
/**
* Returns the (optional) EprInfo to which a server-side
* cancellation of the subscription should be announced.
* <P>
* Be aware that the xAddress of the returned <code>EprInfo</code> may be
* <code>null</code> if the endpoint reference is not a transport address
* </P>
* @return the <code>EprInfo</code> to which to send a subscription-end
* announcement
*/
public EprInfo getEndTo() {
return endTo;
}
/**
* Returns the ID of the protocol to communicate over with the client (aka.
* event sink) for this subscription. In other words, this is the same
* protocol to use when sending messages to either one of the
* {@link #getNotifyTo() notify-to} or {@link #getEndTo() end-to} addresses.
*
* @return the ID of the protocol to use for communication with the
* subscriber of this subscription
*/
public String getCommunicationManagerID() {
return communicationManagerId;
}
/**
* Returns a read-only iterator over the set of {@link URI action URIs} to
* which this subscription refers. This method never returns
* <code>null</code>, it will instead return an empty iterator in the case
* where no filter actions are available.
*
* @return an iterator over {@link URI} instances representing the actions
* to which this subscription refers
*/
public Iterator getFilterActions() {
return filterActions == null ? EmptyStructures.EMPTY_ITERATOR : new ReadOnlyIterator(filterActions.iterator());
}
/**
* Returns the EPR of the subscription manager governing the state of this
* service subscription. Usually, this EPR includes - in addition to the
* manager's address - a server-side identifier (e.g. wse:Identifier from
* WS-Eventing) for this subscription instance.
*
* @return the endpoint reference of the subscription manager for this
* subscription
*/
public EndpointReference getSubscriptionManager() {
return subscriptionManager;
}
public ProtocolInfo getProtocolInfo() {
return pInfo;
}
}