<commit_before>/******************************************************************


 * File:        RequestProcessor.java
 * Created by:  <NAME>
 * Created on:  21 Jan 2013
 *
 * (c) Copyright 2013, Epimorphics Limited
 *
 *****************************************************************/

package com.epimorphics.registry.webapi;

import static com.epimorphics.webapi.marshalling.RDFXMLMarshaller.FULL_MIME_RDFXML;
import static com.epimorphics.webapi.marshalling.RDFXMLMarshaller.MIME_RDFXML;

import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import javax.ws.rs.core.UriInfo;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.epimorphics.registry.commands.CommandUpdate;
import com.epimorphics.registry.core.Command;
import com.epimorphics.registry.core.Command.Operation;
import com.epimorphics.registry.core.ForwardingRecord;
import com.epimorphics.registry.core.ForwardingRecord.Type;
import com.epimorphics.registry.core.ForwardingService;
import com.epimorphics.registry.core.MatchResult;
import com.epimorphics.registry.core.Registry;
import com.epimorphics.registry.security.UserInfo;
import com.epimorphics.registry.util.JSONLDSupport;
import com.epimorphics.registry.util.PATCH;
import com.epimorphics.registry.util.UiForm;
import com.epimorphics.server.core.ServiceConfig;
import com.epimorphics.server.templates.VelocityRender;
import com.epimorphics.server.webapi.BaseEndpoint;
import com.epimorphics.server.webapi.WebApiException;
import com.epimorphics.util.NameUtils;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.util.FileManager;
import com.hp.hpl.jena.util.FileUtils;
import com.sun.jersey.api.NotFoundException;
import com.sun.jersey.multipart.FormDataBodyPart;
import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.FormDataParam;

/**
 * Filter all requests as possible register API requests.
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 */
@Path("{path: .*}")
public class RequestProcessor extends BaseEndpoint {
    static final Logger log = LoggerFactory.getLogger( RequestProcessor.class );

    public static final String FULL_MIME_TURTLE = "text/turtle; charset=UTF-8";
    public static final String FORWARDED_FOR_HEADER = "X-Forwarded-For";

    @GET
    @Produces("text/html")
    public Response htmlrender() {
        PassThroughResult result = checkForPassThrough();
        if (result != null && result.isDone()) {
            return result.getResponse();
        }
        MultivaluedMap<String, String> parameters = uriInfo.getQueryParameters();
        if (parameters.containsKey(Parameters.FORMAT)) {
            Response response = doRead(result);
            String mime = MIME_RDFXML;
            String format = parameters.getFirst(Parameters.FORMAT);
            if (format.equals("ttl")) {
                mime = FULL_MIME_TURTLE;
            } else if (format.equals("jsonld")) {
                mime = JSONLDSupport.FULL_MIME_JSONLD;
            }
            return Response.ok().type(mime).entity(response.getEntity()).build();
        } else {
            return render("main.vm", uriInfo, context, request);
        }
    }

    public static Response render(String template, UriInfo uriInfo, ServletContext context, HttpServletRequest request, Object...params) {
        String language = request.getLocale().getLanguage();
        if (language.isEmpty()) {
            language = "en";
        }
        Object[] fullParams = new Object[params.length + 10];
        int i = 0;
        while (i < params.length) {
            fullParams[i] = params[i];
            i++;
        }
        fullParams[i++] = "registry";
        fullParams[i++] = Registry.get();
        fullParams[i++] = "subject";
        fullParams[i++] = SecurityUtils.getSubject();
        fullParams[i++] = "requestor";
        fullParams[i++] = getRequestor(request);
        fullParams[i++] = "request";
        fullParams[i++] = request;
        fullParams[i++] = "language";
        fullParams[i++] = language;

        VelocityRender velocity = ServiceConfig.get().getServiceAs(Registry.VELOCITY_SERVICE, VelocityRender.class);
        StreamingOutput out = velocity.render(template, uriInfo.getPath(), context, uriInfo.getQueryParameters(), fullParams);
        return Response.ok().type("text/html").entity(out).build();
    }

    public static String getRequestor(HttpServletRequest request) {
        try {
            UserInfo user = (UserInfo) SecurityUtils.getSubject().getPrincipal();
            if (user != null) {
                return NameUtils.encodeSafeName(user.toString());
            }
        } catch (UnavailableSecurityManagerException e) {
            // shiro not running, presumably test mode, fall through to default requestor based on IP
        }

        if (request.getHeader(FORWARDED_FOR_HEADER) != null) {
            return request.getHeader(FORWARDED_FOR_HEADER);
        }

        return request.getRemoteAddr();
    }

