1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.jci.examples.serverpages;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.io.PrintWriter;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.Iterator;
26 import java.util.Map;
27 import java.util.Set;
28
29 import javax.servlet.ServletException;
30 import javax.servlet.http.HttpServlet;
31 import javax.servlet.http.HttpServletRequest;
32 import javax.servlet.http.HttpServletResponse;
33
34 import org.apache.commons.jci.ReloadingClassLoader;
35 import org.apache.commons.jci.compilers.CompilationResult;
36 import org.apache.commons.jci.compilers.JavaCompilerFactory;
37 import org.apache.commons.jci.listeners.CompilingListener;
38 import org.apache.commons.jci.monitor.FilesystemAlterationMonitor;
39 import org.apache.commons.jci.monitor.FilesystemAlterationObserver;
40 import org.apache.commons.jci.problems.CompilationProblem;
41 import org.apache.commons.jci.readers.ResourceReader;
42 import org.apache.commons.jci.stores.MemoryResourceStore;
43 import org.apache.commons.jci.stores.TransactionalResourceStore;
44 import org.apache.commons.jci.utils.ConversionUtils;
45
46
47
48
49
50
51
52
53
54 public final class ServerPageServlet extends HttpServlet {
55
56 private static final long serialVersionUID = 1L;
57
58 private final ReloadingClassLoader classloader = new ReloadingClassLoader(ServerPageServlet.class.getClassLoader());
59 private FilesystemAlterationMonitor fam = null;
60 private CompilingListener jspListener = null;
61
62 private Map servletsByClassname = new HashMap();
63
64 public void init() throws ServletException {
65 super.init();
66
67 final File serverpagesDir = new File(getServletContext().getRealPath("/") + getInitParameter("serverpagesDir"));
68
69 log("Monitoring serverpages in " + serverpagesDir);
70
71 final TransactionalResourceStore store = new TransactionalResourceStore(new MemoryResourceStore()) {
72
73 private Set newClasses;
74 private Map newServletsByClassname;
75
76 public void onStart() {
77 super.onStart();
78
79 newClasses = new HashSet();
80 newServletsByClassname = new HashMap(servletsByClassname);
81 }
82
83 public void onStop() {
84 super.onStop();
85
86 boolean reload = false;
87 for (Iterator it = newClasses.iterator(); it.hasNext();) {
88 final String clazzName = (String) it.next();
89
90 try {
91 final Class clazz = classloader.loadClass(clazzName);
92
93 if (!HttpServlet.class.isAssignableFrom(clazz)) {
94 log(clazzName + " is not a servlet");
95 continue;
96 }
97
98
99 final HttpServlet servlet = (HttpServlet) clazz.newInstance();
100 newServletsByClassname.put(clazzName, servlet);
101
102 reload = true;
103 } catch(Exception e) {
104 log("", e);
105 }
106 }
107
108 if (reload) {
109 log("Activating new map of servlets "+ newServletsByClassname);
110 servletsByClassname = newServletsByClassname;
111 }
112 }
113
114 public void write(String pResourceName, byte[] pResourceData) {
115 super.write(pResourceName, pResourceData);
116
117 if (pResourceName.endsWith(".class")) {
118
119
120 newClasses.add(pResourceName.replace('/', '.').substring(0, pResourceName.length() - ".class".length()));
121 }
122 }
123
124 };
125
126
127 jspListener = new CompilingListener(new JavaCompilerFactory().createCompiler("eclipse"), store) {
128
129 private final JspGenerator transformer = new JspGenerator();
130 private final Map sources = new HashMap();
131 private final Set resourceToCompile = new HashSet();
132
133 public void onStart(FilesystemAlterationObserver pObserver) {
134 super.onStart(pObserver);
135
136 resourceToCompile.clear();
137 }
138
139
140 public void onFileChange(File pFile) {
141 if (pFile.getName().endsWith(".jsp")) {
142 final String resourceName = ConversionUtils.stripExtension(getSourceNameFromFile(observer, pFile)) + ".java";
143
144 log("Updating " + resourceName);
145
146 sources.put(resourceName, transformer.generateJavaSource(resourceName, pFile));
147
148 resourceToCompile.add(resourceName);
149 }
150 super.onFileChange(pFile);
151 }
152
153
154 public void onFileCreate(File pFile) {
155 if (pFile.getName().endsWith(".jsp")) {
156 final String resourceName = ConversionUtils.stripExtension(getSourceNameFromFile(observer, pFile)) + ".java";
157
158 log("Creating " + resourceName);
159
160 sources.put(resourceName, transformer.generateJavaSource(resourceName, pFile));
161
162 resourceToCompile.add(resourceName);
163 }
164 super.onFileCreate(pFile);
165 }
166
167
168 public String[] getResourcesToCompile(FilesystemAlterationObserver pObserver) {
169
170 final String[] resourceNames = new String[resourceToCompile.size()];
171 resourceToCompile.toArray(resourceNames);
172 return resourceNames;
173 }
174
175
176 public ResourceReader getReader( final FilesystemAlterationObserver pObserver ) {
177 return new JspReader(sources, super.getReader(pObserver));
178 }
179 };
180 jspListener.addReloadNotificationListener(classloader);
181
182 fam = new FilesystemAlterationMonitor();
183 fam.addListener(serverpagesDir, jspListener);
184 fam.start();
185 }
186
187 private String convertRequestToServletClassname( final HttpServletRequest request ) {
188
189 final String path = request.getPathInfo().substring(1);
190
191 final String clazz = ConversionUtils.stripExtension(path).replace('/', '.');
192
193 return clazz;
194 }
195
196 protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
197
198 log("Request " + request.getRequestURI());
199
200 final CompilationResult result = jspListener.getCompilationResult();
201 final CompilationProblem[] errors = result.getErrors();
202
203 if (errors.length > 0) {
204
205
206
207 final PrintWriter out = response.getWriter();
208
209 out.append("<html><body>");
210
211 for (int i = 0; i < errors.length; i++) {
212 final CompilationProblem problem = errors[i];
213 out.append(problem.toString()).append("<br/>").append('\n');
214 }
215
216 out.append("</body></html>");
217
218 out.flush();
219 out.close();
220 return;
221 }
222
223 final String servletClassname = convertRequestToServletClassname(request);
224
225 log("Checking for serverpage " + servletClassname);
226
227 final HttpServlet servlet = (HttpServlet) servletsByClassname.get(servletClassname);
228
229 if (servlet == null) {
230 log("No servlet for " + request.getRequestURI());
231 response.sendError(404);
232 return;
233 }
234
235 log("Delegating request to " + servletClassname);
236
237 servlet.service(request, response);
238 }
239
240 public void destroy() {
241
242 fam.stop();
243
244 super.destroy();
245 }
246 }