This repository has been archived by the owner on Feb 27, 2023. It is now read-only.
/
ServiceLocator.java
318 lines (296 loc) · 12.8 KB
/
ServiceLocator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
/*
* Copyright 2001-2011 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.juddi.v3.client.mapping;
import java.net.BindException;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import javax.xml.namespace.QName;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.juddi.api_v3.AccessPointType;
import org.apache.juddi.v3.client.ClassUtil;
import org.apache.juddi.v3.client.config.UDDIClerk;
import org.apache.juddi.v3.client.config.UDDIKeyConvention;
import org.apache.juddi.v3.client.subscription.SubscriptionCallbackListener;
import org.apache.juddi.v3.client.transport.TransportException;
import org.uddi.api_v3.AccessPoint;
import org.uddi.api_v3.BindingTemplate;
import org.uddi.api_v3.BindingTemplates;
import org.uddi.api_v3.BusinessService;
/**
* The ServiceLocator contacts the UDDI registry to lookup an Endpoint given a UDDI ServiceKey.<br>
* This class does NOT chase down WSDL, hosting redirectors or other binding references from
* access point useType values. See
* {@link org.apache.juddi.v3.client.config.UDDIClerk#getEndpoints UDDIClerk.getEndpoints}
* @see SubscriptionCallbackListener
* @author <a href="mailto:kstam@apache.org">Kurt T Stam</a>
*/
public class ServiceLocator {
private static final Log log = LogFactory.getLog(ServiceLocator.class);
private UDDIClerk clerk;
private Properties properties = new Properties();
private UDDIServiceCache serviceCache = null;
private String policy = null;
private SelectionPolicy selectionPolicy = null;
private URLLocalizer urlLocalizer = null;
private ConcurrentHashMap<String, Topology> simpleCache= null;
/**
* Requirement in the config is a clerk with access credentials to the UDDI server
* you want the locator to do lookups to. When a live cache is used the clerk
* will register a callback into this UDDI server and the clerk will therefore need
* inquiry and publish access. The credentials can be set in the uddi-client.xml
* configuration file.
*
* @param clerk a UDDI Clerk with publish access to the UDDI Server.
* @throws ConfigurationException
*/
public ServiceLocator(UDDIClerk clerk) {
super();
this.clerk = clerk;
properties =clerk.getUDDINode().getProperties();
}
public ServiceLocator(UDDIClerk clerk, URLLocalizer urlLocalizer, Properties properties) throws ConfigurationException {
super();
this.clerk = clerk;
this.urlLocalizer = urlLocalizer;
this.properties = properties;
if (properties == null)
this.properties = clerk.getUDDINode().getProperties();
}
/**
* Creates a new UDDIServiceCache, which brings up a new WebService Endpoint. This
* EndPoint will be called by the UDDI server if any service changes. A callback
* will result in cleaning the cache.
*
* @param baseCallbackURL
* @throws ConfigurationException
*/
public ServiceLocator withCache(URL baseCallbackURL) throws ConfigurationException {
if (serviceCache == null) {
serviceCache = initCache(baseCallbackURL);
}
return this;
}
/**
* A live cache will receive callbacks from the UDDI server in case there is an update to
* a service's bindings. All callbacks will clear the UDDIClientCache ensuring that subsequent
* lookups will contact the UDDI server for the latest binding information.
*
* The baseCallbackURL can be set to solve binding issue. If
*
* @param baseCallbackURL
* @return a service locator object
* @throws ConfigurationException
* @throws BindException
*/
public ServiceLocator withLiveCache(URL baseCallbackURL) throws ConfigurationException, BindException {
if (serviceCache == null) {
serviceCache = initCache(baseCallbackURL);
serviceCache.registerAsMBean();
}
if (! serviceCache.hasListener()) {
serviceCache.publishAndRegisterHttpCallbackEndpoint();
}
return this;
}
public ServiceLocator withSimpleCache(){
if (simpleCache==null){
simpleCache= new ConcurrentHashMap<String, Topology>();
}
return this;
}
public UDDIServiceCache getUDDIServiceCache() {
return serviceCache;
}
/**
* The policy selection can be set as property "juddi.client.selection.policy"
* or it can be set programmatically using this method. A Policy is a class which
* implements the SelectionPolicy interface. Known implementations are
* org.apache.juddi.v3.client.mapping.PolicyLocalFirst and
* org.apache.juddi.v3.client.mapping.PolicyRoundRobin. If the policy is not
* set the default org.apache.juddi.v3.client.mapping.PolicyLocalFirst is used.
*
* @param policy - the desired policy.
* @return ServiceLocator
* @see org.apache.juddi.v3.client.mapping.PolicyLocalFirst
* @see org.apache.juddi.v3.client.mapping.PolicyRoundRobin
*/
public ServiceLocator setPolicy(String policy) {
this.policy = policy;
return this;
}
/**
* Returns the selection policy in use by this instance of the ServiceLocator.
*
* @return SelectionPolicy - the selection policy.
* @throws ConfigurationException
*/
public SelectionPolicy getPolicy() throws ConfigurationException {
try {
if (selectionPolicy==null) {
if (policy==null) {
//TODO update .NET schema file to support this
policy = properties.getProperty("juddi.client.selection.policy", "org.apache.juddi.v3.client.mapping.PolicyLocalFirst");
}
@SuppressWarnings("unchecked")
Class<? extends SelectionPolicy> selectionPolicyClass = (Class<? extends SelectionPolicy>)
ClassUtil.forName(policy, this.getClass());
selectionPolicy = selectionPolicyClass.getConstructor(Properties.class).newInstance(properties);
}
return selectionPolicy;
} catch (Exception e) {
throw new ConfigurationException(e.getMessage(),e);
}
}
/**
* Creates a new UDDIServiceCache, which brings up a new WebService Endpoint. This
* EndPoint will be called by the UDDI server if any service changes. A callback
* will result in cleaning the cache.
*
* @param baseCallbackURL
* @throws ConfigurationException
*/
private UDDIServiceCache initCache(URL baseCallbackURL) throws ConfigurationException {
if (clerk==null) throw new ConfigurationException("The UDDIClerk is needed to use the UDDIServiceCache and is null");
if (urlLocalizer==null) urlLocalizer = new URLLocalizerDefaultImpl(baseCallbackURL);
if (properties==null) properties = new Properties();
try {
log.info("Creating a UDDICLientCache");
return new UDDIServiceCache(clerk, urlLocalizer, properties);
} catch (Exception e) {
throw new ConfigurationException(e.getMessage(),e);
}
}
public void clearCaches(){
if (serviceCache!=null)
serviceCache.removeAll();
if (simpleCache!=null)
simpleCache.clear();
}
/**
*
* @throws RemoteException
* @throws ConfigurationException
* @throws TransportException
*/
public void shutdown() throws RemoteException, ConfigurationException, TransportException {
if (serviceCache!=null)
serviceCache.shutdown();
}
/**
* Looks up the Endpoints for a Service. If the cache is in use it will try to
* obtain them from the cache. If no Endpoints are found, or if the cache is not
* in use, the clerk will do a lookup for this service. After Endpoints are found
* it will use a policy to pick one Endpoint to return. Returns null if no endpoints
* are found.
*
* @param serviceKey
* @return endpoint
* @throws RemoteException
* @throws ConfigurationException
* @throws TransportException
*/
public String lookupEndpoint(String serviceKey) throws RemoteException, ConfigurationException, TransportException {
Topology topology = null;
if (simpleCache != null && simpleCache.containsKey(serviceKey)){
topology = simpleCache.get(serviceKey);
} else if (serviceCache==null) { //nocache in use
topology = lookupEndpointInUDDI(serviceKey);
} else { //with cache
//try to get it from the cache first
topology = serviceCache.lookupService(serviceKey);
if (topology == null) { //not found in the cache
topology = lookupEndpointInUDDI(serviceKey);
}
}
if (topology!=null && topology.getEprs().size() > 0) {
if (simpleCache!=null){
simpleCache.put(serviceKey,topology);
}
String epr = getPolicy().select(topology);
return epr;
}
return null;
}
/**
* Looks up the Endpoints for a Service. If the cache is in use it will try to
* obtain them from the cache. If no Endpoints are found, or if the cache is not
* in use, the clerk will do a lookup for this service. After Endpoints are found
* it will use a policy to pick one Endpoint to return. Returns null if no endpoints
* are found.
*
* @param serviceQName
* @param portName
* @return Returns null if no endpoints
* are found.
* @throws TransportException
* @throws ConfigurationException
* @throws RemoteException
*/
public String lookupEndpoint(QName serviceQName, String portName) throws RemoteException, ConfigurationException, TransportException {
String serviceKey = UDDIKeyConvention.getServiceKey(properties, serviceQName.getLocalPart());
return lookupEndpoint(serviceKey);
}
private Topology lookupEndpointInUDDI(String serviceKey) throws RemoteException, ConfigurationException, TransportException {
Topology topology = null;
BusinessService service = clerk.getServiceDetail(serviceKey);
if (service==null) {
log.warn("No Service with key " + serviceKey + " was found in the registry.");
//TODO find service by tModel
}
if (service!=null && service.getBindingTemplates()!=null && service.getBindingTemplates().getBindingTemplate() != null) {
ArrayList<String> eprs = new ArrayList<String>();
BindingTemplates bindingTemplates = service.getBindingTemplates();
if (bindingTemplates==null) {
log.warn("Found service " + service.getName().get(0).getValue()
+ " with serviceKey '" + serviceKey + "'"
+ " but no EPRs");
} else {
log.debug("Found service " + service.getName().get(0).getValue()
+ " with serviceKey '" + serviceKey + "'"
+ " and " + bindingTemplates.getBindingTemplate().size() + " EPRs");
//Loop over all bindingTemplates found and get the endpoints.
for (BindingTemplate bindingTemplate : bindingTemplates.getBindingTemplate()) {
AccessPoint accessPoint = bindingTemplate.getAccessPoint();
if (accessPoint!=null){
if (AccessPointType.END_POINT.toString().equals(accessPoint.getUseType())) {
String url = accessPoint.getValue();
log.debug("epr= " + url);
eprs.add(url);
} else if(AccessPointType.WSDL_DEPLOYMENT.toString().equals(accessPoint.getUseType())) {
//do something here
//try to open that wsdl, then grab the endpoints
//String url=fetchFromWsdl(accessPoint.getValue());
} else if(AccessPointType.BINDING_TEMPLATE.toString().equals(accessPoint.getUseType())) {
//do something here
//grab that binding template and use that address
}
}
}
if (eprs.size()>0) {
topology = new Topology(eprs);
}
}
}
if (serviceCache!=null && topology!=null) { //add to cache
serviceCache.addService(serviceKey, topology);
}
return topology;
}
}