+++ /dev/null
-/*
- * Copyright 2014 gitblit.com.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.gitblit.extensions;
-
-import java.util.List;
-
-import ro.fortsoft.pf4j.ExtensionPoint;
-
-import com.gitblit.models.Menu.MenuItem;
-import com.gitblit.models.UserModel;
-
-/**
- * Extension point to contribute administration menu items.
- *
- * @author James Moger
- * @since 1.6.0
- *
- */
-public abstract class AdminMenuExtension implements ExtensionPoint {
-
- /**
- * @param user
- * @since 1.6.0
- * @return a list of menu items
- */
- public abstract List<MenuItem> getMenuItems(UserModel user);
-}
--- /dev/null
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.extensions;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.IInitializer;
+
+import ro.fortsoft.pf4j.PluginWrapper;
+
+import com.gitblit.wicket.GitblitWicketApp;
+
+/**
+ * A Gitblit plugin that is allowed to extend the Wicket webapp.
+ *
+ * @author James Moger
+ * @since 1.6.0
+ */
+public abstract class GitblitWicketPlugin extends GitblitPlugin implements IInitializer {
+
+ public GitblitWicketPlugin(PluginWrapper wrapper) {
+ super(wrapper);
+ }
+
+ @Override
+ public final void init(Application application) {
+ init((GitblitWicketApp) application);
+ }
+
+ /**
+ * Allows plugins to extend the web application.
+ *
+ * @param app
+ * @since 1.6.0
+ */
+ protected abstract void init(GitblitWicketApp app);
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.extensions;
+
+import java.util.List;
+
+import ro.fortsoft.pf4j.ExtensionPoint;
+
+import com.gitblit.models.NavLink;
+import com.gitblit.models.UserModel;
+
+/**
+ * Extension point to contribute top-level navigation links.
+ *
+ * @author James Moger
+ * @since 1.6.0
+ *
+ */
+public abstract class NavLinkExtension implements ExtensionPoint {
+
+ /**
+ * @param user
+ * @since 1.6.0
+ * @return a list of nav links
+ */
+ public abstract List<NavLink> getNavLinks(UserModel user);
+}
--- /dev/null
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.extensions;
+
+import java.util.List;
+
+import ro.fortsoft.pf4j.ExtensionPoint;
+
+import com.gitblit.models.NavLink;
+import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.UserModel;
+
+/**
+ * Extension point to contribute repository page navigation links.
+ *
+ * @author James Moger
+ * @since 1.6.0
+ *
+ */
+public abstract class RepositoryNavLinkExtension implements ExtensionPoint {
+
+ /**
+ * @param user
+ * @param repository
+ * @since 1.6.0
+ * @return a list of nav links
+ */
+ public abstract List<NavLink> getNavLinks(UserModel user, RepositoryModel repository);
+}
--- /dev/null
+/*\r
+ * Copyright 2011 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.models;\r
+\r
+import java.io.Serializable;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.apache.wicket.PageParameters;\r
+import org.apache.wicket.markup.html.WebPage;\r
+\r
+import com.gitblit.models.Menu.MenuItem;\r
+\r
+/**\r
+ * Represents a navigation link for the navigation panel.\r
+ *\r
+ * @author James Moger\r
+ *\r
+ */\r
+public abstract class NavLink implements Serializable {\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ public final String translationKey;\r
+ public final boolean hiddenPhone;\r
+\r
+ public NavLink(String translationKey, boolean hiddenPhone) {\r
+ this.translationKey = translationKey;\r
+ this.hiddenPhone = hiddenPhone;\r
+ }\r
+\r
+\r
+ /**\r
+ * Represents a Wicket page link.\r
+ *\r
+ * @author James Moger\r
+ *\r
+ */\r
+ public static class PageNavLink extends NavLink implements Serializable {\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ public final Class<? extends WebPage> pageClass;\r
+ public final PageParameters params;\r
+\r
+ public PageNavLink(String translationKey, Class<? extends WebPage> pageClass) {\r
+ this(translationKey, pageClass, null);\r
+ }\r
+\r
+ public PageNavLink(String translationKey, Class<? extends WebPage> pageClass,\r
+ PageParameters params) {\r
+ this(translationKey, pageClass, params, false);\r
+ }\r
+\r
+ public PageNavLink(String translationKey, Class<? extends WebPage> pageClass,\r
+ PageParameters params, boolean hiddenPhone) {\r
+ super(translationKey, hiddenPhone);\r
+ this.pageClass = pageClass;\r
+ this.params = params;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Represents an explicitly href link.\r
+ *\r
+ * @author James Moger\r
+ *\r
+ */\r
+ public static class ExternalNavLink extends NavLink implements Serializable {\r
+\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ public final String url;\r
+\r
+ public ExternalNavLink(String keyOrText, String url) {\r
+ super(keyOrText, false);\r
+ this.url = url;\r
+ }\r
+\r
+ public ExternalNavLink(String keyOrText, String url, boolean hiddenPhone) {\r
+ super(keyOrText, hiddenPhone);\r
+ this.url = url;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Represents a DropDownMenu for the current page.\r
+ *\r
+ * @author James Moger\r
+ *\r
+ */\r
+ public static class DropDownPageMenuNavLink extends PageNavLink implements Serializable {\r
+\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ public final List<MenuItem> menuItems;\r
+\r
+ public DropDownPageMenuNavLink(String keyOrText, Class<? extends WebPage> pageClass) {\r
+ this(keyOrText, pageClass, false);\r
+ }\r
+\r
+ public DropDownPageMenuNavLink(String keyOrText, Class<? extends WebPage> pageClass, boolean hiddenPhone) {\r
+ super(keyOrText, pageClass, null, hiddenPhone);\r
+ menuItems = new ArrayList<MenuItem>();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Represents a DropDownMenu.\r
+ *\r
+ * @author James Moger\r
+ *\r
+ */\r
+ public static class DropDownMenuNavLink extends NavLink implements Serializable {\r
+\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ public final List<MenuItem> menuItems;\r
+\r
+ public DropDownMenuNavLink(String keyOrText) {\r
+ this(keyOrText, false);\r
+ }\r
+\r
+ public DropDownMenuNavLink(String keyOrText, boolean hiddenPhone) {\r
+ super(keyOrText, hiddenPhone);\r
+ menuItems = new ArrayList<MenuItem>();\r
+ }\r
+ }\r
+}
\ No newline at end of file
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.protocol.http.WebApplication;
+import ro.fortsoft.pf4j.PluginState;
+import ro.fortsoft.pf4j.PluginWrapper;
+
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
+import com.gitblit.extensions.GitblitWicketPlugin;
import com.gitblit.manager.IAuthenticationManager;
import com.gitblit.manager.IFederationManager;
import com.gitblit.manager.IGitblit;
import com.gitblit.wicket.pages.UserPage;
import com.gitblit.wicket.pages.UsersPage;
-public class GitBlitWebApp extends WebApplication {
+public class GitBlitWebApp extends WebApplication implements GitblitWicketApp {
private final Class<? extends WebPage> homePageClass = MyDashboardPage.class;
mount("/forks", ForksPage.class, "r");
mount("/fork", ForkPage.class, "r");
+ // allow started Wicket plugins to initialize
+ for (PluginWrapper pluginWrapper : pluginManager.getPlugins()) {
+ if (PluginState.STARTED != pluginWrapper.getPluginState()) {
+ continue;
+ }
+ if (pluginWrapper.getPlugin() instanceof GitblitWicketPlugin) {
+ GitblitWicketPlugin wicketPlugin = (GitblitWicketPlugin) pluginWrapper.getPlugin();
+ wicketPlugin.init(this);
+ }
+ }
+
+ // customize the Wicket class resolver to load from plugins
+ PluginClassResolver classResolver = new PluginClassResolver(pluginManager);
+ getApplicationSettings().setClassResolver(classResolver);
+
getMarkupSettings().setDefaultMarkupEncoding("UTF-8");
- super.init();
}
- private void mount(String location, Class<? extends WebPage> clazz, String... parameters) {
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#mount(java.lang.String, java.lang.Class, java.lang.String)
+ */
+ @Override
+ public void mount(String location, Class<? extends WebPage> clazz, String... parameters) {
if (parameters == null) {
parameters = new String[] {};
}
}
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#getHomePage()
+ */
@Override
public Class<? extends WebPage> getHomePage() {
return homePageClass;
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#isCacheablePage(java.lang.String)
+ */
+ @Override
public boolean isCacheablePage(String mountPoint) {
return cacheablePages.containsKey(mountPoint);
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#getCacheControl(java.lang.String)
+ */
+ @Override
public CacheControl getCacheControl(String mountPoint) {
return cacheablePages.get(mountPoint);
}
return gitBlitWebSession;
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#settings()
+ */
+ @Override
public IStoredSettings settings() {
return settings;
}
- /**
- * Is Gitblit running in debug mode?
- *
- * @return true if Gitblit is running in debug mode
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#isDebugMode()
*/
+ @Override
public boolean isDebugMode() {
return runtimeManager.isDebugMode();
}
* These methods look strange... and they are... but they are the first
* step towards modularization across multiple commits.
*/
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#getBootDate()
+ */
+ @Override
public Date getBootDate() {
return runtimeManager.getBootDate();
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#getLastActivityDate()
+ */
+ @Override
public Date getLastActivityDate() {
return repositoryManager.getLastActivityDate();
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#runtime()
+ */
+ @Override
public IRuntimeManager runtime() {
return runtimeManager;
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#plugins()
+ */
+ @Override
public IPluginManager plugins() {
return pluginManager;
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#notifier()
+ */
+ @Override
public INotificationManager notifier() {
return notificationManager;
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#users()
+ */
+ @Override
public IUserManager users() {
return userManager;
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#authentication()
+ */
+ @Override
public IAuthenticationManager authentication() {
return authenticationManager;
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#keys()
+ */
+ @Override
public IPublicKeyManager keys() {
return publicKeyManager;
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#repositories()
+ */
+ @Override
public IRepositoryManager repositories() {
return repositoryManager;
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#projects()
+ */
+ @Override
public IProjectManager projects() {
return projectManager;
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#federation()
+ */
+ @Override
public IFederationManager federation() {
return federationManager;
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#gitblit()
+ */
+ @Override
public IGitblit gitblit() {
return gitblit;
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#tickets()
+ */
+ @Override
public ITicketService tickets() {
return gitblit.getTicketService();
}
+ /* (non-Javadoc)
+ * @see com.gitblit.wicket.Webapp#getTimezone()
+ */
+ @Override
public TimeZone getTimezone() {
return runtimeManager.getTimezone();
}
--- /dev/null
+package com.gitblit.wicket;
+
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.apache.wicket.markup.html.WebPage;
+
+import com.gitblit.IStoredSettings;
+import com.gitblit.manager.IAuthenticationManager;
+import com.gitblit.manager.IFederationManager;
+import com.gitblit.manager.IGitblit;
+import com.gitblit.manager.INotificationManager;
+import com.gitblit.manager.IPluginManager;
+import com.gitblit.manager.IProjectManager;
+import com.gitblit.manager.IRepositoryManager;
+import com.gitblit.manager.IRuntimeManager;
+import com.gitblit.manager.IUserManager;
+import com.gitblit.tickets.ITicketService;
+import com.gitblit.transport.ssh.IPublicKeyManager;
+
+public interface GitblitWicketApp {
+
+ public abstract void mount(String location, Class<? extends WebPage> clazz, String... parameters);
+
+ public abstract Class<? extends WebPage> getHomePage();
+
+ public abstract boolean isCacheablePage(String mountPoint);
+
+ public abstract CacheControl getCacheControl(String mountPoint);
+
+ public abstract IStoredSettings settings();
+
+ /**
+ * Is Gitblit running in debug mode?
+ *
+ * @return true if Gitblit is running in debug mode
+ */
+ public abstract boolean isDebugMode();
+
+ /*
+ * These methods look strange... and they are... but they are the first
+ * step towards modularization across multiple commits.
+ */
+ public abstract Date getBootDate();
+
+ public abstract Date getLastActivityDate();
+
+ public abstract IRuntimeManager runtime();
+
+ public abstract IPluginManager plugins();
+
+ public abstract INotificationManager notifier();
+
+ public abstract IUserManager users();
+
+ public abstract IAuthenticationManager authentication();
+
+ public abstract IPublicKeyManager keys();
+
+ public abstract IRepositoryManager repositories();
+
+ public abstract IProjectManager projects();
+
+ public abstract IFederationManager federation();
+
+ public abstract IGitblit gitblit();
+
+ public abstract ITicketService tickets();
+
+ public abstract TimeZone getTimezone();
+
+}
\ No newline at end of file
+++ /dev/null
-/*\r
- * Copyright 2011 gitblit.com.\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package com.gitblit.wicket;\r
-\r
-import java.io.Serializable;\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-import org.apache.wicket.PageParameters;\r
-import org.apache.wicket.markup.html.WebPage;\r
-\r
-import com.gitblit.models.Menu.MenuItem;\r
-\r
-/**\r
- * Represents a page link registration for the topbar.\r
- *\r
- * @author James Moger\r
- *\r
- */\r
-public class PageRegistration implements Serializable {\r
- private static final long serialVersionUID = 1L;\r
-\r
- public final String translationKey;\r
- public final Class<? extends WebPage> pageClass;\r
- public final PageParameters params;\r
- public final boolean hiddenPhone;\r
-\r
- public PageRegistration(String translationKey, Class<? extends WebPage> pageClass) {\r
- this(translationKey, pageClass, null);\r
- }\r
-\r
- public PageRegistration(String translationKey, Class<? extends WebPage> pageClass,\r
- PageParameters params) {\r
- this(translationKey, pageClass, params, false);\r
- }\r
-\r
- public PageRegistration(String translationKey, Class<? extends WebPage> pageClass,\r
- PageParameters params, boolean hiddenPhone) {\r
- this.translationKey = translationKey;\r
- this.pageClass = pageClass;\r
- this.params = params;\r
- this.hiddenPhone = hiddenPhone;\r
- }\r
-\r
- /**\r
- * Represents a page link to a non-Wicket page. Might be external.\r
- *\r
- * @author James Moger\r
- *\r
- */\r
- public static class OtherPageLink extends PageRegistration {\r
-\r
- private static final long serialVersionUID = 1L;\r
-\r
- public final String url;\r
-\r
- public OtherPageLink(String keyOrText, String url) {\r
- super(keyOrText, null);\r
- this.url = url;\r
- }\r
-\r
- public OtherPageLink(String keyOrText, String url, boolean hiddenPhone) {\r
- super(keyOrText, null, null, hiddenPhone);\r
- this.url = url;\r
- }\r
- }\r
-\r
- /**\r
- * Represents a DropDownMenu for the topbar\r
- *\r
- * @author James Moger\r
- *\r
- */\r
- public static class DropDownMenuRegistration extends PageRegistration {\r
-\r
- private static final long serialVersionUID = 1L;\r
-\r
- public final List<MenuItem> menuItems;\r
-\r
- public DropDownMenuRegistration(String keyOrText, Class<? extends WebPage> pageClass) {\r
- super(keyOrText, pageClass);\r
- menuItems = new ArrayList<MenuItem>();\r
- }\r
- }\r
-\r
-}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.wicket;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.application.IClassResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ro.fortsoft.pf4j.PluginState;
+import ro.fortsoft.pf4j.PluginWrapper;
+
+import com.gitblit.manager.IPluginManager;
+
+/**
+ * Resolves plugin classes and resources.
+ */
+public class PluginClassResolver implements IClassResolver {
+ private static final Logger logger = LoggerFactory.getLogger(PluginClassResolver.class);
+
+ private final IPluginManager pluginManager;
+
+ public PluginClassResolver(IPluginManager pluginManager) {
+ this.pluginManager = pluginManager;
+ }
+
+ @Override
+ public Class<?> resolveClass(final String className) throws ClassNotFoundException {
+ boolean debugEnabled = logger.isDebugEnabled();
+
+ for (PluginWrapper plugin : pluginManager.getPlugins()) {
+ if (PluginState.STARTED != plugin.getPluginState()) {
+ // ignore this plugin
+ continue;
+ }
+
+ try {
+ return plugin.getPluginClassLoader().loadClass(className);
+ } catch (ClassNotFoundException cnfx) {
+ if (debugEnabled) {
+ logger.debug("ClassResolver '{}' cannot find class: '{}'", plugin.getPluginId(), className);
+ }
+ }
+ }
+
+ throw new ClassNotFoundException(className);
+ }
+
+ @Override
+ public Iterator<URL> getResources(final String name) {
+ Set<URL> urls = new TreeSet<URL>(new UrlExternalFormComparator());
+
+ for (PluginWrapper plugin : pluginManager.getPlugins()) {
+ if (PluginState.STARTED != plugin.getPluginState()) {
+ // ignore this plugin
+ continue;
+ }
+
+ Iterator<URL> it = getResources(name, plugin);
+ while (it.hasNext()) {
+ URL url = it.next();
+ urls.add(url);
+ }
+ }
+
+ return urls.iterator();
+ }
+
+ protected Iterator<URL> getResources(String name, PluginWrapper plugin) {
+ HashSet<URL> loadedFiles = new HashSet<URL>();
+ try {
+ // Try the classloader for the wicket jar/bundle
+ Enumeration<URL> resources = plugin.getPluginClassLoader().getResources(name);
+ loadResources(resources, loadedFiles);
+
+ // Try the classloader for the user's application jar/bundle
+ resources = Application.get().getClass().getClassLoader().getResources(name);
+ loadResources(resources, loadedFiles);
+
+ // Try the context class loader
+ resources = Thread.currentThread().getContextClassLoader().getResources(name);
+ loadResources(resources, loadedFiles);
+ } catch (IOException e) {
+ throw new WicketRuntimeException(e);
+ }
+
+ return loadedFiles.iterator();
+ }
+
+ private void loadResources(Enumeration<URL> resources, Set<URL> loadedFiles) {
+ if (resources != null) {
+ while (resources.hasMoreElements()) {
+ final URL url = resources.nextElement();
+ if (!loadedFiles.contains(url)) {
+ loadedFiles.add(url);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.wicket;
+
+import java.net.URL;
+import java.util.Comparator;
+
+/**
+ * A comparator of URL instances.
+ *
+ * Comparing URLs with their implementation of #equals() is
+ * bad because it may cause problems like DNS resolving, or other
+ * slow checks. This comparator uses the external form of an URL
+ * to make a simple comparison of two Strings.
+ *
+ * @since 1.5.6
+ */
+public class UrlExternalFormComparator implements Comparator<URL>
+{
+ @Override
+ public int compare(URL url1, URL url2)
+ {
+ return url1.toExternalForm().compareTo(url2.toExternalForm());
+ }
+}
\ No newline at end of file
import com.gitblit.Keys;\r
import com.gitblit.models.Activity;\r
import com.gitblit.models.Menu.ParameterMenuItem;\r
+import com.gitblit.models.NavLink.DropDownPageMenuNavLink;\r
import com.gitblit.models.Metric;\r
+import com.gitblit.models.NavLink;\r
import com.gitblit.models.RepositoryModel;\r
import com.gitblit.utils.ActivityUtils;\r
import com.gitblit.utils.StringUtils;\r
import com.gitblit.wicket.CacheControl;\r
import com.gitblit.wicket.CacheControl.LastModified;\r
-import com.gitblit.wicket.PageRegistration;\r
-import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;\r
import com.gitblit.wicket.WicketUtils;\r
import com.gitblit.wicket.charting.Chart;\r
import com.gitblit.wicket.charting.Charts;\r
}\r
\r
@Override\r
- protected void addDropDownMenus(List<PageRegistration> pages) {\r
- DropDownMenuRegistration filters = new DropDownMenuRegistration("gb.filters",\r
+ protected void addDropDownMenus(List<NavLink> navLinks) {\r
+ DropDownPageMenuNavLink filters = new DropDownPageMenuNavLink("gb.filters",\r
ActivityPage.class);\r
\r
PageParameters currentParameters = getPageParameters();\r
// Reset Filter\r
filters.menuItems.add(new ParameterMenuItem(getString("gb.reset")));\r
}\r
- pages.add(filters);\r
+ navLinks.add(filters);\r
}\r
\r
/**\r
import com.gitblit.Keys;\r
import com.gitblit.models.DailyLogEntry;\r
import com.gitblit.models.Menu.ParameterMenuItem;\r
+import com.gitblit.models.NavLink.DropDownPageMenuNavLink;\r
import com.gitblit.models.Metric;\r
+import com.gitblit.models.NavLink;\r
import com.gitblit.models.RefLogEntry;\r
import com.gitblit.models.RepositoryCommit;\r
import com.gitblit.models.RepositoryModel;\r
import com.gitblit.utils.RefLogUtils;\r
import com.gitblit.utils.StringUtils;\r
import com.gitblit.wicket.GitBlitWebApp;\r
-import com.gitblit.wicket.PageRegistration;\r
-import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;\r
import com.gitblit.wicket.charting.Chart;\r
import com.gitblit.wicket.charting.Charts;\r
import com.gitblit.wicket.charting.Flotr2Charts;\r
}\r
\r
@Override\r
- protected void addDropDownMenus(List<PageRegistration> pages) {\r
+ protected void addDropDownMenus(List<NavLink> navLinks) {\r
PageParameters params = getPageParameters();\r
\r
- DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters",\r
+ DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters",\r
GitBlitWebApp.get().getHomePage());\r
\r
// preserve repository filter option on time choices\r
menu.menuItems.add(new ParameterMenuItem(getString("gb.reset")));\r
}\r
\r
- pages.add(menu);\r
+ navLinks.add(menu);\r
}\r
\r
\r
import com.gitblit.models.Menu.MenuDivider;\r
import com.gitblit.models.Menu.MenuItem;\r
import com.gitblit.models.Menu.ParameterMenuItem;\r
+import com.gitblit.models.NavLink.DropDownPageMenuNavLink;\r
+import com.gitblit.models.NavLink;\r
import com.gitblit.models.ProjectModel;\r
import com.gitblit.models.RepositoryModel;\r
import com.gitblit.models.UserModel;\r
import com.gitblit.wicket.GitBlitWebApp;\r
import com.gitblit.wicket.GitBlitWebSession;\r
import com.gitblit.wicket.GitblitRedirectException;\r
-import com.gitblit.wicket.PageRegistration;\r
-import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;\r
import com.gitblit.wicket.WicketUtils;\r
import com.gitblit.wicket.panels.FilterableRepositoryList;\r
\r
}\r
\r
@Override\r
- protected void addDropDownMenus(List<PageRegistration> pages) {\r
+ protected void addDropDownMenus(List<NavLink> navLinks) {\r
PageParameters params = getPageParameters();\r
\r
- DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters",\r
+ DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters",\r
ProjectPage.class);\r
// preserve time filter option on repository choices\r
menu.menuItems.addAll(getRepositoryFilterItems(params));\r
menu.menuItems.add(new ParameterMenuItem(getString("gb.reset"), "p", WicketUtils.getProjectName(params)));\r
}\r
\r
- pages.add(menu);\r
+ navLinks.add(menu);\r
\r
- DropDownMenuRegistration projects = new DropDownMenuRegistration("gb.projects",\r
+ DropDownPageMenuNavLink projects = new DropDownPageMenuNavLink("gb.projects",\r
ProjectPage.class);\r
projects.menuItems.addAll(getProjectsMenu());\r
- pages.add(projects);\r
+ navLinks.add(projects);\r
}\r
\r
@Override\r
\r
import com.gitblit.Keys;\r
import com.gitblit.models.Menu.ParameterMenuItem;\r
+import com.gitblit.models.NavLink.DropDownPageMenuNavLink;\r
+import com.gitblit.models.NavLink;\r
import com.gitblit.models.ProjectModel;\r
import com.gitblit.wicket.GitBlitWebSession;\r
-import com.gitblit.wicket.PageRegistration;\r
-import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;\r
import com.gitblit.wicket.WicketUtils;\r
import com.gitblit.wicket.panels.LinkPanel;\r
\r
}\r
\r
@Override\r
- protected void addDropDownMenus(List<PageRegistration> pages) {\r
+ protected void addDropDownMenus(List<NavLink> navLinks) {\r
PageParameters params = getPageParameters();\r
\r
- DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters",\r
+ DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters",\r
ProjectsPage.class);\r
// preserve time filter option on repository choices\r
menu.menuItems.addAll(getRepositoryFilterItems(params));\r
menu.menuItems.add(new ParameterMenuItem(getString("gb.reset")));\r
}\r
\r
- pages.add(menu);\r
+ navLinks.add(menu);\r
}\r
}\r
\r
import com.gitblit.Keys;\r
import com.gitblit.models.Menu.ParameterMenuItem;\r
+import com.gitblit.models.NavLink.DropDownPageMenuNavLink;\r
+import com.gitblit.models.NavLink;\r
import com.gitblit.models.RepositoryModel;\r
import com.gitblit.utils.MarkdownUtils;\r
import com.gitblit.utils.StringUtils;\r
import com.gitblit.wicket.CacheControl;\r
import com.gitblit.wicket.CacheControl.LastModified;\r
import com.gitblit.wicket.GitBlitWebSession;\r
-import com.gitblit.wicket.PageRegistration;\r
-import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;\r
import com.gitblit.wicket.WicketUtils;\r
import com.gitblit.wicket.panels.RepositoriesPanel;\r
\r
}\r
\r
@Override\r
- protected void addDropDownMenus(List<PageRegistration> pages) {\r
+ protected void addDropDownMenus(List<NavLink> navLinks) {\r
PageParameters params = getPageParameters();\r
\r
- DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters",\r
+ DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters",\r
RepositoriesPage.class);\r
// preserve time filter option on repository choices\r
menu.menuItems.addAll(getRepositoryFilterItems(params));\r
menu.menuItems.add(new ParameterMenuItem(getString("gb.reset")));\r
}\r
\r
- pages.add(menu);\r
+ navLinks.add(menu);\r
}\r
\r
private String readMarkdown(String messageSource, String resource) {\r
import java.util.Arrays;\r
import java.util.Date;\r
import java.util.HashMap;\r
-import java.util.LinkedHashMap;\r
import java.util.LinkedHashSet;\r
import java.util.List;\r
import java.util.Map;\r
import com.gitblit.Constants;\r
import com.gitblit.GitBlitException;\r
import com.gitblit.Keys;\r
+import com.gitblit.extensions.RepositoryNavLinkExtension;\r
+import com.gitblit.models.NavLink;\r
+import com.gitblit.models.NavLink.ExternalNavLink;\r
+import com.gitblit.models.NavLink.PageNavLink;\r
import com.gitblit.models.ProjectModel;\r
import com.gitblit.models.RefModel;\r
import com.gitblit.models.RepositoryModel;\r
import com.gitblit.utils.StringUtils;\r
import com.gitblit.wicket.CacheControl;\r
import com.gitblit.wicket.GitBlitWebSession;\r
-import com.gitblit.wicket.PageRegistration;\r
-import com.gitblit.wicket.PageRegistration.OtherPageLink;\r
import com.gitblit.wicket.SessionlessForm;\r
import com.gitblit.wicket.TicketsUI;\r
import com.gitblit.wicket.WicketUtils;\r
\r
private Map<String, SubmoduleModel> submodules;\r
\r
- private final Map<String, PageRegistration> registeredPages;\r
private boolean showAdmin;\r
private boolean isOwner;\r
\r
}\r
}\r
\r
- // register the available page links for this page and user\r
- registeredPages = registerPages();\r
+ // register the available navigation links for this page and user\r
+ List<NavLink> navLinks = registerNavLinks();\r
\r
- // standard page links\r
- List<PageRegistration> pages = new ArrayList<PageRegistration>(registeredPages.values());\r
- NavigationPanel navigationPanel = new NavigationPanel("repositoryNavPanel", getRepoNavPageClass(), pages);\r
+ // standard navigation links\r
+ NavigationPanel navigationPanel = new NavigationPanel("repositoryNavPanel", getRepoNavPageClass(), navLinks);\r
add(navigationPanel);\r
\r
add(new ExternalLink("syndication", SyndicationServlet.asLink(getRequest()\r
return new BugtraqProcessor(app().settings());\r
}\r
\r
- private Map<String, PageRegistration> registerPages() {\r
+ private List<NavLink> registerNavLinks() {\r
PageParameters params = null;\r
if (!StringUtils.isEmpty(repositoryName)) {\r
params = WicketUtils.newRepositoryParameter(repositoryName);\r
}\r
- Map<String, PageRegistration> pages = new LinkedHashMap<String, PageRegistration>();\r
+ List<NavLink> navLinks = new ArrayList<NavLink>();\r
\r
Repository r = getRepository();\r
RepositoryModel model = getRepositoryModel();\r
\r
// standard links\r
if (RefLogUtils.getRefLogBranch(r) == null) {\r
- pages.put("summary", new PageRegistration("gb.summary", SummaryPage.class, params));\r
+ navLinks.add(new PageNavLink("gb.summary", SummaryPage.class, params));\r
} else {\r
- pages.put("summary", new PageRegistration("gb.summary", SummaryPage.class, params));\r
+ navLinks.add(new PageNavLink("gb.summary", SummaryPage.class, params));\r
// pages.put("overview", new PageRegistration("gb.overview", OverviewPage.class, params));\r
- pages.put("reflog", new PageRegistration("gb.reflog", ReflogPage.class, params));\r
+ navLinks.add(new PageNavLink("gb.reflog", ReflogPage.class, params));\r
}\r
- pages.put("commits", new PageRegistration("gb.commits", LogPage.class, params));\r
- pages.put("tree", new PageRegistration("gb.tree", TreePage.class, params));\r
+ navLinks.add(new PageNavLink("gb.commits", LogPage.class, params));\r
+ navLinks.add(new PageNavLink("gb.tree", TreePage.class, params));\r
if (app().tickets().isReady() && (app().tickets().isAcceptingNewTickets(getRepositoryModel()) || app().tickets().hasTickets(getRepositoryModel()))) {\r
PageParameters tParams = new PageParameters(params);\r
for (String state : TicketsUI.openStatii) {\r
tParams.add(Lucene.status.name(), state);\r
}\r
- pages.put("tickets", new PageRegistration("gb.tickets", TicketsPage.class, tParams));
+ navLinks.add(new PageNavLink("gb.tickets", TicketsPage.class, tParams));
}
- pages.put("docs", new PageRegistration("gb.docs", DocsPage.class, params, true));\r
+ navLinks.add(new PageNavLink("gb.docs", DocsPage.class, params, true));\r
if (app().settings().getBoolean(Keys.web.allowForking, true)) {\r
- pages.put("forks", new PageRegistration("gb.forks", ForksPage.class, params, true));\r
+ navLinks.add(new PageNavLink("gb.forks", ForksPage.class, params, true));\r
}\r
- pages.put("compare", new PageRegistration("gb.compare", ComparePage.class, params, true));
+ navLinks.add(new PageNavLink("gb.compare", ComparePage.class, params, true));
\r
// conditional links\r
- // per-repository extra page links\r
+ // per-repository extra navlinks\r
if (JGitUtils.getPagesBranch(r) != null) {\r
- OtherPageLink pagesLink = new OtherPageLink("gb.pages", PagesServlet.asLink(\r
+ ExternalNavLink pagesLink = new ExternalNavLink("gb.pages", PagesServlet.asLink(\r
getRequest().getRelativePathPrefixToContextRoot(), repositoryName, null), true);\r
- pages.put("pages", pagesLink);\r
+ navLinks.add(pagesLink);\r
+ }\r
+\r
+ UserModel user = UserModel.ANONYMOUS;\r
+ if (GitBlitWebSession.get().isLoggedIn()) {\r
+ user = GitBlitWebSession.get().getUser();\r
+ }\r
+\r
+ // add repository nav link extensions\r
+ List<RepositoryNavLinkExtension> extensions = app().plugins().getExtensions(RepositoryNavLinkExtension.class);\r
+ for (RepositoryNavLinkExtension ext : extensions) {\r
+ navLinks.addAll(ext.getNavLinks(user, model));\r
}\r
\r
// Conditionally add edit link\r
showAdmin = app().settings().getBoolean(Keys.web.allowAdministration, false);\r
}\r
isOwner = GitBlitWebSession.get().isLoggedIn()\r
- && (model.isOwner(GitBlitWebSession.get()\r
- .getUsername()));\r
- return pages;\r
+ && (model.isOwner(GitBlitWebSession.get().getUsername()));\r
+ return navLinks;\r
}\r
\r
protected boolean allowForkControls() {\r
import com.gitblit.Constants;
import com.gitblit.Keys;
+import com.gitblit.extensions.NavLinkExtension;
import com.gitblit.extensions.UserMenuExtension;
import com.gitblit.models.Menu.ExternalLinkMenuItem;
import com.gitblit.models.Menu.MenuDivider;
import com.gitblit.models.Menu.PageLinkMenuItem;
import com.gitblit.models.Menu.ParameterMenuItem;
import com.gitblit.models.Menu.ToggleMenuItem;
+import com.gitblit.models.NavLink;
+import com.gitblit.models.NavLink.PageNavLink;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ModelUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebSession;
-import com.gitblit.wicket.PageRegistration;
import com.gitblit.wicket.SessionlessForm;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.panels.GravatarImage;
}
// navigation links
- List<PageRegistration> pages = new ArrayList<PageRegistration>();
+ List<NavLink> navLinks = new ArrayList<NavLink>();
if (!authenticateView || (authenticateView && isLoggedIn)) {
- pages.add(new PageRegistration(isLoggedIn ? "gb.myDashboard" : "gb.dashboard", MyDashboardPage.class,
+ navLinks.add(new PageNavLink(isLoggedIn ? "gb.myDashboard" : "gb.dashboard", MyDashboardPage.class,
getRootPageParameters()));
if (isLoggedIn && app().tickets().isReady()) {
- pages.add(new PageRegistration("gb.myTickets", MyTicketsPage.class));
+ navLinks.add(new PageNavLink("gb.myTickets", MyTicketsPage.class));
}
- pages.add(new PageRegistration("gb.repositories", RepositoriesPage.class,
+ navLinks.add(new PageNavLink("gb.repositories", RepositoriesPage.class,
getRootPageParameters()));
- pages.add(new PageRegistration("gb.activity", ActivityPage.class, getRootPageParameters()));
+ navLinks.add(new PageNavLink("gb.activity", ActivityPage.class, getRootPageParameters()));
if (allowLucene) {
- pages.add(new PageRegistration("gb.search", LuceneSearchPage.class));
+ navLinks.add(new PageNavLink("gb.search", LuceneSearchPage.class));
}
- UserModel user = GitBlitWebSession.get().getUser();
-
- if (showAdmin) {
- // admin dropdown menu
- DropDownMenuRegistration adminMenu = new DropDownMenuRegistration("gb.adminMenuItem", MyDashboardPage.class);
-
- adminMenu.menuItems.add(new PageLinkMenuItem(getString("gb.users"), UsersPage.class));
-
- boolean showRegistrations = app().federation().canFederate()
- && app().settings().getBoolean(Keys.web.showFederationRegistrations, false);
- if (showRegistrations) {
- adminMenu.menuItems.add(new PageLinkMenuItem(getString("gb.federation"), FederationPage.class));
- }
-
- // allow plugins to contribute admin menu items
- List<AdminMenuExtension> extensions = app().plugins().getExtensions(AdminMenuExtension.class);
- for (AdminMenuExtension ext : extensions) {
- adminMenu.menuItems.add(new MenuDivider());
- adminMenu.menuItems.addAll(ext.getMenuItems(user));
- }
+ if (!authenticateView || (authenticateView && isLoggedIn)) {
+ addDropDownMenus(navLinks);
+ }
- pages.add(adminMenu);
+ UserModel user = UserModel.ANONYMOUS;
+ if (isLoggedIn) {
+ user = GitBlitWebSession.get().getUser();
}
- if (!authenticateView || (authenticateView && isLoggedIn)) {
- addDropDownMenus(pages);
+ // add nav link extensions
+ List<NavLinkExtension> extensions = app().plugins().getExtensions(NavLinkExtension.class);
+ for (NavLinkExtension ext : extensions) {
+ navLinks.addAll(ext.getNavLinks(user));
}
}
- NavigationPanel navPanel = new NavigationPanel("navPanel", getRootNavPageClass(), pages);
+ NavigationPanel navPanel = new NavigationPanel("navPanel", getRootNavPageClass(), navLinks);
add(navPanel);
// display an error message cached from a redirect
return repositoryModels;
}
- protected void addDropDownMenus(List<PageRegistration> pages) {
+ protected void addDropDownMenus(List<NavLink> navLinks) {
}
\r
import com.gitblit.Keys;\r
import com.gitblit.models.Menu.ParameterMenuItem;\r
+import com.gitblit.models.NavLink.DropDownPageMenuNavLink;\r
+import com.gitblit.models.NavLink;\r
import com.gitblit.models.ProjectModel;\r
import com.gitblit.models.RepositoryModel;\r
import com.gitblit.models.UserModel;\r
import com.gitblit.wicket.GitBlitWebApp;\r
import com.gitblit.wicket.GitBlitWebSession;\r
import com.gitblit.wicket.GitblitRedirectException;\r
-import com.gitblit.wicket.PageRegistration;\r
-import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;\r
import com.gitblit.wicket.WicketUtils;\r
import com.gitblit.wicket.panels.GravatarImage;\r
import com.gitblit.wicket.panels.LinkPanel;\r
}\r
\r
@Override\r
- protected void addDropDownMenus(List<PageRegistration> pages) {\r
+ protected void addDropDownMenus(List<NavLink> navLinks) {\r
PageParameters params = getPageParameters();\r
\r
- DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters",\r
+ DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters",\r
UserPage.class);\r
// preserve time filter option on repository choices\r
menu.menuItems.addAll(getRepositoryFilterItems(params));\r
menu.menuItems.add(new ParameterMenuItem(getString("gb.reset")));\r
}\r
\r
- pages.add(menu);\r
+ navLinks.add(menu);\r
}\r
}\r
import org.apache.wicket.markup.repeater.data.DataView;\r
import org.apache.wicket.markup.repeater.data.ListDataProvider;\r
\r
-import com.gitblit.models.Menu.MenuDivider;\r
import com.gitblit.models.Menu.ExternalLinkMenuItem;\r
+import com.gitblit.models.Menu.MenuDivider;\r
import com.gitblit.models.Menu.MenuItem;\r
import com.gitblit.models.Menu.PageLinkMenuItem;\r
import com.gitblit.models.Menu.ParameterMenuItem;\r
-import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;\r
+import com.gitblit.models.NavLink.DropDownMenuNavLink;\r
+import com.gitblit.models.NavLink.DropDownPageMenuNavLink;\r
import com.gitblit.wicket.WicketUtils;\r
\r
public class DropDownMenu extends Panel {\r
\r
private static final long serialVersionUID = 1L;\r
\r
- public DropDownMenu(String id, String label, final DropDownMenuRegistration menu) {\r
+ public DropDownMenu(String id, String label, final DropDownPageMenuNavLink menu) {\r
super(id);\r
\r
add(new Label("label", label).setRenderBodyOnly(true));\r
- ListDataProvider<MenuItem> items = new ListDataProvider<MenuItem>(\r
- menu.menuItems);\r
+ ListDataProvider<MenuItem> items = new ListDataProvider<MenuItem>(menu.menuItems);\r
DataView<MenuItem> view = new DataView<MenuItem>("menuItems", items) {\r
private static final long serialVersionUID = 1L;\r
\r
add(view);\r
setRenderBodyOnly(true);\r
}\r
+\r
+ public DropDownMenu(String id, String label, final DropDownMenuNavLink menu) {\r
+ super(id);\r
+\r
+ add(new Label("label", label).setRenderBodyOnly(true));\r
+ ListDataProvider<MenuItem> items = new ListDataProvider<MenuItem>(menu.menuItems);\r
+ DataView<MenuItem> view = new DataView<MenuItem>("menuItems", items) {\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ @Override\r
+ public void populateItem(final Item<MenuItem> item) {\r
+ MenuItem entry = item.getModelObject();\r
+ if (entry instanceof PageLinkMenuItem) {\r
+ // link to another Wicket page\r
+ PageLinkMenuItem pageLink = (PageLinkMenuItem) entry;\r
+ item.add(new LinkPanel("menuItem", null, null, pageLink.toString(), pageLink.getPageClass(),\r
+ pageLink.getPageParameters(), false).setRenderBodyOnly(true));\r
+ } else if (entry instanceof ExternalLinkMenuItem) {\r
+ // link to a specified href\r
+ ExternalLinkMenuItem extLink = (ExternalLinkMenuItem) entry;\r
+ item.add(new LinkPanel("menuItem", null, extLink.toString(), extLink.getHref(),\r
+ extLink.openInNewWindow()).setRenderBodyOnly(true));\r
+ } else if (entry instanceof MenuDivider) {\r
+ // divider\r
+ item.add(new Label("menuItem").setRenderBodyOnly(true));\r
+ WicketUtils.setCssClass(item, "divider");\r
+ } else {\r
+ throw new IllegalArgumentException(String.format("Unexpected menuitem type %s",\r
+ entry.getClass().getSimpleName()));\r
+ }\r
+ }\r
+ };\r
+ add(view);\r
+ setRenderBodyOnly(true);\r
+ }\r
}
\ No newline at end of file
import org.apache.wicket.markup.repeater.data.DataView;\r
import org.apache.wicket.markup.repeater.data.ListDataProvider;\r
\r
-import com.gitblit.wicket.PageRegistration;\r
-import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;\r
-import com.gitblit.wicket.PageRegistration.OtherPageLink;\r
+import com.gitblit.models.NavLink;\r
+import com.gitblit.models.NavLink.DropDownMenuNavLink;\r
+import com.gitblit.models.NavLink.DropDownPageMenuNavLink;\r
+import com.gitblit.models.NavLink.ExternalNavLink;\r
+import com.gitblit.models.NavLink.PageNavLink;\r
import com.gitblit.wicket.WicketUtils;\r
import com.gitblit.wicket.pages.BasePage;\r
\r
private static final long serialVersionUID = 1L;\r
\r
public NavigationPanel(String id, final Class<? extends BasePage> pageClass,\r
- List<PageRegistration> registeredPages) {\r
+ List<NavLink> navLinks) {\r
super(id);\r
\r
- ListDataProvider<PageRegistration> refsDp = new ListDataProvider<PageRegistration>(\r
- registeredPages);\r
- DataView<PageRegistration> refsView = new DataView<PageRegistration>("navLink", refsDp) {\r
+ ListDataProvider<NavLink> refsDp = new ListDataProvider<NavLink>(navLinks);\r
+ DataView<NavLink> linksView = new DataView<NavLink>("navLink", refsDp) {\r
private static final long serialVersionUID = 1L;\r
\r
@Override\r
- public void populateItem(final Item<PageRegistration> item) {\r
- PageRegistration entry = item.getModelObject();\r
- String linkText = entry.translationKey;\r
+ public void populateItem(final Item<NavLink> item) {\r
+ NavLink navLink = item.getModelObject();\r
+ String linkText = navLink.translationKey;\r
try {\r
// try to lookup translation key\r
- linkText = getString(entry.translationKey);\r
+ linkText = getString(navLink.translationKey);\r
} catch (Exception e) {\r
}\r
\r
- if (entry.hiddenPhone) {\r
+ if (navLink.hiddenPhone) {\r
WicketUtils.setCssClass(item, "hidden-phone");\r
}\r
- if (entry instanceof OtherPageLink) {\r
+ if (navLink instanceof ExternalNavLink) {\r
// other link\r
- OtherPageLink link = (OtherPageLink) entry;\r
+ ExternalNavLink link = (ExternalNavLink) navLink;\r
Component c = new LinkPanel("link", null, linkText, link.url);\r
c.setRenderBodyOnly(true);\r
item.add(c);\r
- } else if (entry instanceof DropDownMenuRegistration) {\r
+ } else if (navLink instanceof DropDownPageMenuNavLink) {\r
// drop down menu\r
- DropDownMenuRegistration reg = (DropDownMenuRegistration) entry;\r
+ DropDownPageMenuNavLink reg = (DropDownPageMenuNavLink) navLink;\r
Component c = new DropDownMenu("link", linkText, reg);\r
c.setRenderBodyOnly(true);\r
item.add(c);\r
WicketUtils.setCssClass(item, "dropdown");\r
- } else {\r
+ } else if (navLink instanceof DropDownMenuNavLink) {\r
+ // drop down menu\r
+ DropDownMenuNavLink reg = (DropDownMenuNavLink) navLink;\r
+ Component c = new DropDownMenu("link", linkText, reg);\r
+ c.setRenderBodyOnly(true);\r
+ item.add(c);\r
+ WicketUtils.setCssClass(item, "dropdown");\r
+ } else if (navLink instanceof PageNavLink) {\r
+ PageNavLink reg = (PageNavLink) navLink;\r
// standard page link\r
Component c = new LinkPanel("link", null, linkText,\r
- entry.pageClass, entry.params);\r
+ reg.pageClass, reg.params);\r
c.setRenderBodyOnly(true);\r
- if (entry.pageClass.equals(pageClass)) {\r
+ if (reg.pageClass.equals(pageClass)) {\r
WicketUtils.setCssClass(item, "active");\r
}\r
item.add(c);\r
}\r
}\r
};\r
- add(refsView);\r
+ add(linksView);\r
}\r
}
\ No newline at end of file
public void onUninstall() {
}
}
+
+/**
+ * You can also create Webapp plugins that register mounted pages.
+ */
+public class ExampleWicketPlugin extends GitblitWicketPlugin {
+ @Override
+ public void start() {
+ }
+
+ @Override
+ public void stop() {
+ }
+
+ @Override
+ public void onInstall() {
+ }
+
+ @Override
+ public void onUpgrade(Version oldVersion) {
+ }
+
+ @Override
+ public void onUninstall() {
+ }
+
+ @Override
+ protected void init(GitblitWicketApp app) {
+ app.mount("/logo", LogoPage.class);
+ app.mount("/hello", HelloWorldPage.class);
+ }
+}
```
### SSH Dispatch Command
@Override
public List<MenuItem> getMenuItems(UserModel user) {
- return Arrays.asList((MenuItem) new ExternalLinkMenuItem("Github", String.format("https://github.com/%s", user.username));
+ MenuItem item = new ExternalLinkMenuItem("Github", String.format("https://github.com/%s", user.username));
+ return Arrays.asList(item);
+ }
+}
+```
+
+### Navigation Links
+
+*SINCE 1.6.0*
+
+You can provide your own top-level navigation links by subclassing the *NavLinkExtension* class.
+
+```java
+import java.util.Arrays;
+import java.util.List;
+import ro.fortsoft.pf4j.Extension;
+import com.gitblit.extensions.NavLinkExtension;
+import com.gitblit.models.UserModel;
+
+@Extension
+public class MyNavLink extends NavLinkExtension {
+
+ @Override
+ public List<NavLink> getNavLinks(UserModel user) {
+ NavLink link = new ExternalLinkMenuItem("Github", String.format("https://github.com/%s", user.username));
+ return Arrays.asList(link);
}
}
```