/* * Copyright (c) 2013 Lockheed Martin Corporation * * Licensed 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.eurekastreams.web.services; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletResponse; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.map.ObjectMapper; import org.eurekastreams.commons.exceptions.ExecutionException; import org.eurekastreams.commons.logging.LogFactory; import org.eurekastreams.server.persistence.mappers.DomainMapper; import org.eurekastreams.server.persistence.mappers.ReadMapper; import org.eurekastreams.server.search.modelview.PersonModelView; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import java.util.Arrays; /** * This class handles the REST endpoint for retrieving non locked users from the Eureka Streams db. * It takes in a json array in the format [{"id":"ntid", "avatarId":"avatarId"}], it will check if * the avatarId has changed and only return the base64 encoded image if it is different. */ public class PersonPropertiesAvatarController { /** * Local logger instance for this class. */ private final Log logger = LogFactory.make(); /** * mapper to read people from db. */ private final DomainMapper<List<String>, List<PersonModelView>> peopleMapper; /** * acceptable image prefixes. */ private final String[] acceptablePrefixes = {"s" , "n" , "o"}; /** * mapper to read avatars from db. */ private final ReadMapper<List<String>, List<Map<String, Object>>> avatarMapper; /** JSON Factory for building JSON Generators. */ private final JsonFactory jsonFactory; /** JSON object mapper. */ private final ObjectMapper jsonObjectMapper; /** * Constructor. * * @param inGetPersonModelViewsByAccountIdsMapper * - gets all users avatarId by ntid. * @param inGetAllPersonAvatarIdMapper * - gets all users image blobs * @param inJsonFactory * - used to build the json response * @param inJsonObjectMapper * - used to build the json response */ public PersonPropertiesAvatarController( final DomainMapper<List<String>, List<PersonModelView>> inGetPersonModelViewsByAccountIdsMapper, final ReadMapper<List<String>, List<Map<String, Object>>> inGetAllPersonAvatarIdMapper, final JsonFactory inJsonFactory, final ObjectMapper inJsonObjectMapper) { peopleMapper = inGetPersonModelViewsByAccountIdsMapper; avatarMapper = inGetAllPersonAvatarIdMapper; jsonFactory = inJsonFactory; jsonObjectMapper = inJsonObjectMapper; } /** * {@inheritDoc}. return the ntid, avatarid and imageBlob if it is needed * proper avatar sizes are s|n|o, for small|normal|original */ @RequestMapping(value = "json", method = RequestMethod.GET) public void getAvatars(@RequestParam("urlJson") final String urlJson, @RequestParam("avatarSize") final String imagePrefix, final HttpServletResponse response) { List<PersonModelView> people = null; Map<String, String> avatarIdToPeopleMap = new HashMap<String, String>(); List<Map<String, Object>> avatars = null; String json; if(!Arrays.asList(acceptablePrefixes).contains(imagePrefix)) { logger.error("Invalid image size"); throw new ExecutionException("Invalid image size."); } //parse the json input from the url try { json = URLDecoder.decode(urlJson, "UTF-8"); } catch (UnsupportedEncodingException e) { logger.error("Invalid incoming JSON"); throw new ExecutionException("Invalid JSON."); } JSONArray jsonArray = JSONArray.fromObject(json); //get users from url list and create map of users try { List<String> peopleIdsToFetch = new ArrayList<String>(); for (Object jsonItem:jsonArray) { String accountId = ((JSONObject) jsonItem).get("id").toString(); String avatarId = ((JSONObject) jsonItem).get("avatarId").toString(); peopleIdsToFetch.add(accountId); if(avatarId!=null && !avatarId.isEmpty()) { avatarIdToPeopleMap.put(avatarId, accountId); } } // fetch the people people = peopleMapper.execute(peopleIdsToFetch); } catch (Exception ex) { logger.error("Error occurred retrieving the users from the db.", ex); throw new ExecutionException("error retrieving users"); } //create new object to be passed back as json and create list of avatarIds to be passed to the db query JSONArray personProperties = new JSONArray(); List<String> avatarIdList = new ArrayList<String>(); for (PersonModelView currentPersonProperties : people) { if(!avatarIdToPeopleMap.containsKey(currentPersonProperties.getAvatarId())) { avatarIdList.add(imagePrefix+currentPersonProperties.getAvatarId()); } } //get all avatar by avatarId try { if(!avatarIdList.isEmpty()) { avatars = avatarMapper.execute(avatarIdList); } } catch (Exception ex) { logger.error("Error occurred retrieving the users from the db.", ex); throw new ExecutionException("Error retieving avatars"); } //loop through and build json object for response for (PersonModelView currentPersonProperties : people) { JSONObject p = new JSONObject(); //if it's not the same send back base64 image and info if(avatarIdList.contains(imagePrefix+currentPersonProperties.getAvatarId())) { p.put("id", currentPersonProperties.getAccountId()); p.put("avatarId", currentPersonProperties.getAvatarId()); for(Map<String, Object>currentAvatar:avatars) { String imageId = (String) currentAvatar.get("imageIdentifier"); if((imagePrefix+currentPersonProperties.getAvatarId()).equals(imageId)) { byte[] baseBytes = Base64.encodeBase64((byte[]) currentAvatar.get("imageBlob")); String baseString = new String(baseBytes); p.put("imageBlob", baseString); } } personProperties.add(p); } } //return response response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0"); response.addHeader("Pragma", "no-cache"); response.setHeader("Content-Type", "application/json"); JsonGenerator jsonGenerator; try { jsonGenerator = jsonFactory.createJsonGenerator(response.getWriter()); jsonObjectMapper.writeValue(jsonGenerator, personProperties); } catch (IOException e) { logger.error("error creating json", e); throw new ExecutionException("error creating json format"); } } }