commit | author | age
|
f13c4c
|
1 |
/*
|
JM |
2 |
* Copyright 2011 gitblit.com.
|
|
3 |
*
|
|
4 |
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5 |
* you may not use this file except in compliance with the License.
|
|
6 |
* You may obtain a copy of the License at
|
|
7 |
*
|
|
8 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9 |
*
|
|
10 |
* Unless required by applicable law or agreed to in writing, software
|
|
11 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13 |
* See the License for the specific language governing permissions and
|
|
14 |
* limitations under the License.
|
|
15 |
*/
|
1f9dae
|
16 |
package com.gitblit.wicket.pages;
|
5fe7df
|
17 |
|
5e3521
|
18 |
import java.io.IOException;
|
JM |
19 |
import java.io.InputStream;
|
b0e164
|
20 |
import java.text.MessageFormat;
|
13a3f5
|
21 |
import java.util.ArrayList;
|
JM |
22 |
import java.util.Calendar;
|
|
23 |
import java.util.Collections;
|
|
24 |
import java.util.Date;
|
|
25 |
import java.util.HashSet;
|
f98825
|
26 |
import java.util.LinkedHashMap;
|
13a3f5
|
27 |
import java.util.List;
|
f98825
|
28 |
import java.util.Map;
|
9adf62
|
29 |
import java.util.ResourceBundle;
|
13a3f5
|
30 |
import java.util.Set;
|
bc10f9
|
31 |
import java.util.TimeZone;
|
13a3f5
|
32 |
import java.util.regex.Pattern;
|
bc10f9
|
33 |
|
cebf45
|
34 |
import javax.servlet.http.HttpServletRequest;
|
JM |
35 |
|
5e3521
|
36 |
import org.apache.commons.io.IOUtils;
|
3cc6e2
|
37 |
import org.apache.wicket.Application;
|
1078f8
|
38 |
import org.apache.wicket.Page;
|
5fe7df
|
39 |
import org.apache.wicket.PageParameters;
|
d97e52
|
40 |
import org.apache.wicket.RedirectToUrlException;
|
62cec2
|
41 |
import org.apache.wicket.markup.html.CSSPackageResource;
|
5fe7df
|
42 |
import org.apache.wicket.markup.html.basic.Label;
|
94750e
|
43 |
import org.apache.wicket.markup.html.link.ExternalLink;
|
c1c3c6
|
44 |
import org.apache.wicket.markup.html.panel.FeedbackPanel;
|
bae957
|
45 |
import org.apache.wicket.markup.html.resources.JavascriptResourceReference;
|
T |
46 |
import org.apache.wicket.markup.repeater.RepeatingView;
|
d97e52
|
47 |
import org.apache.wicket.protocol.http.RequestUtils;
|
a7db57
|
48 |
import org.apache.wicket.protocol.http.WebResponse;
|
cebf45
|
49 |
import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
|
2598bf
|
50 |
import org.apache.wicket.request.target.basic.RedirectRequestTarget;
|
a7db57
|
51 |
import org.apache.wicket.util.time.Duration;
|
JM |
52 |
import org.apache.wicket.util.time.Time;
|
5fe7df
|
53 |
import org.slf4j.Logger;
|
JM |
54 |
import org.slf4j.LoggerFactory;
|
|
55 |
|
cebf45
|
56 |
import com.gitblit.Constants;
|
b0e164
|
57 |
import com.gitblit.Constants.AccessPermission;
|
f98825
|
58 |
import com.gitblit.Constants.AccessRestrictionType;
|
092f0a
|
59 |
import com.gitblit.Constants.AuthorizationControl;
|
831469
|
60 |
import com.gitblit.Constants.FederationStrategy;
|
155bf7
|
61 |
import com.gitblit.Keys;
|
13a3f5
|
62 |
import com.gitblit.models.ProjectModel;
|
JM |
63 |
import com.gitblit.models.TeamModel;
|
85c2e6
|
64 |
import com.gitblit.models.UserModel;
|
13a3f5
|
65 |
import com.gitblit.utils.StringUtils;
|
9adf62
|
66 |
import com.gitblit.utils.TimeUtils;
|
a7db57
|
67 |
import com.gitblit.wicket.CacheControl;
|
6ef8d7
|
68 |
import com.gitblit.wicket.GitBlitWebApp;
|
1f9dae
|
69 |
import com.gitblit.wicket.GitBlitWebSession;
|
94750e
|
70 |
import com.gitblit.wicket.WicketUtils;
|
5fe7df
|
71 |
|
0f3cb2
|
72 |
public abstract class BasePage extends SessionPage {
|
5fe7df
|
73 |
|
e92cef
|
74 |
private transient Logger logger;
|
699e71
|
75 |
|
9adf62
|
76 |
private transient TimeUtils timeUtils;
|
5fe7df
|
77 |
|
JM |
78 |
public BasePage() {
|
|
79 |
super();
|
62cec2
|
80 |
customizeHeader();
|
5fe7df
|
81 |
}
|
JM |
82 |
|
|
83 |
public BasePage(PageParameters params) {
|
|
84 |
super(params);
|
62cec2
|
85 |
customizeHeader();
|
e92cef
|
86 |
}
|
JM |
87 |
|
|
88 |
protected Logger logger() {
|
|
89 |
if (logger == null) {
|
|
90 |
logger = LoggerFactory.getLogger(getClass());
|
|
91 |
}
|
|
92 |
return logger;
|
85c2e6
|
93 |
}
|
699e71
|
94 |
|
62cec2
|
95 |
private void customizeHeader() {
|
99d0d4
|
96 |
if (app().settings().getBoolean(Keys.web.useResponsiveLayout, true)) {
|
62cec2
|
97 |
add(CSSPackageResource.getHeaderContribution("bootstrap/css/bootstrap-responsive.css"));
|
JM |
98 |
}
|
5ec752
|
99 |
if (app().settings().getBoolean(Keys.web.hideHeader, false)) {
|
JM |
100 |
add(CSSPackageResource.getHeaderContribution("hideheader.css"));
|
|
101 |
}
|
62cec2
|
102 |
}
|
699e71
|
103 |
|
ff17f7
|
104 |
protected String getContextUrl() {
|
JM |
105 |
return getRequest().getRelativePathPrefixToContextRoot();
|
|
106 |
}
|
|
107 |
|
307910
|
108 |
protected String getCanonicalUrl() {
|
JM |
109 |
return getCanonicalUrl(getClass(), getPageParameters());
|
|
110 |
}
|
|
111 |
|
|
112 |
protected String getCanonicalUrl(Class<? extends BasePage> clazz, PageParameters params) {
|
|
113 |
String relativeUrl = urlFor(clazz, params).toString();
|
|
114 |
String canonicalUrl = RequestUtils.toAbsolutePath(relativeUrl);
|
|
115 |
return canonicalUrl;
|
2598bf
|
116 |
}
|
JM |
117 |
|
60bbdf
|
118 |
protected void redirectTo(Class<? extends BasePage> pageClass) {
|
JM |
119 |
redirectTo(pageClass, null);
|
2598bf
|
120 |
}
|
JM |
121 |
|
60bbdf
|
122 |
protected void redirectTo(Class<? extends BasePage> pageClass, PageParameters parameters) {
|
2598bf
|
123 |
String absoluteUrl = getCanonicalUrl(pageClass, parameters);
|
JM |
124 |
getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
|
307910
|
125 |
}
|
JM |
126 |
|
9adf62
|
127 |
protected String getLanguageCode() {
|
JM |
128 |
return GitBlitWebSession.get().getLocale().getLanguage();
|
|
129 |
}
|
699e71
|
130 |
|
55037b
|
131 |
protected String getCountryCode() {
|
JM |
132 |
return GitBlitWebSession.get().getLocale().getCountry().toLowerCase();
|
|
133 |
}
|
699e71
|
134 |
|
9adf62
|
135 |
protected TimeUtils getTimeUtils() {
|
JM |
136 |
if (timeUtils == null) {
|
699e71
|
137 |
ResourceBundle bundle;
|
9adf62
|
138 |
try {
|
JM |
139 |
bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", GitBlitWebSession.get().getLocale());
|
|
140 |
} catch (Throwable t) {
|
|
141 |
bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp");
|
|
142 |
}
|
9b26b7
|
143 |
timeUtils = new TimeUtils(bundle, getTimeZone());
|
9adf62
|
144 |
}
|
JM |
145 |
return timeUtils;
|
|
146 |
}
|
699e71
|
147 |
|
3cc6e2
|
148 |
@Override
|
JM |
149 |
protected void onBeforeRender() {
|
99d0d4
|
150 |
if (app().isDebugMode()) {
|
3cc6e2
|
151 |
// strip Wicket tags in debug mode for jQuery DOM traversal
|
JM |
152 |
Application.get().getMarkupSettings().setStripWicketTags(true);
|
|
153 |
}
|
|
154 |
super.onBeforeRender();
|
|
155 |
}
|
|
156 |
|
|
157 |
@Override
|
|
158 |
protected void onAfterRender() {
|
99d0d4
|
159 |
if (app().isDebugMode()) {
|
3cc6e2
|
160 |
// restore Wicket debug tags
|
JM |
161 |
Application.get().getMarkupSettings().setStripWicketTags(false);
|
|
162 |
}
|
|
163 |
super.onAfterRender();
|
a7db57
|
164 |
}
|
699e71
|
165 |
|
a7db57
|
166 |
@Override
|
JM |
167 |
protected void setHeaders(WebResponse response) {
|
307910
|
168 |
// set canonical link as http header for SEO (issue-304)
|
JM |
169 |
// https://support.google.com/webmasters/answer/139394?hl=en
|
99d0d4
|
170 |
response.setHeader("Link", MessageFormat.format("<{0}>; rel=\"canonical\"", getCanonicalUrl()));
|
JM |
171 |
int expires = app().settings().getInteger(Keys.web.pageCacheExpires, 0);
|
a7db57
|
172 |
if (expires > 0) {
|
JM |
173 |
// pages are personalized for the authenticated user so they must be
|
|
174 |
// marked private to prohibit proxy servers from caching them
|
|
175 |
response.setHeader("Cache-Control", "private, must-revalidate");
|
|
176 |
setLastModified();
|
|
177 |
} else {
|
|
178 |
// use default Wicket caching behavior
|
|
179 |
super.setHeaders(response);
|
|
180 |
}
|
71647a
|
181 |
|
JM |
182 |
// XRF vulnerability. issue-500 / ticket-166
|
|
183 |
response.setHeader("X-Frame-Options", "SAMEORIGIN");
|
a7db57
|
184 |
}
|
699e71
|
185 |
|
a7db57
|
186 |
/**
|
JM |
187 |
* Sets the last-modified header date, if appropriate, for this page. The
|
|
188 |
* date used is determined by the CacheControl annotation.
|
699e71
|
189 |
*
|
a7db57
|
190 |
*/
|
JM |
191 |
protected void setLastModified() {
|
|
192 |
if (getClass().isAnnotationPresent(CacheControl.class)) {
|
|
193 |
CacheControl cacheControl = getClass().getAnnotation(CacheControl.class);
|
|
194 |
switch (cacheControl.value()) {
|
|
195 |
case ACTIVITY:
|
99d0d4
|
196 |
setLastModified(app().getLastActivityDate());
|
a7db57
|
197 |
break;
|
JM |
198 |
case BOOT:
|
99d0d4
|
199 |
setLastModified(app().getBootDate());
|
a7db57
|
200 |
break;
|
JM |
201 |
case NONE:
|
|
202 |
break;
|
|
203 |
default:
|
e92cef
|
204 |
logger().warn(getClass().getSimpleName() + ": unhandled LastModified type " + cacheControl.value());
|
a7db57
|
205 |
break;
|
JM |
206 |
}
|
|
207 |
}
|
|
208 |
}
|
699e71
|
209 |
|
a7db57
|
210 |
/**
|
JM |
211 |
* Sets the last-modified header field and the expires field.
|
699e71
|
212 |
*
|
a7db57
|
213 |
* @param when
|
JM |
214 |
*/
|
|
215 |
protected final void setLastModified(Date when) {
|
|
216 |
if (when == null) {
|
|
217 |
return;
|
|
218 |
}
|
699e71
|
219 |
|
99d0d4
|
220 |
if (when.before(app().getBootDate())) {
|
a7db57
|
221 |
// last-modified can not be before the Gitblit boot date
|
JM |
222 |
// this helps ensure that pages are properly refreshed after a
|
|
223 |
// server config change
|
99d0d4
|
224 |
when = app().getBootDate();
|
a7db57
|
225 |
}
|
699e71
|
226 |
|
99d0d4
|
227 |
int expires = app().settings().getInteger(Keys.web.pageCacheExpires, 0);
|
a7db57
|
228 |
WebResponse response = (WebResponse) getResponse();
|
JM |
229 |
response.setLastModifiedTime(Time.valueOf(when));
|
|
230 |
response.setDateHeader("Expires", System.currentTimeMillis() + Duration.minutes(expires).getMilliseconds());
|
|
231 |
}
|
155bf7
|
232 |
|
81c90e
|
233 |
protected String getPageTitle(String repositoryName) {
|
99d0d4
|
234 |
String siteName = app().settings().getString(Keys.web.siteName, Constants.NAME);
|
9b26b7
|
235 |
if (StringUtils.isEmpty(siteName)) {
|
JM |
236 |
siteName = Constants.NAME;
|
|
237 |
}
|
cebf45
|
238 |
if (repositoryName != null && repositoryName.trim().length() > 0) {
|
81c90e
|
239 |
return repositoryName + " - " + siteName;
|
cebf45
|
240 |
} else {
|
81c90e
|
241 |
return siteName;
|
cebf45
|
242 |
}
|
81c90e
|
243 |
}
|
JM |
244 |
|
|
245 |
protected void setupPage(String repositoryName, String pageName) {
|
|
246 |
add(new Label("title", getPageTitle(repositoryName)));
|
9f92fb
|
247 |
getBottomScriptContainer();
|
99d0d4
|
248 |
String rootLinkUrl = app().settings().getString(Keys.web.rootLink, urlFor(GitBlitWebApp.get().getHomePage(), null).toString());
|
a0831d
|
249 |
ExternalLink rootLink = new ExternalLink("rootLink", rootLinkUrl);
|
99d0d4
|
250 |
WicketUtils.setHtmlTooltip(rootLink, app().settings().getString(Keys.web.siteName, Constants.NAME));
|
94750e
|
251 |
add(rootLink);
|
JM |
252 |
|
c1c3c6
|
253 |
// Feedback panel for info, warning, and non-fatal error messages
|
JM |
254 |
add(new FeedbackPanel("feedback"));
|
20165d
|
255 |
|
f6b200
|
256 |
add(new Label("gbVersion", "v" + Constants.getVersion()));
|
99d0d4
|
257 |
if (app().settings().getBoolean(Keys.web.aggressiveHeapManagement, false)) {
|
cebf45
|
258 |
System.gc();
|
JM |
259 |
}
|
|
260 |
}
|
155bf7
|
261 |
|
f98825
|
262 |
protected Map<AccessRestrictionType, String> getAccessRestrictions() {
|
JM |
263 |
Map<AccessRestrictionType, String> map = new LinkedHashMap<AccessRestrictionType, String>();
|
|
264 |
for (AccessRestrictionType type : AccessRestrictionType.values()) {
|
|
265 |
switch (type) {
|
|
266 |
case NONE:
|
|
267 |
map.put(type, getString("gb.notRestricted"));
|
|
268 |
break;
|
|
269 |
case PUSH:
|
|
270 |
map.put(type, getString("gb.pushRestricted"));
|
|
271 |
break;
|
|
272 |
case CLONE:
|
|
273 |
map.put(type, getString("gb.cloneRestricted"));
|
|
274 |
break;
|
|
275 |
case VIEW:
|
|
276 |
map.put(type, getString("gb.viewRestricted"));
|
|
277 |
break;
|
|
278 |
}
|
|
279 |
}
|
|
280 |
return map;
|
|
281 |
}
|
699e71
|
282 |
|
b0e164
|
283 |
protected Map<AccessPermission, String> getAccessPermissions() {
|
JM |
284 |
Map<AccessPermission, String> map = new LinkedHashMap<AccessPermission, String>();
|
|
285 |
for (AccessPermission type : AccessPermission.values()) {
|
|
286 |
switch (type) {
|
|
287 |
case NONE:
|
|
288 |
map.put(type, MessageFormat.format(getString("gb.noPermission"), type.code));
|
|
289 |
break;
|
2d48e2
|
290 |
case EXCLUDE:
|
JM |
291 |
map.put(type, MessageFormat.format(getString("gb.excludePermission"), type.code));
|
|
292 |
break;
|
b0e164
|
293 |
case VIEW:
|
JM |
294 |
map.put(type, MessageFormat.format(getString("gb.viewPermission"), type.code));
|
|
295 |
break;
|
|
296 |
case CLONE:
|
|
297 |
map.put(type, MessageFormat.format(getString("gb.clonePermission"), type.code));
|
|
298 |
break;
|
|
299 |
case PUSH:
|
|
300 |
map.put(type, MessageFormat.format(getString("gb.pushPermission"), type.code));
|
|
301 |
break;
|
|
302 |
case CREATE:
|
|
303 |
map.put(type, MessageFormat.format(getString("gb.createPermission"), type.code));
|
|
304 |
break;
|
|
305 |
case DELETE:
|
|
306 |
map.put(type, MessageFormat.format(getString("gb.deletePermission"), type.code));
|
|
307 |
break;
|
|
308 |
case REWIND:
|
|
309 |
map.put(type, MessageFormat.format(getString("gb.rewindPermission"), type.code));
|
|
310 |
break;
|
|
311 |
}
|
|
312 |
}
|
|
313 |
return map;
|
|
314 |
}
|
699e71
|
315 |
|
831469
|
316 |
protected Map<FederationStrategy, String> getFederationTypes() {
|
JM |
317 |
Map<FederationStrategy, String> map = new LinkedHashMap<FederationStrategy, String>();
|
|
318 |
for (FederationStrategy type : FederationStrategy.values()) {
|
|
319 |
switch (type) {
|
|
320 |
case EXCLUDE:
|
|
321 |
map.put(type, getString("gb.excludeFromFederation"));
|
|
322 |
break;
|
|
323 |
case FEDERATE_THIS:
|
|
324 |
map.put(type, getString("gb.federateThis"));
|
|
325 |
break;
|
|
326 |
case FEDERATE_ORIGIN:
|
|
327 |
map.put(type, getString("gb.federateOrigin"));
|
|
328 |
break;
|
|
329 |
}
|
|
330 |
}
|
|
331 |
return map;
|
|
332 |
}
|
699e71
|
333 |
|
092f0a
|
334 |
protected Map<AuthorizationControl, String> getAuthorizationControls() {
|
JM |
335 |
Map<AuthorizationControl, String> map = new LinkedHashMap<AuthorizationControl, String>();
|
|
336 |
for (AuthorizationControl type : AuthorizationControl.values()) {
|
|
337 |
switch (type) {
|
|
338 |
case AUTHENTICATED:
|
|
339 |
map.put(type, getString("gb.allowAuthenticatedDescription"));
|
|
340 |
break;
|
|
341 |
case NAMED:
|
|
342 |
map.put(type, getString("gb.allowNamedDescription"));
|
|
343 |
break;
|
|
344 |
}
|
|
345 |
}
|
|
346 |
return map;
|
|
347 |
}
|
f98825
|
348 |
|
bc10f9
|
349 |
protected TimeZone getTimeZone() {
|
99d0d4
|
350 |
return app().settings().getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get()
|
JM |
351 |
.getTimezone() : app().getTimezone();
|
bc10f9
|
352 |
}
|
155bf7
|
353 |
|
cebf45
|
354 |
protected String getServerName() {
|
JM |
355 |
ServletWebRequest servletWebRequest = (ServletWebRequest) getRequest();
|
|
356 |
HttpServletRequest req = servletWebRequest.getHttpServletRequest();
|
|
357 |
return req.getServerName();
|
|
358 |
}
|
699e71
|
359 |
|
13a3f5
|
360 |
protected List<ProjectModel> getProjectModels() {
|
JM |
361 |
final UserModel user = GitBlitWebSession.get().getUser();
|
99d0d4
|
362 |
List<ProjectModel> projects = app().projects().getProjectModels(user, true);
|
13a3f5
|
363 |
return projects;
|
JM |
364 |
}
|
699e71
|
365 |
|
13a3f5
|
366 |
protected List<ProjectModel> getProjects(PageParameters params) {
|
JM |
367 |
if (params == null) {
|
|
368 |
return getProjectModels();
|
|
369 |
}
|
|
370 |
|
|
371 |
boolean hasParameter = false;
|
|
372 |
String regex = WicketUtils.getRegEx(params);
|
|
373 |
String team = WicketUtils.getTeam(params);
|
|
374 |
int daysBack = params.getInt("db", 0);
|
99d0d4
|
375 |
int maxDaysBack = app().settings().getInteger(Keys.web.activityDurationMaximum, 30);
|
13a3f5
|
376 |
|
JM |
377 |
List<ProjectModel> availableModels = getProjectModels();
|
|
378 |
Set<ProjectModel> models = new HashSet<ProjectModel>();
|
|
379 |
|
|
380 |
if (!StringUtils.isEmpty(regex)) {
|
|
381 |
// filter the projects by the regex
|
|
382 |
hasParameter = true;
|
|
383 |
Pattern pattern = Pattern.compile(regex);
|
|
384 |
for (ProjectModel model : availableModels) {
|
|
385 |
if (pattern.matcher(model.name).find()) {
|
|
386 |
models.add(model);
|
|
387 |
}
|
|
388 |
}
|
|
389 |
}
|
|
390 |
|
|
391 |
if (!StringUtils.isEmpty(team)) {
|
|
392 |
// filter the projects by the specified teams
|
|
393 |
hasParameter = true;
|
|
394 |
List<String> teams = StringUtils.getStringsFromValue(team, ",");
|
|
395 |
|
|
396 |
// need TeamModels first
|
|
397 |
List<TeamModel> teamModels = new ArrayList<TeamModel>();
|
|
398 |
for (String name : teams) {
|
99d0d4
|
399 |
TeamModel teamModel = app().users().getTeamModel(name);
|
13a3f5
|
400 |
if (teamModel != null) {
|
JM |
401 |
teamModels.add(teamModel);
|
|
402 |
}
|
|
403 |
}
|
|
404 |
|
|
405 |
// brute-force our way through finding the matching models
|
|
406 |
for (ProjectModel projectModel : availableModels) {
|
|
407 |
for (String repositoryName : projectModel.repositories) {
|
|
408 |
for (TeamModel teamModel : teamModels) {
|
20714a
|
409 |
if (teamModel.hasRepositoryPermission(repositoryName)) {
|
13a3f5
|
410 |
models.add(projectModel);
|
JM |
411 |
}
|
|
412 |
}
|
|
413 |
}
|
|
414 |
}
|
|
415 |
}
|
|
416 |
|
|
417 |
if (!hasParameter) {
|
|
418 |
models.addAll(availableModels);
|
|
419 |
}
|
|
420 |
|
|
421 |
// time-filter the list
|
|
422 |
if (daysBack > 0) {
|
da7151
|
423 |
if (maxDaysBack > 0 && daysBack > maxDaysBack) {
|
OL |
424 |
daysBack = maxDaysBack;
|
|
425 |
}
|
13a3f5
|
426 |
Calendar cal = Calendar.getInstance();
|
JM |
427 |
cal.set(Calendar.HOUR_OF_DAY, 0);
|
|
428 |
cal.set(Calendar.MINUTE, 0);
|
|
429 |
cal.set(Calendar.SECOND, 0);
|
|
430 |
cal.set(Calendar.MILLISECOND, 0);
|
|
431 |
cal.add(Calendar.DATE, -1 * daysBack);
|
|
432 |
Date threshold = cal.getTime();
|
|
433 |
Set<ProjectModel> timeFiltered = new HashSet<ProjectModel>();
|
|
434 |
for (ProjectModel model : models) {
|
|
435 |
if (model.lastChange.after(threshold)) {
|
|
436 |
timeFiltered.add(model);
|
|
437 |
}
|
|
438 |
}
|
|
439 |
models = timeFiltered;
|
|
440 |
}
|
|
441 |
|
|
442 |
List<ProjectModel> list = new ArrayList<ProjectModel>(models);
|
|
443 |
Collections.sort(list);
|
|
444 |
return list;
|
|
445 |
}
|
85c2e6
|
446 |
|
5450d0
|
447 |
public void warn(String message, Throwable t) {
|
e92cef
|
448 |
logger().warn(message, t);
|
5450d0
|
449 |
}
|
699e71
|
450 |
|
bc9d4a
|
451 |
public void error(String message, boolean redirect) {
|
1078f8
|
452 |
error(message, null, redirect ? getApplication().getHomePage() : null);
|
bc9d4a
|
453 |
}
|
JM |
454 |
|
|
455 |
public void error(String message, Throwable t, boolean redirect) {
|
1078f8
|
456 |
error(message, t, getApplication().getHomePage());
|
JM |
457 |
}
|
699e71
|
458 |
|
1078f8
|
459 |
public void error(String message, Throwable t, Class<? extends Page> toPage) {
|
JM |
460 |
error(message, t, toPage, null);
|
|
461 |
}
|
699e71
|
462 |
|
1078f8
|
463 |
public void error(String message, Throwable t, Class<? extends Page> toPage, PageParameters params) {
|
JM |
464 |
if (t == null) {
|
e92cef
|
465 |
logger().error(message + " for " + GitBlitWebSession.get().getUsername());
|
1078f8
|
466 |
} else {
|
e92cef
|
467 |
logger().error(message + " for " + GitBlitWebSession.get().getUsername(), t);
|
1078f8
|
468 |
}
|
JM |
469 |
if (toPage != null) {
|
bc9d4a
|
470 |
GitBlitWebSession.get().cacheErrorMessage(message);
|
1078f8
|
471 |
String relativeUrl = urlFor(toPage, params).toString();
|
JM |
472 |
String absoluteUrl = RequestUtils.toAbsolutePath(relativeUrl);
|
|
473 |
throw new RedirectToUrlException(absoluteUrl);
|
bc9d4a
|
474 |
} else {
|
JM |
475 |
super.error(message);
|
|
476 |
}
|
5fe7df
|
477 |
}
|
85c2e6
|
478 |
|
JM |
479 |
public void authenticationError(String message) {
|
e92cef
|
480 |
logger().error(getRequest().getURL() + " for " + GitBlitWebSession.get().getUsername());
|
d97e52
|
481 |
if (!GitBlitWebSession.get().isLoggedIn()) {
|
JM |
482 |
// cache the request if we have not authenticated.
|
|
483 |
// the request will continue after authentication.
|
|
484 |
GitBlitWebSession.get().cacheRequest(getClass());
|
85c2e6
|
485 |
}
|
d97e52
|
486 |
error(message, true);
|
20165d
|
487 |
}
|
5e3521
|
488 |
|
JM |
489 |
protected String readResource(String resource) {
|
|
490 |
StringBuilder sb = new StringBuilder();
|
|
491 |
InputStream is = null;
|
|
492 |
try {
|
|
493 |
is = getClass().getResourceAsStream(resource);
|
|
494 |
List<String> lines = IOUtils.readLines(is);
|
|
495 |
for (String line : lines) {
|
|
496 |
sb.append(line).append('\n');
|
|
497 |
}
|
|
498 |
} catch (IOException e) {
|
|
499 |
|
|
500 |
} finally {
|
|
501 |
if (is != null) {
|
|
502 |
try {
|
|
503 |
is.close();
|
|
504 |
} catch (IOException e) {
|
|
505 |
}
|
|
506 |
}
|
|
507 |
}
|
|
508 |
return sb.toString();
|
|
509 |
}
|
2598bf
|
510 |
|
9f92fb
|
511 |
private RepeatingView getBottomScriptContainer() {
|
JM |
512 |
RepeatingView bottomScriptContainer = (RepeatingView) get("bottomScripts");
|
|
513 |
if (bottomScriptContainer == null) {
|
|
514 |
bottomScriptContainer = new RepeatingView("bottomScripts");
|
|
515 |
bottomScriptContainer.setRenderBodyOnly(true);
|
|
516 |
add(bottomScriptContainer);
|
|
517 |
}
|
|
518 |
return bottomScriptContainer;
|
|
519 |
}
|
|
520 |
|
bae957
|
521 |
/**
|
T |
522 |
* Adds a HTML script element loading the javascript designated by the given path.
|
|
523 |
*
|
|
524 |
* @param scriptPath
|
b95f47
|
525 |
* page-relative path to the Javascript resource; normally starts with "scripts/"
|
bae957
|
526 |
*/
|
T |
527 |
protected void addBottomScript(String scriptPath) {
|
9f92fb
|
528 |
RepeatingView bottomScripts = getBottomScriptContainer();
|
JM |
529 |
Label script = new Label(bottomScripts.newChildId(), "<script type='text/javascript' src='"
|
|
530 |
+ urlFor(new JavascriptResourceReference(this.getClass(), scriptPath)) + "'></script>\n");
|
|
531 |
bottomScripts.add(script.setEscapeModelStrings(false).setRenderBodyOnly(true));
|
bae957
|
532 |
}
|
T |
533 |
|
|
534 |
/**
|
|
535 |
* Adds a HTML script element containing the given code.
|
|
536 |
*
|
|
537 |
* @param code
|
|
538 |
* inline script code
|
|
539 |
*/
|
|
540 |
protected void addBottomScriptInline(String code) {
|
9f92fb
|
541 |
RepeatingView bottomScripts = getBottomScriptContainer();
|
JM |
542 |
Label script = new Label(bottomScripts.newChildId(),
|
|
543 |
"<script type='text/javascript'>/*<![CDATA[*/\n" + code + "\n//]]>\n</script>\n");
|
|
544 |
bottomScripts.add(script.setEscapeModelStrings(false).setRenderBodyOnly(true));
|
bae957
|
545 |
}
|
T |
546 |
|
5fe7df
|
547 |
}
|