Java tutorial
/* * * * This file is part of the Hesperides distribution. * * (https://github.com/voyages-sncf-technologies/hesperides) * * Copyright (c) 2016 VSCT. * * * * Hesperides is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as * * published by the Free Software Foundation, version 3. * * * * Hesperides is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see <http://www.gnu.org/licenses/>. * * */ package com.vsct.dt.hesperides.resources; import com.codahale.metrics.annotation.Timed; import com.vsct.dt.hesperides.applications.*; import com.vsct.dt.hesperides.exception.runtime.*; import com.vsct.dt.hesperides.exception.runtime.MissingResourceException; import com.vsct.dt.hesperides.indexation.search.ApplicationSearch; import com.vsct.dt.hesperides.security.UserContext; import com.vsct.dt.hesperides.security.model.User; import com.vsct.dt.hesperides.templating.models.HesperidesPropertiesModel; import com.vsct.dt.hesperides.templating.models.KeyValuePropertyModel; import com.vsct.dt.hesperides.templating.modules.ModuleKey; import com.vsct.dt.hesperides.templating.modules.Modules; import com.vsct.dt.hesperides.templating.platform.ApplicationData; import com.vsct.dt.hesperides.templating.platform.ApplicationModuleData; import com.vsct.dt.hesperides.templating.platform.PlatformData; import com.vsct.dt.hesperides.templating.platform.TimeStampedPlatformData; import com.vsct.dt.hesperides.util.HesperidesUtil; import com.vsct.dt.hesperides.util.Release; import com.vsct.dt.hesperides.util.WorkingCopy; import com.vsct.dt.hesperides.util.converter.ApplicationConverter; import com.vsct.dt.hesperides.util.converter.PlatformConverter; import com.vsct.dt.hesperides.util.converter.PropertiesConverter; import com.vsct.dt.hesperides.util.converter.TimeStampedPlatformConverter; import com.wordnik.swagger.annotations.Api; import com.wordnik.swagger.annotations.ApiOperation; import io.dropwizard.auth.Auth; import org.apache.http.util.Asserts; import org.apache.lucene.search.Collector; import com.google.common.collect.Sets; import javax.validation.Valid; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.*; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import static com.vsct.dt.hesperides.util.CheckArgument.isNonDisplayedChar; /** * Created by william_montaz on 11/07/14. * * Modified by tidiane_sidibe on 05/08/2016 : adding the comment to event */ @Path("/applications") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @Api("/applications") public final class HesperidesApplicationResource extends BaseResource { private final Applications applications; private final Modules modules; private final ApplicationSearch applicationSearch; private final PlatformConverter platformConverter; private final PropertiesConverter propertiesConverter; final TimeStampedPlatformConverter timeStampedPlatformConverter; private ResponseConverter<PlatformData, Platform> responsePlatformConverter; private ResponseConverter<TimeStampedPlatformData, TimeStampedPlatform> responseTimeConverter; private ResponseConverter<ApplicationData, Application> responseApplicationConverter; private final HesperidesModuleResource moduleResource; public HesperidesApplicationResource(final Applications applications, final Modules modules, final ApplicationSearch applicationSearch, final TimeStampedPlatformConverter timeStampedPlatformConverter, final ApplicationConverter applicationDataConverter, final PropertiesConverter propertiesConverter, final HesperidesModuleResource moduleResource) { this.applications = applications; this.modules = modules; this.applicationSearch = applicationSearch; this.platformConverter = timeStampedPlatformConverter.getPlatformConverter(); this.timeStampedPlatformConverter = timeStampedPlatformConverter; this.responsePlatformConverter = obj -> platformConverter.toPlatform(obj); this.responseTimeConverter = obj -> timeStampedPlatformConverter.toTimeStampedPlatform(obj); this.responseApplicationConverter = obj -> applicationDataConverter.toApplication(obj); this.propertiesConverter = propertiesConverter; this.moduleResource = moduleResource; } @Path("/using_module/{module}/{version}/{type}") @GET @Timed @ApiOperation("Get application using module") public Response getApplicationUsingModule(@Auth final User user, @PathParam("module") final String module, @PathParam("version") final String version, @PathParam("type") final String type) { return Response .ok(this.applications .getApplicationsFromSelector( data -> data.getModules().stream() .anyMatch(elem -> elem.getName().equals(module) && elem.getVersion().equals(version) && ((elem.isWorkingCopy() && type.equals("workingcopy")) || (!elem.isWorkingCopy() && type.equals("release")))))) .build(); } @Path("/{application_name}/platforms/{platform_name}/global_properties_usage") @GET @Timed @ApiOperation("Retrieve global properties usage in application") public Response getGlobalPropertiesUsage(@Auth final User user, @PathParam("application_name") final String applicationName, @PathParam("platform_name") final String platformName) { Collection<PlatformData> l = this.applications .getApplicationsFromSelector(data -> data.getApplicationName().equals(applicationName) && data.getPlatformName().equals(platformName)); PlatformData p = l.stream().findFirst().get(); Map<String, Set<HashMap>> usage = new HashMap<>(); applications.getProperties(new PlatformKey(applicationName, platformName), "#").getKeyValueProperties() .stream().forEach(globalProp -> { Set<HashMap> buffer = new HashSet<HashMap>(); p.getModules().stream().forEach(elem -> { PlatformKey currentPlatformKey = new PlatformKey(applicationName, platformName); Optional<HesperidesPropertiesModel> oModel; HesperidesPropertiesModel model; if (!elem.isWorkingCopy()) { oModel = modules.getModel(new ModuleKey(elem.getName(), Release.of(elem.getVersion()))); } else { oModel = modules .getModel(new ModuleKey(elem.getName(), WorkingCopy.of(elem.getVersion()))); } if (oModel.isPresent()) { model = oModel.get(); if (model.getKeyValueProperties().stream() .anyMatch(prop -> prop.getName().equals(globalProp.getName()))) { buffer.add(new HashMap() { { put("path", elem.getPropertiesPath()); put("inModel", true); } }); } } else { model = null; } applications.getProperties(currentPlatformKey, elem.getPropertiesPath()) .getKeyValueProperties().stream().forEach(prop -> { if (prop.getName().equals(globalProp.getName()) || prop.getValue().contains("{{" + globalProp.getName() + "}}")) { if (model == null) { buffer.add(new HashMap() { { put("path", elem.getPropertiesPath()); put("inModel", false); } }); } else { Boolean inModel = model.getKeyValueProperties().stream() .anyMatch(mod -> prop.getName().equals(mod.getName())); buffer.add(new HashMap() { { put("path", elem.getPropertiesPath()); put("inModel", inModel); } }); } } }); }); // usage.put(globalProp.getName(), buffer.stream().distinct().collect(Collectors.toList())); usage.put(globalProp.getName(), buffer); }); return Response.ok(usage).build(); } @Path("/{application_name}") @GET @Timed @ApiOperation("Get application with given name") public Response getApplication(@Auth final User user, @PathParam("application_name") final String name) { checkQueryParameterNotEmpty("application_name", name); return entityWithConverterOrNotFound(applications.getApplication(name), responseApplicationConverter); } @Path("/perform_search") @POST @Timed @ApiOperation("Get application by name") public Set<ApplicationListItem> searchApplications(@Auth final User user, @QueryParam("name") final String name) { checkQueryParameterNotEmpty("name", name); return applicationSearch.getApplicationsLike(name).stream() .map(applicationSearchResponse -> new ApplicationListItem(applicationSearchResponse.getName())) .collect(Collectors.toSet()); } @Path("/platforms/perform_search") @POST @Timed @ApiOperation("Get all platform for a given application name") public Set<PlatformListItem> searchPlatforms(@Auth final User user, @QueryParam("applicationName") final String applicationName, @QueryParam("platformName") final String platformName) { checkQueryParameterNotEmpty("applicationName", applicationName); return applicationSearch.getAllPlatforms(applicationName, platformName).stream() .map(platformSearchResponse -> new PlatformListItem(platformSearchResponse.getName())) .collect(Collectors.toSet()); } @Path("/{application_name}/platforms/{platform_name}") @GET @Timed @ApiOperation("Get platform for application with given name") public Response getPlatform(@Auth final User user, @PathParam("application_name") final String applicationName, @PathParam("platform_name") final String platformName, @QueryParam("timestamp") final Long timestamp) { checkQueryParameterNotEmpty("application_name", applicationName); checkQueryParameterNotEmpty("platform_name", platformName); PlatformKey platformKey = PlatformKey.withName(platformName).withApplicationName(applicationName).build(); if (timestamp != null) { return entityWithConverterOrNotFound(applications.getPlatform(platformKey, timestamp), responseTimeConverter); } else { return entityWithConverterOrNotFound(applications.getPlatform(platformKey), responsePlatformConverter); } } @Path("/{application_name}/platforms/{platform_name}") @DELETE @Timed @ApiOperation("Deletes a platform on a given app") public Response deletePlatform(@Auth final User user, @PathParam("application_name") final String applicationName, @PathParam("platform_name") final String platformName) { checkQueryParameterNotEmpty("application_name", applicationName); checkQueryParameterNotEmpty("platform_name", platformName); PlatformKey platformKey = PlatformKey.withName(platformName).withApplicationName(applicationName).build(); applications.delete(platformKey); return Response.ok().build(); } @Path("/{application_name}/platforms") @POST @Timed @ApiOperation("Create platform for application with given name, possibly from an existing platform") public Platform createPlatform(@Auth final User user, @PathParam("application_name") final String applicationName, @QueryParam("from_application") final String fromApplication, @QueryParam("from_platform") final String fromPlatform, @Valid final Platform platform) { if ((fromApplication == null || isNonDisplayedChar(fromApplication)) && (fromPlatform == null || isNonDisplayedChar(fromPlatform))) { return platformConverter .toPlatform(applications.createPlatform(platformConverter.toPlatformData(platform))); } else { PlatformKey fromPlatformKey = PlatformKey.withName(fromPlatform).withApplicationName(fromApplication) .build(); checkQueryParameterNotEmpty("from_application", fromApplication); checkQueryParameterNotEmpty("from_platform", fromPlatform); return platformConverter.toPlatform(applications.createPlatformFromExistingPlatform( platformConverter.toPlatformData(platform), fromPlatformKey)); } } @Path("/{application_name}/platforms") @PUT @Timed @ApiOperation("Update platform for application with given name") public Platform updatePlatform(@Auth final User user, @PathParam("application_name") final String applicationName, @QueryParam("copyPropertiesForUpgradedModules") final boolean copyPropertiesForUpgradedModules, @Valid final Platform platform) { return platformConverter.toPlatform(applications.updatePlatform(platformConverter.toPlatformData(platform), copyPropertiesForUpgradedModules)); } @Path("/{application_name}/platforms/{platform_name}/properties") @GET @Timed @ApiOperation("Get properties with the given path in a platform") public Properties getProperties(@Auth final User user, @PathParam("application_name") final String applicationName, @PathParam("platform_name") final String platformName, @QueryParam("path") final String path, @QueryParam("timestamp") final Long timestamp) { checkQueryParameterNotEmpty("application_name", applicationName); checkQueryParameterNotEmpty("platform_name", platformName); checkQueryParameterNotEmpty("path", path); PlatformKey platformKey = PlatformKey.withName(platformName).withApplicationName(applicationName).build(); HesperidesPropertiesModel model = new HesperidesPropertiesModel(Sets.newHashSet(), Sets.newHashSet()); if (path.length() > 1) { HesperidesUtil.ModuleInfo info = HesperidesUtil.moduleInfoFromPath(path); model = info.isRelease() ? this.moduleResource.getReleaseModel(user, info.getName(), info.getVersion()) : this.moduleResource.getWorkingCopyModel(user, info.getName(), info.getVersion()); } return (timestamp != null) ? propertiesConverter .toProperties(applications.getSecuredProperties(platformKey, path, timestamp, model)) : propertiesConverter.toProperties(applications.getSecuredProperties(platformKey, path, model)); } @Path("/{application_name}/platforms/{platform_name}/properties/instance_model") @GET @Timed @ApiOperation("Get properties with the given path in a platform") public InstanceModel getInstanceModel(@Auth final User user, @PathParam("application_name") final String applicationName, @PathParam("platform_name") final String platformName, @QueryParam("path") final String path) { checkQueryParameterNotEmpty("application_name", applicationName); checkQueryParameterNotEmpty("platform_name", platformName); checkQueryParameterNotEmpty("path", path); PlatformKey platformKey = PlatformKey.withName(platformName).withApplicationName(applicationName).build(); return applications.getInstanceModel(platformKey, path); } @Path("/{application_name}/platforms/{platform_name}/properties") @POST @Timed @ApiOperation("Save properties in a platform with the given path") public Properties saveProperties(@Auth final User user, @PathParam("application_name") final String applicationName, @PathParam("platform_name") final String platformName, @QueryParam("path") final String path, @QueryParam("platform_vid") final Long platformID, //Using Long wrapper object helps preventing Java Primitive Default value of 0 @QueryParam("comment") final String comment, @Valid final Properties properties) { checkQueryParameterNotEmpty("application_name", applicationName); checkQueryParameterNotEmpty("platform_name", platformName); checkQueryParameterNotEmpty("path", path); checkQueryParameterNotEmpty("platform_vid", platformID); checkQueryParameterNotEmpty("comment", comment); PlatformKey platformKey = PlatformKey.withName(platformName).withApplicationName(applicationName).build(); //Filter properties to remove null or empty valorisations Properties propertiesCleaned; if (path.equals("#")) { propertiesCleaned = properties; } else { propertiesCleaned = properties.makeCopyWithoutNullOrEmptyValorisations(); } return propertiesConverter.toProperties(applications.createOrUpdatePropertiesInPlatform(platformKey, path, propertiesConverter.toPropertiesData(propertiesCleaned), platformID, comment)); } @Path("/{application_name}/platforms/{platform_name}/take_snapshot") @POST @Timed @ApiOperation("Take a snapshot of the platform") public Response takeSnapshot(@Auth final User user, @PathParam("application_name") final String applicationName, @PathParam("platform_name") final String platformName) { checkQueryParameterNotEmpty("application_name", applicationName); checkQueryParameterNotEmpty("platform_name", platformName); PlatformKey platformKey = PlatformKey.withName(platformName).withApplicationName(applicationName).build(); applications.takeSnapshot(platformKey); return Response.ok().build(); } @Path("/{application_name}/platforms/{platform_name}/restore_snapshot") @POST @Timed @ApiOperation("Take a snapshot of the platform") public Platform restaureSnapshot(@Auth final User user, @PathParam("application_name") final String applicationName, @PathParam("platform_name") final String platformName, @QueryParam("timestamp") final long timestamp) { checkQueryParameterNotEmpty("application_name", applicationName); checkQueryParameterNotEmpty("platform_name", platformName); checkQueryParameterNotEmpty("timestamp", timestamp); PlatformKey platformKey = PlatformKey.withName(platformName).withApplicationName(applicationName).build(); return platformConverter.toPlatform(applications.restoreSnapshot(platformKey, timestamp)); } @Path("/{application_name}/platforms/{platform_name}/snapshots") @GET @Timed @ApiOperation("Get the list of timestamps corresponding to snapshots of the platform") public List<Long> getSnapshots(@Auth final User user, @PathParam("application_name") final String applicationName, @PathParam("platform_name") final String platformName) { checkQueryParameterNotEmpty("application_name", applicationName); checkQueryParameterNotEmpty("platform_name", platformName); PlatformKey platformKey = PlatformKey.withName(platformName).withApplicationName(applicationName).build(); List<Long> snapshots = applications.getSnapshots(platformKey); Collections.sort(snapshots, (longA, longB) -> longB.compareTo(longA)); return snapshots; } }