| // Copyright (C) 2008 The Android Open Source Project |
| // |
| // 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.google.gerrit.client; |
| |
| import static com.google.gerrit.common.PageLinks.ADMIN_GROUPS; |
| import static com.google.gerrit.common.PageLinks.ADMIN_PROJECTS; |
| import static com.google.gerrit.common.PageLinks.MINE; |
| import static com.google.gerrit.common.PageLinks.REGISTER; |
| import static com.google.gerrit.common.PageLinks.SETTINGS; |
| import static com.google.gerrit.common.PageLinks.SETTINGS_AGREEMENTS; |
| import static com.google.gerrit.common.PageLinks.SETTINGS_CONTACT; |
| import static com.google.gerrit.common.PageLinks.SETTINGS_HTTP_PASSWORD; |
| import static com.google.gerrit.common.PageLinks.SETTINGS_MYGROUPS; |
| import static com.google.gerrit.common.PageLinks.SETTINGS_NEW_AGREEMENT; |
| import static com.google.gerrit.common.PageLinks.SETTINGS_PREFERENCES; |
| import static com.google.gerrit.common.PageLinks.SETTINGS_PROJECTS; |
| import static com.google.gerrit.common.PageLinks.SETTINGS_SSHKEYS; |
| import static com.google.gerrit.common.PageLinks.SETTINGS_WEBIDENT; |
| import static com.google.gerrit.common.PageLinks.op; |
| |
| import com.google.gerrit.client.account.MyAgreementsScreen; |
| import com.google.gerrit.client.account.MyContactInformationScreen; |
| import com.google.gerrit.client.account.MyGroupsScreen; |
| import com.google.gerrit.client.account.MyIdentitiesScreen; |
| import com.google.gerrit.client.account.MyPasswordScreen; |
| import com.google.gerrit.client.account.MyPreferencesScreen; |
| import com.google.gerrit.client.account.MyProfileScreen; |
| import com.google.gerrit.client.account.MySshKeysScreen; |
| import com.google.gerrit.client.account.MyWatchedProjectsScreen; |
| import com.google.gerrit.client.account.NewAgreementScreen; |
| import com.google.gerrit.client.account.RegisterScreen; |
| import com.google.gerrit.client.account.ValidateEmailScreen; |
| import com.google.gerrit.client.admin.AccountGroupScreen; |
| import com.google.gerrit.client.admin.GroupListScreen; |
| import com.google.gerrit.client.admin.ProjectAccessScreen; |
| import com.google.gerrit.client.admin.ProjectBranchesScreen; |
| import com.google.gerrit.client.admin.ProjectInfoScreen; |
| import com.google.gerrit.client.admin.ProjectListScreen; |
| import com.google.gerrit.client.admin.ProjectScreen; |
| import com.google.gerrit.client.auth.openid.OpenIdSignInDialog; |
| import com.google.gerrit.client.auth.userpass.UserPassSignInDialog; |
| import com.google.gerrit.client.changes.AccountDashboardScreen; |
| import com.google.gerrit.client.changes.ChangeScreen; |
| import com.google.gerrit.client.changes.PatchTable; |
| import com.google.gerrit.client.changes.PublishCommentScreen; |
| import com.google.gerrit.client.changes.QueryScreen; |
| import com.google.gerrit.client.patches.PatchScreen; |
| import com.google.gerrit.client.ui.Screen; |
| import com.google.gerrit.common.auth.SignInMode; |
| import com.google.gerrit.common.data.PatchSetDetail; |
| import com.google.gerrit.reviewdb.Account; |
| import com.google.gerrit.reviewdb.AccountGroup; |
| import com.google.gerrit.reviewdb.Change; |
| import com.google.gerrit.reviewdb.Patch; |
| import com.google.gerrit.reviewdb.PatchSet; |
| import com.google.gerrit.reviewdb.Project; |
| import com.google.gwt.core.client.GWT; |
| import com.google.gwt.core.client.RunAsyncCallback; |
| import com.google.gwtorm.client.KeyUtil; |
| |
| public class Dispatcher { |
| public static String toPatchSideBySide(final Patch.Key id) { |
| return toPatch("sidebyside", id); |
| } |
| |
| public static String toPatchUnified(final Patch.Key id) { |
| return toPatch("unified", id); |
| } |
| |
| public static String toPatch(final String type, final Patch.Key id) { |
| return "patch," + type + "," + id.toString(); |
| } |
| |
| public static String toAccountGroup(final AccountGroup.Id id) { |
| return "admin,group," + id.toString(); |
| } |
| |
| public static String toProjectAdmin(final Project.NameKey n, final String tab) { |
| return "admin,project," + n.toString() + "," + tab; |
| } |
| |
| static final String RELOAD_UI = "reload-ui,"; |
| private static boolean wasStartedByReloadUI; |
| |
| void display(String token) { |
| assert token != null; |
| try { |
| try { |
| if (token.startsWith(RELOAD_UI)) { |
| wasStartedByReloadUI = true; |
| token = skip(RELOAD_UI, token); |
| } |
| select(token); |
| } finally { |
| wasStartedByReloadUI = false; |
| } |
| } catch (RuntimeException err) { |
| GWT.log("Error parsing history token: " + token, err); |
| Gerrit.display(token, new NotFoundScreen()); |
| } |
| } |
| |
| private static void select(final String token) { |
| if (token.startsWith("patch,")) { |
| patch(token, null, 0, null, null); |
| |
| } else if (token.startsWith("change,publish,")) { |
| publish(token); |
| |
| } else if (MINE.equals(token) || token.startsWith("mine,")) { |
| Gerrit.display(token, mine(token)); |
| |
| } else if (token.startsWith("all,")) { |
| Gerrit.display(token, all(token)); |
| |
| } else if (token.startsWith("project,")) { |
| Gerrit.display(token, project(token)); |
| |
| } else if (SETTINGS.equals(token) // |
| || REGISTER.equals(token) // |
| || token.startsWith("settings,") // |
| || token.startsWith("register,") // |
| || token.startsWith("VE,") // |
| || token.startsWith("SignInFailure,")) { |
| settings(token); |
| |
| } else if (token.startsWith("admin,")) { |
| admin(token); |
| |
| } else { |
| Gerrit.display(token, core(token)); |
| } |
| } |
| |
| private static Screen mine(final String token) { |
| if (MINE.equals(token)) { |
| if (Gerrit.isSignedIn()) { |
| return new AccountDashboardScreen(Gerrit.getUserAccount().getId()); |
| |
| } else { |
| final Screen r = new AccountDashboardScreen(null); |
| r.setRequiresSignIn(true); |
| return r; |
| } |
| |
| } else if ("mine,starred".equals(token)) { |
| return QueryScreen.forQuery("is:starred"); |
| |
| } else if ("mine,drafts".equals(token)) { |
| return QueryScreen.forQuery("has:draft"); |
| |
| } else { |
| String p = "mine,watched,"; |
| if (token.startsWith(p)) { |
| return QueryScreen.forQuery("is:watched status:open", skip(p, token)); |
| } |
| |
| return new NotFoundScreen(); |
| } |
| } |
| |
| private static Screen all(final String token) { |
| String p; |
| |
| p = "all,abandoned,"; |
| if (token.startsWith(p)) { |
| return QueryScreen.forQuery("status:abandoned", skip(p, token)); |
| } |
| |
| p = "all,merged,"; |
| if (token.startsWith(p)) { |
| return QueryScreen.forQuery("status:merged", skip(p, token)); |
| } |
| |
| p = "all,open,"; |
| if (token.startsWith(p)) { |
| return QueryScreen.forQuery("status:open", skip(p, token)); |
| } |
| |
| return new NotFoundScreen(); |
| } |
| |
| private static Screen project(final String token) { |
| String p; |
| |
| p = "project,open,"; |
| if (token.startsWith(p)) { |
| final String s = skip(p, token); |
| final int c = s.indexOf(','); |
| Project.NameKey proj = Project.NameKey.parse(s.substring(0, c)); |
| return QueryScreen.forQuery( // |
| "status:open " + op("project", proj.get()), // |
| s.substring(c + 1)); |
| } |
| |
| p = "project,merged,"; |
| if (token.startsWith(p)) { |
| final String s = skip(p, token); |
| final int c = s.indexOf(','); |
| Project.NameKey proj = Project.NameKey.parse(s.substring(0, c)); |
| return QueryScreen.forQuery( // |
| "status:merged " + op("project", proj.get()), // |
| s.substring(c + 1)); |
| } |
| |
| p = "project,abandoned,"; |
| if (token.startsWith(p)) { |
| final String s = skip(p, token); |
| final int c = s.indexOf(','); |
| Project.NameKey proj = Project.NameKey.parse(s.substring(0, c)); |
| return QueryScreen.forQuery( // |
| "status:abandoned " + op("project", proj.get()), // |
| s.substring(c + 1)); |
| } |
| |
| return new NotFoundScreen(); |
| } |
| |
| private static Screen core(final String token) { |
| String p; |
| |
| p = "change,"; |
| if (token.startsWith(p)) |
| return new ChangeScreen(Change.Id.parse(skip(p, token))); |
| |
| p = "dashboard,"; |
| if (token.startsWith(p)) |
| return new AccountDashboardScreen(Account.Id.parse(skip(p, token))); |
| |
| p = "q,"; |
| if (token.startsWith(p)) { |
| final String s = skip(p, token); |
| final int c = s.indexOf(','); |
| return new QueryScreen(s.substring(0, c), s.substring(c + 1)); |
| } |
| |
| return new NotFoundScreen(); |
| } |
| |
| private static void publish(String token) { |
| new AsyncSplit(token) { |
| public void onSuccess() { |
| Gerrit.display(token, select()); |
| } |
| |
| private Screen select() { |
| String p = "change,publish,"; |
| if (token.startsWith(p)) |
| return new PublishCommentScreen(PatchSet.Id.parse(skip(p, token))); |
| return new NotFoundScreen(); |
| } |
| }.onSuccess(); |
| } |
| |
| public static void patch(String token, final Patch.Key id, |
| final int patchIndex, final PatchSetDetail patchSetDetail, |
| final PatchTable patchTable) { |
| GWT.runAsync(new AsyncSplit(token) { |
| public void onSuccess() { |
| Gerrit.display(token, select()); |
| } |
| |
| private Screen select() { |
| String p; |
| |
| p = "patch,sidebyside,"; |
| if (token.startsWith(p)) { |
| return new PatchScreen.SideBySide( // |
| id != null ? id : Patch.Key.parse(skip(p, token)), // |
| patchIndex, // |
| patchSetDetail, // |
| patchTable // |
| ); |
| } |
| |
| p = "patch,unified,"; |
| if (token.startsWith(p)) { |
| return new PatchScreen.Unified( // |
| id != null ? id : Patch.Key.parse(skip(p, token)), // |
| patchIndex, // |
| patchSetDetail, // |
| patchTable // |
| ); |
| } |
| |
| return new NotFoundScreen(); |
| } |
| }); |
| } |
| |
| private static void settings(String token) { |
| GWT.runAsync(new AsyncSplit(token) { |
| public void onSuccess() { |
| Gerrit.display(token, select()); |
| } |
| |
| private Screen select() { |
| String p; |
| |
| if (token.equals(SETTINGS)) { |
| return new MyProfileScreen(); |
| } |
| |
| if (token.equals(SETTINGS_PREFERENCES)) { |
| return new MyPreferencesScreen(); |
| } |
| |
| if (token.equals(SETTINGS_PROJECTS)) { |
| return new MyWatchedProjectsScreen(); |
| } |
| |
| if (token.equals(SETTINGS_CONTACT)) { |
| return new MyContactInformationScreen(); |
| } |
| |
| if (token.equals(SETTINGS_SSHKEYS)) { |
| return new MySshKeysScreen(); |
| } |
| |
| if (token.equals(SETTINGS_WEBIDENT)) { |
| return new MyIdentitiesScreen(); |
| } |
| |
| if (token.equals(SETTINGS_HTTP_PASSWORD)) { |
| return new MyPasswordScreen(); |
| } |
| |
| if (token.equals(SETTINGS_MYGROUPS)) { |
| return new MyGroupsScreen(); |
| } |
| |
| if (token.equals(SETTINGS_AGREEMENTS) |
| && Gerrit.getConfig().isUseContributorAgreements()) { |
| return new MyAgreementsScreen(); |
| } |
| |
| p = "register,"; |
| if (token.startsWith(p)) { |
| return new RegisterScreen(skip(p, token)); |
| } else if (REGISTER.equals(token)) { |
| return new RegisterScreen(MINE); |
| } |
| |
| p = "VE,"; |
| if (token.startsWith(p)) |
| return new ValidateEmailScreen(skip(p, token)); |
| |
| p = "SignInFailure,"; |
| if (token.startsWith(p)) { |
| final String[] args = skip(p, token).split(","); |
| final SignInMode mode = SignInMode.valueOf(args[0]); |
| final String msg = KeyUtil.decode(args[1]); |
| final String to = MINE; |
| switch (Gerrit.getConfig().getAuthType()) { |
| case OPENID: |
| new OpenIdSignInDialog(mode, to, msg).center(); |
| break; |
| case LDAP: |
| case LDAP_BIND: |
| new UserPassSignInDialog(to, msg).center(); |
| break; |
| default: |
| return null; |
| } |
| switch (mode) { |
| case SIGN_IN: |
| return QueryScreen.forQuery("status:open"); |
| case LINK_IDENTIY: |
| return new MyIdentitiesScreen(); |
| } |
| } |
| |
| if (SETTINGS_NEW_AGREEMENT.equals(token)) |
| return new NewAgreementScreen(); |
| |
| p = SETTINGS_NEW_AGREEMENT + ","; |
| if (token.startsWith(p)) { |
| return new NewAgreementScreen(skip(p, token)); |
| } |
| |
| return new NotFoundScreen(); |
| } |
| }); |
| } |
| |
| private static void admin(String token) { |
| GWT.runAsync(new AsyncSplit(token) { |
| public void onSuccess() { |
| Gerrit.display(token, select()); |
| } |
| |
| private Screen select() { |
| String p; |
| |
| p = "admin,group,"; |
| if (token.startsWith(p)) |
| return new AccountGroupScreen(AccountGroup.Id.parse(skip(p, token))); |
| |
| p = "admin,project,"; |
| if (token.startsWith(p)) { |
| p = skip(p, token); |
| final int c = p.indexOf(','); |
| final Project.NameKey k = Project.NameKey.parse(p.substring(0, c)); |
| final boolean isWild = k.equals(Gerrit.getConfig().getWildProject()); |
| p = p.substring(c + 1); |
| |
| if (ProjectScreen.INFO.equals(p)) { |
| return new ProjectInfoScreen(k); |
| } |
| |
| if (!isWild && ProjectScreen.BRANCH.equals(p)) { |
| return new ProjectBranchesScreen(k); |
| } |
| |
| if (ProjectScreen.ACCESS.equals(p)) { |
| return new ProjectAccessScreen(k); |
| } |
| |
| return new NotFoundScreen(); |
| } |
| |
| if (ADMIN_GROUPS.equals(token)) { |
| return new GroupListScreen(); |
| } |
| |
| if (ADMIN_PROJECTS.equals(token)) { |
| return new ProjectListScreen(); |
| } |
| |
| return new NotFoundScreen(); |
| } |
| }); |
| } |
| |
| private static String skip(final String prefix, final String in) { |
| return in.substring(prefix.length()); |
| } |
| |
| private static abstract class AsyncSplit implements RunAsyncCallback { |
| private final boolean isReloadUi; |
| protected final String token; |
| |
| protected AsyncSplit(String token) { |
| this.isReloadUi = wasStartedByReloadUI; |
| this.token = token; |
| } |
| |
| public final void onFailure(Throwable reason) { |
| if (!isReloadUi |
| && "HTTP download failed with status 404".equals(reason.getMessage())) { |
| // The server was upgraded since we last download the main script, |
| // so the pointers to the splits aren't valid anymore. Force the |
| // page to reload itself and pick up the new code. |
| // |
| Gerrit.upgradeUI(token); |
| } else { |
| new ErrorDialog(reason).center(); |
| } |
| } |
| } |
| } |