org.sakaiproject.kernel.rest.RestMySitesProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.sakaiproject.kernel.rest.RestMySitesProvider.java

Source

/*
 * Licensed to the Sakai Foundation (SF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The SF licenses this file
 * to you under the Apache 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.apache.org/licenses/LICENSE-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.sakaiproject.kernel.rest;

import com.google.inject.Inject;
import com.google.inject.name.Named;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.kernel.KernelConstants;
import org.sakaiproject.kernel.api.Kernel;
import org.sakaiproject.kernel.api.KernelManager;
import org.sakaiproject.kernel.api.Registry;
import org.sakaiproject.kernel.api.RegistryService;
import org.sakaiproject.kernel.api.rest.RestProvider;
import org.sakaiproject.kernel.api.serialization.BeanConverter;
import org.sakaiproject.kernel.api.session.Session;
import org.sakaiproject.kernel.api.session.SessionManagerService;
import org.sakaiproject.kernel.api.site.SiteService;
import org.sakaiproject.kernel.api.user.User;
import org.sakaiproject.kernel.api.userenv.UserEnvironment;
import org.sakaiproject.kernel.api.userenv.UserEnvironmentResolverService;
import org.sakaiproject.kernel.model.SiteBean;
import org.sakaiproject.kernel.util.rest.RestDescription;
import org.sakaiproject.kernel.webapp.RestServiceFaultException;

import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Implements the MySites service.
 *
 * This is coded according to OpenSocial API v.8.1
 * http://www.opensocial.org/Technical
 * -Resources/opensocial-spec-v081/restful-protocol#TOC-2.1-Responses
 *
 */
public class RestMySitesProvider implements RestProvider {

    public static final String SITES_ELEMENT = "sites";
    private static final RestDescription DESCRIPTION = new RestDescription();
    private static final Log LOG = LogFactory.getLog(RestMySitesProvider.class);
    private static final boolean debug = LOG.isDebugEnabled();
    private SessionManagerService sessionManagerService;
    private BeanConverter beanConverter;

    public static final String OUTPUT_PARAM_NAME_STARTINDEX = "startIndex";
    public static final String OUTPUT_PARAM_NAME_ITEMSPERPAGE = "startIndex";

    public static final String INPUT_PARAM_NAME_STARTINDEX = "itemsPerPage";
    public static final String INPUT_PARAM_NAME_COUNT = "count";
    private static final String OUTPUT_PARAM_NAME_TOTALRESULTS = "totalResults";
    private static final String OUTPUT_SITES_KEY = "entry";

    private UserEnvironmentResolverService simpleJcrUserEnvironmentResolverService;
    private SiteService siteService;

    @Inject
    public RestMySitesProvider(RegistryService registryService, SessionManagerService sessionManagerService,
            UserEnvironmentResolverService simpleJcrUserEnvironmentResolverService, BeanConverter beanConverter,
            @Named(KernelConstants.JCR_USERENV_BASE) String userEnvironmentBase, SiteService siteService) {
        Registry<String, RestProvider> registry = registryService.getRegistry(RestProvider.REST_REGISTRY);
        registry.add(this);
        this.sessionManagerService = sessionManagerService;
        this.beanConverter = beanConverter;
        this.simpleJcrUserEnvironmentResolverService = simpleJcrUserEnvironmentResolverService;
        this.siteService = siteService;
    }

