Java tutorial
/* * Copyright (C) 2003-2010 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program 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 org.exoplatform.social.service.rest; import static org.exoplatform.social.service.rest.RestChecker.checkAuthenticatedRequest; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import javax.xml.bind.annotation.XmlRootElement; import org.apache.commons.collections.map.HashedMap; import org.exoplatform.commons.utils.Safe; import org.exoplatform.container.ExoContainerContext; import org.exoplatform.container.PortalContainer; import org.exoplatform.portal.config.UserPortalConfig; import org.exoplatform.services.rest.resource.ResourceContainer; import org.exoplatform.services.security.ConversationState; import org.exoplatform.social.core.identity.model.Identity; import org.exoplatform.social.core.identity.provider.OrganizationIdentityProvider; import org.exoplatform.social.core.manager.IdentityManager; import org.exoplatform.social.core.space.SpaceException; import org.exoplatform.social.core.space.SpaceFilter; import org.exoplatform.social.core.space.SpaceListAccess; import org.exoplatform.social.core.space.SpaceUtils; import org.exoplatform.social.core.space.model.Space; import org.exoplatform.social.core.space.spi.SpaceService; import org.exoplatform.web.WebAppController; import org.exoplatform.web.controller.QualifiedName; import org.exoplatform.web.controller.metadata.ControllerDescriptor; import org.exoplatform.web.controller.metadata.DescriptorBuilder; import org.exoplatform.web.controller.router.Router; import org.exoplatform.web.controller.router.RouterConfigException; import org.exoplatform.web.controller.router.URIWriter; /** * * Provides services for the space gadget to display a user's spaces and pending spaces. * * @anchor SpacesRestService * */ @Path("{portalName}/social/spaces") public class SpacesRestService implements ResourceContainer { private SpaceService _spaceService; private IdentityManager _identityManager; /** * Confirmed Status information */ private static final String CONFIRMED_STATUS = "confirmed"; /** * Pending Status information */ private static final String PENDING_STATUS = "pending"; /** * Incoming Status information */ private static final String INCOMING_STATUS = "incoming"; /** * Public Status information */ private static final String ALL_SPACES_STATUS = "all_spaces"; private String portalContainerName; /** * Qualified name path for rendering url. * * @since 1.2.2 */ private static final QualifiedName PATH = QualifiedName.create("gtn", "path"); /** * Qualified name path for rendering url. * * @since 1.2.9 */ private static final QualifiedName LANG = QualifiedName.create("gtn", "lang"); /** * Qualified name site type for rendering url. * * @since 1.2.2 */ private static final QualifiedName REQUEST_SITE_TYPE = QualifiedName.create("gtn", "sitetype"); /** * Qualified name handler for rendering url. * * @since 1.2.2 */ private static final QualifiedName REQUEST_HANDLER = QualifiedName.create("gtn", "handler"); /** * Qualified name site name for rendering url. * * @since 1.2.2 */ private static final QualifiedName REQUEST_SITE_NAME = QualifiedName.create("gtn", "sitename"); private static final String ALL_SPACES = "all-spaces"; /** * constructor */ public SpacesRestService() { } /** * Gets the current user's spaces and pending spaces. * * @param uriInfo The requested URI information. * @param portalName The name of the current container. * @param format The format of the returned result. * * @anchor SpacesRestService.showMySpaceList * * @return response * * @throws Exception * * @LevelAPI Platform */ @GET @Path("mySpaces/show.{format}") public Response showMySpaceList(@Context UriInfo uriInfo, @PathParam("portalName") String portalName, @PathParam("format") String format) throws Exception { MediaType mediaType = Util.getMediaType(format); ConversationState state = ConversationState.getCurrent(); portalContainerName = portalName; String userId = null; if (state != null) { userId = state.getIdentity().getUserId(); } Identity identity = getIdentityManager().getOrCreateIdentity(OrganizationIdentityProvider.NAME, userId, false); if (identity == null) { userId = Util.getViewerId(uriInfo); } SpaceList mySpaceList = showMySpaceList(userId); this.fillUrlAllSpaces(mySpaceList, portalName); return Util.getResponse(mySpaceList, uriInfo, mediaType, Response.Status.OK); } /** * Provides a way to get the latest spaces ordered by last access and to be able to filter spaces, based on the application Id in the spaces. * * * @param uriInfo The requested URI information. * @param portalName The portal container name. * @param format The format of the returned result, for example, JSON, or XML. * @param offset Specifies the staring point of the returned results. It must be greater than or equal to 0. * @param limit Specifies the ending point of the returned results. It must be less than or equal to 10. * @param appId The application Id which is contained in spaces to filter, such as, Wiki, Discussion, Documents, Agenda and more. * @authentication * @request GET: http://localhost:8080/rest/private/social/spaces/lastVisitedSpace/list.json?appId=Wiki&offset=0&limit=10 * @response * { * "spaces":[ * {"groupId":"/spaces/space_2","spaceUrl":null,"name":"space_2","displayName":"space 2","url":"space_2"}, * {"groupId":"/spaces/space_1","spaceUrl":null,"name":"space_1","displayName":"space 1","url":"space_1"} * ], * "moreSpacesUrl":null * } * @return the response * @LevelAPI Platform * @anchor SpacesRestService.getLastVisitedSpace * */ @GET @Path("lastVisitedSpace/list.{format}") public Response getLastVisitedSpace(@Context UriInfo uriInfo, @PathParam("portalName") String portalName, @PathParam("format") String format, @QueryParam("appId") String appId, @QueryParam("offset") int offset, @QueryParam("limit") int limit) throws Exception { checkAuthenticatedRequest(); MediaType mediaType = Util.getMediaType(format, new String[] { format }); ConversationState state = ConversationState.getCurrent(); portalContainerName = portalName; String userId = null; if (state != null) { userId = state.getIdentity().getUserId(); } Identity identity = getIdentityManager().getOrCreateIdentity(OrganizationIdentityProvider.NAME, userId, false); if (identity == null) { userId = Util.getViewerId(uriInfo); } // int newLimit = Math.min(limit, 100); int newOffset = 0; if (offset > 0) { newOffset = Math.min(offset, newLimit); } else { newOffset = 0; } // String newAppId = null; if (appId != null && appId.trim().length() > 0) { newAppId = appId; } SpaceList mySpaceList = getLastVisitedSpace(userId, newAppId, newOffset, newLimit); return Util.getResponse(mySpaceList, uriInfo, mediaType, Response.Status.OK); } /** * Gets a user's pending spaces. * * @param uriInfo The requested URI information. * @param portalName The portal container name. * @param format The format of the returned result, for example, JSON, or XML. * * @anchor SpacesRestService.showPendingSpaceList * * @return response * * @throws Exception * * @LevelAPI Platform */ @GET @Path("pendingSpaces/show.{format}") public Response showPendingSpaceList(@Context UriInfo uriInfo, @PathParam("portalName") String portalName, @PathParam("format") String format) throws Exception { MediaType mediaType = Util.getMediaType(format); String userId = ConversationState.getCurrent().getIdentity().getUserId(); portalContainerName = portalName; if (!userId.equals(Util.getViewerId(uriInfo))) { return null; } SpaceList pendingSpaceList = showPendingSpaceList(userId); return Util.getResponse(pendingSpaceList, uriInfo, mediaType, Response.Status.OK); } /** * Suggests the space's name for searching. * * @param uriInfo The requested URI information. * @param portalName The name of portal. * @param conditionToSearch The input information to search. * @param typeOfRelation The type of relationship of the user and the space. * @param userId The Id of current user. * @param format The format of the returned result, for example, JSON, or XML. * @return * @throws Exception * @LevelAPI Platform * @anchor SpacesRestService.suggestSpacenames * */ @GET @Path("suggest.{format}") public Response suggestSpacenames(@Context UriInfo uriInfo, @PathParam("portalName") String portalName, @QueryParam("conditionToSearch") String conditionToSearch, @QueryParam("typeOfRelation") String typeOfRelation, @QueryParam("currentUser") String userId, @PathParam("format") String format) throws Exception { MediaType mediaType = Util.getMediaType(format); SpaceNameList nameList = new SpaceNameList(); portalContainerName = portalName; SpaceService spaceSrv = getSpaceService(); SpaceListAccess listAccess = spaceSrv.getVisibleSpacesWithListAccess(userId, new SpaceFilter(conditionToSearch)); List<Space> spaces = Arrays.asList(listAccess.load(0, 10)); for (Space space : spaces) { if (ALL_SPACES_STATUS.equals(typeOfRelation)) { nameList.addName(space.getDisplayName()); } else { if (PENDING_STATUS.equals(typeOfRelation) && (spaceSrv.isPending(space, userId))) { nameList.addName(space.getDisplayName()); continue; } else if (INCOMING_STATUS.equals(typeOfRelation) && (spaceSrv.isInvited(space, userId))) { nameList.addName(space.getDisplayName()); continue; } else if (CONFIRMED_STATUS.equals(typeOfRelation) && (spaceSrv.isMember(space, userId))) { nameList.addName(space.getDisplayName()); continue; } } } return Util.getResponse(nameList, uriInfo, mediaType, Response.Status.OK); } /** * List that contains space from space service.<br> Need this class for converter from rest * service. */ @XmlRootElement static public class SpaceList { private String moreSpacesUrl; private List<SpaceRest> _spaces; /** * sets space list * * @param spaces space list */ public void setSpaces(List<SpaceRest> spaces) { _spaces = spaces; } /** * gets space list * * @return space list */ public List<SpaceRest> getSpaces() { return _spaces; } /** * adds space to space list * * @param space * @see Space */ public void addSpace(SpaceRest space) { if (_spaces == null) { _spaces = new LinkedList<SpaceRest>(); } _spaces.add(space); } /** * Get the url of all spaces. * * @return * @since 1.2.9 */ public String getMoreSpacesUrl() { return moreSpacesUrl; } /** * Set the url of all spaces. * * @param allSpacesUrl * @since 1.2.9 */ public void setMoreSpacesUrl(String allSpacesUrl) { moreSpacesUrl = allSpacesUrl; } } @XmlRootElement static public class SpaceNameList { private List<String> _names; /** * Sets space name list * * @param space name list */ public void setNames(List<String> names) { this._names = names; } /** * Gets space name list * * @return space name list */ public List<String> getNames() { return _names; } /** * Add name to space name list * * @param space name */ public void addName(String name) { if (_names == null) { _names = new ArrayList<String>(); } _names.add(name); } } /** * shows my spaceList by userId * * @param userId * @return spaceList * @see SpaceList */ private SpaceList showMySpaceList(String userId) { SpaceList spaceList = new SpaceList(); _spaceService = getSpaceService(); List<Space> mySpaces = null; List<SpaceRest> mySpacesRest = new ArrayList<SpaceRest>(); try { mySpaces = _spaceService.getSpaces(userId); for (Space space : mySpaces) { SpaceRest spaceRest = new SpaceRest(space); mySpacesRest.add(spaceRest); } //fix for issue SOC-2039, sets the space url with new navigation controller Router router = this.getRouter(this.getConfigurationPath()); this.fillSpacesURI(mySpacesRest, router); } catch (SpaceException e) { throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); } catch (Exception e) { throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); } spaceList.setSpaces(mySpacesRest); return spaceList; } /** * get my spaceList by userId which user is last visited * * @param userId * @param appId * @param limit * @return */ private SpaceList getLastVisitedSpace(String userId, String appId, int offset, int limit) { SpaceList spaceList = new SpaceList(); _spaceService = getSpaceService(); List<Space> mySpaces = null; try { mySpaces = _spaceService.getLastAccessedSpace(userId, appId, offset, limit); SpaceRest spaceRest; for (Space space : mySpaces) { spaceRest = new SpaceRest(space); spaceList.addSpace(spaceRest); } } catch (SpaceException e) { throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); } catch (Exception e) { throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); } return spaceList; } /** * shows pending spaceList by userId * * @param userId * @return spaceList * @see SpaceList */ private SpaceList showPendingSpaceList(String userId) { SpaceList spaceList = new SpaceList(); _spaceService = getSpaceService(); List<Space> pendingSpaces; List<SpaceRest> pendingSpacesRest = new ArrayList<SpaceRest>(); try { pendingSpaces = _spaceService.getPendingSpaces(userId); for (Space space : pendingSpaces) { SpaceRest spaceRest = new SpaceRest(space); pendingSpacesRest.add(spaceRest); } } catch (SpaceException e) { throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); } spaceList.setSpaces(pendingSpacesRest); return spaceList; } /** * Fill url for more spaces. * * @param spaceList * @param portalOwner * @since 1.2.9 */ private void fillUrlAllSpaces(SpaceList spaceList, String portalOwner) { try { Router router = this.getRouter(this.getConfigurationPath()); Map<QualifiedName, String> qualifiedName = new HashedMap(); qualifiedName.put(REQUEST_HANDLER, "portal"); qualifiedName.put(REQUEST_SITE_TYPE, "portal"); qualifiedName.put(LANG, ""); StringBuilder urlBuilder = new StringBuilder(); qualifiedName.put(REQUEST_SITE_NAME, portalOwner); qualifiedName.put(PATH, ALL_SPACES); router.render(qualifiedName, new URIWriter(urlBuilder)); spaceList.setMoreSpacesUrl(urlBuilder.toString()); } catch (Exception e) { throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); } } /** * gets spaceService * * @return spaceService * @see SpaceService */ private SpaceService getSpaceService() { return (SpaceService) getPortalContainer().getComponentInstanceOfType(SpaceService.class); } /** * gets identityManager * * @return */ private IdentityManager getIdentityManager() { if (_identityManager == null) { _identityManager = (IdentityManager) getPortalContainer() .getComponentInstanceOfType(IdentityManager.class); } return _identityManager; } private PortalContainer getPortalContainer() { return (PortalContainer) ExoContainerContext.getContainerByName(portalContainerName); } /** * Fills the spaces uri. * * @param mySpaces * @param router * @since 1.2.2 */ @SuppressWarnings("unchecked") private void fillSpacesURI(List<SpaceRest> mySpaces, Router router) { try { Map<QualifiedName, String> qualifiedName = new HashedMap(); qualifiedName.put(REQUEST_HANDLER, "portal"); qualifiedName.put(REQUEST_SITE_TYPE, "group"); for (SpaceRest space : mySpaces) { StringBuilder urlBuilder = new StringBuilder(); qualifiedName.put(REQUEST_SITE_NAME, space.getGroupId()); qualifiedName.put(PATH, space.getUrl()); router.render(qualifiedName, new URIWriter(urlBuilder)); space.setSpaceUrl(urlBuilder.toString()); } } catch (Exception e) { throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); } } /** * Gets the configuration path of file controller.xml * * @return * @since 1.2.2 */ private String getConfigurationPath() { PortalContainer portalContainer = this.getPortalContainer(); WebAppController webAppController = (WebAppController) portalContainer .getComponentInstanceOfType(WebAppController.class); return webAppController.getConfigurationPath(); } /** * Gets the router from path of file controller.xml * * @param path * @return * @throws IOException * @throws RouterConfigException * @since 1.2.2 */ private Router getRouter(String path) throws IOException, RouterConfigException { File f = new File(path); if (!f.exists()) { throw new MalformedURLException("Could not resolve path " + path); } if (!f.isFile()) { throw new MalformedURLException("Could not resolve path " + path + " to a valid file"); } return this.getRouter(f.toURI().toURL()); } /** * Gets the router from url. * * @param url * @return * @throws RouterConfigException * @throws IOException * @since 1.2.2 */ private Router getRouter(URL url) throws RouterConfigException, IOException { InputStream in = url.openStream(); try { ControllerDescriptor routerDesc = new DescriptorBuilder().build(in); return new Router(routerDesc); } finally { Safe.close(in); } } }