Project

General

Profile

1
package eu.dnetlib.enabling.locators;
2

    
3
import java.io.StringReader;
4
import java.io.StringWriter;
5
import java.util.*;
6

    
7
import com.google.common.collect.Lists;
8
import com.google.common.collect.Maps;
9
import com.google.common.collect.Sets;
10
import eu.dnetlib.common.rmi.BaseService;
11
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
12
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
13
import eu.dnetlib.enabling.tools.registration.ServiceNameResolver;
14
import eu.dnetlib.enabling.tools.registration.ValidatingServiceRegistrationManagerImpl;
15
import eu.dnetlib.miscutils.collections.EnsureCollection;
16
import eu.dnetlib.soap.cxf.StandaloneCxfEndpointReferenceBuilder;
17
import org.apache.commons.lang.StringUtils;
18
import org.apache.commons.lang.math.NumberUtils;
19
import org.apache.commons.logging.Log;
20
import org.apache.commons.logging.LogFactory;
21
import org.dom4j.Document;
22
import org.dom4j.DocumentException;
23
import org.dom4j.Element;
24
import org.dom4j.io.SAXReader;
25
import org.springframework.beans.BeansException;
26
import org.springframework.beans.factory.annotation.Autowired;
27
import org.springframework.beans.factory.annotation.Required;
28
import org.springframework.context.ApplicationContext;
29
import org.springframework.context.ApplicationContextAware;
30

    
31
public class DefaultUniqueServiceLocator implements UniqueServiceLocator, ApplicationContextAware {
32

    
33
	private ApplicationContext appContext;
34

    
35
	private Comparator<ServiceRunningInstance> defaultComparator; // = new
36
	// PreferLocalRunningInstanceComparator();
37

    
38
	/**
39
	 * An instance of isLookupService (local or stub)
40
	 */
41
	@Autowired
42
	private ISLookUpService isLookupService;
43

    
44
	@Autowired
45
	private ServiceNameResolver serviceNameResolver;
46

    
47
	/**
48
	 * XML Parser
49
	 */
50
	private SAXReader reader = new SAXReader();
51

    
52
	/**
53
	 * build epr.
54
	 */
55
	@Autowired
56
	private StandaloneCxfEndpointReferenceBuilder eprBuilder;
57

    
58
	/**
59
	 * logger.
60
	 */
61
	private static final Log log = LogFactory.getLog(DefaultUniqueServiceLocator.class);
62

    
63
	@Override
64
	public <T extends BaseService> T getService(final Class<T> clazz) {
65
		return getService(clazz, true);
66
	}
67

    
68
	@Override
69
	public <T extends BaseService> T getService(final Class<T> clazz, final Comparator<ServiceRunningInstance> comparator) {
70
		final String serviceName = serviceNameResolver.getName(clazz);
71
		return findRunningInstances(serviceName, comparator).get(0).obtainClient(clazz, eprBuilder);
72
	}
73

    
74
	@Override
75
	public <T extends BaseService> T getService(final Class<T> clazz, final String profileId) {
76
		final String profile = obtainServiceProfile(profileId);
77

    
78
		try {
79
			return obtainRunningInstance(profile, obtainLocalServices()).obtainClient(clazz, eprBuilder);
80
		} catch (Exception e) {
81
			log.error("cannot instantiate service from id: " + profileId, e);
82
			throw new IllegalStateException("cannot instantiate service from id: " + profileId, e);
83
		}
84
	}
85

    
86
	@Override
87
	public <T extends BaseService> T getService(final Class<T> clazz, final boolean local) {
88
		if (clazz.isInstance(isLookupService)) return clazz.cast(isLookupService);
89

    
90
		if (local) {
91
			try {
92
				final Map<String, T> beans = appContext.getBeansOfType(clazz);
93
				if ((beans != null) && !beans.isEmpty()) return beans.values().iterator().next();
94
			} catch (Throwable e) {
95
				log.warn("No beans found in context, class " + clazz);
96
			}
97
		}
98

    
99
		return getService(clazz, defaultComparator);
100
	}
101

    
102
	@Override
103
	public <T extends BaseService> String getServiceId(final Class<T> clazz) {
104
		return getServiceId(clazz, defaultComparator);
105
	}
106

    
107
	@Override
108
	public <T extends BaseService> String getServiceId(final Class<T> clazz, final Comparator<ServiceRunningInstance> comparator) {
109
		return findRunningInstances(serviceNameResolver.getName(clazz), comparator).get(0).getServiceId();
110
	}
111

    
112
	@Override
113
	public <T extends BaseService> String getServiceId(final Class<T> clazz, final String profileId) {
114
		final String profile = obtainServiceProfile(profileId);
115
		final ServiceRunningInstance instance = obtainRunningInstance(profile, obtainLocalServices());
116
		return instance.getServiceId();
117
	}
118

    
119
	@Override
120
	public <T extends BaseService> Set<T> getAllServices(final Class<T> clazz) {
121
		final Set<T> res = Sets.newHashSet();
122
		for (ServiceRunningInstance instance : findRunningInstances(serviceNameResolver.getName(clazz), null)) {
123
			res.add(instance.obtainClient(clazz, eprBuilder));
124
		}
125
		return res;
126
	}
127

    
128
	@Override
129
	public <T extends BaseService> Set<String> getAllServiceIds(final Class<T> clazz) {
130
		final Set<String> res = Sets.newHashSet();
131
		for (ServiceRunningInstance instance : findRunningInstances(serviceNameResolver.getName(clazz), null)) {
132
			res.add(instance.getServiceId());
133
		}
134
		return res;
135
	}
136

    
137
	private synchronized <T extends BaseService> ServiceRunningInstance obtainRunningInstance(final String profile, final Map<String, BaseService> locals) {
138
		try {
139
			final Document doc = reader.read(new StringReader(profile));
140
			final String url = doc.valueOf("//PROTOCOL[@name = 'SOAP']/@address");
141
			final String id = doc.valueOf("//RESOURCE_IDENTIFIER/@value");
142
			final Map<String, String> props = Maps.newHashMap();
143
			final BaseService local = locals.containsKey(id) ? locals.get(id) : null;
144
			final int usedDiskpace = NumberUtils.toInt(doc.valueOf("//USED_DISKSPACE"), 0);
145
			final int handledDatastructures = NumberUtils.toInt(doc.valueOf("//HANDLED_DATASTRUCTURE"), 0);;
146

    
147
			for (Object o : doc.selectNodes("//SERVICE_PROPERTIES/PROPERTY")) {
148
				final Element p = (Element) o;
149
				props.put(p.valueOf("@key"), p.valueOf("@value"));
150
			}
151

    
152
			return new ServiceRunningInstance(id, url, local, usedDiskpace, handledDatastructures, props);
153
		} catch (DocumentException e) {
154
			log.error("Error parsing profile: " + profile, e);
155
			throw new RuntimeException("Error parsing profile: " + profile, e);
156
		}
157
	}
158

    
159
	private List<ServiceRunningInstance> findRunningInstances(final String serviceName, final Comparator<ServiceRunningInstance> comparator) {
160
		final List<ServiceRunningInstance> list = findRegisteredServices(serviceName);
161

    
162
		if (list.isEmpty()) {
163
			log.error("Service not found, name: " + serviceName);
164
			throw new RuntimeException("Service not found, name: " + serviceName);
165
		}
166

    
167
		if (comparator != null) {
168
			Collections.sort(list, comparator);
169
		}
170

    
171
		return list;
172
	}
173

    
174
	private List<ServiceRunningInstance> findRegisteredServices(final String serviceName) {
175
		log.debug("searching for service: " + serviceName);
176

    
177
		final String xquery = "for $x in collection('/db/DRIVER/ServiceResources/" + serviceName + "ResourceType') return $x";
178
		log.debug(xquery);
179

    
180
		try {
181
			final List<String> services = isLookupService.quickSearchProfile(xquery);
182
			final List<ServiceRunningInstance> instances = Lists.newArrayList();
183
			final Map<String, BaseService> locals = obtainLocalServices();
184

    
185
			for (final String source : EnsureCollection.list(services)) {
186
				final ServiceRunningInstance instance = obtainRunningInstance(source, locals);
187
				instances.add(instance);
188
			}
189
			return instances;
190
		} catch (final Exception e) {
191
			throw new IllegalStateException("cannot locate service " + serviceName, e);
192
		}
193
	}
194

    
195
	private Map<String, BaseService> obtainLocalServices() {
196
		final Map<String, BaseService> locals = Maps.newHashMap();
197

    
198
		for (ValidatingServiceRegistrationManagerImpl r : appContext.getBeansOfType(ValidatingServiceRegistrationManagerImpl.class).values()) {
199
			if (r.getService() instanceof BaseService) {
200
				if (!StringUtils.isBlank(r.getProfileId())) {
201
					final BaseService baseService = (BaseService) r.getService();
202
					if (baseService != null) {
203
						locals.put(r.getProfileId(), baseService);
204
						log.debug(" -> Service: " + r.getService().getClass().getName() + " has id " + r.getServiceProfile().getResourceId());
205
					}
206
				}
207
			}
208
		}
209
		return locals;
210
	}
211

    
212
	private String obtainServiceProfile(final String profileId) {
213
		final StringWriter sw = new StringWriter();
214
		sw.append("let $uri:=/RESOURCE_PROFILE/HEADER[./RESOURCE_IDENTIFIER/@value='");
215
		sw.append(profileId);
216
		sw.append("']/RESOURCE_URI/@value/string()");
217
		sw.append("\n\n");
218
		sw.append("for $x in collection('/db/DRIVER/ServiceResources')");
219
		sw.append("\n");
220
		sw.append("where $x/RESOURCE_PROFILE/HEADER/RESOURCE_URI/@value = $uri");
221
		sw.append("\n");
222
		sw.append("return $x");
223

    
224
		final String xq = sw.toString();
225

    
226
		try {
227
			return isLookupService.getResourceProfileByQuery(xq);
228
		} catch (ISLookUpException e) {
229
			log.error("cannot locate service using query: " + xq, e);
230
			throw new IllegalStateException("cannot locate service using query: " + xq, e);
231
		}
232
	}
233

    
234
	@Override
235
	public void setApplicationContext(final ApplicationContext appContext) throws BeansException {
236
		this.appContext = appContext;
237
	}
238

    
239
	public Comparator<ServiceRunningInstance> getDefaultComparator() {
240
		return defaultComparator;
241
	}
242

    
243
	@Required
244
	public void setDefaultComparator(final Comparator<ServiceRunningInstance> defaultComparator) {
245
		this.defaultComparator = defaultComparator;
246
	}
247

    
248
	public ISLookUpService getIsLookupService() {
249
		return isLookupService;
250
	}
251

    
252
	public void setIsLookupService(final ISLookUpService isLookupService) {
253
		this.isLookupService = isLookupService;
254
	}
255

    
256
	public ServiceNameResolver getServiceNameResolver() {
257
		return serviceNameResolver;
258
	}
259

    
260
	public void setServiceNameResolver(final ServiceNameResolver serviceNameResolver) {
261
		this.serviceNameResolver = serviceNameResolver;
262
	}
263

    
264
}
(1-1/3)