|
1 /* |
|
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
|
3 * |
|
4 * Copyright 2013 Olaf Wintermann. All rights reserved. |
|
5 * |
|
6 * Redistribution and use in source and binary forms, with or without |
|
7 * modification, are permitted provided that the following conditions are met: |
|
8 * |
|
9 * 1. Redistributions of source code must retain the above copyright |
|
10 * notice, this list of conditions and the following disclaimer. |
|
11 * |
|
12 * 2. Redistributions in binary form must reproduce the above copyright |
|
13 * notice, this list of conditions and the following disclaimer in the |
|
14 * documentation and/or other materials provided with the distribution. |
|
15 * |
|
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
26 * POSSIBILITY OF SUCH DAMAGE. |
|
27 */ |
|
28 package webserver; |
|
29 |
|
30 import java.io.File; |
|
31 import java.lang.reflect.InvocationTargetException; |
|
32 import java.lang.reflect.Method; |
|
33 import java.net.MalformedURLException; |
|
34 import java.net.URL; |
|
35 import java.net.URLClassLoader; |
|
36 import java.util.ArrayList; |
|
37 import java.util.logging.Level; |
|
38 import java.util.logging.Logger; |
|
39 import webserver.nsapi.Module; |
|
40 import webserver.nsapi.PBlock; |
|
41 import webserver.nsapi.Request; |
|
42 import webserver.nsapi.SAF; |
|
43 import webserver.nsapi.Session; |
|
44 |
|
45 class ServerPlugin { |
|
46 private ArrayList<ServerFunction> registeredFunctions = new ArrayList<>(32); |
|
47 |
|
48 public ServerPlugin() { |
|
49 |
|
50 } |
|
51 |
|
52 public native void addMethod(String name, int safIndex); |
|
53 |
|
54 static { |
|
55 System.loadLibrary("nsapi_jni"); |
|
56 } |
|
57 |
|
58 public int loadModule(String jar, String classes) { |
|
59 System.out.println("load-jmodule jar=\""+jar+"\" classes=\""+classes+"\""); |
|
60 |
|
61 File jarFile = new File(jar); |
|
62 if(!jarFile.exists()) { |
|
63 System.err.println("jar file does not exist"); |
|
64 return -1; |
|
65 } |
|
66 try { |
|
67 URL[] urls = new URL[]{jarFile.toURI().toURL()}; |
|
68 URLClassLoader cl = new URLClassLoader(urls, this.getClass().getClassLoader()); |
|
69 |
|
70 for(String className : classes.split(",")) { |
|
71 Class moduleClass = Class.forName(className, true, cl); |
|
72 loadClass(moduleClass); |
|
73 } |
|
74 } catch (MalformedURLException e) { |
|
75 System.err.println("ServerPlugin.loadModule: "+e); |
|
76 return -1; |
|
77 } catch (ClassNotFoundException e) { |
|
78 System.err.println("Java Module Class not found: "+e); |
|
79 return -1; |
|
80 } catch (InstantiationException e) { |
|
81 System.err.println("ServerPlugin.loadModule: "+e); |
|
82 return -1; |
|
83 } catch (IllegalAccessException e) { |
|
84 System.err.println("ServerPlugin.loadModule: "+e); |
|
85 return -1; |
|
86 } |
|
87 |
|
88 System.out.println("Java Module loaded"); |
|
89 return 0; |
|
90 } |
|
91 |
|
92 public void loadClass(Class cl) throws InstantiationException, IllegalAccessException { |
|
93 Module module = (Module)cl.getAnnotation(Module.class); |
|
94 if(module == null) { |
|
95 System.err.println("Missing Module annotation for class: "+cl.getCanonicalName()); |
|
96 return; |
|
97 } |
|
98 |
|
99 Object moduleInstance = cl.newInstance(); |
|
100 for(Method m : cl.getMethods()) { |
|
101 if(isSAF(m)) { |
|
102 SAF saf = m.getAnnotation(SAF.class); |
|
103 if(saf.init()) { |
|
104 |
|
105 } |
|
106 if(saf.name().length() > 0) { |
|
107 ServerFunction f = new ServerFunction(); |
|
108 f.module = moduleInstance; |
|
109 f.method = m; |
|
110 |
|
111 String safName = module.name() + "." + saf.name(); |
|
112 registeredFunctions.add(f); |
|
113 int index = registeredFunctions.lastIndexOf(f); |
|
114 addMethod(safName, index); |
|
115 } |
|
116 } |
|
117 } |
|
118 } |
|
119 |
|
120 private boolean isSAF(Method m) { |
|
121 SAF saf = m.getAnnotation(SAF.class); |
|
122 if(saf != null) { |
|
123 // check method signature |
|
124 if(m.getReturnType() != int.class) { |
|
125 System.err.println("wrong return type for SAF: "+m.getName()); |
|
126 return false; |
|
127 } |
|
128 Class paramTypes[] = m.getParameterTypes(); |
|
129 if(paramTypes.length != 3) { |
|
130 System.err.println("wrong number of parameters for SAF: "+m.getName()); |
|
131 return false; |
|
132 } |
|
133 if(paramTypes[0] != PBlock.class) { |
|
134 System.err.println("wrong method signature for SAF: "+m.getName()); |
|
135 return false; |
|
136 } |
|
137 if(paramTypes[1] != Session.class) { |
|
138 System.err.println("wrong method signature for SAF: "+m.getName()); |
|
139 return false; |
|
140 } |
|
141 if(paramTypes[2] != Request.class) { |
|
142 System.err.println("wrong method signature for SAF: "+m.getName()); |
|
143 return false; |
|
144 } |
|
145 return true; |
|
146 } |
|
147 return false; |
|
148 } |
|
149 |
|
150 public int exec(int safIndex) { |
|
151 System.out.println("(Java) exec: "+safIndex); |
|
152 ServerFunction saf = registeredFunctions.get(safIndex); |
|
153 if(saf == null) { |
|
154 return -1; |
|
155 } |
|
156 Integer ret = new Integer(-1); |
|
157 try { |
|
158 ret = (Integer)saf.method.invoke(saf.module, null, null, null); |
|
159 } catch (IllegalAccessException e) { |
|
160 e.printStackTrace(); |
|
161 } catch (IllegalArgumentException e) { |
|
162 e.printStackTrace(); |
|
163 } catch (InvocationTargetException e) { |
|
164 e.printStackTrace(); |
|
165 } |
|
166 return ret.intValue(); |
|
167 } |
|
168 } |