Package org.zanata.webtrans.server

Source Code of org.zanata.webtrans.server.TranslationWorkspaceManagerImpl

package org.zanata.webtrans.server;

import java.util.Collection;
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpServletRequest;

import lombok.extern.slf4j.Slf4j;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Observer;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.core.Events;
import org.jboss.seam.web.ServletContexts;
import org.zanata.ZanataInit;
import org.zanata.action.ProjectHome;
import org.zanata.action.VersionHome;
import org.zanata.common.EntityStatus;
import org.zanata.common.ProjectType;
import org.zanata.dao.AccountDAO;
import org.zanata.dao.ProjectIterationDAO;
import org.zanata.model.HAccount;
import org.zanata.model.HLocale;
import org.zanata.model.HPerson;
import org.zanata.model.HProject;
import org.zanata.model.HProjectIteration;
import org.zanata.security.ZanataIdentity;
import org.zanata.service.GravatarService;
import org.zanata.service.LocaleService;
import org.zanata.service.ValidationService;
import org.zanata.util.ServiceLocator;
import org.zanata.webtrans.shared.NoSuchWorkspaceException;
import org.zanata.webtrans.shared.auth.EditorClientId;
import org.zanata.webtrans.shared.model.Person;
import org.zanata.webtrans.shared.model.PersonId;
import org.zanata.webtrans.shared.model.ProjectIterationId;
import org.zanata.webtrans.shared.model.ValidationAction;
import org.zanata.webtrans.shared.model.ValidationAction.State;
import org.zanata.webtrans.shared.model.ValidationId;
import org.zanata.webtrans.shared.model.WorkspaceContext;
import org.zanata.webtrans.shared.model.WorkspaceId;
import org.zanata.webtrans.shared.rpc.ExitWorkspace;
import org.zanata.webtrans.shared.rpc.WorkspaceContextUpdate;

import com.google.common.base.Optional;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.ibm.icu.util.ULocale;

import de.novanic.eventservice.service.registry.EventRegistry;
import de.novanic.eventservice.service.registry.EventRegistryFactory;
import de.novanic.eventservice.service.registry.user.UserManager;
import de.novanic.eventservice.service.registry.user.UserManagerFactory;

