Paul Martin
2016-04-30 a502d96a860456ec5e8c96761db70f7cabb74751
commit | author | age
c5dfd6 1 ## Extension Points
JM 2
3 Gitblit offers several extension points for enhancing and customizing it's runtime behavior.
4
2d73a0 5 Each available extension point has a sample implementation in the [gitblit-cookbook-plugin (Maven project)](https://github.com/gitblit/gitblit-cookbook-plugin).
JM 6
7 **NOTE:**
8 Gitblit does not yet offer a comprehensize dependency injection architecture.  This will be addressed in a subsequent release.  For now you may access all of Gitblit's core managers through a static singleton app context:
9
10 ```java
11 import com.gitblit.extensions.GitblitPlugin;
12 import com.gitblit.servlet.GitblitContext;
13 import com.gitblit.manager.IRuntimeManager;
14 import com.gitblit.manager.IUserManager;
15 import com.gitblit.manager.IAuthenticationManager;
16 import com.gitblit.manager.INotificationManager;
17 import com.gitblit.manager.IRepositoryManager;
18 import com.gitblit.manager.IProjectManager;
19 import com.gitblit.manager.IFederationManager;
20 import com.gitblit.manager.IPluginManager;
21 import com.gitblit.manager.IGitblit;
cf4004 22 import ro.fortsoft.pf4j.Version;
2d73a0 23
JM 24 public class ExamplePlugin extends GitblitPlugin {
25
26     @Override
27     public void start() {
28         IRuntimeManager runtime = GitblitContext.getManager(IRuntimeManager.class);
29         IUserManager users = GitblitContext.getManager(IUserManager.class);
30         IAuthenticationManager auth = GitblitContext.getManager(IAuthenticationManager.class);
31         INotificationManager notifications = GitblitContext.getManager(INotificationManager.class);
32         IRepositoryManager repos = GitblitContext.getManager(IRepositoryManager.class);
33         IProjectManager projects = GitblitContext.getManager(IProjectManager.class);
34         IFederationManager federation = GitblitContext.getManager(IFederationManager.class);
35         IPluginManager plugins = GitblitContext.getManager(IPluginManager.class);
36         IGitblit gitblit = GitblitContext.getManager(IGitblit.class);
37     }
cf4004 38
JM 39     @Override
40     public void stop() {
41     }
42
43     @Override
44     public void onInstall() {
45     }
46
47     @Override
48     public void onUpgrade(Version oldVersion) {
49     }
50
51     @Override
52     public void onUninstall() {
53     }
2d73a0 54 }
7a401a 55
JM 56 /**
c59584 57  * You can also create Webapp plugins that register pages.
7a401a 58  */
JM 59 public class ExampleWicketPlugin extends GitblitWicketPlugin {
60     @Override
61     public void start() {
62     }
63
64     @Override
65     public void stop() {
66     }
67
68     @Override
69     public void onInstall() {
70     }
71
72     @Override
73     public void onUpgrade(Version oldVersion) {
74     }
75
76     @Override
77     public void onUninstall() {
78     }
79
80     @Override
81     protected void init(GitblitWicketApp app) {
82         app.mount("/logo", LogoPage.class);
83         app.mount("/hello", HelloWorldPage.class);
84     }
85 }
2d73a0 86 ```
c5dfd6 87
JM 88 ### SSH Dispatch Command
89
90 *SINCE 1.5.0*
91
2d73a0 92 You can provide your own custom SSH command hierarchies by subclassing the *DispatchCommand* class.
c5dfd6 93
JM 94 ```java
95 import ro.fortsoft.pf4j.Extension;
2d73a0 96 import org.kohsuke.args4j.Option;
JM 97 import org.slf4j.Logger;
98 import org.slf4j.LoggerFactory;
c5dfd6 99 import com.gitblit.transport.ssh.commands.CommandMetaData;
JM 100 import com.gitblit.transport.ssh.commands.DispatchCommand;
2d73a0 101 import com.gitblit.transport.ssh.commands.UsageExample;
c5dfd6 102
JM 103 @Extension
104 @CommandMetaData(name = "mycommands", description = "Sample SSH dispatcher")
105 public class MyDispatcher extends DispatchCommand {
106
107     @Override
8cbdf3 108     protected void setup() {
c5dfd6 109         // commands in this dispatcher
8cbdf3 110         register(CommandA.class);
JM 111         register(CommandB.class);
c5dfd6 112
JM 113         // nested dispatchers
8cbdf3 114         register(SubDispatcher1.class);
JM 115         register(SubDispatcher2.class);
c5dfd6 116     }
2d73a0 117
JM 118     @CommandMetaData(name = "commanda", aliases = { "ca" }, description = "description of command a")
119     @UsageExample(syntax = "${cmd} --myflag", description = "description of commanda with --myflag")
120     public static class CommandA extends SshCommand {
121
122         protected final Logger log = LoggerFactory.getLogger(getClass());
123
124         @Option(name = "--myflag", aliases = { "-m" }, usage = "enable myflag")
125         boolean myflag;
126
127         @Override
128         public void run() throws Failure {
129             if (myflag) {
130                 log.info("Run with --myflag");
131             } else {
132                 log.info("Run without --myflag");
133             }
134         }
135     }
c5dfd6 136 }
JM 137 ```
138
139 ### Pre- and Post- Receive Hook
140
141 *SINCE 1.5.0*
142
143 You can provide your own custom pre and/or post receive hooks by subclassing the *ReceiveHook* class.
144
145 ```java
146 import com.gitblit.extensions.ReceiveHook;
147 import java.util.Collection;
148 import org.eclipse.jgit.transport.ReceiveCommand;
149 import ro.fortsoft.pf4j.Extension;
150
151 @Extension
152 public class MyReceiveHook extends ReceiveHook {
153
154     @Override
155     public void onPreReceive(GitblitReceivePack receivePack, Collection<ReceiveCommand> commands) {
156     }
157
158     @Override
159     public void onPostReceive(GitblitReceivePack receivePack, Collection<ReceiveCommand> commands) {
160     }
161 }
162
163 ```
164
165 ### Patchset Hook
166
167 *SINCE 1.5.0*
168
169 You can provide your own custom patchset hook by subclassing the *PatchsetHook* class.
170
171 ```java
172 import com.gitblit.extensions.PatchsetHook;
173 import com.gitblit.models.TicketModel;
174 import ro.fortsoft.pf4j.Extension;
175
176 @Extension
177 public class MyPatchsetHook extends PatchsetHook {
178
179     @Override
180     public void onNewPatchset(TicketModel ticket) {
181     }
182
183     @Override
184     public void onUpdatePatchset(TicketModel ticket) {
185     }
186
187     @Override
188     public void onMergePatchset(TicketModel ticket) {
189     }
190 }
191 ```
192
193 ### Ticket Hook
194
195 *SINCE 1.5.0*
196
197 You can provide your own custom ticket hook by subclassing the *TicketHook* class.
198
199 ```java
200 import com.gitblit.extensions.TicketHook;
201 import com.gitblit.models.TicketModel;
202 import com.gitblit.models.TicketModel.Change;
203 import ro.fortsoft.pf4j.Extension;
204
205 @Extension
206 public class MyTicketHook extends TicketHook {
207
208     @Override
209     public void onNewTicket(TicketModel ticket) {
210     }
211
212     @Override
213     public void onUpdateTicket(TicketModel ticket, Change change) {
214     }
215 }
216 ```
217
ec2456 218 ### Request Filter
DO 219
220 *SINCE 1.6.0*
221
222 You can provide your own custom request filter by subclassing the *HttpRequestFilter* class.
223
224 ```java
225 import com.gitblit.extensions.HttpRequestFilter;
226 import ro.fortsoft.pf4j.Extension;
227
228 @Extension
229 public class MyRequestFilter extends HttpRequestFilter {
230
231     @Override
232     public void doFilter(ServletRequest request, ServletResponse response,
233             FilterChain chain) throws IOException, ServletException {
234     }
235 }
236 ```
237
859deb 238 ### User Menu Items
856f3f 239
JM 240 *SINCE 1.6.0*
241
859deb 242 You can provide your own user menu items by subclassing the *UserMenuExtension* class.
856f3f 243
JM 244 ```java
245 import java.util.Arrays;
246 import java.util.List;
247 import ro.fortsoft.pf4j.Extension;
859deb 248 import com.gitblit.extensions.UserMenuExtension;
856f3f 249 import com.gitblit.models.Menu.ExternalLinkMenuItem;
JM 250 import com.gitblit.models.Menu.MenuItem;
251 import com.gitblit.models.UserModel;
252
253 @Extension
859deb 254 public class MyUserMenuContributor extends UserMenuExtension {
856f3f 255
JM 256     @Override
257     public List<MenuItem> getMenuItems(UserModel user) {
7a401a 258         MenuItem item = new ExternalLinkMenuItem("Github", String.format("https://github.com/%s", user.username));
JM 259         return Arrays.asList(item);
260     }
261 }
262 ```
263
264 ### Navigation Links
265
266 *SINCE 1.6.0*
267
268 You can provide your own top-level navigation links by subclassing the *NavLinkExtension* class.
269
270 ```java
271 import java.util.Arrays;
272 import java.util.List;
273 import ro.fortsoft.pf4j.Extension;
274 import com.gitblit.extensions.NavLinkExtension;
275 import com.gitblit.models.UserModel;
276
277 @Extension
278 public class MyNavLink extends NavLinkExtension {
279
280     @Override
281     public List<NavLink> getNavLinks(UserModel user) {
282         NavLink link = new ExternalLinkMenuItem("Github", String.format("https://github.com/%s", user.username));
283         return Arrays.asList(link);
856f3f 284     }
JM 285 }
286 ```
c59584 287
ca4d98 288 ### Server Lifecycle Listener
c59584 289
JM 290 *SINCE 1.6.0*
291
292 You can provide a lifecycle listener to be notified when Gitblit has completely started and just before Gitblit is gracefully terminated.
293
294 ```java
295 import org.slf4j.Logger;
296 import org.slf4j.LoggerFactory;
297 import ro.fortsoft.pf4j.Extension;
298 import com.gitblit.extensions.LifeCycleListener;
299
300 @Extension
301 public class MyLifeCycleListener extends LifeCycleListener {
302
303     final Logger log = LoggerFactory.getLogger(getClass());
304     
305     @Override
306     public void onStartup() {
307         log.info("Gitblit is Ready!!");
308     }
309
310     @Override
311     public void onShutdown() {
312         log.info("Gitblit is Going Down!!");
313     }
314 }
ca4d98 315 ```
JM 316
317 ### Repository Lifecycle Listener
318
319 *SINCE 1.6.0*
320
321 You can provide a lifecycle listener to be notified when Gitblit has created or deleted a repository.
322
323 ```java
324 import org.slf4j.Logger;
325 import org.slf4j.LoggerFactory;
326 import ro.fortsoft.pf4j.Extension;
327 import com.gitblit.extensions.RepositoryLifeCycleListener;
328 import com.gitblit.models.RepositoryModel;
329
330 @Extension
331 public class MyRepoLifeCycleListener extends RepositoryLifeCycleListener {
332
333     final Logger log = LoggerFactory.getLogger(getClass());
334     
335     @Override
336     public void onCreation(RepositoryModel repo) {
337         log.info("Gitblit created {}", repo);
338     }
339
340     @Override
8a28d0 341     public void onFork(RepositoryModel origin, RepositoryModel fork) {
JM 342         log.info("{} forked to {}", origin, fork);
343     }
344
345     @Override
346     public void onRename(String oldName, RepositoryModel repo) {
347         log.info("{} renamed to {}", oldName, repo);
348     }
349
350     @Override
ca4d98 351     public void onDeletion(RepositoryModel repo) {
JM 352         log.info("Gitblit deleted {}", repo);
353     }
354 }
355 ```
356
357 ### User/Team Lifecycle Listener
358
359 *SINCE 1.6.0*
360
361 You can provide a lifecycle listener to be notified when Gitblit has created or deleted a user or a team.
362
363 ```java
364 import org.slf4j.Logger;
365 import org.slf4j.LoggerFactory;
366 import ro.fortsoft.pf4j.Extension;
367 import com.gitblit.extensions.UserTeamLifeCycleListener;
368 import com.gitblit.models.TeamModel;
369 import com.gitblit.models.UserModel;
370
371 @Extension
372 public class MyUserTeamLifeCycleListener extends UserTeamLifeCycleListener {
373
374     final Logger log = LoggerFactory.getLogger(getClass());
375     
376     @Override
377     public void onCreation(UserModel user) {
378         log.info("Gitblit created user {}", user);
379     }
380
381     @Override
382     public void onDeletion(UserModel user) {
383         log.info("Gitblit deleted user {}", user);
384     }
385
386     @Override
387     public void onCreation(TeamModel team) {
388         log.info("Gitblit created team {}", team);
389     }
390
391     @Override
392     public void onDeletion(TeamModel team) {
393         log.info("Gitblit deleted team {}", team);
394     }
395 }
396 ```