org.opencastproject.runtimeinfo.RuntimeInfo.java Source code

Java tutorial

Introduction

Here is the source code for org.opencastproject.runtimeinfo.RuntimeInfo.java

Source

/**
 *  Copyright 2009, 2010 The Regents of the University of California
 *  Licensed under the Educational Community License, Version 2.0
 *  (the "License"); you may not use this file except in compliance
 *  with the License. You may obtain a copy of the License at
 *
 *  http://www.osedu.org/licenses/ECL-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an "AS IS"
 *  BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 *  or implied. See the License for the specific language governing
 *  permissions and limitations under the License.
 *
 */
package org.opencastproject.runtimeinfo;

import static org.opencastproject.rest.RestConstants.SERVICES_FILTER;

import org.opencastproject.rest.RestConstants;
import org.opencastproject.security.api.Organization;
import org.opencastproject.security.api.SecurityService;
import org.opencastproject.security.api.User;
import org.opencastproject.util.UrlSupport;
import org.opencastproject.util.doc.rest.RestQuery;
import org.opencastproject.util.doc.rest.RestResponse;
import org.opencastproject.util.doc.rest.RestService;

import org.apache.commons.lang.StringUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map.Entry;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.servlet.Servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;

/**
 * This REST endpoint provides information about the runtime environment, including the services and user interfaces
 * deployed and the current login context.
 * 
 * If the 'org.opencastproject.anonymous.feedback.url' is set in config.properties, this service will also update the
 * opencast project with the contents of the {@link #getRuntimeInfo()} json feed.
 */
@Path("/")
@RestService(name = "RuntimeInfo", title = "Runtime Information", notes = "", abstractText = "This service provides information about the runtime environment, including the servives that are deployed and the current user context.")
public class RuntimeInfo {

    private static final Logger logger = LoggerFactory.getLogger(RuntimeInfo.class);

    /** Configuration properties id */
    private static final String ADMIN_URL_PROPERTY = "org.opencastproject.admin.ui.url";
    private static final String ENGAGE_URL_PROPERTY = "org.opencastproject.engage.ui.url";
    private static final String SERVER_URL_PROPERTY = "org.opencastproject.server.url";

    /** The rest publisher looks for any non-servlet with the 'opencast.service.path' property */
    public static final String SERVICE_FILTER = "(&(!(objectClass=javax.servlet.Servlet))("
            + RestConstants.SERVICE_PATH_PROPERTY + "=*))";

    private SecurityService securityService;
    private BundleContext bundleContext;
    private URL serverUrl;
    private URL engageBaseUrl;
    private URL adminBaseUrl;

    protected void setSecurityService(SecurityService securityService) {
        this.securityService = securityService;
    }

    protected ServiceReference[] getRestServiceReferences() throws InvalidSyntaxException {
        return bundleContext.getAllServiceReferences(null, SERVICES_FILTER);
    }

    protected ServiceReference[] getUserInterfaceServiceReferences() throws InvalidSyntaxException {
        return bundleContext.getAllServiceReferences(Servlet.class.getName(), "(&(alias=*)(classpath=*))");
    }

    public void activate(ComponentContext cc) throws MalformedURLException {
        logger.debug("start()");

        this.bundleContext = cc.getBundleContext();

        serverUrl = new URL(bundleContext.getProperty(SERVER_URL_PROPERTY));

        // Get admin UI url
        String adminBaseUrlStr = bundleContext.getProperty(ADMIN_URL_PROPERTY);
        if (StringUtils.isBlank(adminBaseUrlStr))
            adminBaseUrl = serverUrl;
        else
            adminBaseUrl = new URL(adminBaseUrlStr);
        logger.debug("Default admin server url is {}", adminBaseUrlStr);

        // Get engage UI url
        String engageBaseUrlStr = bundleContext.getProperty(ENGAGE_URL_PROPERTY);
        if (StringUtils.isBlank(engageBaseUrlStr))
            engageBaseUrl = serverUrl;
        else
            engageBaseUrl = new URL(engageBaseUrlStr);
        logger.debug("Default engage server url is {}", engageBaseUrl);
    }

