/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.commons.jci.examples.serverpages;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.String;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.jci.ReloadingClassLoader;
import org.apache.commons.jci.compilers.CompilationResult;
import org.apache.commons.jci.compilers.JavaCompilerFactory;
import org.apache.commons.jci.listeners.CompilingListener;
import org.apache.commons.jci.monitor.FilesystemAlterationMonitor;
import org.apache.commons.jci.monitor.FilesystemAlterationObserver;
import org.apache.commons.jci.problems.CompilationProblem;
import org.apache.commons.jci.readers.ResourceReader;
import org.apache.commons.jci.stores.MemoryResourceStore;
import org.apache.commons.jci.stores.TransactionalResourceStore;
import org.apache.commons.jci.utils.ConversionUtils;


/**
 * A mini JSP servlet that monitors a certain directory and
 * recompiles and then instantiates the JSP pages as soon as
 * they have changed.
 *
 * @author tcurdt
 */
public final class ServerPageServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    private final ReloadingClassLoader classloader = new ReloadingClassLoader(ServerPageServlet.class.getClassLoader());
    private FilesystemAlterationMonitor fam = null;
    private CompilingListener jspListener = null; 

    private Map servletsByClassname = new HashMap();

    public void init() throws ServletException {
        super.init();

        final File serverpagesDir = new File(getServletContext().getRealPath("/") + getInitParameter("serverpagesDir"));

        log("Monitoring serverpages in " + serverpagesDir);

        final TransactionalResourceStore store = new TransactionalResourceStore(new MemoryResourceStore()) {

            private Set<String> newClasses;
            private Map<String, HttpServlet> newServletsByClassname;

            public void onStart() {
                super.onStart();

                newClasses = new HashSet<String>();
                newServletsByClassname = new HashMap<String, HttpServlet>(servletsByClassname);
            }

            public void onStop() {
                super.onStop();

                boolean reload = false;
                for (String clazzName : newClasses) {
                    try {
                        final Class clazz = classloader.loadClass(clazzName);

                        if (!HttpServlet.class.isAssignableFrom(clazz)) {
                            log(clazzName + " is not a servlet");
                            continue;
                        }

                        // create new instance of jsp page
                        final HttpServlet servlet = (HttpServlet) clazz.newInstance();
                        newServletsByClassname.put(clazzName, servlet);

                        reload = true;
                    } catch(Exception e) {
                        log("", e);
                    }
                }

                if (reload) {
                    log("Activating new map of servlets "+ newServletsByClassname);
                    servletsByClassname = newServletsByClassname;
                }
            }

            public void write(String pResourceName, byte[] pResourceData) {
                super.write(pResourceName, pResourceData);

                if (pResourceName.endsWith(".class")) {

                    // compiler writes a new class, remember the classes to reload
                    newClasses.add(pResourceName.replace('/', '.').substring(0, pResourceName.length() - ".class".length()));
                }
            }

        };

        // listener that generates the java code from the jsp page and provides that to the compiler
        jspListener = new CompilingListener(new JavaCompilerFactory().createCompiler("eclipse"), store) {

            private final JspGenerator transformer = new JspGenerator();
            private final Map<String, File> sources = new HashMap<String, File>();
            private final Set<String> resourceToCompile = new HashSet<String>();

            public void onStart(FilesystemAlterationObserver pObserver) {
                super.onStart(pObserver);

                resourceToCompile.clear();
            }


            public void onFileChange(File pFile) {
                if (pFile.getName().endsWith(".jsp")) {
                    final String resourceName = ConversionUtils.stripExtension(getSourceNameFromFile(observer, pFile)) + ".java";

                    log("Updating " + resourceName);

                    sources.put(resourceName, transformer.generateJavaSource(resourceName, pFile));

                    resourceToCompile.add(resourceName);
                }
                super.onFileChange(pFile);
            }


            public void onFileCreate(File pFile) {
                if (pFile.getName().endsWith(".jsp")) {
                    final String resourceName = ConversionUtils.stripExtension(getSourceNameFromFile(observer, pFile)) + ".java";

                    log("Creating " + resourceName);

                    sources.put(resourceName, transformer.generateJavaSource(resourceName, pFile));

                    resourceToCompile.add(resourceName);
                }
                super.onFileCreate(pFile);
            }


            public String[] getResourcesToCompile(FilesystemAlterationObserver pObserver) {
                // we only want to compile the jsp pages
                final String[] resourceNames = new String[resourceToCompile.size()];
                resourceToCompile.toArray(resourceNames);
                return resourceNames;
            }


            public ResourceReader getReader( final FilesystemAlterationObserver pObserver ) {
                return new JspReader(sources, super.getReader(pObserver));
            }
        };
        jspListener.addReloadNotificationListener(classloader);
        
        fam = new FilesystemAlterationMonitor();
        fam.addListener(serverpagesDir, jspListener);
        fam.start();
    }

    private String convertRequestToServletClassname( final HttpServletRequest request ) {

        final String path = request.getPathInfo().substring(1);

        final String clazz = ConversionUtils.stripExtension(path).replace('/', '.');

        return clazz;
    }

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        log("Request " + request.getRequestURI());

        final CompilationResult result = jspListener.getCompilationResult();
        final CompilationProblem[] errors = result.getErrors();

        if (errors.length > 0) {

            // if there are errors we provide the compilation errors instead of the jsp page

            final PrintWriter out = response.getWriter();

            out.append("<html><body>");

            for (int i = 0; i < errors.length; i++) {
                final CompilationProblem problem = errors[i];
                out.append(problem.toString()).append("<br/>").append('\n');
            }

            out.append("</body></html>");

            out.flush();
            out.close();
            return;
        }

        final String servletClassname = convertRequestToServletClassname(request);

        log("Checking for serverpage " + servletClassname);

        final HttpServlet servlet = (HttpServlet) servletsByClassname.get(servletClassname);

        if (servlet == null) {
            log("No servlet  for " + request.getRequestURI());
            response.sendError(404);
            return;
        }

        log("Delegating request to " + servletClassname);

        servlet.service(request, response);
    }

    public void destroy() {

        fam.stop();

        super.destroy();
    }
}
