/*******************************************************************************
* Copyright (c) 2012-2015 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.api.project.server;
import com.google.inject.Inject;
import org.eclipse.che.api.project.server.type.ProjectType;
import org.eclipse.che.api.project.shared.dto.ImportSourceDescriptor;
import org.eclipse.che.api.project.shared.dto.ProjectTemplateDescriptor;
import org.eclipse.che.dto.server.DtoFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Set;
/**
* Reads project template descriptions that may be described in separate json-files for every project type. This file should be named as
* <project_type_id>.json.
*
* @author Artem Zatsarynnyy
*/
@Singleton
public class ProjectTemplateDescriptionLoader {
private static final Logger LOG = LoggerFactory.getLogger(ProjectTemplateRegistry.class);
/**
* Describe path to the dir where to locate json file that describes templates for project types.
* Json file must have name like: "projectTypeId".json (e.g, maven.json, python.json and so on)
*/
@Inject(optional = true)
@Named("project.template_descriptions_dir")
private String templateDescriptionsDir;
/**
* Describe value to the dir where templates sources are located.
* If in ImportSourceDescriptor.location is set in the path ${project.template_location_dir}
* it will replaced with value that is set in configuration
*/
@Inject(optional = true)
@Named("project.template_location_dir")
private String templateLocationDir;
@Inject
private Set<ProjectType> projectTypes;
@Inject
private ProjectTemplateRegistry templateRegistry;
@Inject
public ProjectTemplateDescriptionLoader() {
}
protected ProjectTemplateDescriptionLoader(String templateDescriptionsDir,
String templateLocationDir,
Set<ProjectType> projectTypes,
ProjectTemplateRegistry templateRegistry) {
this.templateDescriptionsDir = templateDescriptionsDir;
this.templateLocationDir = templateLocationDir;
this.projectTypes = projectTypes;
this.templateRegistry = templateRegistry;
}
@PostConstruct
public void start() {
if (templateDescriptionsDir == null || !Files.exists(Paths.get(templateDescriptionsDir)) ||
!Files.isDirectory(Paths.get(templateDescriptionsDir))) {
LOG.warn("ProjectTemplateDescriptionLoader",
"The configuration of project templates descriptors wasn't found or some problem with configuration was found.");
for (ProjectType projectType : projectTypes) {
load(projectType.getId());
}
} else {
Path dirPath = Paths.get(templateDescriptionsDir);
for (ProjectType projectType : projectTypes) {
load(dirPath, projectType.getId());
}
}
}
private void load(@Nonnull Path dirPath, @Nonnull String projectTypeId) {
try {
Path tmplConf = Paths.get(dirPath.toString() + "/" + projectTypeId + ".json");
if (tmplConf != null && Files.exists(tmplConf)) {
try (InputStream inputStream = Files.newInputStream(tmplConf)) {
resolveTemplate(projectTypeId, inputStream);
}
}
} catch (IOException e) {
LOG.debug(String.format("Can't load information about project templates for %s project type", projectTypeId), e);
}
}
/**
* Load project template descriptions for the specified project type.
*
* @param projectTypeId
* id of the project type for which templates should be loaded
*/
private void load(String projectTypeId) {
try {
final URL url = Thread.currentThread().getContextClassLoader().getResource(projectTypeId + ".json");
if (url != null) {
try (InputStream inputStream = url.openStream()) {
resolveTemplate(projectTypeId, inputStream);
}
}
} catch (IOException e) {
LOG.debug(String.format("Can't load information about project templates for %s project type", projectTypeId), e);
}
}
private void resolveTemplate(String projectTypeId, InputStream stream) throws IOException {
final List<ProjectTemplateDescriptor> templates;
templates = DtoFactory.getInstance().createListDtoFromJson(stream, ProjectTemplateDescriptor.class);
for (ProjectTemplateDescriptor template : templates) {
template.setProjectType(projectTypeId);
ImportSourceDescriptor templateSource = template.getSource();
String location = templateSource.getLocation();
if (location.contains("${project.template_location_dir}") && templateLocationDir != null) {
templateSource.setLocation(location.replace("${project.template_location_dir}", templateLocationDir));
}
}
templateRegistry.register(projectTypeId, templates);
}
}