View Javadoc

1   /*
2    * Copyright  1999-2004 The Apache Software Foundation.
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   *
16   */
17  
18  package org.apache.savan.eventing;
19  
20  import java.util.Calendar;
21  import java.util.Date;
22  
23  import javax.xml.namespace.QName;
24  
25  import org.apache.axiom.om.OMAbstractFactory;
26  import org.apache.axiom.om.OMAttribute;
27  import org.apache.axiom.om.OMElement;
28  import org.apache.axiom.om.OMNode;
29  import org.apache.axiom.soap.SOAP11Constants;
30  import org.apache.axiom.soap.SOAP12Constants;
31  import org.apache.axiom.soap.SOAPBody;
32  import org.apache.axiom.soap.SOAPEnvelope;
33  import org.apache.axiom.soap.SOAPFactory;
34  import org.apache.axiom.soap.SOAPHeader;
35  import org.apache.axis2.AxisFault;
36  import org.apache.axis2.addressing.EndpointReferenceHelper;
37  import org.apache.axis2.addressing.EndpointReference;
38  import org.apache.axis2.context.ConfigurationContext;
39  import org.apache.axis2.databinding.types.Duration;
40  import org.apache.axis2.databinding.utils.ConverterUtil;
41  import org.apache.axiom.om.util.UUIDGenerator;
42  import org.apache.savan.SavanConstants;
43  import org.apache.savan.SavanException;
44  import org.apache.savan.SavanMessageContext;
45  import org.apache.savan.configuration.ConfigurationManager;
46  import org.apache.savan.configuration.Protocol;
47  import org.apache.savan.configuration.SubscriberBean;
48  import org.apache.savan.eventing.subscribers.EventingSubscriber;
49  import org.apache.savan.filters.Filter;
50  import org.apache.savan.subscribers.AbstractSubscriber;
51  import org.apache.savan.subscribers.Subscriber;
52  import org.apache.savan.subscription.ExpirationBean;
53  import org.apache.savan.subscription.SubscriptionProcessor;
54  import org.apache.savan.util.CommonUtil;
55  import org.apache.savan.util.UtilFactory;
56  
57  public class EventingSubscriptionProcessor extends SubscriptionProcessor {
58  
59  	public void init (SavanMessageContext smc) throws SavanException {
60  		//setting the subscriber_id as a property if possible.
61  		
62  		String id = getSubscriberID(smc);
63  		if (id!=null) {
64  			smc.setProperty(EventingConstants.TransferedProperties.SUBSCRIBER_UUID,id);
65  		}
66  	}
67  	
68  	public Subscriber getSubscriberFromMessage(SavanMessageContext smc) throws SavanException {
69  
70  		ConfigurationManager configurationManager = (ConfigurationManager) smc.getConfigurationContext().getProperty(SavanConstants.CONFIGURATION_MANAGER);
71  		if (configurationManager==null)
72  			throw new SavanException ("Configuration Manager not set");
73  		
74  		Protocol protocol = smc.getProtocol();
75  		if (protocol==null)
76  			throw new SavanException ("Protocol not found");
77  		
78  		UtilFactory utilFactory = protocol.getUtilFactory();
79  		
80  		SOAPEnvelope envelope = smc.getEnvelope();
81  		if (envelope==null)
82  			return null;
83  		
84  //		AbstractSubscriber subscriber = utilFactory.createSubscriber();  //eventing only works on leaf subscriber for now.
85  		
86  		String subscriberName = protocol.getDefaultSubscriber();
87  		SubscriberBean subscriberBean = configurationManager.getSubscriberBean(subscriberName);
88  		
89  		AbstractSubscriber subscriber = configurationManager.getSubscriberInstance(subscriberName);
90  		
91  		if (!(subscriber instanceof EventingSubscriber)) {
92  			String message = "Eventing protocol only support implementations of eventing subscriber as Subscribers";
93  			throw new SavanException (message);
94  		}
95  		
96  		EventingSubscriber eventingSubscriber = (EventingSubscriber) subscriber;
97  		String id = UUIDGenerator.getUUID();
98  		smc.setProperty(EventingConstants.TransferedProperties.SUBSCRIBER_UUID,id);
99  	
100 		eventingSubscriber.setId(id);
101 		
102 		SOAPBody body = envelope.getBody();
103 		OMElement subscribeElement = body.getFirstChildWithName(new QName (EventingConstants.EVENTING_NAMESPACE,EventingConstants.ElementNames.Subscribe));
104 		if (subscribeElement==null)
105 			throw new SavanException ("'Subscribe' element is not present");
106 		
107 		OMElement endToElement = subscribeElement.getFirstChildWithName(new QName (EventingConstants.EVENTING_NAMESPACE,EventingConstants.ElementNames.EndTo));
108 		if (endToElement!=null) {
109 			EndpointReference endToEPR = null;
110             
111             try {
112                 endToEPR = EndpointReferenceHelper.fromOM(endToElement);
113             }
114             catch (AxisFault af) {
115                 throw new SavanException(af);
116             }
117             
118 			eventingSubscriber.setEndToEPr(endToEPR);
119 		}
120 		
121 		OMElement deliveryElement = subscribeElement.getFirstChildWithName(new QName (EventingConstants.EVENTING_NAMESPACE,EventingConstants.ElementNames.Delivery));
122 		if (deliveryElement==null)
123 			throw new SavanException ("Delivery element is not present");
124 		
125 		OMElement notifyToElement = deliveryElement.getFirstChildWithName(new QName (EventingConstants.EVENTING_NAMESPACE,EventingConstants.ElementNames.NotifyTo));
126 		if (notifyToElement==null)
127 			throw new SavanException ("NotifyTo element is null");
128 		
129 		EndpointReference notifyToEPr = null;
130         
131         try {
132             notifyToEPr = EndpointReferenceHelper.fromOM(notifyToElement);
133         }
134         catch (AxisFault af) {    
135             throw new SavanException(af);
136         }
137         
138 		OMAttribute deliveryModeAttr = deliveryElement.getAttribute(new QName (EventingConstants.ElementNames.Mode));
139 		String deliveryMode = null;
140 		if (deliveryModeAttr!=null) {
141 			deliveryMode = deliveryModeAttr.getAttributeValue().trim();
142 		} else {
143 			deliveryMode = EventingConstants.DEFAULT_DELIVERY_MODE;
144 		}
145 		
146 		if (!deliveryModesupported()) {
147 			//TODO throw unsupported delivery mode fault.
148 		}
149 		
150 		Delivery delivery = new Delivery ();
151 		delivery.setDeliveryEPR(notifyToEPr);
152 		delivery.setDeliveryMode(deliveryMode);
153 		
154 		eventingSubscriber.setDelivery(delivery);
155 		
156 		OMElement expiresElement = subscribeElement.getFirstChildWithName(new QName (EventingConstants.EVENTING_NAMESPACE,EventingConstants.ElementNames.Expires));
157 		if (expiresElement!=null) {
158 			String expiresText = expiresElement.getText();
159 
160 			if (expiresText==null){
161 				String message = "Expires Text is null";
162 				throw new SavanException (message);
163 			}
164 			
165 			expiresText = expiresText.trim();
166 			
167 			ExpirationBean expirationBean = getExpirationBeanFromString(expiresText);
168 			Date expiration = null;
169 			if (expirationBean.isDuration()) {
170 				Calendar calendar = Calendar.getInstance();
171 				CommonUtil.addDurationToCalendar(calendar,expirationBean.getDurationValue());
172 				expiration = calendar.getTime();
173 			} else
174 				expiration = expirationBean.getDateValue();
175 			
176 			
177 			if (expiration==null) {
178 				String message = "Cannot understand the given date-time value for the Expiration";
179 				throw new SavanException (message);
180 			}
181 			
182 			eventingSubscriber.setSubscriptionEndingTime(expiration);
183 		}
184 		
185 		OMElement filterElement = subscribeElement.getFirstChildWithName(new QName (EventingConstants.EVENTING_NAMESPACE,EventingConstants.ElementNames.Filter));
186 		if (filterElement!=null) {
187 			OMNode filterNode = filterElement.getFirstOMChild();
188 			OMAttribute dialectAttr = filterElement.getAttribute(new QName (EventingConstants.ElementNames.Dialect));
189 			Filter filter = null;
190 			
191 			String filterKey = EventingConstants.DEFAULT_FILTER_IDENTIFIER;
192 			if (dialectAttr!=null) {
193 				filterKey = dialectAttr.getAttributeValue();
194 			}
195 			filter = configurationManager.getFilterInstanceFromId(filterKey);
196 			if (filter==null)
197 				throw new SavanException ("The Filter defined by the dialect is not available");
198 			
199 			filter.setUp (filterNode);
200 			
201 			eventingSubscriber.setFilter(filter);
202 		}
203 		
204 		return eventingSubscriber;
205 	}
206 
207 	public void pauseSubscription(SavanMessageContext pauseSubscriptionMessage) throws SavanException {
208 		throw new UnsupportedOperationException ("Eventing specification does not support this type of messages");
209 	}
210 
211 	public void resumeSubscription(SavanMessageContext resumeSubscriptionMessage) throws SavanException {
212 		throw new UnsupportedOperationException ("Eventing specification does not support this type of messages");
213 	}
214 
215 	public ExpirationBean getExpirationBean(SavanMessageContext renewMessage) throws SavanException {
216 
217 		SOAPEnvelope envelope = renewMessage.getEnvelope();
218 		SOAPBody body = envelope.getBody();
219 		
220 		ExpirationBean expirationBean = null;
221 		
222 		OMElement renewElement = body.getFirstChildWithName(new QName (EventingConstants.EVENTING_NAMESPACE,EventingConstants.ElementNames.Renew));
223 		if (renewElement==null) {
224 			String message = "Renew element not present in the assumed Renew Message";
225 			throw new SavanException (message);
226 		}
227 		
228 		OMElement expiresElement = renewElement.getFirstChildWithName(new QName (EventingConstants.EVENTING_NAMESPACE,EventingConstants.ElementNames.Expires));
229 		if (expiresElement!=null) {
230 			String expiresText = expiresElement.getText().trim();
231 			expirationBean = getExpirationBeanFromString(expiresText);
232 		}
233 		
234 		String subscriberID = getSubscriberID(renewMessage);
235 		if (subscriberID==null) {
236 			String message = "Cannot find the subscriber ID";
237 			throw new SavanException (message);
238 		}
239 		
240 		renewMessage.setProperty(EventingConstants.TransferedProperties.SUBSCRIBER_UUID,subscriberID);
241 		
242 		expirationBean.setSubscriberID(subscriberID);
243 		return expirationBean;
244 	}
245 
246 	public String getSubscriberID(SavanMessageContext smc) throws SavanException {
247 		SOAPEnvelope envelope = smc.getEnvelope();
248 		SOAPHeader header = envelope.getHeader();
249 		if (header==null) {
250 			return null;
251 		}
252 		
253 		OMElement ideltifierElement = envelope.getHeader().getFirstChildWithName(new QName (EventingConstants.EVENTING_NAMESPACE,EventingConstants.ElementNames.Identifier));
254 		if (ideltifierElement==null) {
255 			return null;
256 		}
257 		
258 		return ideltifierElement.getText().trim();
259 	}
260 	
261 	private ExpirationBean getExpirationBeanFromString (String expiresStr) throws SavanException {
262 
263 		ExpirationBean bean = new ExpirationBean ();
264 		
265 		//expires can be a duration or a date time.
266 		//Doing the conversion using the ConverUtil helper class.
267 		
268 		Date date = null;
269 		boolean isDuration = CommonUtil.isDuration(expiresStr);
270 		
271 		if (isDuration) {
272 			try {
273 				bean.setDuration(true);
274 				Duration duration = ConverterUtil.convertToDuration(expiresStr);
275 				bean.setDurationValue(duration);
276 			} catch (IllegalArgumentException e) {
277 				String message = "Cannot convert the Expiration value to a valid duration";
278 				throw new SavanException (message,e);
279 			}
280 		} else {
281 			try {
282 			    Calendar calendar = ConverterUtil.convertToDateTime(expiresStr);
283 			    date = calendar.getTime();
284 			    bean.setDateValue(date);
285 			} catch (Exception e) {
286 				String message = "Cannot convert the Expiration value to a valid DATE/TIME";
287 				throw new SavanException (message,e);
288 			}
289 		}
290 		
291 		boolean invalidExpirationTime = false;
292 		if (bean.isDuration()) {
293 			if (isInvalidDiration (bean.getDurationValue()))
294 				invalidExpirationTime = true;
295 		} else {
296 			if (isDateInThePast (bean.getDateValue())) 
297 				invalidExpirationTime = true;
298 		}
299 		
300 		if (invalidExpirationTime) {
301 			//TODO throw Invalid Expiration Time fault
302 		}
303 		
304 		return bean;
305 	}
306 
307 	public void doProtocolSpecificEndSubscription(Subscriber subscriber, String reason, ConfigurationContext configurationContext) throws SavanException {
308 		String SOAPVersion = (String) subscriber.getProperty(EventingConstants.Properties.SOAPVersion);
309 		if (SOAPVersion==null) 
310 			throw new SavanException ("Cant find the SOAP version of the subscriber");
311 		
312 		SOAPFactory factory = null;
313 		if (SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(SOAPVersion))
314 			factory = OMAbstractFactory.getSOAP11Factory();
315 		else if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(SOAPVersion))
316 			factory = OMAbstractFactory.getSOAP12Factory();
317 		else
318 			throw new SavanException ("The subscriber has a unknown SOAP version property set");
319 		
320 		SOAPEnvelope envelope = factory.getDefaultEnvelope();
321 	}
322 	
323 	private boolean deliveryModesupported() {
324 		return true;
325 	}
326 	
327 	private boolean isInvalidDiration (Duration duration) {
328 		return false;
329 	}
330 	
331 	private boolean isDateInThePast (Date date) {
332 		return false;
333 	}
334 	
335 	private boolean filterDilalectSupported (String filterDialect){ 
336 		return true;
337 	}
338 	
339 }