@Scope(ScopeType.APPLICATION)
@Name("translationWorkspaceManager")
@Slf4j
public class TranslationWorkspaceManagerImpl implements
        TranslationWorkspaceManager {

    private static final String EVENT_WORKSPACE_CREATED =
            "webtrans.WorkspaceCreated";

    private final ConcurrentHashMap<WorkspaceId, TranslationWorkspace> workspaceMap;
    private final Multimap<ProjectIterationId, TranslationWorkspace> projIterWorkspaceMap;
    private final EventRegistry eventRegistry;

    public TranslationWorkspaceManagerImpl() {
        this.workspaceMap =
                new ConcurrentHashMap<WorkspaceId, TranslationWorkspace>();
        Multimap<ProjectIterationId, TranslationWorkspace> piwm =
                HashMultimap.create();
        this.projIterWorkspaceMap = Multimaps.synchronizedMultimap(piwm);
        this.eventRegistry =
                EventRegistryFactory.getInstance().getEventRegistry();
    }

    // TODO Requesting component by name for testability. This should be fixed
    // in subsequent versions of AutoWire
    AccountDAO getAccountDAO() {
        return ServiceLocator.instance().getInstance("accountDAO",
                AccountDAO.class);
    }

    // TODO Requesting component by name for testability. This should be fixed
    // in subsequent versions of AutoWire
    GravatarService getGravatarService() {
        return ServiceLocator.instance().getInstance("gravatarServiceImpl",
                GravatarService.class);
    }

    // TODO Requesting component by name for testability. This should be fixed
    // in subsequent versions of AutoWire
    ProjectIterationDAO getProjectIterationDAO() {
        return ServiceLocator.instance().getInstance("projectIterationDAO",
                ProjectIterationDAO.class);
    }

    // TODO Requesting component by name for testability. This should be fixed
    // in subsequent versions of AutoWire
    LocaleService getLocaleService() {
        return ServiceLocator.instance().getInstance("localeServiceImpl",
                LocaleService.class);
    }

    // TODO Requesting component by name for testability. This should be fixed
    // in subsequent versions of AutoWire
    ValidationService getValidationService() {
        return ServiceLocator.instance().getInstance("validationServiceImpl",
                ValidationService.class);
    }

    @Observer(ZanataInit.EVENT_Zanata_Startup)
    public void start() {
        log.info("starting...");
    }

    @Observer(ZanataIdentity.USER_LOGOUT_EVENT)
    public void exitWorkspace(String username) {
        String httpSessionId = getSessionId();
        if (httpSessionId == null) {
            log.debug("Logout: null session");
            return;
        }
        log.info("Logout: Removing user {} from all workspaces, session: {}",
                username, httpSessionId);
        String personName = "<unknown>";
        String personEmail = "<unknown>";
        HAccount account = getAccountDAO().getByUsername(username);
        if (account != null) {
            HPerson person = account.getPerson();
            if (person != null) {
                personName = person.getName();
                personEmail = person.getEmail();
            }
        }
        ImmutableSet<TranslationWorkspace> workspaceSet =
                ImmutableSet.copyOf(workspaceMap.values());
        for (TranslationWorkspace workspace : workspaceSet) {
            Collection<EditorClientId> editorClients =
                    workspace.removeEditorClients(httpSessionId);
            for (EditorClientId editorClientId : editorClients) {
                log.info(
                        "Publishing ExitWorkspace event for user {} with editorClientId {} from workspace {}",
                        new Object[] { username, editorClientId,
                                workspace.getWorkspaceContext() });
                // Send GWT Event to client to update the userlist
                ExitWorkspace event =
                        new ExitWorkspace(editorClientId, new Person(
                                new PersonId(username), personName,
                                getGravatarService().getUserImageUrl(16,
                                        personEmail)));
                workspace.publish(event);
            }
        }
    }

    protected String getSessionId() {
        HttpServletRequest request = ServletContexts.instance().getRequest();
        if (request == null) {
            return null;
        }
        return request.getSession().getId();
    }

    @Observer(ProjectHome.PROJECT_UPDATE)
    public void projectUpdate(HProject project) {
        String projectSlug = project.getSlug();
        log.info("Project {} updated, status={}", projectSlug,
                project.getStatus());

        for (HProjectIteration iter : project.getProjectIterations()) {
            projectIterationUpdate(iter);
        }
    }

    @Observer(VersionHome.PROJECT_ITERATION_UPDATE)
    public void projectIterationUpdate(HProjectIteration projectIteration) {
        HashMap<ValidationId, State> validationStates = Maps.newHashMap();

        for (ValidationAction validationAction : getValidationService()
                .getValidationActions(projectIteration.getProject().getSlug(),
                        projectIteration.getSlug())) {
            validationStates.put(validationAction.getId(),
                    validationAction.getState());
        }

        String projectSlug = projectIteration.getProject().getSlug();
        String iterSlug = projectIteration.getSlug();
        HProject project = projectIteration.getProject();
        Boolean isProjectActive =
                projectIterationIsActive(project.getStatus(),
                        projectIteration.getStatus());
        ProjectType projectType = projectIteration.getProjectType();
        log.info(
                "Project {} iteration {} updated, status={}, isProjectActive={}, projectType={}",
                new Object[] { projectSlug, iterSlug,
                        projectIteration.getStatus(), isProjectActive,
                        projectType });

        ProjectIterationId iterId =
                new ProjectIterationId(projectSlug, iterSlug,
                        projectIteration.getProjectType());
        for (TranslationWorkspace workspace : projIterWorkspaceMap.get(iterId)) {
            WorkspaceContextUpdate event =
                    new WorkspaceContextUpdate(isProjectActive, projectType,
                            validationStates);
            workspace.publish(event);
        }
    }

    private boolean projectIterationIsActive(EntityStatus projectStatus,
            EntityStatus iterStatus) {
        return (projectStatus.equals(EntityStatus.ACTIVE) && iterStatus
                .equals(EntityStatus.ACTIVE));
    }

    @Destroy
    public void stop() {
        log.info("stopping...");
        log.info("closing down {} workspaces: ", workspaceMap.size());

        // Stopping the listeners frees up the EventServiceImpl servlet, which
        // would otherwise prevent Apache Coyote from shutting down quickly.
        // Note that the servlet may still hang around up to the max timeout
        // configured in eventservice.properties.
        Set<String> registeredUserIds = eventRegistry.getRegisteredUserIds();
        int clientCount = registeredUserIds.size();
        log.info("Removing {} client(s)", clientCount);
        for (String userId : registeredUserIds) {
            log.debug("Removing client {}", userId);
            eventRegistry.unlisten(userId);
        }
        log.info(
                "Removed {} client(s).  Waiting for outstanding polls to time out...",
                clientCount);
        UserManager userManager =
                UserManagerFactory.getInstance().getUserManager();
        userManager.getUserActivityScheduler().stop();
    }

    @Override
    public TranslationWorkspace getOrRegisterWorkspace(WorkspaceId workspaceId)
            throws NoSuchWorkspaceException {
        TranslationWorkspace workspace = workspaceMap.get(workspaceId);
        if (workspace == null) {
            workspace = createWorkspace(workspaceId);
            TranslationWorkspace prev =
                    workspaceMap.putIfAbsent(workspaceId, workspace);

            if (prev == null) {
                projIterWorkspaceMap.put(workspaceId.getProjectIterationId(),
                        workspace);
                if (Events.exists()) {
                    Events.instance().raiseEvent(EVENT_WORKSPACE_CREATED,
                            workspaceId);
                }
            }

            return prev == null ? workspace : prev;
        }
        return workspace;
    }

    @Override
    public Optional<TranslationWorkspace> tryGetWorkspace(WorkspaceId workspaceId) {
        return Optional.fromNullable(workspaceMap.get(workspaceId));
    }

    private WorkspaceContext validateAndGetWorkspaceContext(
            WorkspaceId workspaceId) throws NoSuchWorkspaceException {
        String projectSlug =
                workspaceId.getProjectIterationId().getProjectSlug();
        String iterationSlug =
                workspaceId.getProjectIterationId().getIterationSlug();
        HProjectIteration projectIteration =
                getProjectIterationDAO().getBySlug(projectSlug, iterationSlug);

        if (projectIteration == null) {
            throw new NoSuchWorkspaceException("Invalid workspace Id");
        }
        HProject project = projectIteration.getProject();
        if (project.getStatus() == EntityStatus.OBSOLETE) {
            throw new NoSuchWorkspaceException("Project is obsolete");
        }
        if (projectIteration.getStatus() == EntityStatus.OBSOLETE) {
            throw new NoSuchWorkspaceException("Project Iteration is obsolete");
        }
        HLocale locale =
                getLocaleService().getByLocaleId(workspaceId.getLocaleId());
        if (locale == null) {
            throw new NoSuchWorkspaceException("Invalid Workspace Locale");
        }
        if (!locale.isActive()) {
            throw new NoSuchWorkspaceException("Locale '"
                    + locale.retrieveDisplayName() + "' disabled in server");
        }

        String workspaceName =
                project.getName() + " (" + projectIteration.getSlug() + ")";
        String localeDisplayName =
                ULocale.getDisplayName(workspaceId.getLocaleId().toJavaName(),
                        ULocale.ENGLISH);

        return new WorkspaceContext(workspaceId, workspaceName,
                localeDisplayName);
    }

    protected TranslationWorkspace createWorkspace(WorkspaceId workspaceId)
            throws NoSuchWorkspaceException {
        WorkspaceContext workspaceContext =
                validateAndGetWorkspaceContext(workspaceId);
        return new TranslationWorkspaceImpl(workspaceContext);
    }
}
TOP

Related Classes of org.zanata.webtrans.server.TranslationWorkspaceManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.