/*
* (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed 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.
*
* Contributors:
* bstefanescu
*/
package org.nuxeo.runtime.tomcat.dev;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Writer;
import javax.servlet.ServletException;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Enable remote hot deploy and getting configuration from remote Nuxeo SDK servers
* <p>
* This valve is enabled only in SDK profile (i.e. dev mode). It will intercept any call to '/sdk' under the context
* path (i.e. /nuxeo/sdk)
*
* @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
*/
public class DevValve extends ValveBase {
Log log = LogFactory.getLog(DevValve.class);
@Override
public void invoke(Request req, Response resp) throws IOException, ServletException {
String path = req.getServletPath();
if (path != null && path.startsWith("/sdk/")) {
path = path.substring("/sdk/".length());
if ("reload".equals(path)) {
if ("GET".equals(req.getMethod())) {
getReload(req, resp);
} else if ("POST".equals(req.getMethod())) {
postReload(req, resp);
}
return;
} else if (path.startsWith("files/")) {
path = path.substring("files/".length());
getFile(path, req, resp);
return;
}
resp.setStatus(404);
return;
}
getNext().invoke(req, resp);
}
private final File getHome() {
return new File(System.getProperty("catalina.base"));
}
private final File getSDKFile(String path) {
return new File(new File(getHome(), "sdk"), path);
}
private void getFile(String path, Request req, Response resp) {
File file = getSDKFile(path);
if (file == null) {
resp.setStatus(404);
} else {
resp.setContentType("text/plain");
resp.setCharacterEncoding("UTF-8");
resp.setStatus(200);
try {
Writer out = resp.getWriter();
sendFile(file, out);
out.flush();
} catch (IOException e) {
resp.setStatus(500);
log.error("Failed to send file: " + file, e);
}
}
}
private void sendFile(File file, Writer out) throws IOException {
Reader in = new InputStreamReader(new FileInputStream(file), "UTF-8");
try {
char cbuf[] = new char[64 * 1024];
int r = -1;
while ((r = in.read(cbuf)) != -1) {
if (r > 0) {
out.write(cbuf, 0, r);
}
}
} finally {
in.close();
}
}
private void getReload(Request req, Response resp) {
ClassLoader webLoader = req.getContext().getLoader().getClassLoader();
if (webLoader instanceof NuxeoDevWebappClassLoader) {
NuxeoDevWebappClassLoader loader = (NuxeoDevWebappClassLoader) webLoader;
// only if dev.bundles was modified
loader.getBootstrap().loadDevBundles();
// log.error("###### reloaded dev bundles");
}
resp.setStatus(200);
}
private void postReload(Request req, Response resp) {
log.error("#### TODO: POST RELOAD");
resp.setStatus(200);
}
}