xref: /OpenGrok/opengrok-web/src/main/webapp/list.jsp (revision 7af88e20c2ba86418b6682ba70b9e68e239fe482)
10d40e9d0SAdam Hornáček<%--
20d40e9d0SAdam HornáčekCDDL HEADER START
30d40e9d0SAdam Hornáček
40d40e9d0SAdam HornáčekThe contents of this file are subject to the terms of the
50d40e9d0SAdam HornáčekCommon Development and Distribution License (the "License").
60d40e9d0SAdam HornáčekYou may not use this file except in compliance with the License.
70d40e9d0SAdam Hornáček
80d40e9d0SAdam HornáčekSee LICENSE.txt included in this distribution for the specific
90d40e9d0SAdam Hornáčeklanguage governing permissions and limitations under the License.
100d40e9d0SAdam Hornáček
110d40e9d0SAdam HornáčekWhen distributing Covered Code, include this CDDL HEADER in each
120d40e9d0SAdam Hornáčekfile and include the License file at LICENSE.txt.
130d40e9d0SAdam HornáčekIf applicable, add the following below this CDDL HEADER, with the
140d40e9d0SAdam Hornáčekfields enclosed by brackets "[]" replaced with your own identifying
150d40e9d0SAdam Hornáčekinformation: Portions Copyright [yyyy] [name of copyright owner]
160d40e9d0SAdam Hornáček
170d40e9d0SAdam HornáčekCDDL HEADER END
180d40e9d0SAdam Hornáček
19b13c5a0eSAdam HornacekCopyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
200d40e9d0SAdam HornáčekPortions Copyright 2011 Jens Elkner.
215c931ce8SChris FrairePortions Copyright (c) 2017-2020, Chris Fraire <cfraire@me.com>.
220d40e9d0SAdam Hornáček
230d40e9d0SAdam Hornáček--%>
240d40e9d0SAdam Hornáček<%@page errorPage="error.jsp" import="
250d40e9d0SAdam Hornáčekjava.io.BufferedInputStream,
261c830032SChris Frairejava.io.File,
270d40e9d0SAdam Hornáčekjava.io.FileInputStream,
280d40e9d0SAdam Hornáčekjava.io.InputStreamReader,
291c830032SChris Frairejava.io.IOException,
300d40e9d0SAdam Hornáčekjava.io.Reader,
310d40e9d0SAdam Hornáčekjava.net.URLEncoder,
320d40e9d0SAdam Hornáčekjava.nio.charset.StandardCharsets,
330d40e9d0SAdam Hornáčekjava.util.List,
3452dccac1SChris Frairejava.util.Locale,
35e829566cSChris Frairejava.util.logging.Level,
36e829566cSChris Frairejava.util.logging.Logger,
375c931ce8SChris Frairejava.util.Set,
385c931ce8SChris Frairejava.util.TreeSet,
39686556f2SAdam Hornáčekorg.opengrok.indexer.analysis.AnalyzerGuru,
40686556f2SAdam Hornáčekorg.opengrok.indexer.analysis.Definitions,
41e829566cSChris Fraireorg.opengrok.indexer.analysis.AbstractAnalyzer,
42e829566cSChris Fraireorg.opengrok.indexer.analysis.AnalyzerFactory,
4341351de3SChris Fraireorg.opengrok.indexer.analysis.NullableNumLinesLOC,
44686556f2SAdam Hornáčekorg.opengrok.indexer.history.Annotation,
45686556f2SAdam Hornáčekorg.opengrok.indexer.index.IndexDatabase,
46e829566cSChris Fraireorg.opengrok.indexer.logger.LoggerFactory,
47686556f2SAdam Hornáčekorg.opengrok.indexer.search.DirectoryEntry,
48686556f2SAdam Hornáčekorg.opengrok.indexer.search.DirectoryExtraReader,
49686556f2SAdam Hornáčekorg.opengrok.indexer.util.FileExtraZipper,
507d004396SChris Fraireorg.opengrok.indexer.util.ForbiddenSymlinkException,
51686556f2SAdam Hornáčekorg.opengrok.indexer.util.IOUtils,
5256f072caSAdam Hornáčekorg.opengrok.web.DirectoryListing,
53686556f2SAdam Hornáčekorg.opengrok.indexer.web.SearchHelper"
5457eefa47SKryštof Tulinger%>
55*7af88e20SVladimir Kotal<%@ page import="static org.opengrok.web.PageConfig.DUMMY_REVISION" %>
5657eefa47SKryštof Tulinger<%
570d40e9d0SAdam Hornáček{
580d40e9d0SAdam Hornáček    // need to set it here since requesting parameters
590d40e9d0SAdam Hornáček    if (request.getCharacterEncoding() == null) {
600d40e9d0SAdam Hornáček        request.setCharacterEncoding("UTF-8");
610d40e9d0SAdam Hornáček    }
620d40e9d0SAdam Hornáček
630d40e9d0SAdam Hornáček    PageConfig cfg = PageConfig.get(request);
640d40e9d0SAdam Hornáček    cfg.checkSourceRootExistence();
650d40e9d0SAdam Hornáček
6655774b8bSChris Fraire    String rev = cfg.getRequestedRevision();
6755774b8bSChris Fraire    if (!cfg.isDir() && rev.length() == 0) {
6855774b8bSChris Fraire        /*
6955774b8bSChris Fraire         * Get the latest revision and redirect so that the revision number
7055774b8bSChris Fraire         * appears in the URL.
7155774b8bSChris Fraire         */
7296b0c142SChris Fraire        String latestRevision = cfg.getLatestRevision();
7396b0c142SChris Fraire        if (latestRevision != null) {
74eeb95924SChris Fraire            cfg.evaluateMatchOffset();
7596b0c142SChris Fraire            String location = cfg.getRevisionLocation(latestRevision);
7655774b8bSChris Fraire            response.sendRedirect(location);
7755774b8bSChris Fraire            return;
7855774b8bSChris Fraire        }
7955774b8bSChris Fraire        if (!cfg.getEnv().isGenerateHtml()) {
80eeb95924SChris Fraire            cfg.evaluateMatchOffset();
8155774b8bSChris Fraire            /*
8255774b8bSChris Fraire             * Economy mode is on and failed to get the last revision
8355774b8bSChris Fraire             * (presumably running with history turned off).  Use dummy
8455774b8bSChris Fraire             * revision string so that xref can be generated from the resource
8555774b8bSChris Fraire             * file directly.
8655774b8bSChris Fraire             */
8796b0c142SChris Fraire            String location = cfg.getRevisionLocation(DUMMY_REVISION);
8855774b8bSChris Fraire            response.sendRedirect(location);
8955774b8bSChris Fraire            return;
9055774b8bSChris Fraire        }
91eeb95924SChris Fraire
92eeb95924SChris Fraire        if (cfg.evaluateMatchOffset()) {
93eeb95924SChris Fraire            /*
94eeb95924SChris Fraire             * If after calling, a match offset has been translated to a
95eeb95924SChris Fraire             * fragment identifier (specifying a line#), then redirect to self.
96eeb95924SChris Fraire             * This block will not be activated again the second time.
97eeb95924SChris Fraire             */
98eeb95924SChris Fraire            String location = cfg.getRevisionLocation(""); // empty
9955774b8bSChris Fraire            response.sendRedirect(location);
10055774b8bSChris Fraire            return;
10155774b8bSChris Fraire        }
10255774b8bSChris Fraire    }
10355774b8bSChris Fraire
1040d40e9d0SAdam Hornáček    Annotation annotation = cfg.getAnnotation();
1050d40e9d0SAdam Hornáček    if (annotation != null) {
1060d40e9d0SAdam Hornáček        int r = annotation.getWidestRevision();
1070d40e9d0SAdam Hornáček        int a = annotation.getWidestAuthor();
1080d40e9d0SAdam Hornáček        cfg.addHeaderData("<style type=\"text/css\">"
1090d40e9d0SAdam Hornáček            + ".blame .r { width: " + (r == 0 ? 6 : Math.ceil(r * 0.7)) + "em; } "
1100d40e9d0SAdam Hornáček            + ".blame .a { width: " + (a == 0 ? 6 : Math.ceil(a * 0.7)) + "em; } "
1110d40e9d0SAdam Hornáček            + "</style>");
1120d40e9d0SAdam Hornáček    }
1130d40e9d0SAdam Hornáček}
1140d40e9d0SAdam Hornáček%><%@include
1150d40e9d0SAdam Hornáček
1160d40e9d0SAdam Hornáčekfile="mast.jsp"
1170d40e9d0SAdam Hornáček
1180d40e9d0SAdam Hornáček%><script type="text/javascript">/* <![CDATA[ */
1190d40e9d0SAdam Hornáčekdocument.pageReady.push(function() { pageReadyList();});
1200d40e9d0SAdam Hornáček/* ]]> */</script>
1210d40e9d0SAdam Hornáček<%
1220d40e9d0SAdam Hornáček/* ---------------------- list.jsp start --------------------- */
1230d40e9d0SAdam Hornáček{
124e829566cSChris Fraire    final Logger LOGGER = LoggerFactory.getLogger(getClass());
125e829566cSChris Fraire
1260d40e9d0SAdam Hornáček    PageConfig cfg = PageConfig.get(request);
1270d40e9d0SAdam Hornáček    String rev = cfg.getRequestedRevision();
128e393cb49SAdam Hornáček    Project project = cfg.getProject();
1290d40e9d0SAdam Hornáček
130e393cb49SAdam Hornáček    String navigateWindowEnabled = project != null ? Boolean.toString(
131e393cb49SAdam Hornáček            project.isNavigateWindowEnabled()) : "false";
1320d40e9d0SAdam Hornáček    File resourceFile = cfg.getResourceFile();
1330d40e9d0SAdam Hornáček    String path = cfg.getPath();
1340d40e9d0SAdam Hornáček    String basename = resourceFile.getName();
1350d40e9d0SAdam Hornáček    String rawPath = request.getContextPath() + Prefix.DOWNLOAD_P + path;
1360d40e9d0SAdam Hornáček    Reader r = null;
1370d40e9d0SAdam Hornáček    if (cfg.isDir()) {
1380d40e9d0SAdam Hornáček        // valid resource is requested
1390d40e9d0SAdam Hornáček        // mast.jsp assures, that resourceFile is valid and not /
1400d40e9d0SAdam Hornáček        // see cfg.resourceNotAvailable()
1410d40e9d0SAdam Hornáček        String cookieValue = cfg.getRequestedProjectsAsString();
1425c931ce8SChris Fraire        String projectName = null;
143e393cb49SAdam Hornáček        if (project != null) {
1445c931ce8SChris Fraire            projectName = project.getName();
1450d40e9d0SAdam Hornáček            Set<String>  projects = cfg.getRequestedProjects();
1465c931ce8SChris Fraire            if (!projects.contains(projectName)) {
1475c931ce8SChris Fraire                projects.add(projectName);
1480d40e9d0SAdam Hornáček                // update cookie
1495c931ce8SChris Fraire                cookieValue = cookieValue.length() == 0 ? projectName :
1505c931ce8SChris Fraire                        projectName + ',' + cookieValue;
151b13c5a0eSAdam Hornacek                Cookie cookie = new Cookie(PageConfig.OPEN_GROK_PROJECT, URLEncoder.encode(cookieValue, StandardCharsets.UTF_8));
1520d40e9d0SAdam Hornáček                // TODO hmmm, projects.jspf doesn't set a path
1530d40e9d0SAdam Hornáček                cookie.setPath(request.getContextPath() + '/');
1540d40e9d0SAdam Hornáček                response.addCookie(cookie);
1550d40e9d0SAdam Hornáček            }
1560d40e9d0SAdam Hornáček        }
1570d40e9d0SAdam Hornáček        // requesting a directory listing
1580d40e9d0SAdam Hornáček        DirectoryListing dl = new DirectoryListing(cfg.getEftarReader());
1590d40e9d0SAdam Hornáček        List<String> files = cfg.getResourceFileList();
1600d40e9d0SAdam Hornáček        if (!files.isEmpty()) {
16141351de3SChris Fraire            List<NullableNumLinesLOC> extras = null;
1620d40e9d0SAdam Hornáček            SearchHelper searchHelper = cfg.prepareInternalSearch();
1635c931ce8SChris Fraire            /*
1645c931ce8SChris Fraire             * N.b. searchHelper.destroy() is called via
1655c931ce8SChris Fraire             * WebappListener.requestDestroyed() on presence of the following
1665c931ce8SChris Fraire             * REQUEST_ATTR.
1675c931ce8SChris Fraire             */
1680d40e9d0SAdam Hornáček            request.setAttribute(SearchHelper.REQUEST_ATTR, searchHelper);
1695c931ce8SChris Fraire            if (project != null) {
170e393cb49SAdam Hornáček                searchHelper.prepareExec(project);
1715c931ce8SChris Fraire            } else {
1725c931ce8SChris Fraire                //noinspection Convert2Diamond
1735c931ce8SChris Fraire                searchHelper.prepareExec(new TreeSet<String>());
1745c931ce8SChris Fraire            }
1750d40e9d0SAdam Hornáček
1760d40e9d0SAdam Hornáček            if (searchHelper.searcher != null) {
1775c931ce8SChris Fraire                DirectoryExtraReader extraReader = new DirectoryExtraReader();
1787d004396SChris Fraire                String primePath = path;
1797d004396SChris Fraire                try {
1805c931ce8SChris Fraire                    primePath = searchHelper.getPrimeRelativePath(projectName, path);
1817d004396SChris Fraire                } catch (IOException | ForbiddenSymlinkException ex) {
1827d004396SChris Fraire                    LOGGER.log(Level.WARNING, String.format(
1837d004396SChris Fraire                            "Error getting prime relative for %s", path), ex);
1847d004396SChris Fraire                }
1857d004396SChris Fraire                extras = extraReader.search(searchHelper.searcher, primePath);
1860d40e9d0SAdam Hornáček            }
1870d40e9d0SAdam Hornáček
1880d40e9d0SAdam Hornáček            FileExtraZipper zipper = new FileExtraZipper();
189*7af88e20SVladimir Kotal            List<DirectoryEntry> entries = zipper.zip(resourceFile, files, extras);
1900d40e9d0SAdam Hornáček
191*7af88e20SVladimir Kotal            List<String> readMes = dl.extraListTo(Util.URIEncodePath(request.getContextPath()),
1920d40e9d0SAdam Hornáček                    resourceFile, out, path, entries);
1930d40e9d0SAdam Hornáček            File[] catfiles = cfg.findDataFiles(readMes);
1940d40e9d0SAdam Hornáček            for (int i=0; i < catfiles.length; i++) {
1950d40e9d0SAdam Hornáček                if (catfiles[i] == null) {
1960d40e9d0SAdam Hornáček                    continue;
1970d40e9d0SAdam Hornáček                }
1980d40e9d0SAdam Hornáček%>
1990d40e9d0SAdam Hornáček<%
20052dccac1SChris Fraire    String lcName = readMes.get(i).toLowerCase(Locale.ROOT);
2010d40e9d0SAdam Hornáček    if (lcName.endsWith(".md") || lcName.endsWith(".markdown")) {
2020d40e9d0SAdam Hornáček    %><div id="src<%=i%>" data-markdown>
2030d40e9d0SAdam Hornáček        <div class="markdown-heading">
2040d40e9d0SAdam Hornáček            <h3><%= readMes.get(i) %></h3>
2050d40e9d0SAdam Hornáček        </div>
2060d40e9d0SAdam Hornáček        <div class="markdown-content"
2070d40e9d0SAdam Hornáček             data-markdown-download="<%= request.getContextPath() + Prefix.DOWNLOAD_P + Util.URIEncodePath(cfg.getPath() + readMes.get(i)) %>">
2080d40e9d0SAdam Hornáček        </div>
2090d40e9d0SAdam Hornáček        <pre data-markdown-original><%
2100d40e9d0SAdam Hornáček            Util.dump(out, catfiles[i], catfiles[i].getName().endsWith(".gz"));
2110d40e9d0SAdam Hornáček        %></pre>
2120d40e9d0SAdam Hornáček    </div>
2130d40e9d0SAdam Hornáček<% } else { %>
2140d40e9d0SAdam Hornáček    <h3><%= readMes.get(i) %></h3>
2150d40e9d0SAdam Hornáček    <div id="src<%=i%>">
2160d40e9d0SAdam Hornáček        <pre><%
2170d40e9d0SAdam Hornáček            Util.dump(out, catfiles[i], catfiles[i].getName().endsWith(".gz"));
2180d40e9d0SAdam Hornáček        %></pre>
2190d40e9d0SAdam Hornáček    </div>
2200d40e9d0SAdam Hornáček<%
2210d40e9d0SAdam Hornáček    }
2220d40e9d0SAdam Hornáček
2230d40e9d0SAdam Hornáček            }
2240d40e9d0SAdam Hornáček        }
225a03922c4SAdam Hornáček    } else if (rev.length() != 0) {
226a03922c4SAdam Hornáček        // requesting a revision
22755774b8bSChris Fraire        File xrefFile;
2281532fde5SVladimir Kotal        if (cfg.isLatestRevision(rev) && (xrefFile = cfg.findDataFile()) != null) {
229a03922c4SAdam Hornáček            if (cfg.annotate()) {
2300d40e9d0SAdam Hornáček                // annotate
2311532fde5SVladimir Kotal                BufferedInputStream bin = new BufferedInputStream(new FileInputStream(resourceFile));
2320d40e9d0SAdam Hornáček                try {
23357eefa47SKryštof Tulinger                    AnalyzerFactory a = AnalyzerGuru.find(basename);
23457eefa47SKryštof Tulinger                    AbstractAnalyzer.Genre g = AnalyzerGuru.getGenre(a);
2350d40e9d0SAdam Hornáček                    if (g == null) {
2360d40e9d0SAdam Hornáček                        a = AnalyzerGuru.find(bin);
2370d40e9d0SAdam Hornáček                        g = AnalyzerGuru.getGenre(a);
2380d40e9d0SAdam Hornáček                    }
23957eefa47SKryštof Tulinger                    if (g == AbstractAnalyzer.Genre.IMAGE) {
2400d40e9d0SAdam Hornáček%>
2410d40e9d0SAdam Hornáček<div id="src">
2421c830032SChris Fraire    <img src="<%= rawPath %>" alt="Image from Source Repository"/>
2430d40e9d0SAdam Hornáček</div><%
24457eefa47SKryštof Tulinger                    } else if ( g == AbstractAnalyzer.Genre.HTML) {
245*7af88e20SVladimir Kotal                        /*
2460d40e9d0SAdam Hornáček                         * For backward compatibility, read the OpenGrok-produced
2470d40e9d0SAdam Hornáček                         * document using the system default charset.
2480d40e9d0SAdam Hornáček                         */
2490d40e9d0SAdam Hornáček                        r = new InputStreamReader(bin);
250e393cb49SAdam Hornáček                        // dumpXref() is also useful here for translating links.
251e393cb49SAdam Hornáček                        Util.dumpXref(out, r, request.getContextPath());
25257eefa47SKryštof Tulinger                    } else if (g == AbstractAnalyzer.Genre.PLAIN) {
2530d40e9d0SAdam Hornáček%>
2540d40e9d0SAdam Hornáček<div id="src" data-navigate-window-enabled="<%= navigateWindowEnabled %>">
2550d40e9d0SAdam Hornáček    <pre><%
2560d40e9d0SAdam Hornáček                        // We're generating xref for the latest revision, so we can
2570d40e9d0SAdam Hornáček                        // find the definitions in the index.
2580d40e9d0SAdam Hornáček                        Definitions defs = IndexDatabase.getDefinitions(resourceFile);
2590d40e9d0SAdam Hornáček                        Annotation annotation = cfg.getAnnotation();
2604c692fbfSVladimir Kotal                        // Data under source root is read with UTF-8 as a default.
2610d40e9d0SAdam Hornáček                        r = IOUtils.createBOMStrippedReader(bin,
2620d40e9d0SAdam Hornáček                            StandardCharsets.UTF_8.name());
263e393cb49SAdam Hornáček                        AnalyzerGuru.writeDumpedXref(request.getContextPath(), a,
264e393cb49SAdam Hornáček                                r, out, defs, annotation, project);
2650d40e9d0SAdam Hornáček    %></pre>
2660d40e9d0SAdam Hornáček</div><%
2670d40e9d0SAdam Hornáček                    } else {
2680d40e9d0SAdam Hornáček%>
2690d40e9d0SAdam HornáčekClick <a href="<%= rawPath %>">download <%= basename %></a><%
2700d40e9d0SAdam Hornáček                    }
2710d40e9d0SAdam Hornáček                } finally {
2720d40e9d0SAdam Hornáček                    if (r != null) {
273963a3f81SChris Fraire                        IOUtils.close(r);
274963a3f81SChris Fraire                        bin = null;
2750d40e9d0SAdam Hornáček                    }
2760d40e9d0SAdam Hornáček                    if (bin != null) {
277963a3f81SChris Fraire                        IOUtils.close(bin);
278963a3f81SChris Fraire                        bin = null;
2790d40e9d0SAdam Hornáček                    }
2800d40e9d0SAdam Hornáček                }
281a03922c4SAdam Hornáček
282a03922c4SAdam Hornáček            } else {
2830d40e9d0SAdam Hornáček%>
2840d40e9d0SAdam Hornáček<div id="src" data-navigate-window-enabled="<%= navigateWindowEnabled %>">
2850d40e9d0SAdam Hornáček    <pre><%
286e393cb49SAdam Hornáček                    boolean compressed = xrefFile.getName().endsWith(".gz");
287e393cb49SAdam Hornáček                    Util.dumpXref(out, xrefFile, compressed,
288e393cb49SAdam Hornáček                            request.getContextPath());
2890d40e9d0SAdam Hornáček    %></pre>
290*7af88e20SVladimir Kotal</div>
291*7af88e20SVladimir Kotal<%
2920d40e9d0SAdam Hornáček            }
2930d40e9d0SAdam Hornáček        } else {
2940d40e9d0SAdam Hornáček%>
295*7af88e20SVladimir Kotal<%@
296*7af88e20SVladimir Kotal
297*7af88e20SVladimir Kotalinclude file="xref.jspf"
298*7af88e20SVladimir Kotal
2990d40e9d0SAdam Hornáček%>
300*7af88e20SVladimir Kotal<%
3010d40e9d0SAdam Hornáček        }
3020d40e9d0SAdam Hornáček    } else {
3034c692fbfSVladimir Kotal        // Requesting cross referenced file with no known revision.
30455774b8bSChris Fraire        File xrefFile = cfg.findDataFile();
3050d40e9d0SAdam Hornáček        if (xrefFile != null) {
3060d40e9d0SAdam Hornáček%>
3070d40e9d0SAdam Hornáček<div id="src" data-navigate-window-enabled="<%= navigateWindowEnabled %>">
3080d40e9d0SAdam Hornáček    <pre><%
309e393cb49SAdam Hornáček            boolean compressed = xrefFile.getName().endsWith(".gz");
310e393cb49SAdam Hornáček            Util.dumpXref(out, xrefFile, compressed, request.getContextPath());
3110d40e9d0SAdam Hornáček    %></pre>
312*7af88e20SVladimir Kotal</div>
313*7af88e20SVladimir Kotal<%
31417c862aeSVladimir Kotal        } else {
315*7af88e20SVladimir Kotal            // Failed to get xref, generate on the fly.
31617c862aeSVladimir Kotal%>
317*7af88e20SVladimir Kotal<%@
318*7af88e20SVladimir Kotal
319*7af88e20SVladimir Kotalinclude file="xref.jspf"
320*7af88e20SVladimir Kotal
321*7af88e20SVladimir Kotal%>
322*7af88e20SVladimir Kotal<%
3230d40e9d0SAdam Hornáček        }
3240d40e9d0SAdam Hornáček    }
3250d40e9d0SAdam Hornáček}
3260d40e9d0SAdam Hornáček/* ---------------------- list.jsp end --------------------- */
3270d40e9d0SAdam Hornáček%><%@
3280d40e9d0SAdam Hornáček
3290d40e9d0SAdam Hornáčekinclude file="foot.jspf"
3300d40e9d0SAdam Hornáček
3310d40e9d0SAdam Hornáček%>
332