Project

General

Profile

1
package eu.dnetlib.common.services.locators;
2

    
3
import java.util.Collections;
4
import java.util.Comparator;
5
import java.util.List;
6
import java.util.Map;
7
import java.util.Set;
8

    
9
import javax.annotation.PostConstruct;
10
import javax.annotation.Resource;
11

    
12
import org.apache.commons.lang.StringUtils;
13
import org.apache.commons.logging.Log;
14
import org.apache.commons.logging.LogFactory;
15
import org.springframework.beans.BeansException;
16
import org.springframework.beans.factory.annotation.Required;
17
import org.springframework.context.ApplicationContext;
18
import org.springframework.context.ApplicationContextAware;
19

    
20
import com.google.common.collect.Lists;
21
import com.google.common.collect.Maps;
22
import com.google.common.collect.Sets;
23

    
24
import eu.dnetlib.common.services.ServiceNameResolver;
25
import eu.dnetlib.rmi.objects.is.DnetDataStructure;
26
import eu.dnetlib.rmi.objects.is.DnetService;
27
import eu.dnetlib.rmi.soap.BaseService;
28
import eu.dnetlib.rmi.soap.InformationService;
29
import eu.dnetlib.rmi.soap.exceptions.InformationServiceException;
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 informationService (local or stub)
40
	 */
41
	@Resource
42
	private InformationService informationService;
43

    
44
	/**
45
	 * logger.
46
	 */
47
	private static final Log log = LogFactory.getLog(DefaultUniqueServiceLocator.class);
48

    
49
	@PostConstruct
50
	public void init() {
51
		log.info("****************************************");
52
		log.info("*     I'm the new service locator      *");
53
		log.info("****************************************");
54
	}
55

    
56
	@Override
57
	public <T extends BaseService> T getService(final Class<T> clazz) {
58
		return getService(clazz, true);
59
	}
60

    
61
	@Override
62
	public <T extends BaseService> T getService(final Class<T> clazz, final Comparator<ServiceRunningInstance> comparator) {
63
		final String serviceName = ServiceNameResolver.resolveServiceName(clazz);
64
		return findRunningInstances(serviceName, comparator).get(0).obtainClient(clazz);
65
	}
66

    
67
	@Override
68
	public <T extends BaseService> T getService(final Class<T> clazz, final String id) {
69
		try {
70
			final String serviceId = getServiceId(clazz, id);
71
			final DnetService desc = informationService.getService(serviceId);
72
			return obtainRunningInstance(desc, obtainLocalServices()).obtainClient(clazz);
73
		} catch (Exception e) {
74
			log.error("cannot instantiate service from id: " + id, e);
75
			throw new IllegalStateException("cannot instantiate service from id: " + id, e);
76
		}
77
	}
78

    
79
	@Override
80
	public <T extends BaseService> T getService(final Class<T> clazz, final boolean local) {
81
		if (clazz.isInstance(informationService)) { return clazz.cast(informationService); }
82

    
83
		if (local) {
84
			try {
85
				final Map<String, T> beans = appContext.getBeansOfType(clazz);
86
				if (beans != null && !beans.isEmpty()) { return beans.values().iterator().next(); }
87
			} catch (Throwable e) {
88
				log.warn("No beans found in context, class " + clazz);
89
			}
90
		}
91

    
92
		return getService(clazz, defaultComparator);
93
	}
94

    
95
	@Override
96
	public <T extends BaseService> String getServiceId(final Class<T> clazz) {
97
		return getServiceId(clazz, defaultComparator);
98
	}
99

    
100
	@Override
101
	public <T extends BaseService> String getServiceId(final Class<T> clazz, final Comparator<ServiceRunningInstance> comparator) {
102
		return findRunningInstances(ServiceNameResolver.resolveServiceName(clazz), comparator).get(0).getServiceId();
103
	}
104

    
105
	@Override
106
	public <T extends BaseService> String getServiceId(final Class<T> clazz, final String id) {
107
		try {
108
			if (id.startsWith("service-")) {
109
				return id;
110
			} else {
111
				DnetDataStructure dsById;
112
				dsById = informationService.getDsById(id);
113
				if (dsById != null) {
114
					return dsById.getServiceId();
115
				} else {
116
					return null;
117
				}
118
			}
119
		} catch (InformationServiceException e) {
120
			log.error("Error searching service for resource:" + id);
121
			return null;
122
		}
123
	}
124

    
125
	@Override
126
	public <T extends BaseService> Set<T> getAllServices(final Class<T> clazz) {
127
		final Set<T> res = Sets.newHashSet();
128
		for (ServiceRunningInstance instance : findRunningInstances(ServiceNameResolver.resolveServiceName(clazz), null)) {
129
			res.add(instance.obtainClient(clazz));
130
		}
131
		return res;
132
	}
133

    
134
	@Override
135
	public <T extends BaseService> Set<String> getAllServiceIds(
136
			final Class<T> clazz) {
137
		final Set<String> res = Sets.newHashSet();
138
		for (ServiceRunningInstance instance : findRunningInstances(ServiceNameResolver.resolveServiceName(clazz), null)) {
139
			res.add(instance.getServiceId());
140
		}
141
		return res;
142
	}
143

    
144
	private synchronized <T extends BaseService> ServiceRunningInstance obtainRunningInstance(
145
			final DnetService desc, final Map<String, BaseService> locals) {
146

    
147
		final String id = desc.getId();
148
		final String url = desc.getProtocols().get("SOAP");
149

    
150
		final BaseService local = locals.containsKey(id) ? locals.get(id) : null;
151

    
152
		final int usedDiskpace = 0; // TODO
153
		final int handledDatastructures = 0; // TODO
154

    
155
		return new ServiceRunningInstance(id, url, local, usedDiskpace, handledDatastructures, desc.getProperties());
156
	}
157

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

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

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

    
170
		return list;
171
	}
172

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

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

    
179
		try {
180
			final List<ServiceRunningInstance> instances = Lists.newArrayList();
181
			final Map<String, BaseService> locals = obtainLocalServices();
182
			for (final DnetService s : informationService.listServices()) {
183
				if (s.getName().equals(serviceName)) {
184
					instances.add(obtainRunningInstance(s, locals));
185
				}
186
			}
187
			return instances;
188
		} catch (final Exception e) {
189
			throw new IllegalStateException("cannot locate service " + serviceName, e);
190
		}
191
	}
192

    
193
	private Map<String, BaseService> obtainLocalServices() {
194
		final Map<String, BaseService> locals = Maps.newHashMap();
195
		for (BaseService service : appContext.getBeansOfType(BaseService.class).values()) {
196
			final DnetService info = service.identify();
197
			if (info != null && StringUtils.isNotBlank(info.getId())) {
198
				locals.put(info.getId(), service);
199
			}
200
		}
201
		return locals;
202
	}
203

    
204
	@Override
205
	public void setApplicationContext(final ApplicationContext appContext) throws BeansException {
206
		this.appContext = appContext;
207
	}
208

    
209
	public Comparator<ServiceRunningInstance> getDefaultComparator() {
210
		return defaultComparator;
211
	}
212

    
213
	@Required
214
	public void setDefaultComparator(final Comparator<ServiceRunningInstance> defaultComparator) {
215
		this.defaultComparator = defaultComparator;
216
	}
217

    
218
	public InformationService getInformationService() {
219
		return informationService;
220
	}
221

    
222
	public void setInformationService(final InformationService informationService) {
223
		this.informationService = informationService;
224
	}
225

    
226
}
(1-1/3)