    public void deactivate() {
        // Nothing to do
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("components.json")
    @RestQuery(name = "services", description = "List the REST services and user interfaces running on this host", reponses = {
            @RestResponse(description = "The components running on this host", responseCode = HttpServletResponse.SC_OK) }, returnDescription = "")
    @SuppressWarnings("unchecked")
    public String getRuntimeInfo(@Context HttpServletRequest request) throws MalformedURLException {
        Organization organization = securityService.getOrganization();

        // Get request protocol and port
        String targetScheme = request.getScheme();

        // Create the engage target URL
        URL targetEngageBaseUrl = null;
        String organizationEngageURL = organization.getProperties().get(ENGAGE_URL_PROPERTY);
        if (StringUtils.isNotBlank(organizationEngageURL)) {
            try {
                targetEngageBaseUrl = new URL(organizationEngageURL);
            } catch (MalformedURLException e) {
                logger.warn("Engage url '{}' of organization '{}' is malformed", organizationEngageURL,
                        organization.getId());
                targetEngageBaseUrl = new URL(targetScheme, engageBaseUrl.getHost(), engageBaseUrl.getPort(),
                        engageBaseUrl.getFile());
            }
        } else {
            targetEngageBaseUrl = new URL(targetScheme, engageBaseUrl.getHost(), engageBaseUrl.getPort(),
                    engageBaseUrl.getFile());
        }

        // Create the admin target URL
        URL targetAdminBaseUrl = null;
        String organizationAdminURL = organization.getProperties().get(ADMIN_URL_PROPERTY);
        if (StringUtils.isNotBlank(organizationAdminURL)) {
            try {
                targetAdminBaseUrl = new URL(organizationAdminURL);
            } catch (MalformedURLException e) {
                logger.warn("Admin url '{}' of organization '{}' is malformed", organizationAdminURL,
                        organization.getId());
                targetAdminBaseUrl = new URL(targetScheme, adminBaseUrl.getHost(), adminBaseUrl.getPort(),
                        adminBaseUrl.getFile());
            }
        } else {
            targetAdminBaseUrl = new URL(targetScheme, adminBaseUrl.getHost(), adminBaseUrl.getPort(),
                    adminBaseUrl.getFile());
        }

        JSONObject json = new JSONObject();
        json.put("engage", targetEngageBaseUrl.toString());
        json.put("admin", targetAdminBaseUrl.toString());
        json.put("rest", getRestEndpointsAsJson(request));
        json.put("ui", getUserInterfacesAsJson());

        return json.toJSONString();
    }

    @GET
    @Path("me.json")
    @Produces(MediaType.APPLICATION_JSON)
    @RestQuery(name = "me", description = "Information about the curent user", reponses = {
            @RestResponse(description = "Returns information about the current user", responseCode = HttpServletResponse.SC_OK) }, returnDescription = "")
    @SuppressWarnings("unchecked")
    public String getMyInfo() {
        JSONObject json = new JSONObject();

        User user = securityService.getUser();
        json.put("username", user.getUserName());

        // Add the current user's roles
        JSONArray roles = new JSONArray();
        for (String role : user.getRoles()) {
            roles.add(role);
        }
        json.put("roles", roles);

        // Add the current user's organizational information
        Organization org = securityService.getOrganization();

        JSONObject jsonOrg = new JSONObject();
        jsonOrg.put("id", org.getId());
        jsonOrg.put("name", org.getName());
        jsonOrg.put("adminRole", org.getAdminRole());
        jsonOrg.put("anonymousRole", org.getAnonymousRole());

        // and organization properties
        JSONObject orgProps = new JSONObject();
        jsonOrg.put("properties", orgProps);
        for (Entry<String, String> entry : org.getProperties().entrySet()) {
            orgProps.put(entry.getKey(), entry.getValue());
        }
        json.put("org", jsonOrg);

        return json.toJSONString();
    }

    @SuppressWarnings("unchecked")
    protected JSONArray getRestEndpointsAsJson(HttpServletRequest request) throws MalformedURLException {
        JSONArray json = new JSONArray();
        ServiceReference[] serviceRefs = null;
        try {
            serviceRefs = getRestServiceReferences();
        } catch (InvalidSyntaxException e) {
            e.printStackTrace();
        }
        if (serviceRefs == null)
            return json;
        for (ServiceReference servletRef : sort(serviceRefs)) {
            String version = servletRef.getBundle().getVersion().toString();
            String description = (String) servletRef.getProperty(Constants.SERVICE_DESCRIPTION);
            String type = (String) servletRef.getProperty(RestConstants.SERVICE_TYPE_PROPERTY);
            String servletContextPath = (String) servletRef.getProperty(RestConstants.SERVICE_PATH_PROPERTY);
            JSONObject endpoint = new JSONObject();
            endpoint.put("description", description);
            endpoint.put("version", version);
            endpoint.put("type", type);
            URL url = new URL(request.getScheme(), request.getServerName(), request.getServerPort(),
                    servletContextPath);
            endpoint.put("path", servletContextPath);
            endpoint.put("docs", UrlSupport.concat(url.toExternalForm(), "/docs")); // This is a Matterhorn convention
            endpoint.put("wadl", UrlSupport.concat(url.toExternalForm(), "/?_wadl&_type=xml")); // This triggers a
            json.add(endpoint);
        }
        return json;
    }

    @SuppressWarnings("unchecked")
    protected JSONArray getUserInterfacesAsJson() {
        JSONArray json = new JSONArray();
        ServiceReference[] serviceRefs = null;
        try {
            serviceRefs = getUserInterfaceServiceReferences();
        } catch (InvalidSyntaxException e) {
            e.printStackTrace();
        }
        if (serviceRefs == null)
            return json;
        for (ServiceReference ref : sort(serviceRefs)) {
            String description = (String) ref.getProperty(Constants.SERVICE_DESCRIPTION);
            String version = ref.getBundle().getVersion().toString();
            String alias = (String) ref.getProperty("alias");
            String welcomeFile = (String) ref.getProperty("welcome.file");
            String welcomePath = "/".equals(alias) ? alias + welcomeFile : alias + "/" + welcomeFile;
            JSONObject endpoint = new JSONObject();
            endpoint.put("description", description);
            endpoint.put("version", version);
            endpoint.put("welcomepage", serverUrl + welcomePath);
            json.add(endpoint);
        }
        return json;
    }

    /**
     * Returns the array of references sorted by their {@link Constants.SERVICE_DESCRIPTION} property.
     * 
     * @param references
     *          the referencens
     * @return the sorted set of references
     */
    protected static SortedSet<ServiceReference> sort(ServiceReference[] references) {
        // Sort the service references
        SortedSet<ServiceReference> sortedServiceRefs = new TreeSet<ServiceReference>(
                new Comparator<ServiceReference>() {
                    @Override
                    public int compare(ServiceReference o1, ServiceReference o2) {
                        String o1Description = (String) o1.getProperty(Constants.SERVICE_DESCRIPTION);
                        if (StringUtils.isBlank(o1Description))
                            o1Description = o1.toString();
                        String o2Description = (String) o2.getProperty(Constants.SERVICE_DESCRIPTION);
                        if (StringUtils.isBlank(o2Description))
                            o2Description = o2.toString();
                        return o1Description.compareTo(o2Description);
                    }
                });
        sortedServiceRefs.addAll(Arrays.asList(references));
        return sortedServiceRefs;
    }
}