/*
* Copyright 2013- Yan Bonnel
*
* 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.
*/
package fr.ybonnel.simpleweb4j.handlers;
import fr.ybonnel.simpleweb4j.exception.CompileErrorException;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Scanner;
/**
* Compiler for any files to compile.
*/
public abstract class AbstractCompilerHandler extends AbstractHandler {
/**
* Logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractCompilerHandler.class);
/**
* Path to public resource.
*/
private String publicResourcePath = "/public";
/**
* Change the path to public resources.
* @param newPublicResourcePath new path.
*/
public void setPublicResourcePath(String newPublicResourcePath) {
this.publicResourcePath = newPublicResourcePath;
}
/**
* Get suffixe name like ".coffee" of files to handle.
* @return the suffixe name.
*/
protected abstract String getSuffixeName();
/**
* Compile the file.
* @param source source to compile.
* @return the compiled content.
* @throws CompileErrorException in case of compile error.
*/
protected abstract String compile(String source) throws CompileErrorException;
/**
* Content type to return.
* @return content type.
*/
protected abstract String getContentType();
/** Handle a request.
* @param target The target of the request - either a URI or a name.
* @param baseRequest The original unwrapped request object.
* @param request The request either as the {@link Request}
* object or a wrapper of that request.
* @param response The response as the {@link org.eclipse.jetty.server.Response}
* object or a wrapper of that request.
* @throws IOException in case of IO error.
*/
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException {
if (baseRequest.isHandled() || !"GET".equals(request.getMethod())) {
return;
}
if (!request.getPathInfo().endsWith(getSuffixeName())) {
return;
}
try {
InputStream resource = AbstractCompilerHandler.class.getResourceAsStream(
publicResourcePath + request.getPathInfo());
if (resource != null) {
String result = compile(
convertStreamToString(
resource));
baseRequest.setHandled(true);
response.setContentType(getContentType());
response.setStatus(HttpServletResponse.SC_OK);
response.getOutputStream().print(result);
response.getOutputStream().flush();
response.getOutputStream().close();
}
} catch (CompileErrorException exception) {
LOGGER.warn("Compile error on {}", request.getPathInfo());
LOGGER.warn("Compile error", exception.getCause());
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
StringWriter writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
exception.getCause().printStackTrace(printWriter);
response.getWriter().print(writer.toString());
response.getWriter().close();
baseRequest.setHandled(true);
}
}
/**
* Convert InputStream to string.
* @param is inputStream to convert.
* @return the string converted.
*/
protected static String convertStreamToString(InputStream is) {
return new Scanner(is, "UTF-8").useDelimiter("\\A").next();
}
}