    static {
        DESCRIPTION.setTitle("MySites Service");
        DESCRIPTION.setBackUrl("../__describe__");
        DESCRIPTION.setShortDescription(
                "The MySites service provides information about " + "sites associated with the current user");
        DESCRIPTION.addSection(1, "Introduction",
                "The MySites Service, when queried will respond with a json specific "
                        + "to the logged in user. If no logged in user is present, then an "
                        + "anonymous json response will be sent. In addition some headers "
                        + "will be modified to reflect the locale preferences of the user.");
        DESCRIPTION.addSection(2, "Response: Anon User",
                "Where the user is an anon user the response will contain a list of sites "
                        + "that are accessible anonymously.");
        DESCRIPTION.addSection(2, "Response: Authenticated User",
                "Where the user is an authenticaated user the response will contain a list of "
                        + "sites associated wit the user including the role(s) in each.");
        DESCRIPTION.addParameter("count (optional) - TODO", "Number of items to return for paging");// TODO
        DESCRIPTION.addParameter("startIndex (optional) - TODO ", "Index (integer) of item starting page");// TODO
        DESCRIPTION.addParameter("itemsPerPage (optional) - TODO", "The number of items to display");// TODO
        DESCRIPTION.addHeader("none", "The service neither looks for headers nor sets any non standard headers");
        DESCRIPTION.addURLTemplate("sites",
                "The service is selected by /rest/sites. If there is any training path the request will be ignored by this provider");
        DESCRIPTION.addResponse("200", "The service returns a JSON body with a list of N 'items' structures. eg "

                + "    {" + "      \"entry\": [" + "          {" + "              \"type\": \"course\","
                + "              \"description\": \"An Example site definition. This is just the required fields that we might see inside a object that defines a site \","
                + "              \"roles\": [" + "                  {" + "                      \"permissions\": ["
                + "                          \"read\"," + "                          \"write\","
                + "                          \"delete\"" + "                      ],"
                + "                      \"name\": \"access\"" + "                  }," + "                  {"
                + "                      \"permissions\": [" + "                          \"read\","
                + "                          \"write\"," + "                          \"delete\""
                + "                      ]," + "                      \"name\": \"maintain\""
                + "                  }" + "              ]," + "              \"subjectTokens\": ["
                + "                  \"Site 2:access\"," + "                  \"Site 2:maintain\""
                + "              ]," + "              \"name\": \"Site 2\"," + "              \"id\": \"group2\""
                + "          }," + "          {" + "              \"type\": \"course\","
                + "              \"description\": \"An Example site definition. This is just the required fields that we might see inside a object that defines a site \","
                + "              \"roles\": [" + "                  {" + "                      \"permissions\": ["
                + "                          \"read\"," + "                          \"write\","
                + "                          \"delete\"" + "                      ],"
                + "                      \"name\": \"access\"" + "                  }," + "                  {"
                + "                      \"permissions\": [" + "                          \"read\","
                + "                          \"write\"," + "                          \"delete\""
                + "                      ]," + "                      \"name\": \"maintain\""
                + "                  }" + "              ]," + "              \"subjectTokens\": ["
                + "                  \"Site 1:access\"," + "                  \"Site 1:maintain\""
                + "              ]," + "              \"name\": \"Site 1\"," + "              \"id\": \"group1\""
                + "          }," + "          {" + "              \"type\": \"course\","
                + "              \"description\": \"An Example site definition. This is just the required fields that we might see inside a object that defines a site \","
                + "              \"roles\": [" + "                  {" + "                      \"permissions\": ["
                + "                          \"read\"," + "                          \"write\","
                + "                          \"delete\"" + "                      ],"
                + "                      \"name\": \"access\"" + "                  }," + "                  {"
                + "                      \"permissions\": [" + "                          \"read\","
                + "                          \"write\"," + "                          \"delete\""
                + "                      ]," + "                      \"name\": \"maintain\""
                + "                  }" + "              ]," + "              \"subjectTokens\": ["
                + "                  \"Site 2:access\"," + "                  \"Site 2:maintain\""
                + "              ]," + "              \"name\": \"Site 2\"," + "              \"id\": \"group2\""
                + "          }" + "      ]," + "      \"totalResults\": 3" + "  }");

    }

