001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.servicemix.wsn;
018
019 import java.util.Map;
020 import java.util.concurrent.ConcurrentHashMap;
021
022 import javax.jws.Oneway;
023 import javax.jws.WebMethod;
024 import javax.jws.WebParam;
025 import javax.jws.WebResult;
026 import javax.jws.WebService;
027 import javax.xml.ws.wsaddressing.W3CEndpointReference;
028 import javax.xml.namespace.QName;
029
030 import org.apache.commons.logging.Log;
031 import org.apache.commons.logging.LogFactory;
032 import org.apache.servicemix.id.IdGenerator;
033 import org.apache.servicemix.wsn.client.AbstractWSAClient;
034 import org.oasis_open.docs.wsn.b_2.GetCurrentMessage;
035 import org.oasis_open.docs.wsn.b_2.GetCurrentMessageResponse;
036 import org.oasis_open.docs.wsn.b_2.NoCurrentMessageOnTopicFaultType;
037 import org.oasis_open.docs.wsn.b_2.NotificationMessageHolderType;
038 import org.oasis_open.docs.wsn.b_2.Notify;
039 import org.oasis_open.docs.wsn.b_2.Subscribe;
040 import org.oasis_open.docs.wsn.b_2.SubscribeCreationFailedFaultType;
041 import org.oasis_open.docs.wsn.b_2.SubscribeResponse;
042 import org.oasis_open.docs.wsn.b_2.InvalidTopicExpressionFaultType;
043 import org.oasis_open.docs.wsn.br_2.PublisherRegistrationFailedFaultType;
044 import org.oasis_open.docs.wsn.br_2.RegisterPublisher;
045 import org.oasis_open.docs.wsn.br_2.RegisterPublisherResponse;
046 import org.oasis_open.docs.wsn.brw_2.NotificationBroker;
047 import org.oasis_open.docs.wsn.brw_2.PublisherRegistrationFailedFault;
048 import org.oasis_open.docs.wsn.brw_2.PublisherRegistrationRejectedFault;
049 import org.oasis_open.docs.wsn.brw_2.ResourceNotDestroyedFault;
050 import org.oasis_open.docs.wsn.bw_2.InvalidFilterFault;
051 import org.oasis_open.docs.wsn.bw_2.InvalidMessageContentExpressionFault;
052 import org.oasis_open.docs.wsn.bw_2.InvalidProducerPropertiesExpressionFault;
053 import org.oasis_open.docs.wsn.bw_2.InvalidTopicExpressionFault;
054 import org.oasis_open.docs.wsn.bw_2.MultipleTopicsSpecifiedFault;
055 import org.oasis_open.docs.wsn.bw_2.NoCurrentMessageOnTopicFault;
056 import org.oasis_open.docs.wsn.bw_2.SubscribeCreationFailedFault;
057 import org.oasis_open.docs.wsn.bw_2.TopicExpressionDialectUnknownFault;
058 import org.oasis_open.docs.wsn.bw_2.TopicNotSupportedFault;
059 import org.oasis_open.docs.wsn.bw_2.UnableToDestroySubscriptionFault;
060 import org.oasis_open.docs.wsn.bw_2.UnacceptableInitialTerminationTimeFault;
061 import org.oasis_open.docs.wsn.bw_2.UnsupportedPolicyRequestFault;
062 import org.oasis_open.docs.wsn.bw_2.UnrecognizedPolicyRequestFault;
063 import org.oasis_open.docs.wsrf.rw_2.ResourceUnknownFault;
064 import org.oasis_open.docs.wsrf.rw_2.ResourceUnavailableFault;
065 import org.oasis_open.docs.wsrf.rpw_2.GetResourceProperty;
066 import org.oasis_open.docs.wsrf.rpw_2.InvalidResourcePropertyQNameFault;
067 import org.oasis_open.docs.wsrf.rp_2.GetResourcePropertyResponse;
068 import org.oasis_open.docs.wsrf.rp_2.InvalidResourcePropertyQNameFaultType;
069
070 @WebService(endpointInterface = "org.oasis_open.docs.wsn.brw_2.NotificationBroker")
071 public abstract class AbstractNotificationBroker extends AbstractEndpoint implements NotificationBroker, GetResourceProperty {
072
073 public static final String NAMESPACE_URI = "http://docs.oasis-open.org/wsn/b-2";
074 public static final String PREFIX = "wsnt";
075 public static final QName TOPIC_EXPRESSION_QNAME = new QName(NAMESPACE_URI, "TopicExpression", PREFIX);
076 public static final QName FIXED_TOPIC_SET_QNAME = new QName(NAMESPACE_URI, "FixedTopicSet", PREFIX);
077 public static final QName TOPIC_EXPRESSION_DIALECT_QNAME = new QName(NAMESPACE_URI, "TopicExpressionDialect", PREFIX);
078 public static final QName TOPIC_SET_QNAME = new QName(NAMESPACE_URI, "TopicSet", PREFIX);
079
080
081 private static Log log = LogFactory.getLog(AbstractNotificationBroker.class);
082
083 private IdGenerator idGenerator;
084
085 private AbstractPublisher anonymousPublisher;
086
087 private Map<String, AbstractPublisher> publishers;
088
089 private Map<String, AbstractSubscription> subscriptions;
090
091 public AbstractNotificationBroker(String name) {
092 super(name);
093 idGenerator = new IdGenerator();
094 subscriptions = new ConcurrentHashMap<String, AbstractSubscription>();
095 publishers = new ConcurrentHashMap<String, AbstractPublisher>();
096 }
097
098 public void init() throws Exception {
099 register();
100 anonymousPublisher = createPublisher("Anonymous");
101 anonymousPublisher.register();
102 }
103
104 public void destroy() throws Exception {
105 anonymousPublisher.destroy();
106 unregister();
107 }
108
109 protected String createAddress() {
110 return "http://servicemix.org/wsnotification/NotificationBroker/" + getName();
111 }
112
113 /**
114 *
115 * @param notify
116 */
117 @WebMethod(operationName = "Notify")
118 @Oneway
119 public void notify(
120 @WebParam(name = "Notify",
121 targetNamespace = "http://docs.oasis-open.org/wsn/b-1",
122 partName = "Notify")
123 Notify notify) {
124
125 log.debug("Notify");
126 handleNotify(notify);
127 }
128
129 protected void handleNotify(Notify notify) {
130 for (NotificationMessageHolderType messageHolder : notify.getNotificationMessage()) {
131 W3CEndpointReference producerReference = messageHolder.getProducerReference();
132 AbstractPublisher publisher = getPublisher(producerReference);
133 if (publisher != null) {
134 publisher.notify(messageHolder);
135 }
136 }
137 }
138
139 protected AbstractPublisher getPublisher(W3CEndpointReference producerReference) {
140 AbstractPublisher publisher = null;
141 if (producerReference != null) {
142 String address = AbstractWSAClient.getWSAAddress(producerReference);
143 publisher = publishers.get(address);
144 }
145 if (publisher == null) {
146 publisher = anonymousPublisher;
147 }
148 return publisher;
149 }
150
151 /**
152 *
153 * @param subscribeRequest
154 * @return returns org.oasis_open.docs.wsn.b_1.SubscribeResponse
155 * @throws SubscribeCreationFailedFault
156 * @throws InvalidTopicExpressionFault
157 * @throws TopicNotSupportedFault
158 * @throws InvalidFilterFault
159 * @throws InvalidProducerPropertiesExpressionFault
160 * @throws ResourceUnknownFault
161 * @throws InvalidUseRawValueFault
162 * @throws InvalidMessageContentExpressionFault
163 * @throws TopicExpressionDialectUnknownFault
164 * @throws UnacceptableInitialTerminationTimeFault
165 */
166 @WebMethod(operationName = "Subscribe")
167 @WebResult(name = "SubscribeResponse",
168 targetNamespace = "http://docs.oasis-open.org/wsn/b-1",
169 partName = "SubscribeResponse")
170 public SubscribeResponse subscribe(
171 @WebParam(name = "Subscribe",
172 targetNamespace = "http://docs.oasis-open.org/wsn/b-1",
173 partName = "SubscribeRequest")
174 Subscribe subscribeRequest) throws InvalidFilterFault, InvalidMessageContentExpressionFault,
175 InvalidProducerPropertiesExpressionFault, InvalidTopicExpressionFault, ResourceUnknownFault,
176 SubscribeCreationFailedFault, TopicExpressionDialectUnknownFault, TopicNotSupportedFault,
177 UnacceptableInitialTerminationTimeFault, UnsupportedPolicyRequestFault, UnrecognizedPolicyRequestFault {
178
179 log.debug("Subscribe");
180 return handleSubscribe(subscribeRequest, null);
181 }
182
183 public SubscribeResponse handleSubscribe(
184 Subscribe subscribeRequest,
185 EndpointManager manager) throws InvalidFilterFault, InvalidMessageContentExpressionFault,
186 InvalidProducerPropertiesExpressionFault, InvalidTopicExpressionFault,
187 SubscribeCreationFailedFault, TopicExpressionDialectUnknownFault,
188 TopicNotSupportedFault, UnacceptableInitialTerminationTimeFault,
189 UnsupportedPolicyRequestFault, UnrecognizedPolicyRequestFault {
190 AbstractSubscription subscription = null;
191 boolean success = false;
192 try {
193 subscription = createSubcription(idGenerator.generateSanitizedId());
194 subscription.setBroker(this);
195 subscriptions.put(subscription.getAddress(), subscription);
196 subscription.create(subscribeRequest);
197 if (manager != null) {
198 subscription.setManager(manager);
199 }
200 subscription.register();
201 SubscribeResponse response = new SubscribeResponse();
202 response.setSubscriptionReference(AbstractWSAClient.createWSA(subscription.getAddress()));
203 success = true;
204 return response;
205 } catch (EndpointRegistrationException e) {
206 SubscribeCreationFailedFaultType fault = new SubscribeCreationFailedFaultType();
207 throw new SubscribeCreationFailedFault("Unable to register endpoint", fault, e);
208 } finally {
209 if (!success && subscription != null) {
210 subscriptions.remove(subscription);
211 try {
212 subscription.unsubscribe();
213 } catch (UnableToDestroySubscriptionFault e) {
214 log.info("Error destroying subscription", e);
215 }
216 }
217 }
218 }
219
220 public void unsubscribe(String address) throws UnableToDestroySubscriptionFault {
221 AbstractSubscription subscription = (AbstractSubscription) subscriptions.remove(address);
222 if (subscription != null) {
223 subscription.unsubscribe();
224 }
225 }
226
227 /**
228 *
229 * @param getCurrentMessageRequest
230 * @return returns org.oasis_open.docs.wsn.b_1.GetCurrentMessageResponse
231 * @throws MultipleTopicsSpecifiedFault
232 * @throws TopicNotSupportedFault
233 * @throws InvalidTopicExpressionFault
234 * @throws ResourceUnknownFault
235 * @throws TopicExpressionDialectUnknownFault
236 * @throws NoCurrentMessageOnTopicFault
237 */
238 @WebMethod(operationName = "GetCurrentMessage")
239 @WebResult(name = "GetCurrentMessageResponse",
240 targetNamespace = "http://docs.oasis-open.org/wsn/b-1",
241 partName = "GetCurrentMessageResponse")
242 public GetCurrentMessageResponse getCurrentMessage(
243 @WebParam(name = "GetCurrentMessage",
244 targetNamespace = "http://docs.oasis-open.org/wsn/b-1",
245 partName = "GetCurrentMessageRequest")
246 GetCurrentMessage getCurrentMessageRequest) throws InvalidTopicExpressionFault,
247 MultipleTopicsSpecifiedFault, NoCurrentMessageOnTopicFault, ResourceUnknownFault,
248 TopicExpressionDialectUnknownFault, TopicNotSupportedFault {
249
250 log.debug("GetCurrentMessage");
251 NoCurrentMessageOnTopicFaultType fault = new NoCurrentMessageOnTopicFaultType();
252 throw new NoCurrentMessageOnTopicFault("There is no current message on this topic.", fault);
253 }
254
255 /**
256 *
257 * @param registerPublisherRequest
258 * @return returns org.oasis_open.docs.wsn.br_1.RegisterPublisherResponse
259 * @throws PublisherRegistrationRejectedFault
260 * @throws InvalidTopicExpressionFault
261 * @throws TopicNotSupportedFault
262 * @throws ResourceUnknownFault
263 * @throws PublisherRegistrationFailedFault
264 */
265 @WebMethod(operationName = "RegisterPublisher")
266 @WebResult(name = "RegisterPublisherResponse",
267 targetNamespace = "http://docs.oasis-open.org/wsn/br-1",
268 partName = "RegisterPublisherResponse")
269 public RegisterPublisherResponse registerPublisher(
270 @WebParam(name = "RegisterPublisher",
271 targetNamespace = "http://docs.oasis-open.org/wsn/br-1",
272 partName = "RegisterPublisherRequest")
273 RegisterPublisher registerPublisherRequest) throws InvalidTopicExpressionFault,
274 PublisherRegistrationFailedFault, PublisherRegistrationRejectedFault, ResourceUnknownFault,
275 TopicNotSupportedFault {
276
277 log.debug("RegisterPublisher");
278 return handleRegisterPublisher(registerPublisherRequest, null);
279 }
280
281 public RegisterPublisherResponse handleRegisterPublisher(RegisterPublisher registerPublisherRequest,
282 EndpointManager manager) throws InvalidTopicExpressionFault, PublisherRegistrationFailedFault,
283 PublisherRegistrationRejectedFault, ResourceUnknownFault, TopicNotSupportedFault {
284 AbstractPublisher publisher = null;
285 boolean success = false;
286 try {
287 publisher = createPublisher(idGenerator.generateSanitizedId());
288 publishers.put(publisher.getAddress(), publisher);
289 if (manager != null) {
290 publisher.setManager(manager);
291 }
292 publisher.register();
293 publisher.create(registerPublisherRequest);
294 RegisterPublisherResponse response = new RegisterPublisherResponse();
295 response.setPublisherRegistrationReference(AbstractWSAClient.createWSA(publisher.getAddress()));
296 success = true;
297 return response;
298 } catch (EndpointRegistrationException e) {
299 PublisherRegistrationFailedFaultType fault = new PublisherRegistrationFailedFaultType();
300 throw new PublisherRegistrationFailedFault("Unable to register new endpoint", fault, e);
301 } finally {
302 if (!success && publisher != null) {
303 publishers.remove(publisher.getAddress());
304 try {
305 publisher.destroy();
306 } catch (ResourceNotDestroyedFault e) {
307 log.info("Error destroying publisher", e);
308 }
309 }
310 }
311 }
312
313 protected abstract AbstractPublisher createPublisher(String name);
314
315 protected abstract AbstractSubscription createSubcription(String name);
316
317 @WebResult(name = "GetResourcePropertyResponse", targetNamespace = "http://docs.oasis-open.org/wsrf/rp-2", partName = "GetResourcePropertyResponse")
318 @WebMethod(operationName = "GetResourceProperty")
319 public GetResourcePropertyResponse getResourceProperty(
320 @WebParam(partName = "GetResourcePropertyRequest", name = "GetResourceProperty", targetNamespace = "http://docs.oasis-open.org/wsrf/rp-2")
321 javax.xml.namespace.QName getResourcePropertyRequest
322 ) throws ResourceUnavailableFault, ResourceUnknownFault, InvalidResourcePropertyQNameFault {
323
324 log.debug("GetResourceProperty");
325 return handleGetResourceProperty(getResourcePropertyRequest);
326 }
327
328 protected GetResourcePropertyResponse handleGetResourceProperty(QName property)
329 throws ResourceUnavailableFault, ResourceUnknownFault, InvalidResourcePropertyQNameFault {
330 InvalidResourcePropertyQNameFaultType fault = new InvalidResourcePropertyQNameFaultType();
331 throw new InvalidResourcePropertyQNameFault("Invalid resource property QName: " + property, fault);
332 }
333
334 }