All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.intellij.openapi.externalSystem.service.AbstractExternalSystemFacadeImpl Maven / Gradle / Ivy

package com.intellij.openapi.externalSystem.service;

import com.intellij.execution.rmi.RemoteServer;
import com.intellij.openapi.externalSystem.model.settings.ExternalSystemExecutionSettings;
import com.intellij.openapi.externalSystem.model.task.*;
import com.intellij.openapi.externalSystem.service.project.ExternalSystemProjectResolver;
import com.intellij.openapi.externalSystem.service.remote.*;
import com.intellij.openapi.externalSystem.task.ExternalSystemTaskManager;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.rmi.RemoteException;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author Denis Zhdanov
 * @since 8/8/11 12:51 PM
 */
public abstract class AbstractExternalSystemFacadeImpl extends RemoteServer
  implements RemoteExternalSystemFacade
{

  private final ConcurrentMap, RemoteExternalSystemService> myRemotes = ContainerUtil.newConcurrentMap();

  private final AtomicReference mySettings              = new AtomicReference();
  private final AtomicReference myNotificationListener =
    new AtomicReference(new ExternalSystemTaskNotificationListenerAdapter() {});

  @NotNull private final RemoteExternalSystemProjectResolverImpl myProjectResolver;
  @NotNull private final RemoteExternalSystemTaskManagerImpl     myTaskManager;

  public AbstractExternalSystemFacadeImpl(@NotNull Class> projectResolverClass,
                                          @NotNull Class> buildManagerClass)
    throws IllegalAccessException, InstantiationException
  {
    myProjectResolver = new RemoteExternalSystemProjectResolverImpl(projectResolverClass.newInstance());
    myTaskManager = new RemoteExternalSystemTaskManagerImpl(buildManagerClass.newInstance());
  }

  protected void init() throws RemoteException {
    applyProgressManager(RemoteExternalSystemProgressNotificationManager.NULL_OBJECT);
  }

  @Nullable
  protected S getSettings() {
    return mySettings.get();
  }
  
  @NotNull
  protected ExternalSystemTaskNotificationListener getNotificationListener() {
    return myNotificationListener.get();
  }
  
  @SuppressWarnings("unchecked")
  @NotNull
  @Override
  public RemoteExternalSystemProjectResolver getResolver() throws RemoteException, IllegalStateException {
    try {
      return getService(RemoteExternalSystemProjectResolver.class, myProjectResolver);
    }
    catch (Exception e) {
      throw new IllegalStateException(String.format("Can't create '%s' service", RemoteExternalSystemProjectResolverImpl.class.getName()),
                                      e);
    }
  }

  @SuppressWarnings("unchecked")
  @NotNull
  @Override
  public RemoteExternalSystemTaskManager getTaskManager() throws RemoteException {
    try {
      return getService(RemoteExternalSystemTaskManager.class, myTaskManager);
    }
    catch (Exception e) {
      throw new IllegalStateException(String.format("Can't create '%s' service", ExternalSystemTaskManager.class.getName()), e);
    }
  }

  @SuppressWarnings({"unchecked", "IOResourceOpenedButNotSafelyClosed", "UseOfSystemOutOrSystemErr"})
  private , C extends I> I getService(@NotNull Class interfaceClass,
                                                                               @NotNull final C impl)
    throws ClassNotFoundException, IllegalAccessException, InstantiationException, RemoteException
  {
    Object cachedResult = myRemotes.get(interfaceClass);
    if (cachedResult != null) {
      return (I)cachedResult;
    }
    S settings = getSettings();
    if (settings != null) {
      impl.setNotificationListener(getNotificationListener());
      impl.setSettings(settings);
    }
    impl.setNotificationListener(getNotificationListener());
    try {
      I created = createService(interfaceClass, impl);
      I stored = (I)myRemotes.putIfAbsent(interfaceClass, created);
      return stored == null ? created : stored;
    }
    catch (RemoteException e) {
      Object raceResult = myRemotes.get(interfaceClass);
      if (raceResult != null) {
        // Race condition occurred
        return (I)raceResult;
      }
      else {
        throw new IllegalStateException(
          String.format("Can't prepare remote service for interface '%s', implementation '%s'", interfaceClass, impl),
          e
        );
      }
    }
  }

  /**
   * Generic method to retrieve exposed implementations of the target interface.
   * 

* Uses cached value if it's found; creates new and caches it otherwise. * * @param interfaceClass target service interface class * @param impl service implementation * @param service interface class * @param service implementation * @return implementation of the target service * @throws IllegalAccessException in case of incorrect assumptions about server class interface * @throws InstantiationException in case of incorrect assumptions about server class interface * @throws ClassNotFoundException in case of incorrect assumptions about server class interface * @throws RemoteException */ @SuppressWarnings({"unchecked", "IOResourceOpenedButNotSafelyClosed", "UseOfSystemOutOrSystemErr"}) protected abstract , C extends I> I createService(@NotNull Class interfaceClass, @NotNull final C impl) throws ClassNotFoundException, IllegalAccessException, InstantiationException, RemoteException; @Override public boolean isTaskInProgress(@NotNull ExternalSystemTaskId id) throws RemoteException { for (RemoteExternalSystemService service : myRemotes.values()) { if (service.isTaskInProgress(id)) { return true; } } return false; } @NotNull @Override public Map> getTasksInProgress() throws RemoteException { Map> result = null; for (RemoteExternalSystemService service : myRemotes.values()) { final Map> tasks = service.getTasksInProgress(); if (tasks.isEmpty()) { continue; } if (result == null) { result = new HashMap>(); } for (Map.Entry> entry : tasks.entrySet()) { Set ids = result.get(entry.getKey()); if (ids == null) { result.put(entry.getKey(), ids = new HashSet()); } ids.addAll(entry.getValue()); } } if (result == null) { result = Collections.emptyMap(); } return result; } @Override public void applySettings(@NotNull S settings) throws RemoteException { mySettings.set(settings); List> services = ContainerUtilRt.newArrayList(myRemotes.values()); for (RemoteExternalSystemService service : services) { service.setSettings(settings); } } @Override public void applyProgressManager(@NotNull RemoteExternalSystemProgressNotificationManager progressManager) throws RemoteException { ExternalSystemTaskNotificationListener listener = new SwallowingNotificationListener(progressManager); myNotificationListener.set(listener); myProjectResolver.setNotificationListener(listener); myTaskManager.setNotificationListener(listener); } @Override public boolean cancelTask(@NotNull ExternalSystemTaskId id) throws RemoteException { if(id.getType() == ExternalSystemTaskType.RESOLVE_PROJECT) { return myProjectResolver.cancelTask(id); } else{ return myTaskManager.cancelTask(id); } } private static class SwallowingNotificationListener implements ExternalSystemTaskNotificationListener { @NotNull private final RemoteExternalSystemProgressNotificationManager myManager; SwallowingNotificationListener(@NotNull RemoteExternalSystemProgressNotificationManager manager) { myManager = manager; } @Override public void onQueued(@NotNull ExternalSystemTaskId id) { } @Override public void onStart(@NotNull ExternalSystemTaskId id) { try { myManager.onStart(id); } catch (RemoteException e) { // Ignore } } @Override public void onStatusChange(@NotNull ExternalSystemTaskNotificationEvent event) { try { myManager.onStatusChange(event); } catch (RemoteException e) { // Ignore } } @Override public void onTaskOutput(@NotNull ExternalSystemTaskId id, @NotNull String text, boolean stdOut) { try { myManager.onTaskOutput(id, text, stdOut); } catch (RemoteException e) { // Ignore } } @Override public void onEnd(@NotNull ExternalSystemTaskId id) { try { myManager.onEnd(id); } catch (RemoteException e) { // Ignore } } @Override public void onSuccess(@NotNull ExternalSystemTaskId id) { try { myManager.onSuccess(id); } catch (RemoteException e) { // Ignore } } @Override public void onFailure(@NotNull ExternalSystemTaskId id, @NotNull Exception ex) { try { myManager.onFailure(id, ex); } catch (RemoteException e) { // Ignore } } } }