ProjectConnectionManagerResult connect()

in source/com.microsoft.tfs.client.eclipse/src/com/microsoft/tfs/client/eclipse/project/ProjectConnectionManager.java [113:398]


    ProjectConnectionManagerResult connect(final IProject project, final boolean disconnectOtherServers) {
        Check.notNull(project, "project"); //$NON-NLS-1$

        final ProjectManagerDataProvider dataProvider = ProjectManagerDataProviderFactory.getDataProvider();

        if (project.isOpen() == false) {
            return new ProjectConnectionManagerResult(
                new Status(
                    Status.ERROR,
                    TFSEclipseClientPlugin.PLUGIN_ID,
                    0,
                    MessageFormat.format(
                        Messages.getString("ProjectConnectionManager.ProjectNotOpenFormat"), //$NON-NLS-1$
                        project.getName()),
                    null));
        }

        if (project.getLocation() == null) {
            final String message = MessageFormat.format(
                Messages.getString("ProjectConnectionManager.ProjectDoesNotHaveLocalFileSystemMappingFormat"), //$NON-NLS-1$
                project.getName());

            return new ProjectConnectionManagerResult(
                new Status(Status.ERROR, TFSEclipseClientPlugin.PLUGIN_ID, 0, message, null));
        }

        WorkspaceInfo cachedWorkspace;
        TFSRepository repository;

        /*
         * Lock the cachedWorkspaceLock when we fetch a cached workspace for
         * this Project. We do this because if we cannot immediately locate a
         * cached workspace, we may prompt the user to connect to their TFS
         * Server in order to query workspaces (and thus refresh the workspace
         * cache.) We want to let the workspace cache refresh before we query it
         * again in a different thread, since its data will likely be complete.
         */
        synchronized (cachedWorkspaceLock) {
            cachedWorkspace = getCachedWorkspace(project);

            if (cachedWorkspace == null) {
                if (emptyCachedWorkspaceFailures) {
                    log.error(MessageFormat.format("Project {0} was not found in workspace cache", project.getName())); //$NON-NLS-1$

                    return new ProjectConnectionManagerResult(
                        new Status(
                            Status.ERROR,
                            TFSEclipseClientPlugin.PLUGIN_ID,
                            0,
                            MessageFormat.format(projectDoesNotHaveWorkingFolderMappingFormat, project.getName()),
                            null));
                }

                log.warn(MessageFormat.format("Project {0} was not found in workspace cache", project.getName())); //$NON-NLS-1$

                /*
                 * If we cannot find a cached workspace, prompt the user to
                 * connect. This will allow us to query workspaces on the server
                 * and rebuild the workspace cache. Hold a lock on the
                 * cachedWorkspaceLock to prevent other threads from prompting
                 * for a damaged workspace cache.
                 */
                repository = connectRepository(project);

                if (repository == null) {
                    /*
                     * Abort further connections to empty cached workspaces.
                     * Prevents us from prompting forever.
                     */
                    emptyCachedWorkspaceFailures = true;

                    return new ProjectConnectionManagerResult(
                        new Status(
                            Status.ERROR,
                            TFSEclipseClientPlugin.PLUGIN_ID,
                            0,
                            MessageFormat.format(projectDoesNotHaveWorkingFolderMappingFormat, project.getName()),
                            null));
                }

                return new ProjectConnectionManagerResult(repository);
            }
        }

        ProjectManagerRepositoryJob repositoryJob;
        final WorkspaceKey workspaceKey = new WorkspaceKey(cachedWorkspace);

        synchronized (connectionLock) {
            /* We've already got a TFS Repository for this workspace */
            if ((repository =
                TFSEclipseClientPlugin.getDefault().getRepositoryManager().getRepository(cachedWorkspace)) != null) {
                log.debug(MessageFormat.format(
                    "Project {0} can be connected to repository {1}", //$NON-NLS-1$
                    project.getName(),
                    repository));

                return new ProjectConnectionManagerResult(repository);
            }

            /*
             * See if we're already running a connection job for this workspace
             */
            if ((repositoryJob = workspaceJobMap.get(workspaceKey)) == null) {
                /* See if there already exists a connection for this profile. */
                final URI connectionURI = cachedWorkspace.getServerURI();
                TFSServer server;

                if ((server = serverManager.getServer(connectionURI)) != null) {
                    log.debug(
                        MessageFormat.format("Project {0} will be connected to server {1}", project.getName(), server)); //$NON-NLS-1$

                    /*
                     * Do not obliterate the current repository if it's
                     * configured.
                     */
                    if (repositoryManager.getDefaultRepository() != null && disconnectOtherServers == false) {

                        return new ProjectConnectionManagerResult(
                            new Status(
                                Status.ERROR,
                                TFSEclipseClientPlugin.PLUGIN_ID,
                                0,
                                MessageFormat.format(
                                    projectWillNotBeConnectedExistingConnectionExistsFormat,
                                    project.getName()),
                                null));
                    }

                    /*
                     * Hook up our workspace to this TFS Connection instead of
                     * building a new one.
                     */
                    repositoryJob =
                        new ProjectManagerRepositoryJob(this, dataProvider, cachedWorkspace, server.getConnection());
                    repositoryJob.addJobChangeListener(repositoryJobChangeListener);
                    repositoryJob.schedule();
                    workspaceJobMap.put(workspaceKey, repositoryJob);
                } else {
                    ProjectManagerConnectionJob connectionJob;

                    /*
                     * See if another thread is trying to connect this profile.
                     */
                    if ((connectionJob = serverConnectionJobMap.get(connectionURI)) == null) {
                        /*
                         * Make sure the user hasn't cancelled connections for
                         * this cached workspace.
                         */
                        synchronized (cachedWorkspaceLock) {
                            if (cachedWorkspaceFailures.contains(cachedWorkspace)) {
                                return new ProjectConnectionManagerResult(
                                    new Status(
                                        Status.ERROR,
                                        TFSEclipseClientPlugin.PLUGIN_ID,
                                        0,
                                        MessageFormat.format(
                                            projectWillNotBeConnectedPreviousConnectionCancelledFormat,
                                            project.getName()),
                                        null));
                            }
                        }

                        /*
                         * There is no connection going on to this server:
                         * before we build a server connection, ensure that
                         * there are no other server connections in the server
                         * manager.
                         */
                        if (serverManager.getDefaultServer() != null) {
                            log.debug(
                                MessageFormat.format(
                                    "Another connection already exists while connecting project {0}", //$NON-NLS-1$
                                    project.getName()));

                            /*
                             * Do not prompt to disconnect from the other server
                             */
                            if (disconnectOtherServers == false) {
                                return new ProjectConnectionManagerResult(
                                    new Status(
                                        Status.ERROR,
                                        TFSEclipseClientPlugin.PLUGIN_ID,
                                        0,
                                        MessageFormat.format(
                                            projectWillNotBeConnectedExistingConnectionExistsFormat,
                                            project.getName()),
                                        null));
                            }

                            /* Allow users to close the existing connection. */
                            final boolean retry = dataProvider.getConnectionConflictHandler().resolveServerConflict();

                            /*
                             * If the user cancelled the retry, or we still have
                             * a default server, fail.
                             */
                            if (retry == false || serverManager.getDefaultServer() != null) {
                                log.debug(
                                    MessageFormat.format(
                                        "Cancelled connection for project {0}, another connection already exists", //$NON-NLS-1$
                                        project.getName()));

                                return new ProjectConnectionManagerResult(
                                    new Status(
                                        Status.ERROR,
                                        TFSEclipseClientPlugin.PLUGIN_ID,
                                        0,
                                        MessageFormat.format(
                                            projectWillNotBeConnectedExistingConnectionExistsFormat,
                                            project.getName()),
                                        null));
                            }
                        }

                        connectionJob = new ProjectManagerCachedWorkspaceConnectionJob(
                            this,
                            dataProvider,
                            connectionURI,
                            cachedWorkspace);
                        connectionJob.addJobChangeListener(connectionJobChangeListener);
                        connectionJob.setSystem(true);
                        connectionJob.schedule();
                        serverConnectionJobMap.put(connectionURI, connectionJob);
                    }

                    log.debug(MessageFormat.format(
                        "Project {0} will be connected through connection job {1}", //$NON-NLS-1$
                        project.getName(),
                        connectionJob));

                    /*
                     * Now build a job that will realize the Workspace when this
                     * profile is connected.
                     */

                    repositoryJob = new ProjectManagerRepositoryJob(this, dataProvider, cachedWorkspace, connectionJob);
                    repositoryJob.addJobChangeListener(repositoryJobChangeListener);
                    repositoryJob.schedule();

                    log.debug(
                        MessageFormat.format(
                            "Project {0} will be connected through repository realization job {1}", //$NON-NLS-1$
                            project.getName(),
                            repositoryJob));

                    workspaceJobMap.put(workspaceKey, repositoryJob);
                }
            }
        }

        /* Wait for the workspace connector job to finish. */
        IStatus result;
        try {
            log.debug("Waiting for repository job to finish"); //$NON-NLS-1$

            new ExtensionPointAsyncObjectWaiter().joinJob(repositoryJob);
            result = repositoryJob.getResult();
        } catch (final InterruptedException e) {
            result =
                new Status(
                    Status.ERROR,
                    TFSEclipseClientPlugin.PLUGIN_ID,
                    0,
                    MessageFormat.format(
                        Messages.getString("ProjectConnectionManager.CouldNotConnectToConnectionFormat"), //$NON-NLS-1$
                        getConnectionName(cachedWorkspace)),
                    e);
        }

        if (result == null) {
            result = new Status(
                Status.ERROR,
                TFSEclipseClientPlugin.PLUGIN_ID,
                0,
                Messages.getString("ProjectConnectionManager.CouldNotExecuteProjectConnectionJobFormat"), //$NON-NLS-1$
                null);
        }

        if (!result.isOK()) {
            return new ProjectConnectionManagerResult(null, result);
        }

        repository = repositoryJob.getRepository();

        return new ProjectConnectionManagerResult(repositoryJob.getRepository(), result);
    }