    /**
     * {@inheritDoc}
     *
     * @see org.sakaiproject.kernel.api.rest.RestProvider#dispatch(java.lang.String[],
     *      javax.servlet.http.HttpServletRequest,
     *      javax.servlet.http.HttpServletResponse)
     */
    public void dispatch(String[] elements, HttpServletRequest request, HttpServletResponse response) {
        try {
            if (elements.length == 1 && SITES_ELEMENT.equals(elements[0])) {

                KernelManager kernelManager = new KernelManager();
                Kernel kernel = kernelManager.getKernel();

                if (null == sessionManagerService) {
                    sessionManagerService = kernel.getService(SessionManagerService.class);
                }

                Session session = sessionManagerService.getCurrentSession();
                User user = session.getUser();

                String uuid = null;

                if (user == null || user.getUuid() == null) {
                    uuid = "anon";
                } else {
                    uuid = user.getUuid();
                }
                UserEnvironment env = simpleJcrUserEnvironmentResolverService.resolve(user);

                LOG.info("getting subjects....");
                String[] subjects = env.getSubjects();
                LOG.info("list of subjects for user (" + uuid + ", " + subjects.length + " total):");
                for (int i = 0; i < subjects.length; ++i) {
                    LOG.info("--> " + subjects[i]);
                }

                LOG.info("Parsing for startindex param from request ....." + request);

                /*
                 * parse and handle the paging This is coded according to OpenSocial API
                 * v.8.1
                 * http://www.opensocial.org/Technical-Resources/opensocial-spec-v081
                 * /restful -protocol#TOC-2.1-Responses
                 */
                Map<String, Object> pagingEnvelope = new HashMap<String, Object>();

                // check for startIndex param
                try {
                    String param = request.getParameter(INPUT_PARAM_NAME_STARTINDEX);
                    int startIndex = Integer.parseInt(param);
                    pagingEnvelope.put(OUTPUT_PARAM_NAME_STARTINDEX, startIndex);
                } catch (NumberFormatException e) {// just skip it
                } catch (Exception e) {
                    LOG.error("General Exception thrown parsing request for startIndex");
                }

                // / check for 'count' param
                try {
                    // /set to 'count' until we know how many values we have left to
                    // display
                    int itemsPerPage = Integer.parseInt(request.getParameter(INPUT_PARAM_NAME_COUNT));
                    pagingEnvelope.put(OUTPUT_PARAM_NAME_ITEMSPERPAGE, itemsPerPage);
                } catch (NumberFormatException e) {
                    // just skip it
                } catch (Exception e) {
                    LOG.error("General Exception thrown parsing request for itemsPerPage");
                }

                if (debug) {
                    LOG.debug("getting subjects as sites....");
                }

                SiteBean memSite = null;
                Set<SiteBean> sites = new HashSet<SiteBean>();

                for (String s : subjects) {
                    if (s != null) {
                        String[] parts = s.split(":");
                        if (parts.length == 2) {
                            memSite = siteService.getSiteById(parts[0]);

                            if (null == memSite) {
                                LOG.warn("group id not found as a site id... subject token: " + s);
                            } else {
                                if (debug) {
                                    LOG.debug("Site found: " + memSite.getName());
                                }
                                if (!sites.contains(memSite)) {
                                    sites.add(memSite);
                                }
                            }
                        } else {
                            LOG.error("malformed subject in userenvronment (user: " + uuid + ")");
                        }
                    } else {
                        LOG.error("null subject found in userenvironment (user: " + uuid + ")");
                    }
                }
                pagingEnvelope.put(OUTPUT_PARAM_NAME_TOTALRESULTS, sites.size());
                pagingEnvelope.put(OUTPUT_SITES_KEY, sites.toArray());
                sendOutput(response, pagingEnvelope);
            }
        } catch (SecurityException ex) {
            throw ex;
        } catch (RestServiceFaultException ex) {
            throw ex;
        } catch (Exception ex) {
            throw new RestServiceFaultException(ex.getMessage(), ex);
        }

    }

    /**
     * @param response
     * @param itemMap
     * @throws IOException
     */
    private void sendOutput(HttpServletResponse response, Map<String, Object> itemMap) throws IOException {
        response.setContentType(RestProvider.CONTENT_TYPE);
        ServletOutputStream outputStream = response.getOutputStream();

        outputStream.print(beanConverter.convertToString(itemMap));

        outputStream.flush();
        outputStream.close();

    }

    /**
     * {@inheritDoc}
     *
     * @see org.sakaiproject.kernel.api.rest.RestProvider#getDescription()
     */
    public RestDescription getDescription() {
        return DESCRIPTION;
    }

    /**
     * {@inheritDoc}
     *
     * @see org.sakaiproject.kernel.api.Provider#getKey()
     */
    public String getKey() {
        return "sites";
    }

    /**
     * {@inheritDoc}
     *
     * @see org.sakaiproject.kernel.api.Provider#getPriority()
     */
    public int getPriority() {
        return 0;
    }

}