Skip to content

Commit f276b9a

Browse files
committed
use serviceloader to create/start server
define 'contract' between bootstrap and server (AditoServerFactory) to create/start server. Because switch of classloader needed, reflection can not be replace completly. But do not use/load classes from different module. fixes adito/#15
1 parent a67f536 commit f276b9a

File tree

5 files changed

+142
-110
lines changed

5 files changed

+142
-110
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.adito.boot;
2+
3+
/**
4+
*
5+
* @author toepi <toepi@users.noreply.github.com>
6+
*/
7+
public interface AditoServerFactory {
8+
9+
void createServer(ClassLoader bootLoader, String[] args);
10+
}
Lines changed: 68 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
2-
/*
1+
/*
32
* Adito
43
*
54
* Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
@@ -17,7 +16,6 @@
1716
* License along with this program; if not, write to the Free Software
1817
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1918
*/
20-
2119
package com.adito.boot;
2220

2321
import java.io.File;
@@ -38,8 +36,8 @@
3836

3937
/**
4038
* ALL CHANGED - REWRITE
41-
*
42-
*
39+
*
40+
*
4341
* Bootstrap an Adito server implementation. The first argument passed to
4442
* {@link #main(String[])} should be the class name of the server
4543
* implementation.
@@ -48,33 +46,56 @@
4846
* <code>setBootLoader(ClassLoader bootLoader)</code> and
4947
* <code>main(String[] args)</code>.
5048
* <p>
51-
* A classpath.properties file in the
49+
* A classpath.properties file in the
5250
* <p>
5351
* The server will be loaded using a new class loader that scans the
5452
* <b>serverlib</b> directory for any jars specific to this implementation. The
5553
* parent of this classloader is the <i>Boot Loader</i>
56-
*
57-
* The <i>Boot Loader</i> is the class loader that loads all of the boot
58-
* classes and anything in lib.
54+
*
55+
* The <i>Boot Loader</i> is the class loader that loads all of the boot classes
56+
* and anything in lib.
5957
* <p>
60-
* The server implementation should use the <i>Boot Loader</i> as the parent
61-
* for the Adito web application. This hides the server implementation
62-
* from the Adito core and any of its extensions.
63-
*
58+
* The server implementation should use the <i>Boot Loader</i> as the parent for
59+
* the Adito web application. This hides the server implementation from the
60+
* Adito core and any of its extensions.
61+
*
6462
*/
6563
public class Bootstrap {
6664

67-
// Private instance variables
65+
/**
66+
* Entry point. First argument should be the server implementation class
67+
* name. Remaining arguments are passed to create server.
68+
*
69+
* @param args arguments
70+
* @throws Exception
71+
*/
72+
public static void main(final String[] args) throws Exception {
73+
final List<String> argList = new ArrayList<String>(Arrays.asList(args));
74+
if (argList.size() > 1 && argList.get(0).equals("--serverImpl")) {
75+
argList.remove(0);
76+
argList.remove(0);
77+
}
78+
79+
// Look for --conf argument and add that to that classpath
80+
File conf = new File("conf");
81+
for (String arg : argList) {
82+
if (arg.startsWith("--conf=")) {
83+
conf = new File(arg.substring(7));
84+
}
85+
}
6886

87+
// Create the bootstrap, configure it and start the server
88+
new Bootstrap().withClassLoaders(conf)
89+
.start(argList.toArray(new String[argList.size()]));
90+
}
6991
private ClassLoader serverLoader;
70-
private ClassLoader bootLoader;
92+
private ClassLoader bootLoader;
7193
private File conf;
7294
private Properties classpath;
7395

7496
/**
7597
* Start the server implementation.
76-
*
77-
* @param serverImplClassName server implementation
98+
*
7899
* @param args arguments
79100
* @throws ClassNotFoundException
80101
* @throws SecurityException
@@ -83,21 +104,29 @@ public class Bootstrap {
83104
* @throws IllegalAccessException
84105
* @throws InvocationTargetException
85106
*/
86-
public void start(String serverImplClassName, String[] args) throws ClassNotFoundException, SecurityException,
87-
NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
88-
Class<?> serverClass = Class.forName(serverImplClassName, true, serverLoader);
89-
Method setBootLoaderMethod = serverClass.getMethod("setBootLoader", new Class[] { ClassLoader.class });
90-
setBootLoaderMethod.invoke(null, new Object[] { bootLoader });
91-
Method mainMethod = serverClass.getMethod("main", new Class[] { String[].class });
92-
mainMethod.invoke(null, new Object[] { args });
107+
public void start(final String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalArgumentException,
108+
InvocationTargetException, IllegalAccessException {
109+
110+
if (serverLoader == null || bootLoader == null) {
111+
throw new IllegalStateException("Needed classloaders not configured!");
112+
}
113+
114+
Thread.currentThread().setContextClassLoader(serverLoader);
115+
Class.forName(ServerStarter.class.getName(), true, serverLoader)
116+
.getMethod("start", ClassLoader.class, String[].class).invoke(null, bootLoader, args);
117+
}
118+
119+
public Bootstrap withClassLoaders(final File conf) throws IOException, URISyntaxException {
120+
configureClassLoaders(conf);
121+
return this;
93122
}
94123

95124
/**
96125
* Configure the class loaders.
97-
*
126+
*
98127
* @param conf conf directory
99128
* @throws IOException
100-
* @throws URISyntaxException
129+
* @throws URISyntaxException
101130
*/
102131
public void configureClassLoaders(File conf) throws IOException, URISyntaxException {
103132
this.conf = conf;
@@ -114,29 +143,29 @@ public void configureClassLoaders(File conf) throws IOException, URISyntaxExcept
114143
serverLoader = new URLClassLoader(serverLibs.toArray(new URL[serverLibs.size()]), bootLoader);
115144

116145
}
117-
146+
118147
private void addJarPaths(String propertyName, List<URL> libs) throws MalformedURLException, IOException {
119148
String paths = classpath.getProperty(propertyName);
120-
if(paths != null) {
149+
if (paths != null) {
121150
StringTokenizer t = new StringTokenizer(paths, ",");
122-
while(t.hasMoreTokens()) {
151+
while (t.hasMoreTokens()) {
123152
addDirLibs(new File(t.nextToken()), libs);
124153
}
125154
}
126155
}
127-
156+
128157
private void addDirPaths(String propertyName, List<URL> libs) throws MalformedURLException, IOException {
129158
String paths = classpath.getProperty(propertyName);
130-
if(paths != null) {
159+
if (paths != null) {
131160
StringTokenizer t = new StringTokenizer(paths, ",");
132-
while(t.hasMoreTokens()) {
161+
while (t.hasMoreTokens()) {
133162
addDir(new File(t.nextToken()), libs);
134163
}
135164
}
136165
}
137166

138167
private void addDirLibs(File dir, List<URL> libs) throws MalformedURLException, IOException {
139-
if(!dir.exists() || !dir.isDirectory()) {
168+
if (!dir.exists() || !dir.isDirectory()) {
140169
return;
141170
}
142171
for (File jar : dir.listFiles(new FileFilter() {
@@ -150,59 +179,25 @@ public boolean accept(File pathname) {
150179

151180
private URL[] debugClasspath(String string, URL[] urls) throws URISyntaxException {
152181
System.out.println("Classloader " + string);
153-
for(int i = 0 ; i < urls.length ; i++) {
182+
for (int i = 0; i < urls.length; i++) {
154183
System.out.println(new File(urls[i].toURI()).getAbsolutePath());
155184
}
156185
return urls;
157186
}
158187

159188
private void addDir(File dir, List<URL> libs) throws MalformedURLException, IOException {
160-
if(dir.exists() || !dir.isDirectory()) {
189+
if (dir.exists() || !dir.isDirectory()) {
161190
libs.add(dir.getCanonicalFile().toURI().toURL());
162-
}
191+
}
163192
}
164-
193+
165194
private void loadClasspathConfiguration() throws IOException {
166195
FileInputStream fin = new FileInputStream(new File(conf, "classpath.properties"));
167196
try {
168197
classpath = new Properties();
169198
classpath.load(fin);
199+
} finally {
200+
fin.close();
170201
}
171-
finally {
172-
if(fin != null) {
173-
fin.close();
174-
}
175-
}
176-
}
177-
178-
/**
179-
* Entry point. First argument should be the server implementation class
180-
* name. Remaining arguments are passed to create server.
181-
*
182-
* @param args arguments
183-
* @throws Exception
184-
*/
185-
public static void main(String[] args) throws Exception {
186-
List<String> argList = new ArrayList<String>(Arrays.asList(args));
187-
String serverImplClassName = "com.adito.server.Main";
188-
if(argList.size() > 1 && argList.get(0).equals("--serverImpl")) {
189-
argList.remove(0);
190-
serverImplClassName = argList.get(0);
191-
argList.remove(0);
192-
}
193-
args = argList.toArray(new String[argList.size()]);
194-
195-
// Look for --conf argument and add that to that classpath
196-
File conf = new File("conf");
197-
for(String arg : argList) {
198-
if(arg.startsWith("--conf=")) {
199-
conf = new File(arg.substring(7));
200-
}
201-
}
202-
203-
// Create the bootstrap, configure it and start the server
204-
Bootstrap bootstrap = new Bootstrap();
205-
bootstrap.configureClassLoaders(conf);
206-
bootstrap.start(serverImplClassName, args);
207202
}
208203
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.adito.boot;
2+
3+
import java.util.Iterator;
4+
import java.util.ServiceLoader;
5+
6+
/**
7+
*
8+
* @author toepi <toepi@users.noreply.github.com>
9+
*/
10+
public final class ServerStarter {
11+
12+
public static void start(final ClassLoader bootLoader, final String[] args) {
13+
if (bootLoader == null) {
14+
throw new IllegalStateException("Bootloader must be not null!");
15+
}
16+
final Iterator<AditoServerFactory> serverFactoryIterator = ServiceLoader.load(AditoServerFactory.class).iterator();
17+
if (serverFactoryIterator.hasNext()) {
18+
serverFactoryIterator.next().createServer(bootLoader, args);
19+
} else {
20+
throw new IllegalStateException("No AditoServerFactory found! Check your classpath.");
21+
}
22+
}
23+
24+
private ServerStarter() {
25+
}
26+
}

0 commit comments

Comments
 (0)