You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

GitblitManager.java 37KB

Ticket tracker with patchset contributions A basic issue tracker styled as a hybrid of GitHub and BitBucket issues. You may attach commits to an existing ticket or you can push a single commit to create a *proposal* ticket. Tickets keep track of patchsets (one or more commits) and allow patchset rewriting (rebase, amend, squash) by detecing the non-fast-forward update and assigning a new patchset number to the new commits. Ticket tracker -------------- The ticket tracker stores tickets as an append-only journal of changes. The journals are deserialized and a ticket is built by applying the journal entries. Tickets are indexed using Apache Lucene and all queries and searches are executed against this Lucene index. There is one trade-off to this persistence design: user attributions are non-relational. What does that mean? Each journal entry stores the username of the author. If the username changes in the user service, the journal entry will not reflect that change because the values are hard-coded. Here are a few reasons/justifications for this design choice: 1. commit identifications (author, committer, tagger) are non-relational 2. maintains the KISS principle 3. your favorite text editor can still be your administration tool Persistence Choices ------------------- **FileTicketService**: stores journals on the filesystem **BranchTicketService**: stores journals on an orphan branch **RedisTicketService**: stores journals in a Redis key-value datastore It should be relatively straight-forward to develop other backends (MongoDB, etc) as long as the journal design is preserved. Pushing Commits --------------- Each push to a ticket is identified as a patchset revision. A patchset revision may add commits to the patchset (fast-forward) OR a patchset revision may rewrite history (rebase, squash, rebase+squash, or amend). Patchset authors should not be afraid to polish, revise, and rewrite their code before merging into the proposed branch. Gitblit will create one ref for each patchset. These refs are updated for fast-forward pushes or created for rewrites. They are formatted as `refs/tickets/{shard}/{id}/{patchset}`. The *shard* is the last two digits of the id. If the id < 10, prefix a 0. The *shard* is always two digits long. The shard's purpose is to ensure Gitblit doesn't exceed any filesystem directory limits for file creation. **Creating a Proposal Ticket** You may create a new change proposal ticket just by pushing a **single commit** to `refs/for/{branch}` where branch is the proposed integration branch OR `refs/for/new` or `refs/for/default` which both will use the default repository branch. git push origin HEAD:refs/for/new **Updating a Patchset** The safe way to update an existing patchset is to push to the patchset ref. git push origin HEAD:refs/heads/ticket/{id} This ensures you do not accidentally create a new patchset in the event that the patchset was updated after you last pulled. The not-so-safe way to update an existing patchset is to push using the magic ref. git push origin HEAD:refs/for/{id} This push ref will update an exisitng patchset OR create a new patchset if the update is non-fast-forward. **Rebasing, Squashing, Amending** Gitblit makes rebasing, squashing, and amending patchsets easy. Normally, pushing a non-fast-forward update would require rewind (RW+) repository permissions. Gitblit provides a magic ref which will allow ticket participants to rewrite a ticket patchset as long as the ticket is open. git push origin HEAD:refs/for/{id} Pushing changes to this ref allows the patchset authors to rebase, squash, or amend the patchset commits without requiring client-side use of the *--force* flag on push AND without requiring RW+ permission to the repository. Since each patchset is tracked with a ref it is easy to recover from accidental non-fast-forward updates. Features -------- - Ticket tracker with status changes and responsible assignments - Patchset revision scoring mechanism - Update/Rewrite patchset handling - Close-on-push detection - Server-side Merge button for simple merges - Comments with Markdown syntax support - Rich mail notifications - Voting - Mentions - Watch lists - Querying - Searches - Partial miletones support - Multiple backend options
10 years ago
Ticket tracker with patchset contributions A basic issue tracker styled as a hybrid of GitHub and BitBucket issues. You may attach commits to an existing ticket or you can push a single commit to create a *proposal* ticket. Tickets keep track of patchsets (one or more commits) and allow patchset rewriting (rebase, amend, squash) by detecing the non-fast-forward update and assigning a new patchset number to the new commits. Ticket tracker -------------- The ticket tracker stores tickets as an append-only journal of changes. The journals are deserialized and a ticket is built by applying the journal entries. Tickets are indexed using Apache Lucene and all queries and searches are executed against this Lucene index. There is one trade-off to this persistence design: user attributions are non-relational. What does that mean? Each journal entry stores the username of the author. If the username changes in the user service, the journal entry will not reflect that change because the values are hard-coded. Here are a few reasons/justifications for this design choice: 1. commit identifications (author, committer, tagger) are non-relational 2. maintains the KISS principle 3. your favorite text editor can still be your administration tool Persistence Choices ------------------- **FileTicketService**: stores journals on the filesystem **BranchTicketService**: stores journals on an orphan branch **RedisTicketService**: stores journals in a Redis key-value datastore It should be relatively straight-forward to develop other backends (MongoDB, etc) as long as the journal design is preserved. Pushing Commits --------------- Each push to a ticket is identified as a patchset revision. A patchset revision may add commits to the patchset (fast-forward) OR a patchset revision may rewrite history (rebase, squash, rebase+squash, or amend). Patchset authors should not be afraid to polish, revise, and rewrite their code before merging into the proposed branch. Gitblit will create one ref for each patchset. These refs are updated for fast-forward pushes or created for rewrites. They are formatted as `refs/tickets/{shard}/{id}/{patchset}`. The *shard* is the last two digits of the id. If the id < 10, prefix a 0. The *shard* is always two digits long. The shard's purpose is to ensure Gitblit doesn't exceed any filesystem directory limits for file creation. **Creating a Proposal Ticket** You may create a new change proposal ticket just by pushing a **single commit** to `refs/for/{branch}` where branch is the proposed integration branch OR `refs/for/new` or `refs/for/default` which both will use the default repository branch. git push origin HEAD:refs/for/new **Updating a Patchset** The safe way to update an existing patchset is to push to the patchset ref. git push origin HEAD:refs/heads/ticket/{id} This ensures you do not accidentally create a new patchset in the event that the patchset was updated after you last pulled. The not-so-safe way to update an existing patchset is to push using the magic ref. git push origin HEAD:refs/for/{id} This push ref will update an exisitng patchset OR create a new patchset if the update is non-fast-forward. **Rebasing, Squashing, Amending** Gitblit makes rebasing, squashing, and amending patchsets easy. Normally, pushing a non-fast-forward update would require rewind (RW+) repository permissions. Gitblit provides a magic ref which will allow ticket participants to rewrite a ticket patchset as long as the ticket is open. git push origin HEAD:refs/for/{id} Pushing changes to this ref allows the patchset authors to rebase, squash, or amend the patchset commits without requiring client-side use of the *--force* flag on push AND without requiring RW+ permission to the repository. Since each patchset is tracked with a ref it is easy to recover from accidental non-fast-forward updates. Features -------- - Ticket tracker with status changes and responsible assignments - Patchset revision scoring mechanism - Update/Rewrite patchset handling - Close-on-push detection - Server-side Merge button for simple merges - Comments with Markdown syntax support - Rich mail notifications - Voting - Mentions - Watch lists - Querying - Searches - Partial miletones support - Multiple backend options
10 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303
  1. /*
  2. * Copyright 2013 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. */
  16. package com.gitblit.manager;
  17. import java.io.BufferedReader;
  18. import java.io.File;
  19. import java.io.FileInputStream;
  20. import java.io.IOException;
  21. import java.io.InputStream;
  22. import java.io.InputStreamReader;
  23. import java.lang.reflect.Type;
  24. import java.text.MessageFormat;
  25. import java.util.ArrayList;
  26. import java.util.Collection;
  27. import java.util.Date;
  28. import java.util.List;
  29. import java.util.Locale;
  30. import java.util.Map;
  31. import java.util.TimeZone;
  32. import javax.servlet.http.HttpServletRequest;
  33. import javax.servlet.http.HttpServletResponse;
  34. import org.eclipse.jgit.api.CloneCommand;
  35. import org.eclipse.jgit.api.FetchCommand;
  36. import org.eclipse.jgit.api.Git;
  37. import org.eclipse.jgit.lib.Ref;
  38. import org.eclipse.jgit.lib.Repository;
  39. import org.eclipse.jgit.transport.RefSpec;
  40. import org.slf4j.Logger;
  41. import org.slf4j.LoggerFactory;
  42. import ro.fortsoft.pf4j.PluginState;
  43. import ro.fortsoft.pf4j.PluginWrapper;
  44. import ro.fortsoft.pf4j.Version;
  45. import com.gitblit.Constants;
  46. import com.gitblit.Constants.AccessPermission;
  47. import com.gitblit.Constants.AccessRestrictionType;
  48. import com.gitblit.Constants.FederationRequest;
  49. import com.gitblit.Constants.FederationToken;
  50. import com.gitblit.GitBlitException;
  51. import com.gitblit.IStoredSettings;
  52. import com.gitblit.Keys;
  53. import com.gitblit.models.FederationModel;
  54. import com.gitblit.models.FederationProposal;
  55. import com.gitblit.models.FederationSet;
  56. import com.gitblit.models.ForkModel;
  57. import com.gitblit.models.GitClientApplication;
  58. import com.gitblit.models.Mailing;
  59. import com.gitblit.models.Metric;
  60. import com.gitblit.models.PluginRegistry.InstallState;
  61. import com.gitblit.models.PluginRegistry.PluginRegistration;
  62. import com.gitblit.models.PluginRegistry.PluginRelease;
  63. import com.gitblit.models.ProjectModel;
  64. import com.gitblit.models.RegistrantAccessPermission;
  65. import com.gitblit.models.RepositoryModel;
  66. import com.gitblit.models.RepositoryUrl;
  67. import com.gitblit.models.SearchResult;
  68. import com.gitblit.models.ServerSettings;
  69. import com.gitblit.models.ServerStatus;
  70. import com.gitblit.models.SettingModel;
  71. import com.gitblit.models.TeamModel;
  72. import com.gitblit.models.UserModel;
  73. import com.gitblit.tickets.ITicketService;
  74. import com.gitblit.transport.ssh.IPublicKeyManager;
  75. import com.gitblit.transport.ssh.SshKey;
  76. import com.gitblit.utils.ArrayUtils;
  77. import com.gitblit.utils.HttpUtils;
  78. import com.gitblit.utils.JsonUtils;
  79. import com.gitblit.utils.ObjectCache;
  80. import com.gitblit.utils.StringUtils;
  81. import com.google.gson.Gson;
  82. import com.google.gson.JsonIOException;
  83. import com.google.gson.JsonSyntaxException;
  84. import com.google.gson.reflect.TypeToken;
  85. /**
  86. * GitblitManager is an aggregate interface delegate. It implements all the manager
  87. * interfaces and delegates most methods calls to the proper manager implementation.
  88. * It's primary purpose is to provide complete management control to the git
  89. * upload and receive pack functions.
  90. *
  91. * GitblitManager also implements several integration methods when it is required
  92. * to manipulate several manages for one operation.
  93. *
  94. * @author James Moger
  95. *
  96. */
  97. public class GitblitManager implements IGitblit {
  98. protected final Logger logger = LoggerFactory.getLogger(getClass());
  99. protected final ObjectCache<Collection<GitClientApplication>> clientApplications = new ObjectCache<Collection<GitClientApplication>>();
  100. protected final IStoredSettings settings;
  101. protected final IRuntimeManager runtimeManager;
  102. protected final IPluginManager pluginManager;
  103. protected final INotificationManager notificationManager;
  104. protected final IUserManager userManager;
  105. protected final IAuthenticationManager authenticationManager;
  106. protected final IPublicKeyManager publicKeyManager;
  107. protected final IRepositoryManager repositoryManager;
  108. protected final IProjectManager projectManager;
  109. protected final IFederationManager federationManager;
  110. public GitblitManager(
  111. IRuntimeManager runtimeManager,
  112. IPluginManager pluginManager,
  113. INotificationManager notificationManager,
  114. IUserManager userManager,
  115. IAuthenticationManager authenticationManager,
  116. IPublicKeyManager publicKeyManager,
  117. IRepositoryManager repositoryManager,
  118. IProjectManager projectManager,
  119. IFederationManager federationManager) {
  120. this.settings = runtimeManager.getSettings();
  121. this.runtimeManager = runtimeManager;
  122. this.pluginManager = pluginManager;
  123. this.notificationManager = notificationManager;
  124. this.userManager = userManager;
  125. this.authenticationManager = authenticationManager;
  126. this.publicKeyManager = publicKeyManager;
  127. this.repositoryManager = repositoryManager;
  128. this.projectManager = projectManager;
  129. this.federationManager = federationManager;
  130. }
  131. @Override
  132. public GitblitManager start() {
  133. loadSettingModels(runtimeManager.getSettingsModel());
  134. return this;
  135. }
  136. @Override
  137. public GitblitManager stop() {
  138. return this;
  139. }
  140. /*
  141. * IGITBLIT
  142. */
  143. /**
  144. * Creates a personal fork of the specified repository. The clone is view
  145. * restricted by default and the owner of the source repository is given
  146. * access to the clone.
  147. *
  148. * @param repository
  149. * @param user
  150. * @return the repository model of the fork, if successful
  151. * @throws GitBlitException
  152. */
  153. @Override
  154. public RepositoryModel fork(RepositoryModel repository, UserModel user) throws GitBlitException {
  155. String cloneName = MessageFormat.format("{0}/{1}.git", user.getPersonalPath(), StringUtils.stripDotGit(StringUtils.getLastPathElement(repository.name)));
  156. String fromUrl = MessageFormat.format("file://{0}/{1}", repositoryManager.getRepositoriesFolder().getAbsolutePath(), repository.name);
  157. // clone the repository
  158. try {
  159. Repository canonical = getRepository(repository.name);
  160. File folder = new File(repositoryManager.getRepositoriesFolder(), cloneName);
  161. CloneCommand clone = new CloneCommand();
  162. clone.setBare(true);
  163. // fetch branches with exclusions
  164. Collection<Ref> branches = canonical.getRefDatabase().getRefs(Constants.R_HEADS).values();
  165. List<String> branchesToClone = new ArrayList<String>();
  166. for (Ref branch : branches) {
  167. String name = branch.getName();
  168. if (name.startsWith(Constants.R_TICKET)) {
  169. // exclude ticket branches
  170. continue;
  171. }
  172. branchesToClone.add(name);
  173. }
  174. clone.setBranchesToClone(branchesToClone);
  175. clone.setURI(fromUrl);
  176. clone.setDirectory(folder);
  177. Git git = clone.call();
  178. // fetch tags
  179. FetchCommand fetch = git.fetch();
  180. fetch.setRefSpecs(new RefSpec("+refs/tags/*:refs/tags/*"));
  181. fetch.call();
  182. git.getRepository().close();
  183. } catch (Exception e) {
  184. throw new GitBlitException(e);
  185. }
  186. // create a Gitblit repository model for the clone
  187. RepositoryModel cloneModel = repository.cloneAs(cloneName);
  188. // owner has REWIND/RW+ permissions
  189. cloneModel.addOwner(user.username);
  190. repositoryManager.updateRepositoryModel(cloneName, cloneModel, false);
  191. // add the owner of the source repository to the clone's access list
  192. if (!ArrayUtils.isEmpty(repository.owners)) {
  193. for (String owner : repository.owners) {
  194. UserModel originOwner = userManager.getUserModel(owner);
  195. if (originOwner != null && !originOwner.canClone(cloneModel)) {
  196. // origin owner can't yet clone fork, grant explicit clone access
  197. originOwner.setRepositoryPermission(cloneName, AccessPermission.CLONE);
  198. reviseUser(originOwner.username, originOwner);
  199. }
  200. }
  201. }
  202. // grant origin's user list clone permission to fork
  203. List<String> users = repositoryManager.getRepositoryUsers(repository);
  204. List<UserModel> cloneUsers = new ArrayList<UserModel>();
  205. for (String name : users) {
  206. if (!name.equalsIgnoreCase(user.username)) {
  207. UserModel cloneUser = userManager.getUserModel(name);
  208. if (cloneUser.canClone(repository) && !cloneUser.canClone(cloneModel)) {
  209. // origin user can't yet clone fork, grant explicit clone access
  210. cloneUser.setRepositoryPermission(cloneName, AccessPermission.CLONE);
  211. }
  212. cloneUsers.add(cloneUser);
  213. }
  214. }
  215. userManager.updateUserModels(cloneUsers);
  216. // grant origin's team list clone permission to fork
  217. List<String> teams = repositoryManager.getRepositoryTeams(repository);
  218. List<TeamModel> cloneTeams = new ArrayList<TeamModel>();
  219. for (String name : teams) {
  220. TeamModel cloneTeam = userManager.getTeamModel(name);
  221. if (cloneTeam.canClone(repository) && !cloneTeam.canClone(cloneModel)) {
  222. // origin team can't yet clone fork, grant explicit clone access
  223. cloneTeam.setRepositoryPermission(cloneName, AccessPermission.CLONE);
  224. }
  225. cloneTeams.add(cloneTeam);
  226. }
  227. userManager.updateTeamModels(cloneTeams);
  228. // add this clone to the cached model
  229. repositoryManager.addToCachedRepositoryList(cloneModel);
  230. return cloneModel;
  231. }
  232. /**
  233. * Adds a TeamModel object.
  234. *
  235. * @param team
  236. */
  237. @Override
  238. public void addTeam(TeamModel team) throws GitBlitException {
  239. if (!userManager.updateTeamModel(team)) {
  240. throw new GitBlitException("Failed to add team!");
  241. }
  242. }
  243. /**
  244. * Updates the TeamModel object for the specified name.
  245. *
  246. * @param teamname
  247. * @param team
  248. */
  249. @Override
  250. public void reviseTeam(String teamname, TeamModel team) throws GitBlitException {
  251. if (!teamname.equalsIgnoreCase(team.name)) {
  252. if (userManager.getTeamModel(team.name) != null) {
  253. throw new GitBlitException(MessageFormat.format(
  254. "Failed to rename ''{0}'' because ''{1}'' already exists.", teamname,
  255. team.name));
  256. }
  257. }
  258. if (!userManager.updateTeamModel(teamname, team)) {
  259. throw new GitBlitException("Failed to update team!");
  260. }
  261. }
  262. /**
  263. * Adds a user object.
  264. *
  265. * @param user
  266. * @throws GitBlitException
  267. */
  268. @Override
  269. public void addUser(UserModel user) throws GitBlitException {
  270. if (!userManager.updateUserModel(user)) {
  271. throw new GitBlitException("Failed to add user!");
  272. }
  273. }
  274. /**
  275. * Updates a user object keyed by username. This method allows
  276. * for renaming a user.
  277. *
  278. * @param username
  279. * @param user
  280. * @throws GitBlitException
  281. */
  282. @Override
  283. public void reviseUser(String username, UserModel user) throws GitBlitException {
  284. if (!username.equalsIgnoreCase(user.username)) {
  285. if (userManager.getUserModel(user.username) != null) {
  286. throw new GitBlitException(MessageFormat.format(
  287. "Failed to rename ''{0}'' because ''{1}'' already exists.", username,
  288. user.username));
  289. }
  290. // rename repositories and owner fields for all repositories
  291. for (RepositoryModel model : repositoryManager.getRepositoryModels(user)) {
  292. if (model.isUsersPersonalRepository(username)) {
  293. // personal repository
  294. model.addOwner(user.username);
  295. String oldRepositoryName = model.name;
  296. model.name = user.getPersonalPath() + model.name.substring(model.projectPath.length());
  297. model.projectPath = user.getPersonalPath();
  298. repositoryManager.updateRepositoryModel(oldRepositoryName, model, false);
  299. } else if (model.isOwner(username)) {
  300. // common/shared repo
  301. model.addOwner(user.username);
  302. repositoryManager.updateRepositoryModel(model.name, model, false);
  303. }
  304. }
  305. // rename the user's ssh public keystore
  306. getPublicKeyManager().renameUser(username, user.username);
  307. }
  308. if (!userManager.updateUserModel(username, user)) {
  309. throw new GitBlitException("Failed to update user!");
  310. }
  311. }
  312. /**
  313. * Returns a list of repository URLs and the user access permission.
  314. *
  315. * @param request
  316. * @param user
  317. * @param repository
  318. * @return a list of repository urls
  319. */
  320. @Override
  321. public List<RepositoryUrl> getRepositoryUrls(HttpServletRequest request, UserModel user, RepositoryModel repository) {
  322. if (user == null) {
  323. user = UserModel.ANONYMOUS;
  324. }
  325. String username = StringUtils.encodeUsername(UserModel.ANONYMOUS.equals(user) ? "" : user.username);
  326. List<RepositoryUrl> list = new ArrayList<RepositoryUrl>();
  327. // http/https url
  328. if (settings.getBoolean(Keys.git.enableGitServlet, true)) {
  329. AccessPermission permission = user.getRepositoryPermission(repository).permission;
  330. if (permission.exceeds(AccessPermission.NONE)) {
  331. list.add(new RepositoryUrl(getRepositoryUrl(request, username, repository), permission));
  332. }
  333. }
  334. // add all other urls
  335. // {0} = repository
  336. // {1} = username
  337. for (String url : settings.getStrings(Keys.web.otherUrls)) {
  338. if (url.contains("{1}")) {
  339. // external url requires username, only add url IF we have one
  340. if (!StringUtils.isEmpty(username)) {
  341. list.add(new RepositoryUrl(MessageFormat.format(url, repository.name, username), null));
  342. }
  343. } else {
  344. // external url does not require username
  345. list.add(new RepositoryUrl(MessageFormat.format(url, repository.name), null));
  346. }
  347. }
  348. return list;
  349. }
  350. protected String getRepositoryUrl(HttpServletRequest request, String username, RepositoryModel repository) {
  351. String gitblitUrl = settings.getString(Keys.web.canonicalUrl, null);
  352. if (StringUtils.isEmpty(gitblitUrl)) {
  353. gitblitUrl = HttpUtils.getGitblitURL(request);
  354. }
  355. StringBuilder sb = new StringBuilder();
  356. sb.append(gitblitUrl);
  357. sb.append(Constants.R_PATH);
  358. sb.append(repository.name);
  359. // inject username into repository url if authentication is required
  360. if (repository.accessRestriction.exceeds(AccessRestrictionType.NONE)
  361. && !StringUtils.isEmpty(username)) {
  362. sb.insert(sb.indexOf("://") + 3, username + "@");
  363. }
  364. return sb.toString();
  365. }
  366. /**
  367. * Returns the list of custom client applications to be used for the
  368. * repository url panel;
  369. *
  370. * @return a collection of client applications
  371. */
  372. @Override
  373. public Collection<GitClientApplication> getClientApplications() {
  374. // prefer user definitions, if they exist
  375. File userDefs = new File(runtimeManager.getBaseFolder(), "clientapps.json");
  376. if (userDefs.exists()) {
  377. Date lastModified = new Date(userDefs.lastModified());
  378. if (clientApplications.hasCurrent("user", lastModified)) {
  379. return clientApplications.getObject("user");
  380. } else {
  381. // (re)load user definitions
  382. try {
  383. InputStream is = new FileInputStream(userDefs);
  384. Collection<GitClientApplication> clients = readClientApplications(is);
  385. is.close();
  386. if (clients != null) {
  387. clientApplications.updateObject("user", lastModified, clients);
  388. return clients;
  389. }
  390. } catch (IOException e) {
  391. logger.error("Failed to deserialize " + userDefs.getAbsolutePath(), e);
  392. }
  393. }
  394. }
  395. // no user definitions, use system definitions
  396. if (!clientApplications.hasCurrent("system", new Date(0))) {
  397. try {
  398. InputStream is = GitblitManager.class.getResourceAsStream("/clientapps.json");
  399. Collection<GitClientApplication> clients = readClientApplications(is);
  400. is.close();
  401. if (clients != null) {
  402. clientApplications.updateObject("system", new Date(0), clients);
  403. }
  404. } catch (IOException e) {
  405. logger.error("Failed to deserialize clientapps.json resource!", e);
  406. }
  407. }
  408. return clientApplications.getObject("system");
  409. }
  410. private Collection<GitClientApplication> readClientApplications(InputStream is) {
  411. try {
  412. Type type = new TypeToken<Collection<GitClientApplication>>() {
  413. }.getType();
  414. InputStreamReader reader = new InputStreamReader(is);
  415. Gson gson = JsonUtils.gson();
  416. Collection<GitClientApplication> links = gson.fromJson(reader, type);
  417. return links;
  418. } catch (JsonIOException e) {
  419. logger.error("Error deserializing client applications!", e);
  420. } catch (JsonSyntaxException e) {
  421. logger.error("Error deserializing client applications!", e);
  422. }
  423. return null;
  424. }
  425. /**
  426. * Parse the properties file and aggregate all the comments by the setting
  427. * key. A setting model tracks the current value, the default value, the
  428. * description of the setting and and directives about the setting.
  429. *
  430. * @return Map<String, SettingModel>
  431. */
  432. private void loadSettingModels(ServerSettings settingsModel) {
  433. try {
  434. // Read bundled Gitblit properties to extract setting descriptions.
  435. // This copy is pristine and only used for populating the setting
  436. // models map.
  437. InputStream is = GitblitManager.class.getResourceAsStream("/reference.properties");
  438. BufferedReader propertiesReader = new BufferedReader(new InputStreamReader(is));
  439. StringBuilder description = new StringBuilder();
  440. SettingModel setting = new SettingModel();
  441. String line = null;
  442. while ((line = propertiesReader.readLine()) != null) {
  443. if (line.length() == 0) {
  444. description.setLength(0);
  445. setting = new SettingModel();
  446. } else {
  447. if (line.charAt(0) == '#') {
  448. if (line.length() > 1) {
  449. String text = line.substring(1).trim();
  450. if (SettingModel.CASE_SENSITIVE.equals(text)) {
  451. setting.caseSensitive = true;
  452. } else if (SettingModel.RESTART_REQUIRED.equals(text)) {
  453. setting.restartRequired = true;
  454. } else if (SettingModel.SPACE_DELIMITED.equals(text)) {
  455. setting.spaceDelimited = true;
  456. } else if (text.startsWith(SettingModel.SINCE)) {
  457. try {
  458. setting.since = text.split(" ")[1];
  459. } catch (Exception e) {
  460. setting.since = text;
  461. }
  462. } else {
  463. description.append(text);
  464. description.append('\n');
  465. }
  466. }
  467. } else {
  468. String[] kvp = line.split("=", 2);
  469. String key = kvp[0].trim();
  470. setting.name = key;
  471. setting.defaultValue = kvp[1].trim();
  472. setting.currentValue = setting.defaultValue;
  473. setting.description = description.toString().trim();
  474. settingsModel.add(setting);
  475. description.setLength(0);
  476. setting = new SettingModel();
  477. }
  478. }
  479. }
  480. propertiesReader.close();
  481. } catch (NullPointerException e) {
  482. logger.error("Failed to find resource copy of gitblit.properties");
  483. } catch (IOException e) {
  484. logger.error("Failed to load resource copy of gitblit.properties");
  485. }
  486. }
  487. /**
  488. * Throws an exception if trying to get a ticket service.
  489. *
  490. */
  491. @Override
  492. public ITicketService getTicketService() {
  493. throw new RuntimeException("This class does not have a ticket service!");
  494. }
  495. @Override
  496. public IPublicKeyManager getPublicKeyManager() {
  497. return publicKeyManager;
  498. }
  499. /*
  500. * ISTOREDSETTINGS
  501. *
  502. * these methods are necessary for (nearly) seamless Groovy hook operation
  503. * after the massive refactor.
  504. */
  505. public boolean getBoolean(String key, boolean defaultValue) {
  506. return runtimeManager.getSettings().getBoolean(key, defaultValue);
  507. }
  508. public String getString(String key, String defaultValue) {
  509. return runtimeManager.getSettings().getString(key, defaultValue);
  510. }
  511. public int getInteger(String key, int defaultValue) {
  512. return runtimeManager.getSettings().getInteger(key, defaultValue);
  513. }
  514. public List<String> getStrings(String key) {
  515. return runtimeManager.getSettings().getStrings(key);
  516. }
  517. /*
  518. * RUNTIME MANAGER
  519. */
  520. @Override
  521. public File getBaseFolder() {
  522. return runtimeManager.getBaseFolder();
  523. }
  524. @Override
  525. public void setBaseFolder(File folder) {
  526. runtimeManager.setBaseFolder(folder);
  527. }
  528. @Override
  529. public Date getBootDate() {
  530. return runtimeManager.getBootDate();
  531. }
  532. @Override
  533. public ServerSettings getSettingsModel() {
  534. return runtimeManager.getSettingsModel();
  535. }
  536. @Override
  537. public boolean isServingRepositories() {
  538. return runtimeManager.isServingRepositories();
  539. }
  540. @Override
  541. public TimeZone getTimezone() {
  542. return runtimeManager.getTimezone();
  543. }
  544. @Override
  545. public Locale getLocale() {
  546. return runtimeManager.getLocale();
  547. }
  548. @Override
  549. public boolean isDebugMode() {
  550. return runtimeManager.isDebugMode();
  551. }
  552. @Override
  553. public File getFileOrFolder(String key, String defaultFileOrFolder) {
  554. return runtimeManager.getFileOrFolder(key, defaultFileOrFolder);
  555. }
  556. @Override
  557. public File getFileOrFolder(String fileOrFolder) {
  558. return runtimeManager.getFileOrFolder(fileOrFolder);
  559. }
  560. @Override
  561. public IStoredSettings getSettings() {
  562. return runtimeManager.getSettings();
  563. }
  564. @Override
  565. public boolean updateSettings(Map<String, String> updatedSettings) {
  566. return runtimeManager.updateSettings(updatedSettings);
  567. }
  568. @Override
  569. public ServerStatus getStatus() {
  570. return runtimeManager.getStatus();
  571. }
  572. /*
  573. * NOTIFICATION MANAGER
  574. */
  575. @Override
  576. public void sendMailToAdministrators(String subject, String message) {
  577. notificationManager.sendMailToAdministrators(subject, message);
  578. }
  579. @Override
  580. public void sendMail(String subject, String message, Collection<String> toAddresses) {
  581. notificationManager.sendMail(subject, message, toAddresses);
  582. }
  583. @Override
  584. public void sendHtmlMail(String subject, String message, Collection<String> toAddresses) {
  585. notificationManager.sendHtmlMail(subject, message, toAddresses);
  586. }
  587. @Override
  588. public void send(Mailing mail) {
  589. notificationManager.send(mail);
  590. }
  591. /*
  592. * SESSION MANAGER
  593. */
  594. @Override
  595. public UserModel authenticate(String username, char[] password) {
  596. return authenticationManager.authenticate(username, password);
  597. }
  598. @Override
  599. public UserModel authenticate(HttpServletRequest httpRequest) {
  600. UserModel user = authenticationManager.authenticate(httpRequest, false);
  601. if (user == null) {
  602. user = federationManager.authenticate(httpRequest);
  603. }
  604. return user;
  605. }
  606. @Override
  607. public UserModel authenticate(String username, SshKey key) {
  608. return authenticationManager.authenticate(username, key);
  609. }
  610. @Override
  611. public UserModel authenticate(HttpServletRequest httpRequest, boolean requiresCertificate) {
  612. UserModel user = authenticationManager.authenticate(httpRequest, requiresCertificate);
  613. if (user == null) {
  614. user = federationManager.authenticate(httpRequest);
  615. }
  616. return user;
  617. }
  618. @Override
  619. public String getCookie(HttpServletRequest request) {
  620. return authenticationManager.getCookie(request);
  621. }
  622. @Override
  623. public void setCookie(HttpServletResponse response, UserModel user) {
  624. authenticationManager.setCookie(response, user);
  625. }
  626. @Override
  627. public void logout(HttpServletResponse response, UserModel user) {
  628. authenticationManager.logout(response, user);
  629. }
  630. @Override
  631. public boolean supportsCredentialChanges(UserModel user) {
  632. return authenticationManager.supportsCredentialChanges(user);
  633. }
  634. @Override
  635. public boolean supportsDisplayNameChanges(UserModel user) {
  636. return authenticationManager.supportsDisplayNameChanges(user);
  637. }
  638. @Override
  639. public boolean supportsEmailAddressChanges(UserModel user) {
  640. return authenticationManager.supportsEmailAddressChanges(user);
  641. }
  642. @Override
  643. public boolean supportsTeamMembershipChanges(UserModel user) {
  644. return authenticationManager.supportsTeamMembershipChanges(user);
  645. }
  646. @Override
  647. public boolean supportsTeamMembershipChanges(TeamModel team) {
  648. return authenticationManager.supportsTeamMembershipChanges(team);
  649. }
  650. /*
  651. * USER MANAGER
  652. */
  653. @Override
  654. public void setup(IRuntimeManager runtimeManager) {
  655. }
  656. @Override
  657. public boolean isInternalAccount(String username) {
  658. return userManager.isInternalAccount(username);
  659. }
  660. @Override
  661. public List<String> getAllUsernames() {
  662. return userManager.getAllUsernames();
  663. }
  664. @Override
  665. public List<UserModel> getAllUsers() {
  666. return userManager.getAllUsers();
  667. }
  668. @Override
  669. public boolean deleteUser(String username) {
  670. return userManager.deleteUser(username);
  671. }
  672. @Override
  673. public UserModel getUserModel(String username) {
  674. return userManager.getUserModel(username);
  675. }
  676. @Override
  677. public List<TeamModel> getAllTeams() {
  678. return userManager.getAllTeams();
  679. }
  680. @Override
  681. public TeamModel getTeamModel(String teamname) {
  682. return userManager.getTeamModel(teamname);
  683. }
  684. @Override
  685. public String getCookie(UserModel model) {
  686. return userManager.getCookie(model);
  687. }
  688. @Override
  689. public UserModel getUserModel(char[] cookie) {
  690. return userManager.getUserModel(cookie);
  691. }
  692. @Override
  693. public boolean updateUserModel(UserModel model) {
  694. return userManager.updateUserModel(model);
  695. }
  696. @Override
  697. public boolean updateUserModels(Collection<UserModel> models) {
  698. return userManager.updateUserModels(models);
  699. }
  700. @Override
  701. public boolean updateUserModel(String username, UserModel model) {
  702. return userManager.updateUserModel(username, model);
  703. }
  704. @Override
  705. public boolean deleteUserModel(UserModel model) {
  706. return userManager.deleteUserModel(model);
  707. }
  708. @Override
  709. public List<String> getAllTeamNames() {
  710. return userManager.getAllTeamNames();
  711. }
  712. @Override
  713. public List<String> getTeamNamesForRepositoryRole(String role) {
  714. return userManager.getTeamNamesForRepositoryRole(role);
  715. }
  716. @Override
  717. public boolean updateTeamModel(TeamModel model) {
  718. return userManager.updateTeamModel(model);
  719. }
  720. @Override
  721. public boolean updateTeamModels(Collection<TeamModel> models) {
  722. return userManager.updateTeamModels(models);
  723. }
  724. @Override
  725. public boolean updateTeamModel(String teamname, TeamModel model) {
  726. return userManager.updateTeamModel(teamname, model);
  727. }
  728. @Override
  729. public boolean deleteTeamModel(TeamModel model) {
  730. return userManager.deleteTeamModel(model);
  731. }
  732. @Override
  733. public List<String> getUsernamesForRepositoryRole(String role) {
  734. return userManager.getUsernamesForRepositoryRole(role);
  735. }
  736. @Override
  737. public boolean renameRepositoryRole(String oldRole, String newRole) {
  738. return userManager.renameRepositoryRole(oldRole, newRole);
  739. }
  740. @Override
  741. public boolean deleteRepositoryRole(String role) {
  742. return userManager.deleteRepositoryRole(role);
  743. }
  744. @Override
  745. public boolean deleteTeam(String teamname) {
  746. return userManager.deleteTeam(teamname);
  747. }
  748. /*
  749. * REPOSITORY MANAGER
  750. */
  751. @Override
  752. public Date getLastActivityDate() {
  753. return repositoryManager.getLastActivityDate();
  754. }
  755. @Override
  756. public File getRepositoriesFolder() {
  757. return repositoryManager.getRepositoriesFolder();
  758. }
  759. @Override
  760. public File getHooksFolder() {
  761. return repositoryManager.getHooksFolder();
  762. }
  763. @Override
  764. public File getGrapesFolder() {
  765. return repositoryManager.getGrapesFolder();
  766. }
  767. @Override
  768. public List<RegistrantAccessPermission> getUserAccessPermissions(UserModel user) {
  769. return repositoryManager.getUserAccessPermissions(user);
  770. }
  771. @Override
  772. public List<RegistrantAccessPermission> getUserAccessPermissions(RepositoryModel repository) {
  773. return repositoryManager.getUserAccessPermissions(repository);
  774. }
  775. @Override
  776. public boolean setUserAccessPermissions(RepositoryModel repository, Collection<RegistrantAccessPermission> permissions) {
  777. return repositoryManager.setUserAccessPermissions(repository, permissions);
  778. }
  779. @Override
  780. public List<String> getRepositoryUsers(RepositoryModel repository) {
  781. return repositoryManager.getRepositoryUsers(repository);
  782. }
  783. @Override
  784. public List<RegistrantAccessPermission> getTeamAccessPermissions(RepositoryModel repository) {
  785. return repositoryManager.getTeamAccessPermissions(repository);
  786. }
  787. @Override
  788. public boolean setTeamAccessPermissions(RepositoryModel repository, Collection<RegistrantAccessPermission> permissions) {
  789. return repositoryManager.setTeamAccessPermissions(repository, permissions);
  790. }
  791. @Override
  792. public List<String> getRepositoryTeams(RepositoryModel repository) {
  793. return repositoryManager.getRepositoryTeams(repository);
  794. }
  795. @Override
  796. public void addToCachedRepositoryList(RepositoryModel model) {
  797. repositoryManager.addToCachedRepositoryList(model);
  798. }
  799. @Override
  800. public void resetRepositoryListCache() {
  801. repositoryManager.resetRepositoryListCache();
  802. }
  803. @Override
  804. public void resetRepositoryCache(String repositoryName) {
  805. repositoryManager.resetRepositoryCache(repositoryName);
  806. }
  807. @Override
  808. public List<String> getRepositoryList() {
  809. return repositoryManager.getRepositoryList();
  810. }
  811. @Override
  812. public Repository getRepository(String repositoryName) {
  813. return repositoryManager.getRepository(repositoryName);
  814. }
  815. @Override
  816. public Repository getRepository(String repositoryName, boolean logError) {
  817. return repositoryManager.getRepository(repositoryName, logError);
  818. }
  819. @Override
  820. public List<RepositoryModel> getRepositoryModels(UserModel user) {
  821. return repositoryManager.getRepositoryModels(user);
  822. }
  823. @Override
  824. public RepositoryModel getRepositoryModel(UserModel user, String repositoryName) {
  825. return repositoryManager.getRepositoryModel(repositoryName);
  826. }
  827. @Override
  828. public RepositoryModel getRepositoryModel(String repositoryName) {
  829. return repositoryManager.getRepositoryModel(repositoryName);
  830. }
  831. @Override
  832. public long getStarCount(RepositoryModel repository) {
  833. return repositoryManager.getStarCount(repository);
  834. }
  835. @Override
  836. public boolean hasRepository(String repositoryName) {
  837. return repositoryManager.hasRepository(repositoryName);
  838. }
  839. @Override
  840. public boolean hasRepository(String repositoryName, boolean caseSensitiveCheck) {
  841. return repositoryManager.hasRepository(repositoryName, caseSensitiveCheck);
  842. }
  843. @Override
  844. public boolean hasFork(String username, String origin) {
  845. return repositoryManager.hasFork(username, origin);
  846. }
  847. @Override
  848. public String getFork(String username, String origin) {
  849. return repositoryManager.getFork(username, origin);
  850. }
  851. @Override
  852. public ForkModel getForkNetwork(String repository) {
  853. return repositoryManager.getForkNetwork(repository);
  854. }
  855. @Override
  856. public long updateLastChangeFields(Repository r, RepositoryModel model) {
  857. return repositoryManager.updateLastChangeFields(r, model);
  858. }
  859. @Override
  860. public List<Metric> getRepositoryDefaultMetrics(RepositoryModel model, Repository repository) {
  861. return repositoryManager.getRepositoryDefaultMetrics(model, repository);
  862. }
  863. @Override
  864. public void updateRepositoryModel(String repositoryName, RepositoryModel repository,
  865. boolean isCreate) throws GitBlitException {
  866. repositoryManager.updateRepositoryModel(repositoryName, repository, isCreate);
  867. }
  868. @Override
  869. public void updateConfiguration(Repository r, RepositoryModel repository) {
  870. repositoryManager.updateConfiguration(r, repository);
  871. }
  872. @Override
  873. public boolean deleteRepositoryModel(RepositoryModel model) {
  874. return repositoryManager.deleteRepositoryModel(model);
  875. }
  876. @Override
  877. public boolean deleteRepository(String repositoryName) {
  878. return repositoryManager.deleteRepository(repositoryName);
  879. }
  880. @Override
  881. public List<String> getAllScripts() {
  882. return repositoryManager.getAllScripts();
  883. }
  884. @Override
  885. public List<String> getPreReceiveScriptsInherited(RepositoryModel repository) {
  886. return repositoryManager.getPreReceiveScriptsInherited(repository);
  887. }
  888. @Override
  889. public List<String> getPreReceiveScriptsUnused(RepositoryModel repository) {
  890. return repositoryManager.getPreReceiveScriptsUnused(repository);
  891. }
  892. @Override
  893. public List<String> getPostReceiveScriptsInherited(RepositoryModel repository) {
  894. return repositoryManager.getPostReceiveScriptsInherited(repository);
  895. }
  896. @Override
  897. public List<String> getPostReceiveScriptsUnused(RepositoryModel repository) {
  898. return repositoryManager.getPostReceiveScriptsUnused(repository);
  899. }
  900. @Override
  901. public List<SearchResult> search(String query, int page, int pageSize, List<String> repositories) {
  902. return repositoryManager.search(query, page, pageSize, repositories);
  903. }
  904. @Override
  905. public boolean isCollectingGarbage() {
  906. return repositoryManager.isCollectingGarbage();
  907. }
  908. @Override
  909. public boolean isCollectingGarbage(String repositoryName) {
  910. return repositoryManager.isCollectingGarbage(repositoryName);
  911. }
  912. /*
  913. * PROJECT MANAGER
  914. */
  915. @Override
  916. public List<ProjectModel> getProjectModels(UserModel user, boolean includeUsers) {
  917. return projectManager.getProjectModels(user, includeUsers);
  918. }
  919. @Override
  920. public ProjectModel getProjectModel(String name, UserModel user) {
  921. return projectManager.getProjectModel(name, user);
  922. }
  923. @Override
  924. public ProjectModel getProjectModel(String name) {
  925. return projectManager.getProjectModel(name);
  926. }
  927. @Override
  928. public List<ProjectModel> getProjectModels(List<RepositoryModel> repositoryModels, boolean includeUsers) {
  929. return projectManager.getProjectModels(repositoryModels, includeUsers);
  930. }
  931. /*
  932. * FEDERATION MANAGER
  933. */
  934. @Override
  935. public File getProposalsFolder() {
  936. return federationManager.getProposalsFolder();
  937. }
  938. @Override
  939. public boolean canFederate() {
  940. return federationManager.canFederate();
  941. }
  942. @Override
  943. public UserModel getFederationUser() {
  944. return federationManager.getFederationUser();
  945. }
  946. @Override
  947. public List<FederationModel> getFederationRegistrations() {
  948. return federationManager.getFederationRegistrations();
  949. }
  950. @Override
  951. public FederationModel getFederationRegistration(String url, String name) {
  952. return federationManager.getFederationRegistration(url, name);
  953. }
  954. @Override
  955. public List<FederationSet> getFederationSets(String gitblitUrl) {
  956. return federationManager.getFederationSets(gitblitUrl);
  957. }
  958. @Override
  959. public List<String> getFederationTokens() {
  960. return federationManager.getFederationTokens();
  961. }
  962. @Override
  963. public String getFederationToken(FederationToken type) {
  964. return federationManager.getFederationToken(type);
  965. }
  966. @Override
  967. public String getFederationToken(String value) {
  968. return federationManager.getFederationToken(value);
  969. }
  970. @Override
  971. public boolean validateFederationRequest(FederationRequest req, String token) {
  972. return federationManager.validateFederationRequest(req, token);
  973. }
  974. @Override
  975. public boolean acknowledgeFederationStatus(String identification, FederationModel registration) {
  976. return federationManager.acknowledgeFederationStatus(identification, registration);
  977. }
  978. @Override
  979. public List<FederationModel> getFederationResultRegistrations() {
  980. return federationManager.getFederationResultRegistrations();
  981. }
  982. @Override
  983. public boolean submitFederationProposal(FederationProposal proposal, String gitblitUrl) {
  984. return federationManager.submitFederationProposal(proposal, gitblitUrl);
  985. }
  986. @Override
  987. public List<FederationProposal> getPendingFederationProposals() {
  988. return federationManager.getPendingFederationProposals();
  989. }
  990. @Override
  991. public Map<String, RepositoryModel> getRepositories(String gitblitUrl, String token) {
  992. return federationManager.getRepositories(gitblitUrl, token);
  993. }
  994. @Override
  995. public FederationProposal createFederationProposal(String gitblitUrl, String token) {
  996. return federationManager.createFederationProposal(gitblitUrl, token);
  997. }
  998. @Override
  999. public FederationProposal getPendingFederationProposal(String token) {
  1000. return federationManager.getPendingFederationProposal(token);
  1001. }
  1002. @Override
  1003. public boolean deletePendingFederationProposal(FederationProposal proposal) {
  1004. return federationManager.deletePendingFederationProposal(proposal);
  1005. }
  1006. @Override
  1007. public void closeAll() {
  1008. repositoryManager.closeAll();
  1009. }
  1010. @Override
  1011. public void close(String repository) {
  1012. repositoryManager.close(repository);
  1013. }
  1014. @Override
  1015. public boolean isIdle(Repository repository) {
  1016. return repositoryManager.isIdle(repository);
  1017. }
  1018. /*
  1019. * PLUGIN MANAGER
  1020. */
  1021. @Override
  1022. public Version getSystemVersion() {
  1023. return pluginManager.getSystemVersion();
  1024. }
  1025. @Override
  1026. public void startPlugins() {
  1027. pluginManager.startPlugins();
  1028. }
  1029. @Override
  1030. public void stopPlugins() {
  1031. pluginManager.stopPlugins();
  1032. }
  1033. @Override
  1034. public List<PluginWrapper> getPlugins() {
  1035. return pluginManager.getPlugins();
  1036. }
  1037. @Override
  1038. public PluginWrapper getPlugin(String pluginId) {
  1039. return pluginManager.getPlugin(pluginId);
  1040. }
  1041. @Override
  1042. public List<Class<?>> getExtensionClasses(String pluginId) {
  1043. return pluginManager.getExtensionClasses(pluginId);
  1044. }
  1045. @Override
  1046. public <T> List<T> getExtensions(Class<T> clazz) {
  1047. return pluginManager.getExtensions(clazz);
  1048. }
  1049. @Override
  1050. public PluginWrapper whichPlugin(Class<?> clazz) {
  1051. return pluginManager.whichPlugin(clazz);
  1052. }
  1053. @Override
  1054. public PluginState startPlugin(String pluginId) {
  1055. return pluginManager.startPlugin(pluginId);
  1056. }
  1057. @Override
  1058. public PluginState stopPlugin(String pluginId) {
  1059. return pluginManager.stopPlugin(pluginId);
  1060. }
  1061. @Override
  1062. public boolean disablePlugin(String pluginId) {
  1063. return pluginManager.disablePlugin(pluginId);
  1064. }
  1065. @Override
  1066. public boolean enablePlugin(String pluginId) {
  1067. return pluginManager.enablePlugin(pluginId);
  1068. }
  1069. @Override
  1070. public boolean uninstallPlugin(String pluginId) {
  1071. return pluginManager.uninstallPlugin(pluginId);
  1072. }
  1073. @Override
  1074. public boolean refreshRegistry(boolean verifyChecksum) {
  1075. return pluginManager.refreshRegistry(verifyChecksum);
  1076. }
  1077. @Override
  1078. public boolean installPlugin(String url, boolean verifyChecksum) throws IOException {
  1079. return pluginManager.installPlugin(url, verifyChecksum);
  1080. }
  1081. @Override
  1082. public boolean upgradePlugin(String pluginId, String url, boolean verifyChecksum) throws IOException {
  1083. return pluginManager.upgradePlugin(pluginId, url, verifyChecksum);
  1084. }
  1085. @Override
  1086. public List<PluginRegistration> getRegisteredPlugins() {
  1087. return pluginManager.getRegisteredPlugins();
  1088. }
  1089. @Override
  1090. public List<PluginRegistration> getRegisteredPlugins(InstallState state) {
  1091. return pluginManager.getRegisteredPlugins(state);
  1092. }
  1093. @Override
  1094. public PluginRegistration lookupPlugin(String pluginId) {
  1095. return pluginManager.lookupPlugin(pluginId);
  1096. }
  1097. @Override
  1098. public PluginRelease lookupRelease(String pluginId, String version) {
  1099. return pluginManager.lookupRelease(pluginId, version);
  1100. }
  1101. }