From f76fee63ed9cb3a30d3c0c092d860b1cb93a481b Mon Sep 17 00:00:00 2001 From: Gerard Smyth <gerard.smyth@gmail.com> Date: Thu, 08 May 2014 13:09:30 -0400 Subject: [PATCH] Updated the SyndicationServlet to provide an additional option to return details of the tags in the repository instead of the commits. This uses a new 'ot' request parameter to indicate the object type of the content to return, which can be ither TAG or COMMIT. If this is not provided, then COMMIT is assumed to maintain backwards compatability. If tags are returned, then the paging parameters, 'l' and 'pg' are still supported, but searching options are currently ignored. --- src/main/java/com/gitblit/wicket/pages/BasePage.java | 232 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 182 insertions(+), 50 deletions(-) diff --git a/src/main/java/com/gitblit/wicket/pages/BasePage.java b/src/main/java/com/gitblit/wicket/pages/BasePage.java index c819c78..4971039 100644 --- a/src/main/java/com/gitblit/wicket/pages/BasePage.java +++ b/src/main/java/com/gitblit/wicket/pages/BasePage.java @@ -15,6 +15,8 @@ */ package com.gitblit.wicket.pages; +import java.io.IOException; +import java.io.InputStream; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Calendar; @@ -31,16 +33,20 @@ import javax.servlet.http.HttpServletRequest; +import org.apache.commons.io.IOUtils; import org.apache.wicket.Application; +import org.apache.wicket.Page; import org.apache.wicket.PageParameters; import org.apache.wicket.RedirectToUrlException; -import org.apache.wicket.RestartResponseException; import org.apache.wicket.markup.html.CSSPackageResource; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.link.ExternalLink; import org.apache.wicket.markup.html.panel.FeedbackPanel; import org.apache.wicket.protocol.http.RequestUtils; +import org.apache.wicket.protocol.http.WebResponse; import org.apache.wicket.protocol.http.servlet.ServletWebRequest; +import org.apache.wicket.util.time.Duration; +import org.apache.wicket.util.time.Time; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,65 +55,87 @@ import com.gitblit.Constants.AccessRestrictionType; import com.gitblit.Constants.AuthorizationControl; import com.gitblit.Constants.FederationStrategy; -import com.gitblit.GitBlit; import com.gitblit.Keys; import com.gitblit.models.ProjectModel; import com.gitblit.models.TeamModel; import com.gitblit.models.UserModel; import com.gitblit.utils.StringUtils; import com.gitblit.utils.TimeUtils; +import com.gitblit.wicket.CacheControl; import com.gitblit.wicket.GitBlitWebApp; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; public abstract class BasePage extends SessionPage { - private final Logger logger; - + private transient Logger logger; + private transient TimeUtils timeUtils; public BasePage() { super(); - logger = LoggerFactory.getLogger(getClass()); customizeHeader(); } public BasePage(PageParameters params) { super(params); - logger = LoggerFactory.getLogger(getClass()); customizeHeader(); } - + + protected Logger logger() { + if (logger == null) { + logger = LoggerFactory.getLogger(getClass()); + } + return logger; + } + private void customizeHeader() { - if (GitBlit.getBoolean(Keys.web.useResponsiveLayout, true)) { + if (app().settings().getBoolean(Keys.web.useResponsiveLayout, true)) { add(CSSPackageResource.getHeaderContribution("bootstrap/css/bootstrap-responsive.css")); } + if (app().settings().getBoolean(Keys.web.hideHeader, false)) { + add(CSSPackageResource.getHeaderContribution("hideheader.css")); + } } - + + protected String getContextUrl() { + return getRequest().getRelativePathPrefixToContextRoot(); + } + + protected String getCanonicalUrl() { + return getCanonicalUrl(getClass(), getPageParameters()); + } + + protected String getCanonicalUrl(Class<? extends BasePage> clazz, PageParameters params) { + String relativeUrl = urlFor(clazz, params).toString(); + String canonicalUrl = RequestUtils.toAbsolutePath(relativeUrl); + return canonicalUrl; + } + protected String getLanguageCode() { return GitBlitWebSession.get().getLocale().getLanguage(); } - + protected String getCountryCode() { return GitBlitWebSession.get().getLocale().getCountry().toLowerCase(); } - + protected TimeUtils getTimeUtils() { if (timeUtils == null) { - ResourceBundle bundle; + ResourceBundle bundle; try { bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", GitBlitWebSession.get().getLocale()); } catch (Throwable t) { bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp"); } - timeUtils = new TimeUtils(bundle); + timeUtils = new TimeUtils(bundle, getTimeZone()); } return timeUtils; } - + @Override protected void onBeforeRender() { - if (GitBlit.isDebugMode()) { + if (app().isDebugMode()) { // strip Wicket tags in debug mode for jQuery DOM traversal Application.get().getMarkupSettings().setStripWicketTags(true); } @@ -116,30 +144,102 @@ @Override protected void onAfterRender() { - if (GitBlit.isDebugMode()) { + if (app().isDebugMode()) { // restore Wicket debug tags Application.get().getMarkupSettings().setStripWicketTags(false); } super.onAfterRender(); - } + } - protected void setupPage(String repositoryName, String pageName) { - String siteName = GitBlit.getString(Keys.web.siteName, Constants.NAME); - if (repositoryName != null && repositoryName.trim().length() > 0) { - add(new Label("title", repositoryName + " - " + siteName)); + @Override + protected void setHeaders(WebResponse response) { + // set canonical link as http header for SEO (issue-304) + // https://support.google.com/webmasters/answer/139394?hl=en + response.setHeader("Link", MessageFormat.format("<{0}>; rel=\"canonical\"", getCanonicalUrl())); + int expires = app().settings().getInteger(Keys.web.pageCacheExpires, 0); + if (expires > 0) { + // pages are personalized for the authenticated user so they must be + // marked private to prohibit proxy servers from caching them + response.setHeader("Cache-Control", "private, must-revalidate"); + setLastModified(); } else { - add(new Label("title", siteName)); + // use default Wicket caching behavior + super.setHeaders(response); + } + } + + /** + * Sets the last-modified header date, if appropriate, for this page. The + * date used is determined by the CacheControl annotation. + * + */ + protected void setLastModified() { + if (getClass().isAnnotationPresent(CacheControl.class)) { + CacheControl cacheControl = getClass().getAnnotation(CacheControl.class); + switch (cacheControl.value()) { + case ACTIVITY: + setLastModified(app().getLastActivityDate()); + break; + case BOOT: + setLastModified(app().getBootDate()); + break; + case NONE: + break; + default: + logger().warn(getClass().getSimpleName() + ": unhandled LastModified type " + cacheControl.value()); + break; + } + } + } + + /** + * Sets the last-modified header field and the expires field. + * + * @param when + */ + protected final void setLastModified(Date when) { + if (when == null) { + return; } - ExternalLink rootLink = new ExternalLink("rootLink", urlFor(GitBlitWebApp.HOME_PAGE_CLASS, null).toString()); - WicketUtils.setHtmlTooltip(rootLink, GitBlit.getString(Keys.web.siteName, Constants.NAME)); + if (when.before(app().getBootDate())) { + // last-modified can not be before the Gitblit boot date + // this helps ensure that pages are properly refreshed after a + // server config change + when = app().getBootDate(); + } + + int expires = app().settings().getInteger(Keys.web.pageCacheExpires, 0); + WebResponse response = (WebResponse) getResponse(); + response.setLastModifiedTime(Time.valueOf(when)); + response.setDateHeader("Expires", System.currentTimeMillis() + Duration.minutes(expires).getMilliseconds()); + } + + protected String getPageTitle(String repositoryName) { + String siteName = app().settings().getString(Keys.web.siteName, Constants.NAME); + if (StringUtils.isEmpty(siteName)) { + siteName = Constants.NAME; + } + if (repositoryName != null && repositoryName.trim().length() > 0) { + return repositoryName + " - " + siteName; + } else { + return siteName; + } + } + + protected void setupPage(String repositoryName, String pageName) { + add(new Label("title", getPageTitle(repositoryName))); + + String rootLinkUrl = app().settings().getString(Keys.web.rootLink, urlFor(GitBlitWebApp.get().getHomePage(), null).toString()); + ExternalLink rootLink = new ExternalLink("rootLink", rootLinkUrl); + WicketUtils.setHtmlTooltip(rootLink, app().settings().getString(Keys.web.siteName, Constants.NAME)); add(rootLink); // Feedback panel for info, warning, and non-fatal error messages add(new FeedbackPanel("feedback")); add(new Label("gbVersion", "v" + Constants.getVersion())); - if (GitBlit.getBoolean(Keys.web.aggressiveHeapManagement, false)) { + if (app().settings().getBoolean(Keys.web.aggressiveHeapManagement, false)) { System.gc(); } } @@ -164,7 +264,7 @@ } return map; } - + protected Map<AccessPermission, String> getAccessPermissions() { Map<AccessPermission, String> map = new LinkedHashMap<AccessPermission, String>(); for (AccessPermission type : AccessPermission.values()) { @@ -197,7 +297,7 @@ } return map; } - + protected Map<FederationStrategy, String> getFederationTypes() { Map<FederationStrategy, String> map = new LinkedHashMap<FederationStrategy, String>(); for (FederationStrategy type : FederationStrategy.values()) { @@ -215,7 +315,7 @@ } return map; } - + protected Map<AuthorizationControl, String> getAuthorizationControls() { Map<AuthorizationControl, String> map = new LinkedHashMap<AuthorizationControl, String>(); for (AuthorizationControl type : AuthorizationControl.values()) { @@ -232,8 +332,8 @@ } protected TimeZone getTimeZone() { - return GitBlit.getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get() - .getTimezone() : GitBlit.getTimezone(); + return app().settings().getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get() + .getTimezone() : app().getTimezone(); } protected String getServerName() { @@ -241,13 +341,13 @@ HttpServletRequest req = servletWebRequest.getHttpServletRequest(); return req.getServerName(); } - + protected List<ProjectModel> getProjectModels() { final UserModel user = GitBlitWebSession.get().getUser(); - List<ProjectModel> projects = GitBlit.self().getProjectModels(user, true); + List<ProjectModel> projects = app().projects().getProjectModels(user, true); return projects; } - + protected List<ProjectModel> getProjects(PageParameters params) { if (params == null) { return getProjectModels(); @@ -257,6 +357,7 @@ String regex = WicketUtils.getRegEx(params); String team = WicketUtils.getTeam(params); int daysBack = params.getInt("db", 0); + int maxDaysBack = app().settings().getInteger(Keys.web.activityDurationMaximum, 30); List<ProjectModel> availableModels = getProjectModels(); Set<ProjectModel> models = new HashSet<ProjectModel>(); @@ -280,7 +381,7 @@ // need TeamModels first List<TeamModel> teamModels = new ArrayList<TeamModel>(); for (String name : teams) { - TeamModel teamModel = GitBlit.self().getTeamModel(name); + TeamModel teamModel = app().users().getTeamModel(name); if (teamModel != null) { teamModels.add(teamModel); } @@ -304,6 +405,9 @@ // time-filter the list if (daysBack > 0) { + if (maxDaysBack > 0 && daysBack > maxDaysBack) { + daysBack = maxDaysBack; + } Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); @@ -326,14 +430,30 @@ } public void warn(String message, Throwable t) { - logger.warn(message, t); + logger().warn(message, t); } - + public void error(String message, boolean redirect) { - logger.error(message + " for " + GitBlitWebSession.get().getUsername()); - if (redirect) { + error(message, null, redirect ? getApplication().getHomePage() : null); + } + + public void error(String message, Throwable t, boolean redirect) { + error(message, t, getApplication().getHomePage()); + } + + public void error(String message, Throwable t, Class<? extends Page> toPage) { + error(message, t, toPage, null); + } + + public void error(String message, Throwable t, Class<? extends Page> toPage, PageParameters params) { + if (t == null) { + logger().error(message + " for " + GitBlitWebSession.get().getUsername()); + } else { + logger().error(message + " for " + GitBlitWebSession.get().getUsername(), t); + } + if (toPage != null) { GitBlitWebSession.get().cacheErrorMessage(message); - String relativeUrl = urlFor(RepositoriesPage.class, null).toString(); + String relativeUrl = urlFor(toPage, params).toString(); String absoluteUrl = RequestUtils.toAbsolutePath(relativeUrl); throw new RedirectToUrlException(absoluteUrl); } else { @@ -341,18 +461,8 @@ } } - public void error(String message, Throwable t, boolean redirect) { - logger.error(message, t); - if (redirect) { - GitBlitWebSession.get().cacheErrorMessage(message); - throw new RestartResponseException(getApplication().getHomePage()); - } else { - super.error(message); - } - } - public void authenticationError(String message) { - logger.error(getRequest().getURL() + " for " + GitBlitWebSession.get().getUsername()); + logger().error(getRequest().getURL() + " for " + GitBlitWebSession.get().getUsername()); if (!GitBlitWebSession.get().isLoggedIn()) { // cache the request if we have not authenticated. // the request will continue after authentication. @@ -360,4 +470,26 @@ } error(message, true); } + + protected String readResource(String resource) { + StringBuilder sb = new StringBuilder(); + InputStream is = null; + try { + is = getClass().getResourceAsStream(resource); + List<String> lines = IOUtils.readLines(is); + for (String line : lines) { + sb.append(line).append('\n'); + } + } catch (IOException e) { + + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + } + } + } + return sb.toString(); + } } -- Gitblit v1.9.1