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 log.warn("Unable to register new endpoint", e);
207 SubscribeCreationFailedFaultType fault = new SubscribeCreationFailedFaultType();
208 throw new SubscribeCreationFailedFault("Unable to register new endpoint", fault, e);
209 } finally {
210 if (!success && subscription != null) {
211 subscriptions.remove(subscription);
212 try {
213 subscription.unsubscribe();
214 } catch (UnableToDestroySubscriptionFault e) {
215 log.info("Error destroying subscription", e);
216 }
217 }
218 }
219 }
220
221 public void unsubscribe(String address) throws UnableToDestroySubscriptionFault {
222 AbstractSubscription subscription = (AbstractSubscription) subscriptions.remove(address);
223 if (subscription != null) {
224 subscription.unsubscribe();
225 }
226 }
227
228 /**
229 *
230 * @param getCurrentMessageRequest
231 * @return returns org.oasis_open.docs.wsn.b_1.GetCurrentMessageResponse
232 * @throws MultipleTopicsSpecifiedFault
233 * @throws TopicNotSupportedFault
234 * @throws InvalidTopicExpressionFault
235 * @throws ResourceUnknownFault
236 * @throws TopicExpressionDialectUnknownFault
237 * @throws NoCurrentMessageOnTopicFault
238 */
239 @WebMethod(operationName = "GetCurrentMessage")
240 @WebResult(name = "GetCurrentMessageResponse",
241 targetNamespace = "http://docs.oasis-open.org/wsn/b-1",
242 partName = "GetCurrentMessageResponse")
243 public GetCurrentMessageResponse getCurrentMessage(
244 @WebParam(name = "GetCurrentMessage",
245 targetNamespace = "http://docs.oasis-open.org/wsn/b-1",
246 partName = "GetCurrentMessageRequest")
247 GetCurrentMessage getCurrentMessageRequest) throws InvalidTopicExpressionFault,
248 MultipleTopicsSpecifiedFault, NoCurrentMessageOnTopicFault, ResourceUnknownFault,
249 TopicExpressionDialectUnknownFault, TopicNotSupportedFault {
250
251 log.debug("GetCurrentMessage");
252 NoCurrentMessageOnTopicFaultType fault = new NoCurrentMessageOnTopicFaultType();
253 throw new NoCurrentMessageOnTopicFault("There is no current message on this topic.", fault);
254 }
255
256 /**
257 *
258 * @param registerPublisherRequest
259 * @return returns org.oasis_open.docs.wsn.br_1.RegisterPublisherResponse
260 * @throws PublisherRegistrationRejectedFault
261 * @throws InvalidTopicExpressionFault
262 * @throws TopicNotSupportedFault
263 * @throws ResourceUnknownFault
264 * @throws PublisherRegistrationFailedFault
265 */
266 @WebMethod(operationName = "RegisterPublisher")
267 @WebResult(name = "RegisterPublisherResponse",
268 targetNamespace = "http://docs.oasis-open.org/wsn/br-1",
269 partName = "RegisterPublisherResponse")
270 public RegisterPublisherResponse registerPublisher(
271 @WebParam(name = "RegisterPublisher",
272 targetNamespace = "http://docs.oasis-open.org/wsn/br-1",
273 partName = "RegisterPublisherRequest")
274 RegisterPublisher registerPublisherRequest) throws InvalidTopicExpressionFault,
275 PublisherRegistrationFailedFault, PublisherRegistrationRejectedFault, ResourceUnknownFault,
276 TopicNotSupportedFault {
277
278 log.debug("RegisterPublisher");
279 return handleRegisterPublisher(registerPublisherRequest, null);
280 }
281
282 public RegisterPublisherResponse handleRegisterPublisher(RegisterPublisher registerPublisherRequest,
283 EndpointManager manager) throws InvalidTopicExpressionFault, PublisherRegistrationFailedFault,
284 PublisherRegistrationRejectedFault, ResourceUnknownFault, TopicNotSupportedFault {
285 AbstractPublisher publisher = null;
286 boolean success = false;
287 try {
288 publisher = createPublisher(idGenerator.generateSanitizedId());
289 publishers.put(publisher.getAddress(), publisher);
290 if (manager != null) {
291 publisher.setManager(manager);
292 }
293 publisher.register();
294 publisher.create(registerPublisherRequest);
295 RegisterPublisherResponse response = new RegisterPublisherResponse();
296 response.setPublisherRegistrationReference(AbstractWSAClient.createWSA(publisher.getAddress()));
297 success = true;
298 return response;
299 } catch (EndpointRegistrationException e) {
300 log.warn("Unable to register new endpoint", e);
301 PublisherRegistrationFailedFaultType fault = new PublisherRegistrationFailedFaultType();
302 throw new PublisherRegistrationFailedFault("Unable to register new endpoint", fault, e);
303 } finally {
304 if (!success && publisher != null) {
305 publishers.remove(publisher.getAddress());
306 try {
307 publisher.destroy();
308 } catch (ResourceNotDestroyedFault e) {
309 log.info("Error destroying publisher", e);
310 }
311 }
312 }
313 }
314
315 protected abstract AbstractPublisher createPublisher(String name);
316
317 protected abstract AbstractSubscription createSubcription(String name);
318
319 @WebResult(name = "GetResourcePropertyResponse", targetNamespace = "http://docs.oasis-open.org/wsrf/rp-2", partName = "GetResourcePropertyResponse")
320 @WebMethod(operationName = "GetResourceProperty")
321 public GetResourcePropertyResponse getResourceProperty(
322 @WebParam(partName = "GetResourcePropertyRequest", name = "GetResourceProperty", targetNamespace = "http://docs.oasis-open.org/wsrf/rp-2")
323 javax.xml.namespace.QName getResourcePropertyRequest
324 ) throws ResourceUnavailableFault, ResourceUnknownFault, InvalidResourcePropertyQNameFault {
325
326 log.debug("GetResourceProperty");
327 return handleGetResourceProperty(getResourcePropertyRequest);
328 }
329
330 protected GetResourcePropertyResponse handleGetResourceProperty(QName property)
331 throws ResourceUnavailableFault, ResourceUnknownFault, InvalidResourcePropertyQNameFault {
332 InvalidResourcePropertyQNameFaultType fault = new InvalidResourcePropertyQNameFaultType();
333 throw new InvalidResourcePropertyQNameFault("Invalid resource property QName: " + property, fault);
334 }
335
336 }