<commit_before>package org.orienteer.core;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.URLClassLoader;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import org.apache.wicket.ThreadContext;
import org.orienteer.core.boot.loader.OrienteerClassLoader;
import org.orienteer.core.module.IOrienteerModule;
import org.orienteer.core.service.OrienteerInitModule;
import org.orienteer.core.util.StartupPropertiesLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.google.inject.servlet.GuiceFilter;

/**
 * Main Orienteer Filter to handle all requests.
 * It allows dynamically reload Orienteer application themselves and provide different class loading context
 */
@Singleton
public final class OrienteerFilter implements Filter {

    private static final Logger LOG = LoggerFactory.getLogger(OrienteerFilter.class);
    
    private static OrienteerFilter instance;
    
    private Filter filter;
    private Injector injector;
    
    private FilterConfig filterConfig;
    private ClassLoader classLoader;
    private boolean reloading;
    
    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {
    	instance = this;
    	this.filterConfig = filterConfig;
    	Properties properties = StartupPropertiesLoader.retrieveProperties();
    	classLoader = initClassLoader(properties);
    	//TODO: Implement classloading here
    	Thread.currentThread().setContextClassLoader(classLoader);
        LOG.info("Start initialization: " + this.getClass().getName());
        ServletContext context = filterConfig.getServletContext();
        injector = Guice.createInjector(new OrienteerInitModule(properties));
        context.setAttribute(Injector.class.getName(), injector);
        initFilter(filterConfig);
    }

    private void initFilter(final FilterConfig filterConfig) throws ServletException {
        filter = new GuiceFilter();
        try {
            filter.init(filterConfig);
        } catch (Throwable ex) {
            LOG.warn("Cannot run Orienteer with untrusted classloader. Orienteer runs with trusted classloader.");
            useTrustedClassLoader();
            try {
                filter.init(filterConfig);
            } catch (Throwable e) {
                LOG.warn("Cannot run Orienteer with trusted classloader. Orienteer runs with custom classloader.");
                useOrienteerClassLoader();
                filter.init(filterConfig);
            }
        }
    }
    
    private ClassLoader initClassLoader(Properties properties) {
        OrienteerClassLoader.create(OrienteerFilter.class.getClassLoader());
    	return OrienteerClassLoader.getClassLoader();
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (reloading) {
            HttpServletResponse res = (HttpServletResponse) response;
            res.setStatus(503);
            LOG.info("Reload application. Send 503 code");
        } else {
            filter(request, response, chain);
        }
    }

    private void filter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        Thread.currentThread().setContextClassLoader(classLoader);
        try {
            if (filter != null) {
                filter.doFilter(request, response, chain);
            } else chain.doFilter(request, response);
        } catch (Throwable ex) {
            useTrustedClassLoader();
            try {
                if (filter != null) {
                    filter.doFilter(request, response, chain);
                } else chain.doFilter(request, response);
            } catch (Throwable t) {
                useOrienteerClassLoader();
                if (filter != null) {
                    filter.doFilter(request, response, chain);
                } else chain.doFilter(request, response);
            }
        }
    }

    @Override
    public void destroy() {
        LOG.info("Destroy filter - " + this.getClass().getName());
        filter.destroy();
        filter = null;
    }

    public void reload(long wait) throws ServletException {
    	if(!reloading) {
	        LOG.info("Start reload filter with filter config: " + filterConfig);
	        reloading = true;
	        destroy();
	        try {<commit_msg>Add correct intercept errors in runtime.<commit_after>package org.orienteer.core;

import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import org.orienteer.core.boot.loader.OrienteerClassLoader;
import org.orienteer.core.service.OrienteerInitModule;
import org.orienteer.core.util.StartupPropertiesLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.google.inject.servlet.GuiceFilter;

/**
 * Main Orienteer Filter to handle all requests.
 * It allows dynamically reload Orienteer application themselves and provide different class loading context
 */
@Singleton
public final class OrienteerFilter implements Filter {

    private static final Logger LOG = LoggerFactory.getLogger(OrienteerFilter.class);

    private static final int HTTP_SERVER_UNAVAILABLE = 503;
    private static final int HTTP_SERVER_ERROR = 500;

    private static OrienteerFilter instance;
    private static boolean useUnTrusted = true;

    private Filter filter;
    private Injector injector;
    
    private FilterConfig filterConfig;
    private ClassLoader classLoader;
    private boolean reloading;
    
    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {
    	instance = this;
    	this.filterConfig = filterConfig;
    	Properties properties = StartupPropertiesLoader.retrieveProperties();
    	classLoader = initClassLoader(properties);
    	//TODO: Implement classloading here
    	Thread.currentThread().setContextClassLoader(classLoader);
        LOG.info("Start initialization: " + this.getClass().getName());
        ServletContext context = filterConfig.getServletContext();
        injector = Guice.createInjector(new OrienteerInitModule(properties));
        context.setAttribute(Injector.class.getName(), injector);
        initFilter(filterConfig);
    }

    private void initFilter(final FilterConfig filterConfig) throws ServletException {
        filter = new GuiceFilter();
        try {
            filter.init(filterConfig);
        } catch (Throwable ex) {
            if (useUnTrusted) {
                LOG.warn("Cannot run Orienteer with untrusted classloader. Orienteer runs with trusted classloader.");
                useTrustedClassLoader();
                useUnTrusted = false;
            } else {
                LOG.warn("Cannot run Orienteer with trusted classloader. Orienteer runs with custom classloader.");
                useOrienteerClassLoader();
            }
            instance.reload(1000);
        }
    }
    
    private ClassLoader initClassLoader(Properties properties) {
        OrienteerClassLoader.create(OrienteerFilter.class.getClassLoader());
    	return OrienteerClassLoader.getClassLoader();
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (reloading) {
            HttpServletResponse res = (HttpServletResponse) response;
            res.setStatus(HTTP_SERVER_UNAVAILABLE);
            LOG.info("Reload application. Send 503 code");
        } else {
            doOrienteerFilter(request, response, chain);
        }
    }

    private void doOrienteerFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        Thread.currentThread().setContextClassLoader(classLoader);
        try {
            if (filter != null) {
                filter.doFilter(request, response, chain);
            } else chain.doFilter(request, response);
        } catch (Throwable t) {
            if (useUnTrusted) {
                LOG.warn("Error in untrusted classloader Orienteer will restart with trusted classloader!", t);
                useTrustedClassLoader();
                useUnTrusted = false;
            } else {
                LOG.warn("Error in trusted classloader Orienteer will restart with custom classloader!", t);
                useOrienteerClassLoader();
            }
            HttpServletResponse res = (HttpServletResponse) response;
            res.setStatus(HTTP_SERVER_ERROR);
            instance.reload(1000);
        }
    }

    @Override
    public void destroy() {
        LOG.info("Destroy doOrienteerFilter - " + this.getClass().getName());
        filter.destroy();
        filter = null;
    }

    public void reload(long wait) throws ServletException {
    	if(!reloading) {
	        LOG.info("Start reload doOrienteerFilter with doOrienteerFilter config: " + filterConfig);
	        reloading = true;
	        destroy();
	        try {
{'fraction_non_alphanumeric': 0.0836264951251382, 'fraction_numerical': 0.0027138405869936676, 'mean_word_length': 2.9943797671617824, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3228727', 'n_tokens_mistral': 2576, 'n_tokens_neox': 2473, 'n_words': 617}