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

org.marid.profile.IdeProfile Maven / Gradle / Ivy

The newest version!
package org.marid.profile;

/*-
 * #%L
 * marid-ide-model
 * %%
 * Copyright (C) 2012 - 2019 MARID software development group
 * %%
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 * 
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the Eclipse
 * Public License, v. 2.0 are satisfied: GNU General Public License, version 2
 * with the GNU Classpath Exception which is
 * available at https://www.gnu.org/software/classpath/license.html.
 * 
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 * #L%
 */

import org.marid.profile.event.AddProjectEvent;
import org.marid.profile.exception.IdeProfileCloseException;
import org.marid.project.IdeProject;
import org.marid.project.IdeProjectContext;
import org.marid.spring.ContextUtils;
import org.marid.spring.scope.ResettableScope;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.ConcurrentHashMap;

import static java.lang.System.Logger.Level.INFO;
import static java.lang.System.Logger.Level.WARNING;

@Component
public final class IdeProfile implements AutoCloseable {

  private static final System.Logger LOGGER = System.getLogger(IdeProfile.class.getName());

  private final Path directory;
  private final GenericApplicationContext context;
  private final Path maridDirectory;
  private final Path projectsDirectory;
  private final ConcurrentHashMap projects = new ConcurrentHashMap<>();

  public IdeProfile(GenericApplicationContext context) throws IOException {
    this.directory = context.getBean("ideProfileDirectory", Path.class);
    this.context = context;
    this.maridDirectory = directory.resolve("marid");
    this.projectsDirectory = maridDirectory.resolve("projects");

    Files.createDirectories(projectsDirectory);

    try (final var projectDirs = Files.newDirectoryStream(projectsDirectory, Files::isDirectory)) {
      for (final var projectDir : projectDirs) {
        try {
          addProject(projectDir.getFileName().toString());
        } catch (Throwable e) {
          LOGGER.log(WARNING, "Unable to add project {0}", projectDir);
        }
      }
    }
  }

  public String getName() {
    return directory.getFileName().toString();
  }

  public Path getMaridDirectory() {
    return maridDirectory;
  }

  public Path getProjectsDirectory() {
    return projectsDirectory;
  }

  public IdeProject addProject(String name) {
    return projects.computeIfAbsent(name, projectName -> {
      final var directory = projectsDirectory.resolve(name);
      if (!directory.startsWith(this.directory)) {
        throw new IllegalArgumentException(name);
      }
      final var child = ContextUtils.context(context, (r, c) -> {
        r.register(IdeProjectContext.class);
        c.getDefaultListableBeanFactory().registerSingleton("ideProjectName", projectName);
        c.getDefaultListableBeanFactory().registerScope("ivy", new ResettableScope(getName() + "/" + projectName));
        c.addApplicationListener(event -> {
          if (event instanceof ContextClosedEvent) {
            projects.remove(projectName);
          } else if (event instanceof ContextRefreshedEvent) {
            c.publishEvent(new AddProjectEvent(this, c.getBean(IdeProject.class)));
          }
        });
      });
      child.refresh();
      child.start();
      return child.getBean(IdeProject.class);
    });
  }

  public boolean removeProject(String name) {
    final var project = projects.remove(name);
    if (project != null) {
      project.delete();
      return true;
    } else {
      return false;
    }
  }

  @Override
  public int hashCode() {
    return directory.hashCode();
  }

  @Override
  public boolean equals(Object obj) {
    return obj == this || obj instanceof IdeProfile && ((IdeProfile) obj).directory.equals(directory);
  }

  @Override
  public String toString() {
    return directory.toString();
  }

  @Override
  public void close() {
    final var exception = new IdeProfileCloseException(this);
    projects.forEach((name, project) -> {
      try (project) {
        LOGGER.log(INFO, "Closing {0}", project);
      } catch (Throwable e) {
        exception.addSuppressed(e);
      }
    });
    try {
      context.close();
    } catch (Throwable e) {
      exception.addSuppressed(e);
    }
    if (exception.getSuppressed().length > 0) {
      throw exception;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy