This repository has been archived by the owner on Dec 15, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 36
/
ServiceContext.java
224 lines (207 loc) · 8.96 KB
/
ServiceContext.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
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.tamaya.spi;
import javax.annotation.Priority;
import java.net.URL;
import java.util.*;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class models the component that is managing the lifecycle current the
* services used by the Configuration API.
*/
public interface ServiceContext extends ClassloaderAware{
/**
* True if the {@link Priority} annotation class is available on the classpath.
*/
boolean PRIORITY_ANNOTATION_AVAILABLE = checkPriorityAnnotation(ServiceContextManager.getDefaultClassLoader());
/**
* Checks if the {@link Priority} annotation class is on the classpath.
* @param classLoader the target classloader, not null.
* @return true, if the annotation is loaded.
*/
static boolean checkPriorityAnnotation(ClassLoader classLoader) {
try{
Class.forName("javax.annotation.Priority", true, classLoader);
return true;
}catch(Exception e){
return false;
}
}
/**
* Get the ordinal of the ServiceContext.
* @return ordinal of the ServiceContext. The one with the highest ordinal will be taken.
*/
default int ordinal(){
return getPriority(this);
}
/**
* Checks the given instance for a @Priority annotation. If present the annotation's value is evaluated. If no such
* annotation is present, a default priority of {@code 1} is returned.
* @param o the instance, not {@code null}.
* @return a priority, by default 1.
*/
static int getPriority(Object o){
int prio = 1;
if(PRIORITY_ANNOTATION_AVAILABLE) {
Priority priority = o.getClass().getAnnotation(Priority.class);
if (priority != null) {
prio = priority.value();
}
}
return prio;
}
/**
* Access a service singleton via its type.
* If multiple implementations for the very serviceType exist then
* the one with the highest {@link javax.annotation.Priority} will be used.
*
* @param <T> the type of the service type.
* @param serviceType the service type.
* @return The instance to be used, or {@code null}
* @throws org.apache.tamaya.ConfigException if there are multiple service implementations with the maximum priority.
*/
default <T> T getService(Class<T> serviceType){
return getService(serviceType, null);
}
/**
* Access a service singleton via its type.
* If multiple implementations for the very serviceType exist then
* the one with the highest {@link javax.annotation.Priority} will be used.
*
* @param <T> the type of the service type.
* @param serviceType the service type.
* @param supplier the supplier to be used, if no services could be evaluated. If null,
* an empty collection is returned, when no services
* could be located.
* @return The instance to be used, or {@code null}
* @throws org.apache.tamaya.ConfigException if there are multiple service implementations with the maximum priority.
*/
<T> T getService(Class<T> serviceType, Supplier<T> supplier);
/**
* Factory method to createObject a type, hereby a new instance is created on each access.
* If multiple implementations for the very serviceType exist then
* the one with the highest {@link javax.annotation.Priority} will be used as the base
* for creating subsequent instances.
*
* @param <T> the type of the service type.
* @param serviceType the service type.
* @return The new instance to be used, or {@code null}
* @throws org.apache.tamaya.ConfigException if there are multiple service implementations with the maximum priority.
*/
default <T> T create(Class<T> serviceType){
return create(serviceType, null);
}
/**
* Factory method to createObject a type, hereby a new instance is created on each access.
* If multiple implementations for the very serviceType exist then
* the one with the highest {@link javax.annotation.Priority} will be used as the base
* for creating subsequent instances.
*
* @param supplier the supplier to create a new service, if no service could be autodetected.
* @param <T> the type of the service type.
* @param serviceType the service type.
* @return The new instance to be used, or {@code null}
* @throws org.apache.tamaya.ConfigException if there are multiple service implementations with the maximum priority.
*/
<T> T create(Class<T> serviceType, Supplier<T> supplier);
/**
* Access a createList current services, given its type. The bootstrap mechanism should
* order the instance for precedence, hereby the most significant should be
* first in order.
*
* @param serviceType
* the service type.
* @param <T> the type of the createList element returned by this method
* @return The instance to be used, never {@code null}
*/
default <T> List<T> getServices(Class<T> serviceType){
return getServices(serviceType, null);
}
/**
* Access a createList current services, given its type. The bootstrap mechanism should
* order the instance for precedence, hereby the most significant should be
* first in order. If no instances could be found, the instances supplied by the
* supplier given are registered and used.
*
* @param serviceType
* the service type.
* @param <T> the type of the createList element returned by this method
* @param supplier the supplier to be used, if no services could be evaluated. If null,
* an empty collection is returned, when no services
* could be located.
* @return The instance to be used, never {@code null}
*/
<T> List<T> getServices(Class<T> serviceType, Supplier<List<T>> supplier);
/**
* Loads resources from the current runtime context. This method allows to use runtime
* specific code to load resources, e.g. within OSGI environments.
* @param resource the resource, not {@code null}.
* @return the resources found
*/
default Collection<URL> getResources(String resource){
List<URL> urls = new ArrayList<>();
try {
Enumeration<URL> found = getClassLoader().getResources(resource);
while (found.hasMoreElements()) {
urls.add(found.nextElement());
}
}catch(Exception e){
Logger.getLogger(ServiceContext.class.getName())
.log(Level.FINEST, e, () -> "Failed to lookup resources: " + resource);
}
return urls;
}
/**
* Loads a resource from the current runtime context. This method allows to use runtime
* specific code to load a resource, e.g. within OSGI environments.
* @param resource the resource, not {@code null}.
* @return the resource found, or {@code null}.
*/
default URL getResource(String resource){
return getClassLoader().getResource(resource);
}
/**
* Registers the given instance as a singleton service for the given instance, if no
* instance already has been registered.
*
* @param type the type to register, not null.
* @param instance the instance, not null.
* @param <T> thy type.
* @param force if true, any existing instance will be replaced.
* @return the instance registered or already present.
*/
<T> T register(Class<T> type, T instance, boolean force);
/**
* Registers the given instancea as servicea for the given instance, if no
* * instance already has been registered.
* @param type the type to register, not null.
* @param instances the instancea, not null.
* @param <T> thy type.
* @param force if true, any existing instances will be replaced.
* @return the instances registered or already present.
*/
<T> List<T> register(Class<T> type, List<T> instances, boolean force);
/**
* Resets the current service context, removing all loaded services. This implicitly triggers a new load
* of the service context.
*/
void reset();
}