    @GET
    @Produces({FULL_MIME_TURTLE, FULL_MIME_RDFXML, JSONLDSupport.FULL_MIME_JSONLD})
    public Response read() {
        PassThroughResult result = checkForPassThrough();
        if (result != null && result.isDone()) {
            return result.getResponse();
        } else {
            return doRead(result);
        }
    }

    private Response doRead(PassThroughResult ptr) {
        Command command = null;
        if (uriInfo.getQueryParameters().containsKey(Parameters.QUERY)) {
            command = makeCommand( Operation.Search );
        } else {
            command = makeCommand( Operation.Read );
            if (ptr != null) {
                command.setDelegation(ptr.getRecord());
            }
        }
        return command.execute();
    }

    private PassThroughResult checkForPassThrough() {
        String path = uriInfo.getPath();
        if (path.startsWith("ui") || path.startsWith("system/query") || path.equals("favicon.ico")) {
            // Pass through all ui requests to the generic velocity handler, which in turn falls through to file serving
            throw new NotFoundException();
        }

        ForwardingService fs = Registry.get().getForwarder();
        if (fs != null) {
            MatchResult match = fs.match(path);
            if (match != null) {
                ForwardingRecord fr = match.getRecord();
                PassThroughResult result = new PassThroughResult(fr);
                if (fr.getType() == Type.DELEGATE) {
                    // Delegation should bubble up to the read command
                    return result;
                }
                String forwardTo = fr.getTarget();
                String remainder = match.getPathRemainder();
                if (!remainder.isEmpty()) {
                    if (!forwardTo.endsWith("/")) {
                        forwardTo += "/";
                    }
                    forwardTo += remainder;<commit_msg>Unify velocity rendering here so that e.g. text search sees the security subject binding<commit_after>/******************************************************************


 * File:        RequestProcessor.java
 * Created by:  <NAME>
 * Created on:  21 Jan 2013
 *
 * (c) Copyright 2013, Epimorphics Limited
 *
 *****************************************************************/

package com.epimorphics.registry.webapi;

import static com.epimorphics.webapi.marshalling.RDFXMLMarshaller.FULL_MIME_RDFXML;
import static com.epimorphics.webapi.marshalling.RDFXMLMarshaller.MIME_RDFXML;

import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import javax.ws.rs.core.UriInfo;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.epimorphics.registry.commands.CommandUpdate;
import com.epimorphics.registry.core.Command;
import com.epimorphics.registry.core.Command.Operation;
import com.epimorphics.registry.core.ForwardingRecord;
import com.epimorphics.registry.core.ForwardingRecord.Type;
import com.epimorphics.registry.core.ForwardingService;
import com.epimorphics.registry.core.MatchResult;
import com.epimorphics.registry.core.Registry;
import com.epimorphics.registry.security.UserInfo;
import com.epimorphics.registry.util.JSONLDSupport;
import com.epimorphics.registry.util.PATCH;
import com.epimorphics.registry.util.UiForm;
import com.epimorphics.server.core.ServiceConfig;
import com.epimorphics.server.templates.VelocityRender;
import com.epimorphics.server.webapi.BaseEndpoint;
import com.epimorphics.server.webapi.WebApiException;
import com.epimorphics.util.NameUtils;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.util.FileManager;
import com.hp.hpl.jena.util.FileUtils;
import com.sun.jersey.api.NotFoundException;
import com.sun.jersey.multipart.FormDataBodyPart;
import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.FormDataParam;

/**
 * Filter all requests as possible register API requests.
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 */
@Path("{path: .*}")
public class RequestProcessor extends BaseEndpoint {
    static final Logger log = LoggerFactory.getLogger( RequestProcessor.class );

    public static final String FULL_MIME_TURTLE = "text/turtle; charset=UTF-8";
    public static final String FORWARDED_FOR_HEADER = "X-Forwarded-For";
    public static final String UI_PATH = "ui";

    @GET
    @Produces("text/html")
    public Response htmlrender() {
        String path = uriInfo.getPath();
        if (path.startsWith(UI_PATH) ) {
            String template = path.substring(UI_PATH.length()+1) + ".vm";
            try {
                return render(template, uriInfo, context, request);
            } catch (ResourceNotFoundException e) {
                // Will chain through to file serving
                throw new NotFoundException();
            }
        } else if (path.startsWith("system/query") || path.equals("favicon.ico")) {
            // Pass to the generic velocity handler, which in turn falls through to file serving
            throw new NotFoundException();
        }
        
        PassThroughResult result = checkForPassThrough();
        if (result != null && result.isDone()) {
            return result.getResponse();
        }
        MultivaluedMap<String, String> parameters = uriInfo.getQueryParameters();
        if (parameters.containsKey(Parameters.FORMAT)) {
            Response response = doRead(result);
            String mime = MIME_RDFXML;
            String format = parameters.getFirst(Parameters.FORMAT);
            if (format.equals("ttl")) {
                mime = FULL_MIME_TURTLE;
            } else if (format.equals("jsonld")) {
                mime = JSONLDSupport.FULL_MIME_JSONLD;
            }
            return Response.ok().type(mime).entity(response.getEntity()).build();
        } else {
            return render("main.vm", uriInfo, context, request);
        }
    }

    public static Response render(String template, UriInfo uriInfo, ServletContext context, HttpServletRequest request, Object...params) {
        String language = request.getLocale().getLanguage();
        if (language.isEmpty()) {
            language = "en";
        }
        Object[] fullParams = new Object[params.length + 10];
        int i = 0;
        while (i < params.length) {
            fullParams[i] = params[i];
            i++;
        }
        fullParams[i++] = "registry";
        fullParams[i++] = Registry.get();
        fullParams[i++] = "subject";
        fullParams[i++] = SecurityUtils.getSubject();
        fullParams[i++] = "requestor";
        fullParams[i++] = getRequestor(request);
        fullParams[i++] = "request";
        fullParams[i++] = request;
        fullParams[i++] = "language";
        fullParams[i++] = language;

        VelocityRender velocity = ServiceConfig.get().getServiceAs(Registry.VELOCITY_SERVICE, VelocityRender.class);
        StreamingOutput out = velocity.render(template, uriInfo.getPath(), context, uriInfo.getQueryParameters(), fullParams);
        return Response.ok().type("text/html").entity(out).build();
    }

    public static String getRequestor(HttpServletRequest request) {
        try {
            UserInfo user = (UserInfo) SecurityUtils.getSubject().getPrincipal();
            if (user != null) {
                return NameUtils.encodeSafeName(user.toString());
            }
        } catch (UnavailableSecurityManagerException e) {
            // shiro not running, presumably test mode, fall through to default requestor based on IP
        }

        if (request.getHeader(FORWARDED_FOR_HEADER) != null) {
            return request.getHeader(FORWARDED_FOR_HEADER);
        }

        return request.getRemoteAddr();
    }

    @GET
    @Produces({FULL_MIME_TURTLE, FULL_MIME_RDFXML, JSONLDSupport.FULL_MIME_JSONLD})
    public Response read() {
        PassThroughResult result = checkForPassThrough();
        if (result != null && result.isDone()) {
            return result.getResponse();
        } else {
            return doRead(result);
        }
    }

    private Response doRead(PassThroughResult ptr) {
        Command command = null;
        if (uriInfo.getQueryParameters().containsKey(Parameters.QUERY)) {
            command = makeCommand( Operation.Search );
        } else {
            command = makeCommand( Operation.Read );
            if (ptr != null) {
                command.setDelegation(ptr.getRecord());
            }
        }
        return command.execute();
    }

    private PassThroughResult checkForPassThrough() {
        String path = uriInfo.getPath();
        ForwardingService fs = Registry.get().getForwarder();
        if (fs != null) {
            MatchResult match = fs.match(path);
            if (match != null) {
                ForwardingRecord fr = match.getRecord();
                PassThroughResult result = new PassThroughResult(fr);
                if (fr.getType() == Type.DELEGATE) {
                    // Delegation should bubble up to the read command
                    return result;
                }
                String forwardTo = fr.getTarget();
                String remainder = match.getPathRemainder();
                if (!remainder.isEmpty()) {
                    if (!forwardTo.endsWith("/")) {
                        forwardTo += "/";
                    }
                    forwardTo += remainder;
{'fraction_non_alphanumeric': 0.12879984832206282, 'fraction_numerical': 0.0020855716362257475, 'mean_word_length': 2.851996105160662, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 15, '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': '1890805', 'n_tokens_mistral': 4555, 'n_tokens_neox': 4430, 'n_words': 899}