| /******************************************************************************* |
| * Copyright (c) 2017 Ericsson |
| * |
| * 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 |
| *******************************************************************************/ |
| |
| package org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services; |
| |
| import java.io.File; |
| import java.nio.file.Paths; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.UUID; |
| |
| import javax.validation.constraints.NotNull; |
| import javax.ws.rs.Consumes; |
| import javax.ws.rs.DELETE; |
| import javax.ws.rs.GET; |
| import javax.ws.rs.POST; |
| import javax.ws.rs.Path; |
| import javax.ws.rs.PathParam; |
| import javax.ws.rs.Produces; |
| import javax.ws.rs.core.MediaType; |
| import javax.ws.rs.core.Response; |
| import javax.ws.rs.core.Response.Status; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspaceRoot; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.jdt.annotation.Nullable; |
| import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.Activator; |
| import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model.views.QueryParameters; |
| import org.eclipse.tracecompass.tmf.core.TmfCommonConstants; |
| import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; |
| import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException; |
| import org.eclipse.tracecompass.tmf.core.io.ResourceUtil; |
| import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceImportException; |
| import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType; |
| import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper; |
| import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager; |
| import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal; |
| import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal; |
| import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; |
| import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; |
| import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment; |
| |
| import com.google.common.base.Optional; |
| import com.google.common.base.Predicates; |
| import com.google.common.collect.Collections2; |
| import com.google.common.collect.Iterables; |
| |
| /** |
| * Service to manage traces. |
| * |
| * @author Loic Prieur-Drevon |
| */ |
| @Path("/traces") |
| public class TraceManagerService { |
| |
| /** |
| * Getter method to access the list of traces |
| * |
| * @return a response containing the list of traces |
| */ |
| @GET |
| @Produces({ MediaType.APPLICATION_JSON }) |
| public Response getTraces() { |
| return Response.ok(Collections2.filter(TmfTraceManager.getInstance().getOpenedTraces(), |
| Predicates.not(TmfExperiment.class::isInstance))).build(); |
| } |
| |
| /** |
| * Method to open the trace, initialize it, index it and add it to the trace |
| * manager. |
| * |
| * @param queryParameters |
| * Parameters to post a trace as described by |
| * {@link QueryParameters} |
| * @return the new trace model object or the exception if it failed to load. |
| */ |
| @POST |
| @Consumes(MediaType.APPLICATION_JSON) |
| @Produces(MediaType.APPLICATION_JSON) |
| public Response putTrace(QueryParameters queryParameters) { |
| Map<String, Object> parameters = queryParameters.getParameters(); |
| String name = (String) parameters.get("name"); |
| String path = (String) parameters.get("uri"); |
| Object typeIDObject = parameters.get("typeID"); |
| String typeID = typeIDObject != null ? (String) typeIDObject : ""; |
| Optional<@NonNull ITmfTrace> optional = Iterables.tryFind(TmfTraceManager.getInstance().getOpenedTraces(), t -> t.getPath().equals(path)); |
| if (optional.isPresent()) { |
| return Response.status(Status.CONFLICT).entity(optional.get()).build(); |
| } |
| if (!Paths.get(path).toFile().exists()) { |
| return Response.status(Status.NOT_FOUND).entity("No trace at " + path).build(); //$NON-NLS-1$ |
| } |
| try { |
| ITmfTrace trace = put(path, name, typeID); |
| if (trace == null) { |
| return Response.status(Status.NOT_IMPLEMENTED).entity("Trace type not supported").build(); //$NON-NLS-1$ |
| } |
| return Response.ok(trace).build(); |
| } catch (TmfTraceException | TmfTraceImportException | InstantiationException |
| | IllegalAccessException | CoreException e) { |
| return Response.status(Status.NOT_ACCEPTABLE).entity(e.getMessage()).build(); |
| } |
| } |
| |
| private ITmfTrace put(String path, String name, String typeID) |
| throws TmfTraceException, TmfTraceImportException, InstantiationException, |
| IllegalAccessException, CoreException { |
| List<TraceTypeHelper> traceTypes = TmfTraceType.selectTraceType(path, typeID); |
| if (traceTypes.isEmpty()) { |
| return null; |
| } |
| |
| IResource resource = getResource(path); |
| |
| TraceTypeHelper helper = traceTypes.get(0); |
| ITmfTrace trace = helper.getTraceClass().newInstance(); |
| trace.initTrace(resource, path, ITmfEvent.class, name, typeID); |
| trace.indexTrace(false); |
| TmfSignalManager.dispatchSignal(new TmfTraceOpenedSignal(this, trace, null)); |
| return trace; |
| } |
| |
| /** |
| * Gets the Eclipse resource from the path and prepares the supplementary |
| * directory for this trace. |
| * |
| * @param path |
| * the absolute path string to the trace |
| * @return The Eclipse resources |
| * |
| * @throws CoreException |
| * if an error occurs |
| */ |
| private static IResource getResource(String path) throws CoreException { |
| IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); |
| IProject project = root.getProject(TmfCommonConstants.DEFAULT_TRACE_PROJECT_NAME); |
| IPath iPath = org.eclipse.core.runtime.Path.forPosix(path); |
| |
| IResource resource = null; |
| boolean isSuccess = false; |
| // create the resource hierarchy. |
| if (new File(path).isFile()) { |
| IFile file = project.getFile(path); |
| createFolder((IFolder) file.getParent(), null); |
| isSuccess = ResourceUtil.createSymbolicLink(file, iPath, true, null); |
| resource = file; |
| } else { |
| IFolder folder = project.getFolder(path); |
| createFolder((IFolder) folder.getParent(), null); |
| isSuccess = ResourceUtil.createSymbolicLink(folder, iPath, true, null); |
| resource = folder; |
| } |
| |
| if (!isSuccess) { |
| return null; |
| } |
| |
| // create supplementary folder on file system: |
| IFolder supplRootFolder = project.getFolder(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER_NAME); |
| IFolder supplFolder = supplRootFolder.getFolder(path); |
| createFolder(supplFolder, null); |
| resource.setPersistentProperty(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER, supplFolder.getLocation().toOSString()); |
| |
| return resource; |
| } |
| |
| /** |
| * Getter method to get a trace object |
| * |
| * @param uuid |
| * Unique trace ID |
| * @return a response containing the trace |
| */ |
| @GET |
| @Path("/{uuid}") |
| @Produces({ MediaType.APPLICATION_JSON }) |
| public Response getTrace(@PathParam("uuid") @NotNull UUID uuid) { |
| ITmfTrace trace = getTraceByUUID(uuid); |
| if (trace == null || trace instanceof TmfExperiment) { |
| return Response.status(Status.NOT_FOUND).build(); |
| } |
| return Response.ok(trace).build(); |
| } |
| |
| /** |
| * Delete a trace from the manager and dispose of it |
| * |
| * @param uuid |
| * Unique trace ID |
| * @return a not found response if there is no such trace or the entity. |
| */ |
| @DELETE |
| @Path("/{uuid}") |
| @Produces({ MediaType.APPLICATION_JSON }) |
| public Response deleteTrace(@PathParam("uuid") @NotNull UUID uuid) { |
| ITmfTrace trace = getTraceByUUID(uuid); |
| if (trace == null || trace instanceof TmfExperiment) { |
| return Response.status(Status.NOT_FOUND).build(); |
| } |
| TmfSignalManager.dispatchSignal(new TmfTraceClosedSignal(this, trace)); |
| TmfTraceManager.deleteSupplementaryFolder(trace); |
| trace.dispose(); |
| try { |
| IResource resource = trace.getResource(); |
| if (resource != null) { |
| resource.delete(IResource.FORCE, null); |
| } |
| ResourcesPlugin.getWorkspace().getRoot() |
| .getProject(TmfCommonConstants.DEFAULT_TRACE_PROJECT_NAME) |
| .refreshLocal(Integer.MAX_VALUE, null); |
| } catch (CoreException e) { |
| Activator.getInstance().logError("Failed to delete trace", e); //$NON-NLS-1$ |
| } |
| return Response.ok(trace).build(); |
| } |
| |
| /** |
| * Try and find a trace with the queried UUID in the {@link TmfTraceManager}. |
| * |
| * @param uuid |
| * queried {@link UUID} |
| * @return the trace or null if none match. |
| */ |
| public static @Nullable ITmfTrace getTraceByUUID(UUID uuid) { |
| return Iterables.tryFind(TmfTraceManager.getInstance().getOpenedTraces(), t -> uuid.equals(t.getUUID())).orNull(); |
| } |
| |
| private static void createFolder(IFolder folder, IProgressMonitor monitor) throws CoreException { |
| // Taken from: org.eclipse.tracecompass.tmf.ui.project.model.TraceUtil.java |
| // TODO: have a tmf.core util for that. |
| if (!folder.exists()) { |
| if (folder.getParent() instanceof IFolder) { |
| createFolder((IFolder) folder.getParent(), monitor); |
| } |
| folder.create(true, true, monitor); |
| } |
| } |
| } |