Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright 1&1 Internet AG, https://github.com/1and1/ 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 net.oneandone.jasmin.main;
 
 import  org.json.JSONException;
 import  org.json.JSONWriter;
 
 import java.io.Writer;
 import java.net.URI;
 import java.net.URL;
 import java.util.Date;
 import java.util.List;
 
 public class Servlet extends HttpServlet {
     public static final Logger LOG = LoggerFactory.getLogger(Servlet.class);
 
     private static final String HOSTNAME = getHostname();
 
     private static String getHostname() {
         try {
             return InetAddress.getLocalHost().getHostName();
         } catch (UnknownHostException e) {
             .error("unknown hostname"e);
             return "unknown";
         }
     }
 
     // re-create engine if one of these files was changed; null if life resolving is off
     private List<NodereloadFiles;
     private long loaded;
     private long otherVmStartupDate;
 
     private FileNode docroot;
     private Application application;
 
     // lazy init, because I need a URL first:
     private Engine engine;
 
     public Servlet() {
         // NOT longer than 10 years because the date format has only 2 digits for the year.
         this. = .getTime() - ;
     }

    
creates configuration.
 
     @Override
     public void init(ServletConfig configthrows ServletException {
         World world;
         String str;
 
         try {
             world = new World();
             configure(world"http");
             configure(world"https");
             str = config.getInitParameter("docroot");
              = Application.file(worldstr != null ? str : config.getServletContext().getRealPath(""));
             .checkDirectory();
             .info("home: " + world.getHome());
              = Application.load(worldconfig);
             .info("docroot: " + );
        } catch (RuntimeException | Error e) {
            error(null"init"e);
            throw e;
        } catch (Exception e) {
            error(null"init"e);
            throw new ServletException(e);
        } catch (Throwable e) {
            error(null"init"e);
            throw new RuntimeException("unexpected throwable"e);
        }
    }
    private static final int HTTP_TIMEOUT = 10 * 1000;
    private static void configure(World worldString scheme) {
        WebdavFilesystem webdav;
        webdav = world.getFilesystem(schemeWebdavFilesystem.class);
        webdav.setDefaultReadTimeout();
    }

    
Creates engine from configuration and resolve. Sychronized ensures we initialize only once.
    private synchronized void lazyInit(HttpServletRequest requestthrows IOException {
        List<Filefiles;
        URL url;
        long lastModified;
        long now;
        Resolver resolver;
        Node localhost;
        FileNode file;
        Object[] tmp;
        resolver = .;
        if ( != null && resolver.isLife()) {
            for (Node node : ) {
                lastModified = node.getLastModified();
                if (lastModified > ) {
                    now = System.currentTimeMillis();
                    if (lastModified > now) {
                        // fail to avoid repeated re-init
                        throw new IOException(node.getURI() + " has lastModifiedDate in the future: "
                                + new Date(lastModified) + "(now: " + new Date(now) + ")");
                    }
                    .info("reloading jasmin for application '" + .getContextPath() + "' - changed file: " + node);
                     = null;
                    resolver.reset();
                }
            }
        }
        if ( == null) {
            url = new URL(request.getRequestURL().toString());
            try {
                localhost = resolver.getWorld().node(new URI(url.getProtocol(), nullurl.getHost(), url.getPort(), ""nullnull));
            } catch (URISyntaxException e) {
                throw new IllegalStateException(e);
            }
            tmp = .createEngine(localhost);
             = (Enginetmp[0];
            .info("started engine, initial url=" + url);
            for (Module module : ..modules()) {
                files = module.files();
                if (files.size() > 2) {
                    .warn("deprecated: module '" + module.getName() + "' contains more than 2 file: " + files);
                }
                for (File f : files) {
                    if (f.getNormal() instanceof WebdavNode) {
                        .warn("deprecated: module '" + module.getName() + "' uses base LOCALHOST: " + f.getNormal().getURI());
                    }
                }
            }
            if (resolver.isLife()) {
                 = (List<Node>) tmp[1];
                file = resolver.getLiveXml();
                if (file != null) {
                    .add(file);
                }
                .info("reload if one of these " + .size() + " files is modified: ");
                for (Node node : ) {
                    .info("  " + node.getURI());
                }
                 = System.currentTimeMillis();
            }
            if ( == null) {
                throw new IllegalStateException();
            }
        }
    }
    //--

    
Called by the servlet engine to process get requests: a) to set the Last-Modified header in the response b) to check if 304 can be redurned if the "if-modified-since" request header is present

Returns:
-1 for when unknown
    @Override
    public long getLastModified(HttpServletRequest request) {
        String path;
        int idx;
        long result;
        result = -1;
        try {
            path = request.getPathInfo();
            if (path != null && path.startsWith("/get/")) {
                lazyInit(request);
                path = path.substring(5);
                idx = path.indexOf('/');
                if (idx != -1) {
                    path = path.substring(idx + 1);
                    result = .getLastModified(path);
                }
            }
        } catch (IOException e) {
            error(request"getLastModified"e);
            // fall-through
        } catch (RuntimeException | Error e) {
            error(request"getLastModified"e);
            throw e;
        }
        .debug("getLastModified(" + request.getPathInfo() + ") -> " + result);
        return result;
    }
    @Override
    public void doGet(HttpServletRequest requestHttpServletResponse responsethrows IOExceptionServletException {
        try {
            doGetUnchecked(requestresponse);
        } catch (IOException e) {
            // I can't compile against this class because the servlet api does not officially
            // report this situation ...
            // See http://tomcat.apache.org/tomcat-5.5-doc/catalina/docs/api/org/apache/catalina/connector/ClientAbortException.html
            if (e.getClass().getName().equals("org.apache.catalina.connector.ClientAbortException")) {
                // this is not an error: the client browser closed the response stream, e.g. because
                // the user already left the page
                .info("aborted by client"e);
            } else {
                error(request"get"e);
            }
            throw e;
        } catch (RuntimeException | Error e) {
            error(request"get"e);
            throw e;
        }
    }
    private static final String MODULE_PREFIX = "/admin/module/";
    private void doGetUnchecked(HttpServletRequest requestHttpServletResponse responsethrows IOException {
        String path;
        path = request.getPathInfo();
        if (path == null) {
            response.sendRedirect(request.getContextPath() + request.getServletPath() + "/");
            return;
        }
        lazyInit(request);
        .debug("get " + path);
        if (path.startsWith("/get/")) {
            get(requestresponsepath.substring(5));
            return;
        }
        if (path.equals("/admin/")) {
            main(response);
            return;
        }
        if (path.equals("/admin/repository")) {
            repository(requestresponse);
            return;
        }
        if (path.equals("/admin/hashCache")) {
            hashCache(response);
            return;
        }
        if (path.equals("/admin/contentCache")) {
            contentCache(response);
            return;
        }
        if (path.startsWith()) {
            module(requestresponsepath.substring(.length()));
            return;
        }
        if (path.equals("/admin/reload")) {
            reload(response);
            return;
        }
        if (path.equals("/admin/check")) {
            fileCheck(response);
            return;
        }
        notFound(requestresponse);
    }
    private static final long FIVE_MINUTES = 1000L * 60 * 5;
    private static final long SEVEN_DAYS = 1000L * 3600 * 24 * 7;
    private static final long TEN_YEARS = 1000L * 3600 * 24 * 365 * 10;
    private void get(HttpServletRequest requestHttpServletResponse responseString paththrows IOException {
        String version;
        boolean expire;
        int idx;
        long started;
        long duration;
        int bytes;
        boolean gzip;
        long date;
        idx = path.indexOf('/');
        if (idx == -1) {
            notFound(requestresponse);
            return;
        }
        started = System.currentTimeMillis();
        version = path.substring(0, idx);
        expire = !"no-expires".equals(version);
        if (expire && !.equals(version)) {
            try {
                synchronized () {
                    date = .parse(version).getTime();
                }
            } catch (ParseException e) {
                notFound(requestresponse);
                return;
            }
            if (sameTime(date) || sameTime(date)) {
                // ok
            } else if (date > ) {
                 = date;
            } else {
                // usually, otherVmStartupDate is smaller, but after switching back, VM_STARTUP will be smaller
                if (Math.min() - date > ) {
                    gone(requestresponse);
                    return;
                }
            }
        }
        path = path.substring(idx + 1);
        if (..isLife()) {
            // unknown headers are ok: see http://tools.ietf.org/html/rfc2616#section-7.1
            response.addHeader("Hi""Sie werden bedient von Jasmin, vielen Dank fuer ihren Request!");
        }
        checkCharset(request.getHeader("Accept-Charset"));
        if (expire && . != null) {
            response.setDateHeader("Expires"started + 1000L * .);
            response.addHeader("Cache-Control""max-age=" + .);
        }
        gzip = canGzip(request);
        bytes = .request(pathresponsegzip);
        duration = System.currentTimeMillis() - started;
        .info(path + "|" + bytes + "|" + duration + "|" + gzip + "|" + referer(request));
    }
    private static boolean sameTime(long leftlong right) {
        long diff;
        diff = left - right;
        if (diff < 0) {
            diff = -diff;
        }
        return diff < ;
    }
    private static boolean canGzip(HttpServletRequest request) {
        String accepted;
        accepted = request.getHeader("Accept-Encoding");
        return accepted != null && contains(accepted"gzip");
    }
    // see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
    public static void checkCharset(String acceptsthrows IOException {
        if (accepts == null) {
            // ie7 does not send this header
            return;
        }
        // I've seen both "utf-8" and "UTF-8" -> test case-insensitive
        if (contains(accepts.toLowerCase(), .)) {
            return;
        }
        if (contains(accepts"*")) {
            return;
        }
        throw new IOException(. + " encoding is not accepted: " + accepts);
    }
    // see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
    public static boolean contains(String listString keyword) {
        int idx;
        int colon;
        String quality;
        idx = list.indexOf(keyword);
        if (idx == -1) {
            return false;
        }
        idx += keyword.length();
        colon = list.indexOf(","idx);
        if (colon == -1) {
            colon = list.length();
        }
        quality = list.substring(idxcolon);
        idx = quality.indexOf('=');
        if (idx == -1) {
            return true;
        }
        return !"0".equals(quality.substring(idx + 1).trim());
    }
    private void main(HttpServletResponse responsethrows IOException {
        html(response,
                "<p>Jasmin Servlet " + getVersion() + "</p>",
                "<p>Hostname: " +  + "</p>",
                "<p>Docroot: " + .getAbsolute() + "</p>",
                "<p>VM Startup: " +  + "</p>",
                "<p>Other VM Startup: " + .format() + "</p>",
                "<p>Loaded: " + new Date() + "</p>",
                "<p>HashCache: " + ..getMaxSize() + "</p>",
                "<p>ContentCache: " + ..getMaxSize() + "</p>",
                "<p>Requested Bytes: " + ..get() + "</p>",
                "<p>Computed Bytes: " + .computedBytes() + "</p>",
                "<p>Removed Bytes: " + .removedBytes() + "</p>",
                "<p>Load: " + .load() + "</p>",
                ..isLife() ? "<a href='reload'>Reload Files</a>" : "(no reload)",
                "<a href='repository'>Repository</a>",
                "<a href='hashCache'>Hash Cache</a>",
                "<a href='contentCache'>Content Cache</a>",
                "<a href='check'>File Check</a>");
    }
    private String getVersion() {
        return getClass().getPackage().getImplementationVersion();
    }
    private void repository(HttpServletRequest requestHttpServletResponse responsethrows IOException {
        JSONWriter dest;
        List<Modulemodules;
        response.setContentType("application/json");
        try (Writer writer = response.getWriter()) {
            dest = new JSONWriter(writer);
            dest.array();
            modules = new ArrayList<Module>(..modules());
            Collections.sort(modulesnew Comparator<Module>() {
                @Override
                public int compare(Module leftModule right) {
                    return left.getName().compareTo(right.getName());
                }
            });
            for (Module module : modules) {
                dest.object();
                dest.key("name");
                dest.value(module.getName());
                dest.key("details");
                dest.value(Strings.removeRight(request.getRequestURL().toString(), "/repository") + "/module/" + module.getName());
                dest.endObject();
            }
            dest.endArray();
        } catch (JSONException e) {
            throw new IllegalStateException(e);
        }
    }
    private void hashCache(HttpServletResponse responsethrows IOException {
        text(response..toString());
    }
    private void contentCache(HttpServletResponse responsethrows IOException {
        text(response..toString());
    }
    private void module(HttpServletRequest requestHttpServletResponse responseString namethrows IOException {
        JSONWriter dest;
        Module module;
        Source source;
        module = ..lookup(name);
        source = module.getSource();
        if (module == null) {
            notFound(requestresponse);
            return;
        }
        response.setContentType("application/json");
        try (Writer writer = response.getWriter()) {
            dest = new JSONWriter(writer);
            dest.object();
            dest.key("name");
            dest.value(module.getName());
            dest.key("files");
            dest.array();
            for (File file : module.files()) {
                dest.object();
                dest.key("type");
                dest.value(file.getType());
                dest.key("normal");
                dest.value(file.getNormal().getURI());
                if (file.getMinimized() != null) {
                    dest.key("minimized");
                    dest.value(file.getMinimized().getURI());
                }
                dest.key("variant");
                dest.value(file.getVariant());
                dest.endObject();
            }
            dest.endArray();
            dest.key("dependencies");
            dest.array();
            for (Module dependency : module.dependencies()) {
                dest.value(dependency.getName());
            }
            dest.endArray();
            dest.key("source");
            dest.object();
            dest.key("artifactId");
            dest.value(source.artifactId);
            dest.key("groupId");
            dest.value(source.groupId);
            dest.key("version");
            dest.value(source.version);
            dest.key("scm");
            dest.value(source.scm);
            dest.endObject();
            dest.endObject();
        } catch (JSONException e) {
            throw new IllegalStateException(e);
        }
    }
    private void reload(HttpServletResponse responsethrows IOException {
        String[] lines;
        lines = new String[.size()];
        for (int i = 0; i < lines.lengthi++) {
            lines[i] = .get(i).getURI().toString();
        }
        text(responselines);
    }
    private void fileCheck(HttpServletResponse responsethrows IOException {
        FileCheck check;
        check = new FileCheck();
        check.minimize(true...getWorld());
        text(responsecheck.toString());
    }
    private void text(HttpServletResponse responseString... linesthrows IOException {
        response.setContentType("text/plain");
        try (Writer writer = response.getWriter()) {
            for (String line : lines) {
                writer.write(line);
                writer.write('\n');
            }
        }
    }
    private void html(HttpServletResponse responseString... linesthrows IOException {
        response.setContentType("text/html");
        try (Writer writer = response.getWriter()) {
            writer.write("<html><header></header><body>\n");
            for (String line : lines) {
                writer.write(line);
                writer.write('\n');
            }
            writer.write("</body>");
        }
    }
    private void notFound(HttpServletRequest requestHttpServletResponse responsethrows IOException {
        .warn("not found: " + request.getPathInfo());
        response.sendError(.);
    }
    private void gone(HttpServletRequest requestHttpServletResponse responsethrows IOException {
        .warn("gone: " + request.getPathInfo());
        response.sendError(.);
    }
    //--

    

Parameters:
request may be null
    private void error(HttpServletRequest requestString methodThrowable throwable) {
        StringBuilder message;
        message = new StringBuilder();
        message.append(method).append(":").append(throwable.getMessage());
        if (request != null) {
            message.append('(');
            message.append("referer=").append(referer(request));
            message.append(",pathinfo=").append(pathInfo(request));
        }
        .error(message.toString(), throwable);
    }
    private static String pathInfo(HttpServletRequest request) {
        if (request == null) {
            return null;
        }
        return request.getPathInfo();
    }
    private static String referer(HttpServletRequest request) {
        if (request == null) {
            return null;
        }
        return request.getHeader("Referer");
    }
    //-- XSLT functions
    public static final SimpleDateFormat FMT = new SimpleDateFormat("yyMMdd-HHmm");
    public static final Date VM_STARTUP_DATE = new Date();
    public static final long VM_STARTUP = .getTime();
    public static final String VM_STARTUP_STR = .format();
    public static String getVmStartup() {
        return ;
    }
New to GrepCode? Check out our FAQ X