APIRegistry.java
5.7 KB
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
package com.mumfrey.liteloader.api.manager;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.minecraft.launchwrapper.Launch;
import com.mumfrey.liteloader.api.LiteAPI;
import com.mumfrey.liteloader.api.exceptions.InvalidAPIStateException;
import com.mumfrey.liteloader.launch.LoaderEnvironment;
import com.mumfrey.liteloader.launch.LoaderProperties;
import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
import com.mumfrey.liteloader.util.log.LiteLoaderLogger.Verbosity;
/**
* This is where we register API classes during early startup before baking the
* registered list into an APIProvider instance
*
* @author Adam Mummery-Smith
*/
public final class APIRegistry
{
private Set<String> registeredAPIClasses = new LinkedHashSet<String>();
private Map<String, LiteAPI> instances = new LinkedHashMap<String, LiteAPI>();
private final LoaderEnvironment environment;
private final LoaderProperties properties;
private APIProviderBasic baked;
/**
* @param environment
* @param properties
*/
public APIRegistry(LoaderEnvironment environment, LoaderProperties properties)
{
this.environment = environment;
this.properties = properties;
}
/**
* Register an API class, throws an exception if the API list has already
* been baked.
*
* @param apiClass
*/
public void registerAPI(String apiClass) throws InvalidAPIStateException
{
if (this.baked != null)
{
throw new InvalidAPIStateException("Unable to register API provider '" + apiClass
+ "' because the API state is now frozen, this probably means you are registering an API too late in the initialisation process");
}
if (!this.registeredAPIClasses.contains(apiClass))
{
LiteLoaderLogger.info(Verbosity.REDUCED, "Registering API provider class %s", apiClass);
this.registeredAPIClasses.add(apiClass);
}
}
/**
* Get all currently registered API classes
*/
public String[] getRegisteredAPIs()
{
return this.registeredAPIClasses.toArray(new String[0]);
}
/**
* @param apiClassName
*/
private LiteAPI spawnAPI(String apiClassName)
{
try
{
LiteLoaderLogger.info("Spawning API provider class '%s' ...", apiClassName);
@SuppressWarnings("unchecked")
Class<? extends LiteAPI> apiClass = (Class<? extends LiteAPI>)Class.forName(apiClassName, true, Launch.classLoader);
LiteAPI api = apiClass.newInstance();
String identifier = api.getIdentifier();
if (!this.instances.containsKey(identifier))
{
LiteLoaderLogger.info(Verbosity.REDUCED, "API provider class '%s' provides API '%s'", apiClassName, identifier);
this.instances.put(identifier, api);
return api;
}
Class<? extends LiteAPI> conflictingAPIClass = this.instances.get(identifier).getClass();
LiteLoaderLogger.severe("API identifier clash while registering '%s', identifier '%s' clashes with '%s'", apiClassName,
identifier, conflictingAPIClass);
}
catch (ClassNotFoundException ex)
{
LiteLoaderLogger.severe("API class '%s' could not be created, the specified class could not be loaded", apiClassName);
}
catch (Exception ex)
{
LiteLoaderLogger.severe(ex, "Error while instancing API class '%s'", apiClassName);
}
return null;
}
/**
* Populate and return the API instance array
*/
private LiteAPI[] getAllAPIs()
{
List<LiteAPI> allAPIs = new ArrayList<LiteAPI>();
for (String apiClass : this.registeredAPIClasses)
{
LiteAPI api = this.spawnAPI(apiClass);
if (api != null)
{
allAPIs.add(api);
}
}
for (LiteAPI api : allAPIs)
{
LiteLoaderLogger.info(Verbosity.REDUCED, "Initialising API '%s' ...", api.getIdentifier());
api.init(this.environment, this.properties);
}
return allAPIs.toArray(new LiteAPI[allAPIs.size()]);
}
/**
* Bakes all currently registered API classes to a new APIProvider
* containing the API instances.
*
* @throws InvalidAPIStateException if the API list was already baked
*/
public APIProvider bake() throws InvalidAPIStateException
{
if (this.baked != null)
{
throw new InvalidAPIStateException("Unable to bake the API provider list because the API list is already baked");
}
LiteAPI[] apis = this.getAllAPIs();
return this.baked = new APIProviderBasic(apis);
}
/**
* Gets the current APIProvider instance
* @throws InvalidAPIStateException if the provider list was not yet baked
*/
public APIProvider getProvider() throws InvalidAPIStateException
{
if (this.baked == null)
{
throw new InvalidAPIStateException("Call to APIRegistry.getProvider() failed because the provider list has not been baked");
}
return this.baked;
}
/**
* Gets the current APIAdapter instance
* @throws InvalidAPIStateException if the provider list was not yet baked
*/
public APIAdapter getAdapter() throws InvalidAPIStateException
{
if (this.baked == null)
{
throw new InvalidAPIStateException("Call to APIRegistry.APIAdapter() failed because the provider list has not been baked");
}
return this.baked;
}
}