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
028 import org.apache.activemq.util.IdGenerator;
029 import org.apache.commons.logging.Log;
030 import org.apache.commons.logging.LogFactory;
031 import org.apache.servicemix.wsn.jaxws.InvalidFilterFault;
032 import org.apache.servicemix.wsn.jaxws.InvalidMessageContentExpressionFault;
033 import org.apache.servicemix.wsn.jaxws.InvalidProducerPropertiesExpressionFault;
034 import org.apache.servicemix.wsn.jaxws.InvalidTopicExpressionFault;
035 import org.apache.servicemix.wsn.jaxws.MultipleTopicsSpecifiedFault;
036 import org.apache.servicemix.wsn.jaxws.NoCurrentMessageOnTopicFault;
037 import org.apache.servicemix.wsn.jaxws.NotificationBroker;
038 import org.apache.servicemix.wsn.jaxws.PublisherRegistrationFailedFault;
039 import org.apache.servicemix.wsn.jaxws.PublisherRegistrationRejectedFault;
040 import org.apache.servicemix.wsn.jaxws.ResourceNotDestroyedFault;
041 import org.apache.servicemix.wsn.jaxws.ResourceUnknownFault;
042 import org.apache.servicemix.wsn.jaxws.SubscribeCreationFailedFault;
043 import org.apache.servicemix.wsn.jaxws.TopicExpressionDialectUnknownFault;
044 import org.apache.servicemix.wsn.jaxws.TopicNotSupportedFault;
045 import org.apache.servicemix.wsn.jaxws.UnableToDestroySubscriptionFault;
046 import org.apache.servicemix.wsn.jaxws.UnacceptableInitialTerminationTimeFault;
047 import org.oasis_open.docs.wsn.b_2.GetCurrentMessage;
048 import org.oasis_open.docs.wsn.b_2.GetCurrentMessageResponse;
049 import org.oasis_open.docs.wsn.b_2.NoCurrentMessageOnTopicFaultType;
050 import org.oasis_open.docs.wsn.b_2.NotificationMessageHolderType;
051 import org.oasis_open.docs.wsn.b_2.Notify;
052 import org.oasis_open.docs.wsn.b_2.Subscribe;
053 import org.oasis_open.docs.wsn.b_2.SubscribeCreationFailedFaultType;
054 import org.oasis_open.docs.wsn.b_2.SubscribeResponse;
055 import org.oasis_open.docs.wsn.br_2.PublisherRegistrationFailedFaultType;
056 import org.oasis_open.docs.wsn.br_2.RegisterPublisher;
057 import org.oasis_open.docs.wsn.br_2.RegisterPublisherResponse;
058 import org.w3._2005._08.addressing.EndpointReferenceType;
059
060 @WebService(endpointInterface = "org.apache.servicemix.wsn.jaxws.NotificationBroker")
061 public abstract class AbstractNotificationBroker extends AbstractEndpoint implements NotificationBroker {
062
063 private static Log log = LogFactory.getLog(AbstractNotificationBroker.class);
064
065 private IdGenerator idGenerator;
066
067 private AbstractPublisher anonymousPublisher;
068
069 private Map<String, AbstractPublisher> publishers;
070
071 private Map<String, AbstractSubscription> subscriptions;
072
073 public AbstractNotificationBroker(String name) {
074 super(name);
075 idGenerator = new IdGenerator();
076 subscriptions = new ConcurrentHashMap<String, AbstractSubscription>();
077 publishers = new ConcurrentHashMap<String, AbstractPublisher>();
078 }
079
080 public void init() throws Exception {
081 register();
082 anonymousPublisher = createPublisher("Anonymous");
083 anonymousPublisher.register();
084 }
085
086 public void destroy() throws Exception {
087 anonymousPublisher.destroy();
088 unregister();
089 }
090
091 protected String createAddress() {
092 return "http://servicemix.org/wsnotification/NotificationBroker/" + getName();
093 }
094
095 /**
096 *
097 * @param notify
098 */
099 @WebMethod(operationName = "Notify")
100 @Oneway
101 public void notify(
102 @WebParam(name = "Notify",
103 targetNamespace = "http://docs.oasis-open.org/wsn/b-1",
104 partName = "Notify")
105 Notify notify) {
106
107 log.debug("Notify");
108 handleNotify(notify);
109 }
110
111 protected void handleNotify(Notify notify) {
112 for (NotificationMessageHolderType messageHolder : notify.getNotificationMessage()) {
113 EndpointReferenceType producerReference = messageHolder.getProducerReference();
114 AbstractPublisher publisher = getPublisher(producerReference);
115 if (publisher != null) {
116 publisher.notify(messageHolder);
117 }
118 }
119 }
120
121 protected AbstractPublisher getPublisher(EndpointReferenceType producerReference) {
122 AbstractPublisher publisher = null;
123 if (producerReference != null && producerReference.getAddress() != null
124 && producerReference.getAddress().getValue() != null) {
125 String address = producerReference.getAddress().getValue();
126 publisher = publishers.get(address);
127 }
128 if (publisher == null) {
129 publisher = anonymousPublisher;
130 }
131 return publisher;
132 }
133
134 /**
135 *
136 * @param subscribeRequest
137 * @return returns org.oasis_open.docs.wsn.b_1.SubscribeResponse
138 * @throws SubscribeCreationFailedFault
139 * @throws InvalidTopicExpressionFault
140 * @throws TopicNotSupportedFault
141 * @throws InvalidFilterFault
142 * @throws InvalidProducerPropertiesExpressionFault
143 * @throws ResourceUnknownFault
144 * @throws InvalidUseRawValueFault
145 * @throws InvalidMessageContentExpressionFault
146 * @throws TopicExpressionDialectUnknownFault
147 * @throws UnacceptableInitialTerminationTimeFault
148 */
149 @WebMethod(operationName = "Subscribe")
150 @WebResult(name = "SubscribeResponse",
151 targetNamespace = "http://docs.oasis-open.org/wsn/b-1",
152 partName = "SubscribeResponse")
153 public SubscribeResponse subscribe(
154 @WebParam(name = "Subscribe",
155 targetNamespace = "http://docs.oasis-open.org/wsn/b-1",
156 partName = "SubscribeRequest")
157 Subscribe subscribeRequest) throws InvalidFilterFault, InvalidMessageContentExpressionFault,
158 InvalidProducerPropertiesExpressionFault, InvalidTopicExpressionFault, ResourceUnknownFault,
159 SubscribeCreationFailedFault, TopicExpressionDialectUnknownFault, TopicNotSupportedFault,
160 UnacceptableInitialTerminationTimeFault {
161
162 log.debug("Subscribe");
163 return handleSubscribe(subscribeRequest, null);
164 }
165
166 public SubscribeResponse handleSubscribe(
167 Subscribe subscribeRequest,
168 EndpointManager manager) throws InvalidFilterFault, InvalidMessageContentExpressionFault,
169 InvalidProducerPropertiesExpressionFault, InvalidTopicExpressionFault,
170 SubscribeCreationFailedFault, TopicExpressionDialectUnknownFault,
171 TopicNotSupportedFault, UnacceptableInitialTerminationTimeFault {
172 AbstractSubscription subscription = null;
173 boolean success = false;
174 try {
175 subscription = createSubcription(idGenerator.generateSanitizedId());
176 subscription.setBroker(this);
177 subscriptions.put(subscription.getAddress(), subscription);
178 subscription.create(subscribeRequest);
179 if (manager != null) {
180 subscription.setManager(manager);
181 }
182 subscription.register();
183 SubscribeResponse response = new SubscribeResponse();
184 response.setSubscriptionReference(createEndpointReference(subscription.getAddress()));
185 success = true;
186 return response;
187 } catch (EndpointRegistrationException e) {
188 SubscribeCreationFailedFaultType fault = new SubscribeCreationFailedFaultType();
189 throw new SubscribeCreationFailedFault("Unable to register endpoint", fault, e);
190 } finally {
191 if (!success && subscription != null) {
192 subscriptions.remove(subscription);
193 try {
194 subscription.unsubscribe();
195 } catch (UnableToDestroySubscriptionFault e) {
196 log.info("Error destroying subscription", e);
197 }
198 }
199 }
200 }
201
202 public void unsubscribe(String address) throws UnableToDestroySubscriptionFault {
203 AbstractSubscription subscription = (AbstractSubscription) subscriptions.remove(address);
204 if (subscription != null) {
205 subscription.unsubscribe();
206 }
207 }
208
209 /**
210 *
211 * @param getCurrentMessageRequest
212 * @return returns org.oasis_open.docs.wsn.b_1.GetCurrentMessageResponse
213 * @throws MultipleTopicsSpecifiedFault
214 * @throws TopicNotSupportedFault
215 * @throws InvalidTopicExpressionFault
216 * @throws ResourceUnknownFault
217 * @throws TopicExpressionDialectUnknownFault
218 * @throws NoCurrentMessageOnTopicFault
219 */
220 @WebMethod(operationName = "GetCurrentMessage")
221 @WebResult(name = "GetCurrentMessageResponse",
222 targetNamespace = "http://docs.oasis-open.org/wsn/b-1",
223 partName = "GetCurrentMessageResponse")
224 public GetCurrentMessageResponse getCurrentMessage(
225 @WebParam(name = "GetCurrentMessage",
226 targetNamespace = "http://docs.oasis-open.org/wsn/b-1",
227 partName = "GetCurrentMessageRequest")
228 GetCurrentMessage getCurrentMessageRequest) throws InvalidTopicExpressionFault,
229 MultipleTopicsSpecifiedFault, NoCurrentMessageOnTopicFault, ResourceUnknownFault,
230 TopicExpressionDialectUnknownFault, TopicNotSupportedFault {
231
232 log.debug("GetCurrentMessage");
233 NoCurrentMessageOnTopicFaultType fault = new NoCurrentMessageOnTopicFaultType();
234 throw new NoCurrentMessageOnTopicFault("There is no current message on this topic.", fault);
235 }
236
237 /**
238 *
239 * @param registerPublisherRequest
240 * @return returns org.oasis_open.docs.wsn.br_1.RegisterPublisherResponse
241 * @throws PublisherRegistrationRejectedFault
242 * @throws InvalidTopicExpressionFault
243 * @throws TopicNotSupportedFault
244 * @throws ResourceUnknownFault
245 * @throws PublisherRegistrationFailedFault
246 */
247 @WebMethod(operationName = "RegisterPublisher")
248 @WebResult(name = "RegisterPublisherResponse",
249 targetNamespace = "http://docs.oasis-open.org/wsn/br-1",
250 partName = "RegisterPublisherResponse")
251 public RegisterPublisherResponse registerPublisher(
252 @WebParam(name = "RegisterPublisher",
253 targetNamespace = "http://docs.oasis-open.org/wsn/br-1",
254 partName = "RegisterPublisherRequest")
255 RegisterPublisher registerPublisherRequest) throws InvalidTopicExpressionFault,
256 PublisherRegistrationFailedFault, PublisherRegistrationRejectedFault, ResourceUnknownFault,
257 TopicNotSupportedFault {
258
259 log.debug("RegisterPublisher");
260 return handleRegisterPublisher(registerPublisherRequest, null);
261 }
262
263 public RegisterPublisherResponse handleRegisterPublisher(RegisterPublisher registerPublisherRequest,
264 EndpointManager manager) throws InvalidTopicExpressionFault, PublisherRegistrationFailedFault,
265 PublisherRegistrationRejectedFault, ResourceUnknownFault, TopicNotSupportedFault {
266 AbstractPublisher publisher = null;
267 boolean success = false;
268 try {
269 publisher = createPublisher(idGenerator.generateSanitizedId());
270 publishers.put(publisher.getAddress(), publisher);
271 if (manager != null) {
272 publisher.setManager(manager);
273 }
274 publisher.register();
275 publisher.create(registerPublisherRequest);
276 RegisterPublisherResponse response = new RegisterPublisherResponse();
277 response.setPublisherRegistrationReference(createEndpointReference(publisher.getAddress()));
278 success = true;
279 return response;
280 } catch (EndpointRegistrationException e) {
281 PublisherRegistrationFailedFaultType fault = new PublisherRegistrationFailedFaultType();
282 throw new PublisherRegistrationFailedFault("Unable to register new endpoint", fault, e);
283 } finally {
284 if (!success && publisher != null) {
285 publishers.remove(publisher.getAddress());
286 try {
287 publisher.destroy();
288 } catch (ResourceNotDestroyedFault e) {
289 log.info("Error destroying publisher", e);
290 }
291 }
292 }
293 }
294
295 protected abstract AbstractPublisher createPublisher(String name);
296
297 protected abstract AbstractSubscription createSubcription(String name);
298
299 }