All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.atlassian.clientpluginsdemorefapp.rest.BackdoorResource Maven / Gradle / Ivy

Go to download

Demonstrates how product developers and plugin developers can make use of the Client-side Extensions APIs.

There is a newer version: 4.0.0-jakarta-m001-6cdaaa6-m5gf9rqt
Show newest version
package com.atlassian.clientpluginsdemorefapp.rest;

import com.atlassian.plugin.ModuleDescriptor;
import com.atlassian.plugin.PluginAccessor;
import com.atlassian.plugin.descriptors.AbstractModuleDescriptor;
import com.atlassian.plugin.osgi.external.ListableModuleDescriptorFactory;
import com.atlassian.plugin.servlet.descriptors.ServletModuleDescriptor;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
import com.atlassian.plugins.rest.common.security.AnonymousAllowed;
import org.codehaus.jackson.annotate.JsonCreator;
import org.codehaus.jackson.annotate.JsonProperty;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.Function;

import static com.atlassian.clientpluginsdemorefapp.rest.BackdoorResource.ModuleDto.toDto;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toCollection;
import static java.util.stream.Collectors.toList;
import static java.util.stream.StreamSupport.stream;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static javax.ws.rs.core.Response.Status.NOT_FOUND;
import static org.osgi.framework.FrameworkUtil.getBundle;

/**
 * Provides a backdoor into this plugin.
 */
@AnonymousAllowed
@Path("backdoor")
@Produces(APPLICATION_JSON)
public class BackdoorResource {

    private static final Function, String> GET_BSN = serviceReference ->
        serviceReference.getBundle().getSymbolicName();

    private final BundleContext bundleContext;
    private final PluginAccessor pluginAccessor;

    public BackdoorResource(@ComponentImport final PluginAccessor pluginAccessor) {
        this.bundleContext = getBundle(getClass()).getBundleContext();
        this.pluginAccessor = requireNonNull(pluginAccessor);
    }

    /**
     * Returns the registered module types.
     *
     * The full URL is http://localhost:5990/refapp/rest/cse-demo/1/backdoor/module-types
     *
     * @return a JSON object where the property names are plugin BSNs and the value of each property is an
     * array of the module types provided by that plugin
     */
    @GET
    @Path("module-types")
    public Map> getModuleTypes() {
        return moduleDescriptorFactories()
            .stream()
            .collect(groupingBy(
                GET_BSN,
                TreeMap::new,
                mapping(this::getModuleType, toCollection(TreeSet::new))));
    }

    private String getModuleType(final ServiceReference serviceReference) {
        final ListableModuleDescriptorFactory moduleDescriptorFactory = bundleContext.getService(serviceReference);
        final Iterable moduleDescriptorKeyIter = moduleDescriptorFactory.getModuleDescriptorKeys();
        final List moduleDescriptorKeys = stream(moduleDescriptorKeyIter.spliterator(), false).collect(toList());
        switch (moduleDescriptorKeys.size()) {
            case 0:
                return "(none)";  // shouldn't happen
            case 1:
                return moduleDescriptorKeys.get(0);
            default:
                return "(multiple)";  // the CSE bootstrapper doesn't do this, so we don't care what these are
        }
    }

    private Collection> moduleDescriptorFactories() {
        try {
            return bundleContext.getServiceReferences(ListableModuleDescriptorFactory.class, null);
        } catch (InvalidSyntaxException e) {
            throw new IllegalStateException("Filter is invalid", e);
        }
    }

    /**
     * Returns the details of all plugin-provided servlets.
     *
     * The full URL is http://localhost:5990/refapp/rest/cse-demo/1/backdoor/servlet-modules
     *
     * @return a JSON object where the property names are plugin keys and the value of each property is an
     * array of the keys of the servlet modules provided by that plugin
     */
    @GET
    @Path("servlet-modules")
    public Map> getServletModules() {
        return pluginAccessor.getEnabledModuleDescriptorsByClass(ServletModuleDescriptor.class)
            .stream()
            .collect(groupingBy(
                AbstractModuleDescriptor::getPluginKey,
                TreeMap::new,
                mapping(ServletModuleDescriptor::getKey, toCollection(TreeSet::new))));
    }

    @GET
    @Path("module/{complete-key}")
    public Object getModule(@PathParam("complete-key") final String completeKey) {
        final ModuleDescriptor moduleDescriptor = pluginAccessor.getEnabledPluginModule(completeKey);
        if (moduleDescriptor == null) {
            return Response.status(NOT_FOUND).build();
        }
        return toDto(moduleDescriptor);
    }

    public static class ModuleDto {

        static ModuleDto toDto(final ModuleDescriptor moduleDescriptor) {
            return new ModuleDto(
                moduleDescriptor.getDescription(),
                moduleDescriptor.getKey(),
                moduleDescriptor.getName(),
                moduleDescriptor.getPluginKey());
        }

        @JsonProperty
        private final String description;

        @JsonProperty
        private final String key;

        @JsonProperty
        private final String name;

        @JsonProperty
        private final String pluginKey;

        @JsonCreator
        private ModuleDto(@JsonProperty("description") final String description,
                          @JsonProperty("key") final String key,
                          @JsonProperty("name") final String name,
                          @JsonProperty("pluginKey") final String pluginKey) {
            this.description = description;
            this.key = key;
            this.name = name;
            this.pluginKey = pluginKey;
        }

        public String getDescription() {
            return description;
        }

        public String getKey() {
            return key;
        }

        public String getName() {
            return name;
        }

        public String getPluginKey() {
            return pluginKey;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy