|
41 | 41 | import java.util.Comparator;
|
42 | 42 | import java.util.EnumSet;
|
43 | 43 | import java.util.List;
|
| 44 | +import java.util.Objects; |
44 | 45 | import java.util.Set;
|
45 | 46 | import java.util.SortedSet;
|
46 | 47 | import java.util.TreeSet;
|
|
51 | 52 | import javax.servlet.ServletRequest;
|
52 | 53 | import javax.servlet.http.Cookie;
|
53 | 54 | import javax.servlet.http.HttpServletRequest;
|
54 |
| -import org.suigeneris.jrcs.diff.Diff; |
55 |
| -import org.suigeneris.jrcs.diff.DifferentiationFailedException; |
| 55 | +import javax.servlet.http.HttpServletResponse; |
| 56 | +import javax.ws.rs.core.HttpHeaders; |
| 57 | +import org.opengrok.indexer.Info; |
56 | 58 | import org.opengrok.indexer.analysis.AnalyzerGuru;
|
57 | 59 | import org.opengrok.indexer.analysis.ExpandTabsReader;
|
58 | 60 | import org.opengrok.indexer.analysis.FileAnalyzer.Genre;
|
|
70 | 72 | import org.opengrok.indexer.search.QueryBuilder;
|
71 | 73 | import org.opengrok.indexer.util.IOUtils;
|
72 | 74 | import org.opengrok.indexer.web.messages.MessagesContainer.AcceptedMessage;
|
| 75 | +import org.suigeneris.jrcs.diff.Diff; |
| 76 | +import org.suigeneris.jrcs.diff.DifferentiationFailedException; |
73 | 77 |
|
74 | 78 | /**
|
75 | 79 | * A simple container to lazy initialize common vars wrt. a single request. It
|
@@ -1619,4 +1623,76 @@ public void checkSourceRootExistence() throws IOException {
|
1619 | 1623 | throw new IOException(String.format("Source root path \"%s\" is not readable", sourceRootPathFile.getAbsolutePath()));
|
1620 | 1624 | }
|
1621 | 1625 | }
|
| 1626 | + |
| 1627 | + /** |
| 1628 | + * Get all project related messages. These include |
| 1629 | + * <ol> |
| 1630 | + * <li>Main messages</li> |
| 1631 | + * <li>Messages with tag = project name</li> |
| 1632 | + * <li>Messages with tag = project's groups names</li> |
| 1633 | + * </ol> |
| 1634 | + * |
| 1635 | + * @return the sorted set of messages according to the accept time |
| 1636 | + * @see org.opengrok.indexer.web.messages.MessagesContainer#MESSAGES_MAIN_PAGE_TAG |
| 1637 | + */ |
| 1638 | + private SortedSet<AcceptedMessage> getProjectMessages() { |
| 1639 | + SortedSet<AcceptedMessage> messages = getMessages(); |
| 1640 | + |
| 1641 | + if (getProject() != null) { |
| 1642 | + messages.addAll(getMessages(getProject().getName())); |
| 1643 | + getProject().getGroups().forEach(group -> { |
| 1644 | + messages.addAll(getMessages(group.getName())); |
| 1645 | + }); |
| 1646 | + } |
| 1647 | + |
| 1648 | + return messages; |
| 1649 | + } |
| 1650 | + |
| 1651 | + /** |
| 1652 | + * Decide if this resource has been modified since the header value in the request. |
| 1653 | + * <p> |
| 1654 | + * The resource is modified since the weak ETag value in the request, the ETag is |
| 1655 | + * computed using: |
| 1656 | + * <ul> |
| 1657 | + * <li>the source file modification</li> |
| 1658 | + * <li>project messages</li> |
| 1659 | + * <li>last timestamp for index</li> |
| 1660 | + * <li>OpenGrok current deployed version</li> |
| 1661 | + * </ul> |
| 1662 | + * <p> |
| 1663 | + * <p> |
| 1664 | + * If the resource was modified, appropriate headers in the response are filled. |
| 1665 | + * |
| 1666 | + * @param request the http request containing the headers |
| 1667 | + * @param response the http response for setting the headers |
| 1668 | + * @return true if resource was not modified; false otherwise |
| 1669 | + * @see <a href="https://tools.ietf.org/html/rfc7232#section-2.3">HTTP ETag</a> |
| 1670 | + * @see <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html">HTTP Caching</a> |
| 1671 | + */ |
| 1672 | + public boolean isNotModified(HttpServletRequest request, HttpServletResponse response) { |
| 1673 | + String currentEtag = String.format("W/\"%s\"", |
| 1674 | + Objects.hash( |
| 1675 | + // last modified time as UTC timestamp in millis |
| 1676 | + getLastModified(), |
| 1677 | + // all project related messages which changes the view |
| 1678 | + getProjectMessages(), |
| 1679 | + // last timestamp value |
| 1680 | + getEnv().getDateForLastIndexRun().getTime(), |
| 1681 | + // OpenGrok version has changed since the last time |
| 1682 | + Info.getVersion() |
| 1683 | + ) |
| 1684 | + ); |
| 1685 | + |
| 1686 | + String headerEtag = request.getHeader(HttpHeaders.IF_NONE_MATCH); |
| 1687 | + |
| 1688 | + if (headerEtag != null && headerEtag.equals(currentEtag)) { |
| 1689 | + // weak ETag has not changed, return 304 NOT MODIFIED |
| 1690 | + response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); |
| 1691 | + return true; |
| 1692 | + } |
| 1693 | + |
| 1694 | + // return 200 OK |
| 1695 | + response.setHeader(HttpHeaders.ETAG, currentEtag); |
| 1696 | + return false; |
| 1697 | + } |
1622 | 1698 | }
|
0 commit comments