<commit_before>package jj.servable;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.IOException;
import java.nio.ByteBuffer;

import jj.Configuration;
import jj.resource.ScriptResource;
import jj.script.AssociatedScriptBundle;
import jj.script.ScriptBundleFinder;
import jj.webbit.JJHttpRequest;
import jj.webbit.RequestProcessor;

import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.webbitserver.HttpControl;
import org.webbitserver.HttpResponse;

/**
 * handles automatic inclusion
 * @author jason
 *
 */
class AssociatedScriptServable extends Servable {
	
	private final Logger log = LoggerFactory.getLogger(AssociatedScriptServable.class);
	
	/**
	 * twenty years in seconds.  not including leap days. it's probably fine
	 */
	private static final String TWENTY_YEARS = String.valueOf(60 * 60 * 24 * 365 * 20);
	
	private final ScriptBundleFinder finder;

	AssociatedScriptServable(final Configuration configuration, final ScriptBundleFinder finder) {
		super(configuration);
		this.finder = finder;
	}
	
	@Override
	protected Rank rank() {
		return Rank.Middle;
	}
	
	private ScriptResource typeFromBundle(AssociatedScriptBundle bundle, String typeSpec) {
		ScriptResource result = null;
		if ("".equals(typeSpec)) {
			result = bundle.clientScriptResource();
		} else if (".shared".equals(typeSpec)) {
			result = bundle.sharedScriptResource();
		} else if (".server".equals(typeSpec)) {
			result = bundle.serverScriptResource();
		}
		return result;
	}
	
	private ScriptResource resourceFromUri(String uri) {
		int firstDot = uri.indexOf('.');
		int lastDot = uri.lastIndexOf('.');
		ScriptResource result = null;
		if (firstDot != -1) {
			// skip the /
			String key = uri.substring(1, firstDot);
			String type = uri.substring(firstDot, lastDot);
			String suffix = uri.substring(lastDot);
			if (".js".equals(suffix)) {
				AssociatedScriptBundle scriptBundle = finder.forBaseNameAndKey(key);
				if (scriptBundle != null) {
					result = typeFromBundle(scriptBundle, type);
				}
			}
		}
		return result;
	}

	@Override
	public boolean isMatchingRequest(final JJHttpRequest request) {
		return resourceFromUri(request.uri()) != null;
	}

	@Override
	public RequestProcessor makeRequestProcessor(
		final JJHttpRequest request,
		final HttpResponse response,
		final HttpControl control
	) throws IOException {
		
		final ScriptResource scriptResource = resourceFromUri(request.uri());
		// we can serve this one inline for now
		return new RequestProcessor() {
			
			@Override
			public void process() {
				
				ByteBuffer buf = UTF_8.encode(scriptResource.script());
				
				response.header(HttpHeaders.Names.CONTENT_LENGTH, buf.remaining())
					.header(HttpHeaders.Names.CACHE_CONTROL, "max-age=" + TWENTY_YEARS)
					.header(HttpHeaders.Names.CONTENT_TYPE, "text/javascript; charset=UTF-8")
					.content(buf)
					.end();

				
				log.info(
					"request for [{}] completed in {} milliseconds (wall time)",
					request.uri(),
					request.wallTime()
				);
			}
		};
	}
}<commit_msg>got rid of a hard-coded mime type<commit_after>package jj.servable;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.IOException;
import java.nio.ByteBuffer;

import jj.Configuration;
import jj.resource.ScriptResource;
import jj.script.AssociatedScriptBundle;
import jj.script.ScriptBundleFinder;
import jj.webbit.JJHttpRequest;
import jj.webbit.RequestProcessor;

import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.webbitserver.HttpControl;
import org.webbitserver.HttpResponse;

/**
 * handles automatic inclusion
 * @author jason
 *
 */
class AssociatedScriptServable extends Servable {
	
	private final Logger log = LoggerFactory.getLogger(AssociatedScriptServable.class);
	
	/**
	 * twenty years in seconds.  not including leap days. it's probably fine
	 */
	private static final String TWENTY_YEARS = String.valueOf(60 * 60 * 24 * 365 * 20);
	
	private final ScriptBundleFinder finder;

	AssociatedScriptServable(final Configuration configuration, final ScriptBundleFinder finder) {
		super(configuration);
		this.finder = finder;
	}
	
	@Override
	protected Rank rank() {
		return Rank.Middle;
	}
	
	private ScriptResource typeFromBundle(AssociatedScriptBundle bundle, String typeSpec) {
		ScriptResource result = null;
		if ("".equals(typeSpec)) {
			result = bundle.clientScriptResource();
		} else if (".shared".equals(typeSpec)) {
			result = bundle.sharedScriptResource();
		} else if (".server".equals(typeSpec)) {
			result = bundle.serverScriptResource();
		}
		return result;
	}
	
	private ScriptResource resourceFromUri(String uri) {
		int firstDot = uri.indexOf('.');
		int lastDot = uri.lastIndexOf('.');
		ScriptResource result = null;
		if (firstDot != -1) {
			// skip the /
			String key = uri.substring(1, firstDot);
			String type = uri.substring(firstDot, lastDot);
			String suffix = uri.substring(lastDot);
			if (".js".equals(suffix)) {
				AssociatedScriptBundle scriptBundle = finder.forBaseNameAndKey(key);
				if (scriptBundle != null) {
					result = typeFromBundle(scriptBundle, type);
				}
			}
		}
		return result;
	}

	@Override
	public boolean isMatchingRequest(final JJHttpRequest request) {
		return resourceFromUri(request.uri()) != null;
	}

	@Override
	public RequestProcessor makeRequestProcessor(
		final JJHttpRequest request,
		final HttpResponse response,
		final HttpControl control
	) throws IOException {
		
		final ScriptResource scriptResource = resourceFromUri(request.uri());
		// we can serve this one inline for now
		return new RequestProcessor() {
			
			@Override
			public void process() {
				
				ByteBuffer buf = UTF_8.encode(scriptResource.script());
				
				response.header(HttpHeaders.Names.CONTENT_LENGTH, buf.remaining())
					.header(HttpHeaders.Names.CACHE_CONTROL, "max-age=" + TWENTY_YEARS)
					.header(HttpHeaders.Names.CONTENT_TYPE, scriptResource.mime())
					.content(buf)
					.end();

				
				log.info(
					"request for [{}] completed in {} milliseconds (wall time)",
					request.uri(),
					request.wallTime()
				);
			}
		};
	}
}
{'fraction_non_alphanumeric': 0.10973451327433628, 'fraction_numerical': 0.0056315366049879325, 'mean_word_length': 4.154228855721393, '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': '2658530', 'n_tokens_mistral': 2161, 'n_tokens_neox': 1828, 'n_words': 441}