/******************************************************************************* * 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 org.eclipse.che.api.core.ApiException; import org.eclipse.che.api.core.ServerException; import org.eclipse.che.api.core.rest.shared.dto.Link; import org.eclipse.che.api.core.util.LinksHelper; import org.eclipse.che.api.project.server.type.AttributeValue; import org.eclipse.che.api.project.server.type.ProjectType; import org.eclipse.che.api.project.shared.Builders; import org.eclipse.che.api.project.shared.Runners; import org.eclipse.che.api.project.shared.dto.AttributeDescriptor; import org.eclipse.che.api.project.shared.dto.BuilderConfiguration; import org.eclipse.che.api.project.shared.dto.BuildersDescriptor; import org.eclipse.che.api.project.shared.dto.ImportSourceDescriptor; import org.eclipse.che.api.project.shared.dto.ItemReference; import org.eclipse.che.api.project.shared.dto.ProjectDescriptor; import org.eclipse.che.api.project.shared.dto.ProjectImporterDescriptor; import org.eclipse.che.api.project.shared.dto.ProjectProblem; import org.eclipse.che.api.project.shared.dto.ProjectReference; import org.eclipse.che.api.project.shared.dto.ProjectTemplateDescriptor; import org.eclipse.che.api.project.shared.dto.ProjectTypeDefinition; import org.eclipse.che.api.project.shared.dto.ProjectUpdate; import org.eclipse.che.api.project.shared.dto.RunnerConfiguration; import org.eclipse.che.api.project.shared.dto.RunnersDescriptor; import org.eclipse.che.api.project.server.type.Attribute; import org.eclipse.che.api.project.server.type.BaseProjectType; import org.eclipse.che.api.project.server.type.ProjectTypeRegistry; import org.eclipse.che.api.vfs.shared.dto.AccessControlEntry; import org.eclipse.che.api.vfs.shared.dto.Principal; import org.eclipse.che.commons.env.EnvironmentContext; import org.eclipse.che.commons.user.User; import org.eclipse.che.dto.server.DtoFactory; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.UriBuilder; import java.util.*; /** * Helper methods for convert server essentials to DTO and back. * * @author andrew00x */ public class DtoConverter { /*================================ Method for conversion from DTO. ===============================*/ private DtoConverter() { //converter } public static ProjectTemplateDescription fromDto(ProjectTemplateDescriptor dto) { final String category = dto.getCategory(); final ImportSourceDescriptor importSource = dto.getSource(); final BuildersDescriptor builders = dto.getBuilders(); final RunnersDescriptor runners = dto.getRunners(); return new ProjectTemplateDescription( category == null ? org.eclipse.che.api.project.shared.Constants.DEFAULT_TEMPLATE_CATEGORY : category, importSource == null ? null : importSource.getType(), dto.getDisplayName(), dto.getDescription(), importSource == null ? null : importSource.getLocation(), importSource == null ? null : importSource.getParameters(), builders == null ? null : fromDto(builders), runners == null ? null : fromDto(runners)); } public static ProjectTemplateDescriptor toDto(ProjectTemplateDescription templateDescription) { final DtoFactory dtoFactory = DtoFactory.getInstance(); ImportSourceDescriptor sources = dtoFactory.createDto(ImportSourceDescriptor.class) .withLocation(templateDescription.getLocation()) .withType(templateDescription.getImporterType()); return dtoFactory.createDto(ProjectTemplateDescriptor.class).withDescription(templateDescription.getDescription()) .withBuilders(toDto(templateDescription.getBuilders())) .withCategory(templateDescription.getCategory()) .withDisplayName(templateDescription.getDisplayName()) .withRunners(toDto(templateDescription.getRunners())) .withSource(sources); } public static ProjectConfig fromDto2(ProjectUpdate dto, ProjectTypeRegistry typeRegistry) throws ServerException, ProjectTypeConstraintException, InvalidValueException, ValueStorageException { if(dto.getType() == null) throw new InvalidValueException("Invalid Project definition. Primary project type is not defined."); if(typeRegistry.getProjectType(dto.getType()) == null) throw new ProjectTypeConstraintException("Primary project type is not registered "+dto.getType()); // primary final Set<ProjectType> validTypes = new HashSet<>(); validTypes.add(typeRegistry.getProjectType(dto.getType())); // mixins final List<String> validMixins = new ArrayList<>(); for(String typeId : dto.getMixinTypes()) { ProjectType mixinType = typeRegistry.getProjectType(typeId); if (mixinType != null) { // otherwise just ignore validTypes.add(mixinType); validMixins.add(typeId); } } // attributes final Map<String, List<String>> updateAttributes = dto.getAttributes(); final HashMap<String, AttributeValue> attributes = new HashMap<>(updateAttributes.size()); for (Map.Entry<String, List<String>> entry : updateAttributes.entrySet()) { for(ProjectType projectType : validTypes) { Attribute attr = projectType.getAttribute(entry.getKey()); if (attr != null) { attributes.put(attr.getName(), new AttributeValue(entry.getValue())); } } } return new ProjectConfig(dto.getDescription(), dto.getType(), attributes, fromDto(dto.getRunners()), fromDto(dto.getBuilders()), validMixins); } /*================================ Methods for conversion to DTO. ===============================*/ public static Builders fromDto(BuildersDescriptor dto) { if (dto == null) return null; final Builders builders = new Builders(dto.getDefault()); for (Map.Entry<String, BuilderConfiguration> e : dto.getConfigs().entrySet()) { final BuilderConfiguration config = e.getValue(); if (config != null) { builders.getConfigs().put(e.getKey(), new Builders.Config(config.getOptions(), config.getTargets())); } } return builders; } public static Runners fromDto(RunnersDescriptor dto) { if(dto == null) return null; final Runners runners = new Runners(dto.getDefault()); for (Map.Entry<String, RunnerConfiguration> e : dto.getConfigs().entrySet()) { final RunnerConfiguration config = e.getValue(); if (config != null) { runners.getConfigs().put(e.getKey(), new Runners.Config(config.getRam(), config.getOptions(), config.getVariables())); } } return runners; } public static ProjectTypeDefinition toTypeDescriptor2(ProjectType projectType) { final DtoFactory dtoFactory = DtoFactory.getInstance(); final ProjectTypeDefinition definition = dtoFactory.createDto(ProjectTypeDefinition.class) .withId(projectType.getId()) .withDisplayName(projectType.getDisplayName()) .withRunnerCategories(projectType.getRunnerCategories()) .withDefaultRunner(projectType.getDefaultRunner()) .withDefaultBuilder(projectType.getDefaultBuilder()) .withPrimaryable(projectType.canBePrimary()) .withMixable(projectType.canBeMixin()); final List<AttributeDescriptor> typeAttributes = new ArrayList<>(); for (Attribute attr : projectType.getAttributes()) { List <String> valueList = null; try { if(attr.getValue() != null) valueList = attr.getValue().getList(); } catch (ValueStorageException e) { } typeAttributes.add(dtoFactory.createDto(AttributeDescriptor.class) .withName(attr.getName()) .withDescription(attr.getDescription()) .withRequired(attr.isRequired()) .withVariable(attr.isVariable()) .withValues(valueList)); } definition.setAttributeDescriptors(typeAttributes); final List<String> parents = new ArrayList<>(); for(ProjectType parent : projectType.getParents()) { parents.add(parent.getId()); } definition.setParents(parents); return definition; } public static ProjectTemplateDescriptor toTemplateDescriptor(ProjectTemplateDescription projectTemplate, String projectType) { return toTemplateDescriptor(DtoFactory.getInstance(), projectTemplate, projectType); } private static ProjectTemplateDescriptor toTemplateDescriptor(DtoFactory dtoFactory, ProjectTemplateDescription projectTemplate, String projectType) { final ImportSourceDescriptor importSource = dtoFactory.createDto(ImportSourceDescriptor.class) .withType(projectTemplate.getImporterType()) .withLocation(projectTemplate.getLocation()) .withParameters(projectTemplate.getParameters()); final Builders builders = projectTemplate.getBuilders(); final Runners runners = projectTemplate.getRunners(); final ProjectTemplateDescriptor dto = dtoFactory.createDto(ProjectTemplateDescriptor.class) .withDisplayName(projectTemplate.getDisplayName()) .withSource(importSource) .withCategory(projectTemplate.getCategory()) .withProjectType(projectType) .withDescription(projectTemplate.getDescription()); if (builders != null) { dto.withBuilders(toDto(dtoFactory, builders)); } if (runners != null) { dto.withRunners(toDto(dtoFactory, runners)); } return dto; } public static ProjectImporterDescriptor toImporterDescriptor(ProjectImporter importer) { return DtoFactory.getInstance().createDto(ProjectImporterDescriptor.class) .withId(importer.getId()) .withInternal(importer.isInternal()) .withDescription(importer.getDescription() != null ? importer.getDescription() : "description not found") .withCategory(importer.getCategory().getValue()); } public static ItemReference toItemReferenceDto(FileEntry file, UriBuilder uriBuilder) throws ServerException { return DtoFactory.getInstance().createDto(ItemReference.class) .withName(file.getName()) .withPath(file.getPath()) .withType("file") .withMediaType(file.getMediaType()) .withAttributes(file.getAttributes()) .withCreated(file.getCreated()) .withModified(file.getModified()) .withContentLength(file.getVirtualFile().getLength()) .withLinks(generateFileLinks(file, uriBuilder)); } public static ItemReference toItemReferenceDto(FolderEntry folder, UriBuilder uriBuilder) throws ServerException { return DtoFactory.getInstance().createDto(ItemReference.class) .withName(folder.getName()) .withPath(folder.getPath()) .withType(folder.isProjectFolder() ? "project" : "folder") .withMediaType("text/directory") .withAttributes(folder.getAttributes()) .withCreated(folder.getCreated()) .withModified(folder.getModified()) .withLinks(generateFolderLinks(folder, uriBuilder)); } public static ProjectDescriptor toDescriptorDto2(Project project, UriBuilder uriBuilder, ProjectTypeRegistry ptRegistry) throws InvalidValueException { final EnvironmentContext environmentContext = EnvironmentContext.getCurrent(); final DtoFactory dtoFactory = DtoFactory.getInstance(); final ProjectDescriptor dto = dtoFactory.createDto(ProjectDescriptor.class); // Try to provide as much as possible information about project. // If get error then save information about error with 'problems' field in ProjectConfig. final String wsId = project.getWorkspace(); final String wsName = environmentContext.getWorkspaceName(); final String name = project.getName(); final String path = project.getPath(); dto.withWorkspaceId(wsId).withWorkspaceName(wsName).withName(name).withPath(path); ProjectConfig config = null; try { config = project.getConfig(); } catch (ServerException | ValueStorageException | ProjectTypeConstraintException e) { dto.getProblems().add(createProjectProblem(dtoFactory, e)); dto.withType(BaseProjectType.ID); } if (config != null) { dto.withDescription(config.getDescription()); String typeId = config.getTypeId(); dto.withType(typeId) .withTypeName(ptRegistry.getProjectType(typeId).getDisplayName()); dto.withMixins(config.getMixinTypes()); final Map<String, AttributeValue> attributes = config.getAttributes(); final Map<String, List<String>> attributesMap = new LinkedHashMap<>(attributes.size()); if (!attributes.isEmpty()) { for (String attrName : attributes.keySet()) { attributesMap.put(attrName, attributes.get(attrName).getList()); } } dto.withAttributes(attributesMap); final Builders builders = config.getBuilders(); if (builders != null) { dto.withBuilders(toDto(dtoFactory, builders)); } final Runners runners = config.getRunners(); if (runners != null) { dto.withRunners(toDto(dtoFactory, runners)); } } final User currentUser = environmentContext.getUser(); List<AccessControlEntry> acl = null; try { acl = project.getPermissions(); } catch (ServerException e) { dto.getProblems().add(createProjectProblem(dtoFactory, e)); } if (acl != null) { final List<String> permissions = new LinkedList<>(); if (acl.isEmpty()) { // there is no any restriction at all permissions.add("all"); } else { for (AccessControlEntry accessControlEntry : acl) { final Principal principal = accessControlEntry.getPrincipal(); if ((Principal.Type.USER == principal.getType() && currentUser.getId().equals(principal.getName())) || (Principal.Type.USER == principal.getType() && "any".equals(principal.getName())) || (Principal.Type.GROUP == principal.getType() && currentUser.isMemberOf(principal.getName()))) { permissions.addAll(accessControlEntry.getPermissions()); } } } dto.withPermissions(permissions); } try { dto.withCreationDate(project.getCreationDate()); } catch (ServerException e) { dto.getProblems().add(createProjectProblem(dtoFactory, e)); } try { dto.withModificationDate(project.getModificationDate()); } catch (ServerException e) { dto.getProblems().add(createProjectProblem(dtoFactory, e)); } try { dto.withVisibility(project.getVisibility()); } catch (ServerException e) { dto.getProblems().add(createProjectProblem(dtoFactory, e)); } if (uriBuilder != null) { dto.withBaseUrl(uriBuilder.clone().path(ProjectService.class, "getProject").build(wsId, path.substring(1)).toString()) .withLinks(generateProjectLinks(project, uriBuilder)); if (wsName != null) { dto.withIdeUrl(uriBuilder.clone().replacePath("ws").path(wsName).path(path).build().toString()); } } return dto; } public static BuildersDescriptor toDto(Builders builders) { return toDto(DtoFactory.getInstance(), builders); } private static BuildersDescriptor toDto(DtoFactory dtoFactory, Builders builders) { BuildersDescriptor dto = dtoFactory.createDto(BuildersDescriptor.class).withDefault(builders.getDefault()); final Map<String, Builders.Config> configs = builders.getConfigs(); Map<String, BuilderConfiguration> configsDto = new LinkedHashMap<>(configs.size()); for (Map.Entry<String, Builders.Config> e : configs.entrySet()) { final Builders.Config config = e.getValue(); if (config != null) { configsDto.put(e.getKey(), dtoFactory.createDto(BuilderConfiguration.class) .withOptions(config.getOptions()) .withTargets(config.getTargets()) ); } } dto.withConfigs(configsDto); return dto; } public static RunnersDescriptor toDto(Runners runners) { return toDto(DtoFactory.getInstance(), runners); } private static RunnersDescriptor toDto(DtoFactory dtoFactory, Runners runners) { final RunnersDescriptor dto = dtoFactory.createDto(RunnersDescriptor.class).withDefault(runners.getDefault()); final Map<String, Runners.Config> configs = runners.getConfigs(); Map<String, RunnerConfiguration> configsDto = new LinkedHashMap<>(configs.size()); for (Map.Entry<String, Runners.Config> e : configs.entrySet()) { final Runners.Config config = e.getValue(); if (config != null) { configsDto.put(e.getKey(), dtoFactory.createDto(RunnerConfiguration.class) .withRam(config.getRam()) .withOptions(config.getOptions()) .withVariables(config.getVariables()) ); } } dto.withConfigs(configsDto); return dto; } private static List<Link> generateProjectLinks(Project project, UriBuilder uriBuilder) { final List<Link> links = generateFolderLinks(project.getBaseFolder(), uriBuilder); final String relPath = project.getPath().substring(1); final String workspace = project.getWorkspace(); links.add( LinksHelper.createLink("PUT", uriBuilder.clone().path(ProjectService.class, "updateProject").build(workspace, relPath).toString(), MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON, Constants.LINK_REL_UPDATE_PROJECT)); links.add( LinksHelper.createLink("GET", uriBuilder.clone().path(ProjectService.class, "getRunnerEnvironments").build(workspace, relPath) .toString(), MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON, Constants.LINK_REL_GET_RUNNER_ENVIRONMENTS)); return links; } private static List<Link> generateFolderLinks(FolderEntry folder, UriBuilder uriBuilder) { final List<Link> links = new LinkedList<>(); final String workspace = folder.getWorkspace(); final String relPath = folder.getPath().substring(1); //String method, String href, String produces, String rel links.add(LinksHelper.createLink("GET", uriBuilder.clone().path(ProjectService.class, "exportZip").build(workspace, relPath).toString(), "application/zip", Constants.LINK_REL_EXPORT_ZIP)); links.add(LinksHelper.createLink("GET", uriBuilder.clone().path(ProjectService.class, "getChildren").build(workspace, relPath).toString(), MediaType.APPLICATION_JSON, Constants.LINK_REL_CHILDREN)); links.add( LinksHelper.createLink("GET", uriBuilder.clone().path(ProjectService.class, "getTree").build(workspace, relPath).toString(), null, MediaType.APPLICATION_JSON, Constants.LINK_REL_TREE)); links.add(LinksHelper.createLink("GET", uriBuilder.clone().path(ProjectService.class, "getModules").build(workspace, relPath).toString(), MediaType.APPLICATION_JSON, Constants.LINK_REL_MODULES)); links.add(LinksHelper.createLink("DELETE", uriBuilder.clone().path(ProjectService.class, "delete").build(workspace, relPath).toString(), Constants.LINK_REL_DELETE)); return links; } private static List<Link> generateFileLinks(FileEntry file, UriBuilder uriBuilder) throws ServerException { final List<Link> links = new LinkedList<>(); final String workspace = file.getWorkspace(); final String relPath = file.getPath().substring(1); links.add( LinksHelper.createLink("GET", uriBuilder.clone().path(ProjectService.class, "getFile").build(workspace, relPath).toString(), null, file.getMediaType(), Constants.LINK_REL_GET_CONTENT)); links.add(LinksHelper.createLink("PUT", uriBuilder.clone().path(ProjectService.class, "updateFile").build(workspace, relPath).toString(), MediaType.WILDCARD, null, Constants.LINK_REL_UPDATE_CONTENT)); links.add(LinksHelper.createLink("DELETE", uriBuilder.clone().path(ProjectService.class, "delete").build(workspace, relPath).toString(), Constants.LINK_REL_DELETE)); return links; } public static ProjectReference toReferenceDto2(Project project, UriBuilder uriBuilder) throws InvalidValueException { final EnvironmentContext environmentContext = EnvironmentContext.getCurrent(); final DtoFactory dtoFactory = DtoFactory.getInstance(); final ProjectReference dto = dtoFactory.createDto(ProjectReference.class); final String wsId = project.getWorkspace(); final String wsName = environmentContext.getWorkspaceName(); final String name = project.getName(); final String path = project.getPath(); dto.withName(name).withPath(path).withWorkspaceId(wsId).withWorkspaceName(wsName); dto.withWorkspaceId(wsId).withWorkspaceName(wsName).withName(name).withPath(path); try { final ProjectConfig projectConfig = project.getConfig(); dto.withDescription(projectConfig.getDescription()).withType(projectConfig.getTypeId()); } catch (ServerException | ValueStorageException | ProjectTypeConstraintException e) { dto.withType("blank").withTypeName("blank"); dto.getProblems().add(createProjectProblem(dtoFactory, e)); } try { dto.withCreationDate(project.getCreationDate()); } catch (ServerException e) { dto.getProblems().add(createProjectProblem(dtoFactory, e)); } try { dto.withModificationDate(project.getModificationDate()); } catch (ServerException e) { dto.getProblems().add(createProjectProblem(dtoFactory, e)); } try { dto.withVisibility(project.getVisibility()); } catch (ServerException e) { dto.getProblems().add(createProjectProblem(dtoFactory, e)); } dto.withUrl(uriBuilder.clone().path(ProjectService.class, "getProject").build(wsId, name).toString()); if (wsName != null) { dto.withIdeUrl(uriBuilder.clone().replacePath("ws").path(wsName).path(path).build().toString()); } return dto; } private static ProjectProblem createProjectProblem(DtoFactory dtoFactory, ApiException error) { // TODO: setup error code return dtoFactory.createDto(ProjectProblem.class).withCode(1).withMessage(error.getMessage()); } }