/*******************************************************************************
* Copyright (c) 2012-2017 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.factory.server.impl;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.factory.server.FactoryConstants;
import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.factory.shared.dto.IdeActionDto;
import org.eclipse.che.api.factory.shared.dto.IdeDto;
import org.eclipse.che.api.factory.shared.dto.OnAppLoadedDto;
import org.eclipse.che.api.factory.shared.dto.OnProjectsLoadedDto;
import org.eclipse.che.api.factory.shared.dto.PoliciesDto;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;
import static java.lang.System.currentTimeMillis;
/**
* Validates values of factory parameters.
*
* @author Alexander Garagatyi
* @author Valeriy Svydenko
*/
public abstract class FactoryBaseValidator {
private static final Pattern PROJECT_NAME_VALIDATOR = Pattern.compile("^[\\\\\\w\\\\\\d]+[\\\\\\w\\\\\\d_.-]*$");
/**
* Validates source parameter of factory.
*
* @param factory
* factory to validate
* @throws BadRequestException
* when source projects in the factory is invalid
*/
protected void validateProjects(FactoryDto factory) throws BadRequestException {
for (ProjectConfigDto project : factory.getWorkspace().getProjects()) {
final String projectName = project.getName();
if (null != projectName && !PROJECT_NAME_VALIDATOR.matcher(projectName)
.matches()) {
throw new BadRequestException("Project name must contain only Latin letters, " +
"digits or these following special characters -._.");
}
if (project.getPath().indexOf('/', 1) == -1) {
if (project.getSource() == null) {
throw new BadRequestException(format(FactoryConstants.MISSING_MANDATORY_MESSAGE,
"project.source"));
}
final String location = project.getSource().getLocation();
final String parameterLocationName = "project.source.location";
if (isNullOrEmpty(location)) {
throw new BadRequestException(format(FactoryConstants.PARAMETRIZED_ILLEGAL_PARAMETER_VALUE_MESSAGE,
parameterLocationName,
location));
}
try {
URLDecoder.decode(location, "UTF-8");
} catch (IllegalArgumentException | UnsupportedEncodingException e) {
throw new BadRequestException(format(FactoryConstants.PARAMETRIZED_ILLEGAL_PARAMETER_VALUE_MESSAGE,
parameterLocationName,
location));
}
}
}
}
/**
* Validates that factory can be used at present time (used on accept)
*
* @param factory
* factory to validate
* @throws BadRequestException
* if since date greater than current date<br/>
* @throws BadRequestException
* if until date less than current date<br/>
*/
protected void validateCurrentTimeBetweenSinceUntil(FactoryDto factory) throws BadRequestException {
final PoliciesDto policies = factory.getPolicies();
if (policies == null) {
return;
}
final Long since = policies.getSince() == null ? 0L : policies.getSince();
final Long until = policies.getUntil() == null ? 0L : policies.getUntil();
if (since != 0 && currentTimeMillis() < since) {
throw new BadRequestException(FactoryConstants.ILLEGAL_FACTORY_BY_SINCE_MESSAGE);
}
if (until != 0 && currentTimeMillis() > until) {
throw new BadRequestException(FactoryConstants.ILLEGAL_FACTORY_BY_UNTIL_MESSAGE);
}
}
/**
* Validates correct valid since and until times are used (on factory creation)
*
* @param factory
* factory to validate
* @throws BadRequestException
* if since date greater or equal than until date
* @throws BadRequestException
* if since date less than current date
* @throws BadRequestException
* if until date less than current date
*/
protected void validateCurrentTimeAfterSinceUntil(FactoryDto factory) throws BadRequestException {
final PoliciesDto policies = factory.getPolicies();
if (policies == null) {
return;
}
final Long since = policies.getSince() == null ? 0L : policies.getSince();
final Long until = policies.getUntil() == null ? 0L : policies.getUntil();
if (since != 0 && until != 0 && since >= until) {
throw new BadRequestException(FactoryConstants.INVALID_SINCEUNTIL_MESSAGE);
}
if (since != 0 && currentTimeMillis() > since) {
throw new BadRequestException(FactoryConstants.INVALID_SINCE_MESSAGE);
}
if (until != 0 && currentTimeMillis() > until) {
throw new BadRequestException(FactoryConstants.INVALID_UNTIL_MESSAGE);
}
}
/**
* Validates IDE actions
*
* @param factory
* factory to validate
* @throws BadRequestException
* when factory actions is invalid
*/
protected void validateProjectActions(FactoryDto factory) throws BadRequestException {
final IdeDto ide = factory.getIde();
if (ide == null) {
return;
}
final List<IdeActionDto> applicationActions = new ArrayList<>();
if (ide.getOnAppClosed() != null) {
applicationActions.addAll(ide.getOnAppClosed().getActions());
}
if (ide.getOnAppLoaded() != null) {
applicationActions.addAll(ide.getOnAppLoaded().getActions());
}
for (IdeActionDto applicationAction : applicationActions) {
String id = applicationAction.getId();
if ("openFile".equals(id) || "findReplace".equals(id) || "runCommand".equals(id) || "newTerminal".equals(id)) {
throw new BadRequestException(format(FactoryConstants.INVALID_ACTION_SECTION, id));
}
}
final OnAppLoadedDto onAppLoaded = ide.getOnAppLoaded();
if (onAppLoaded != null) {
for (IdeActionDto action : onAppLoaded.getActions()) {
final Map<String, String> properties = action.getProperties();
if ("openWelcomePage".equals(action.getId()) && isNullOrEmpty(properties.get("greetingContentUrl"))) {
throw new BadRequestException(FactoryConstants.INVALID_WELCOME_PAGE_ACTION);
}
}
}
final OnProjectsLoadedDto onLoaded = ide.getOnProjectsLoaded();
if (onLoaded != null) {
final List<IdeActionDto> onProjectOpenedActions = onLoaded.getActions();
for (IdeActionDto applicationAction : onProjectOpenedActions) {
final String id = applicationAction.getId();
final Map<String, String> properties = applicationAction.getProperties();
switch (id) {
case "openFile":
if (isNullOrEmpty(properties.get("file"))) {
throw new BadRequestException(FactoryConstants.INVALID_OPENFILE_ACTION);
}
break;
case "runCommand":
if (isNullOrEmpty(properties.get("name"))) {
throw new BadRequestException(FactoryConstants.INVALID_RUNCOMMAND_ACTION);
}
break;
case "findReplace":
if (isNullOrEmpty(properties.get("in")) ||
isNullOrEmpty(properties.get("find")) ||
isNullOrEmpty(properties.get("replace"))) {
throw new BadRequestException(FactoryConstants.INVALID_FIND_REPLACE_ACTION);
}
break;
}
}
}
}
}