Java tutorial
package io.starter.datamodel; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import io.starter.model.Acl; import io.starter.model.AclExample; import io.starter.model.AclExample.Criteria; import io.starter.model.Category; import io.starter.model.Content; import io.starter.model.ContentCategoryIdx; import io.starter.model.ContentExample; import io.starter.model.User; import io.starter.util.ImageUtils; import io.starter.util.Logger; import io.starter.util.S3FS; import io.starter.util.SystemConstants; import org.apache.ibatis.session.SqlSession; import org.apache.shiro.authz.permission.WildcardPermission; import org.jets3t.service.ServiceException; import org.json.JSONObject; import org.json.JSONArray; import org.json.JSONException; import com.sun.jersey.core.header.FormDataContentDisposition; import com.sun.jersey.multipart.FormDataParam; /** * simple content model implementation * * Content * * fetch list of allowed content items (cacheable array of ints) fetch by (top, * bottom, alpha, mime type) X list (alt queries allowed?) post content rate * content comments ARE content items, rateable, shared with current share list * of comment target send messages to share group * * @author John McMahon Copyright 2013 Starter Inc. -- all rights reserved. * @since 1 * @version .1 * */ @Path("/content/{contentId}") public class ContentData extends Model implements SystemConstants { private static final int NUM_RETURN_ROWS = 10; private static final int OPTYPE_SET_PUBLIC = 0; private static final int OPTYPE_SET_PRIVATE = 1; private static final int OPTYPE_SET_TAKEOVER_OWNERSHIP = 2; public ContentData() { Logger.debug("ContentData constructed"); } /** * return a list of content objects from the passed-in query * * @param query * @param servletRequest * @param servletResponse * @throws IOException * @throws ServletException * @throws JSONException * @throws org.json.JSONException */ @GET @Path("list") @Produces(MediaType.APPLICATION_JSON) public String list(@QueryParam("query") String query, @Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse) throws IOException, ServletException, JSONException, org.json.JSONException { List results = null; int begin = 0; if (servletRequest.getParameter("offset") != null) { try { int offs = Integer.parseInt(servletRequest.getParameter("offset")); begin = offs; } catch (Exception x) { Logger.log("Could not parse list position from: " + servletRequest.getParameter("offset")); } } if (begin != 0) // || (!query.equalsIgnoreCase("top") && (query.indexOf("userId") == -1)&& (query.indexOf("new") == -1))) // get results = getCachedContentList(query, servletRequest); User user = null; Object u = servletRequest.getAttribute(SESSION_VAR_USER); boolean categorySelected = false; int catId = -1; int userId = -1; String mimeType = null; boolean restrictToLocal = false; try { catId = Integer.parseInt(query); categorySelected = true; } catch (Exception e) { ; } try { if (query.indexOf("userId") > -1) { String uid = query.substring(query.indexOf("userId=") + 7); userId = Integer.parseInt(uid); } else if (query.indexOf("mimetype") > -1) { // web video picture sound joke // audio/mp4 image/jpeg image/png // video/quicktime, text/plain text/html String mtid = query.substring(query.indexOf("mimetype=") + 9); if (mtid.equalsIgnoreCase("video")) { mimeType = "video/quicktime"; } else if (mtid.equalsIgnoreCase("picture")) { mimeType = "image"; } else if (mtid.equalsIgnoreCase("web")) { mimeType = "text/html"; } else if (mtid.equalsIgnoreCase("joke")) { mimeType = "text/html"; restrictToLocal = true; // this allows us to differentiate // jokes with remote web clips } else if (mtid.equalsIgnoreCase("sound")) { mimeType = "audio/mp4"; } } } catch (Exception e) { ; } // login the anon user to get public content if (u == null) throw new ServletException("No User in Request -- Cannot fetch content list anonymously."); user = (User) u; // TODO: test this for performance hit... user.clearCachedAuthorization(); SqlSession session = (SqlSession) servletRequest.getAttribute(SESSION_VAR_SQLSESSION); if (results == null) { Logger.debug("Content List Cache Miss for: " + query); if (categorySelected) { // filtered by category id results = session.selectList("io.starter.dao.ContentMapper.selectObjByCategory", catId); } else { // return list by other means ContentExample example = new ContentExample(); io.starter.model.ContentExample.Criteria criteria = example.createCriteria(); if (query.equalsIgnoreCase("lbc")) { // location based starter criteria.andLatitudeIsNotNull(); criteria.andLatitudeNotEqualTo(0.0d); criteria.andLongitudeIsNotNull(); criteria.andLongitudeNotEqualTo(0.0d); } else if (query.indexOf("mimetype") > -1) { // mime type // based if (mimeType.indexOf("/") == -1) { // fuzzy match criteria.andMimeTypeLike("%" + mimeType + "%"); } else { // exact match criteria.andMimeTypeEqualTo(mimeType); } } else if (userId > -1) { criteria.andUserIdEqualTo(userId); } if (!user.isAdmin()) { criteria.andFlagGreaterThanOrEqualTo(FLAG_NONE); // any } example.setOrderByClause("post_date DESC"); example.setDistinct(true); results = session.selectList("io.starter.dao.ContentMapper.selectObjByExample", example); // check if it's a local URL List retu = new ArrayList(); Iterator itx = results.iterator(); while (itx.hasNext()) { Content dx = (Content) itx.next(); String rez = dx.getUrl(); if (restrictToLocal) { if (rez.indexOf("http") == -1) { retu.add(dx); } ; } else { // if(rez.indexOf("http") == 0){ retu.add(dx); // }; } } results = retu; // SORT by Top rated if (query.equalsIgnoreCase("top")) { Object[] ret = results.toArray(); Arrays.sort(ret); results = Arrays.asList(ret); } } // add results list to caches addCachedContentList(query, results, servletRequest); } // call every time we return a list to avoid returning unauthorized // stuff List filteredResults = this.removeUnauthorized(servletRequest, results, SECURITY_ACL_READ, SECURITY_TARGET_TYPE_CONTENT); JSONArray j = new JSONArray(); // add the 'isowner' request-specific field Iterator its = filteredResults.iterator(); int countr = 0; while (its.hasNext()) { Content cx = (Content) its.next(); if ((countr >= begin) && (countr < (begin + NUM_RETURN_ROWS))) { int uid = cx.getUserId(); try { User udd = UserData.getUserObjectByID(uid, servletRequest, servletResponse); if (udd != null) { cx.setUser(udd); } } catch (Exception e) { Logger.warn("ContentData.list: Could not get cached User object: " + e.toString()); } // handle ownership here. JSONObject job = new JSONObject(cx); if (user != null) { Integer uidx = user.getId(); if ((uidx != null && (uid == uidx)) || (user.isAdmin())) job.put("isowner", true); else job.put("isowner", false); } else { job.put("isowner", false); } job.put("isdeleted", (cx.getFlag() == FLAG_DELETED)); // content display wrapper job.put("showWrapper", ContentData.getWrapper(cx.getId(), session)); // set pretty date SimpleDateFormat sdf1 = new SimpleDateFormat(PRETTY_DATE_FORMAT); String postPrettyDate = sdf1.format(cx.getPostDate()); job.put("prettyDate", postPrettyDate); // how many reshares job.put("reshare_ct", cx.getRepostCount()); // how many ratings job.put("rating_ct", cx.getRatings().size()); j.put(job); } countr++; } // return the JSON result return j.toString(); } /** * upload a new content item in the system * * @param author * @param device * @param copyright * @param description * @param url * @param servletRequest * @param servletResponse * @throws Exception */ @PUT @Path("upload") @Produces(MediaType.APPLICATION_JSON) @Consumes({ MediaType.MULTIPART_FORM_DATA, MediaType.APPLICATION_OCTET_STREAM }) public String upload(@FormDataParam("binary_content") FormDataContentDisposition fileDetail, @FormDataParam("binary_content") InputStream uploadedInputStream, @FormDataParam("userImage") int userImage, @Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse) throws Exception { User u = (User) servletRequest.getSession(true).getAttribute(SESSION_VAR_USER); /* * TODO: remove mediadir? String mediadir = * servletRequest.getSession().getServletContext() * .getInitParameter("media.dir"); */ String uploadedFileLocation = fileDetail.getFileName(); // save it File[] uploadedFileset = saveToFile(uploadedInputStream, uploadedFileLocation, u.getId()); Logger.log( "UserData.upload() File uploaded via Jersey based RESTFul Webservice to: " + uploadedFileLocation); if (userImage > 0) { String f = fileDetail.getFileName(); u.setAvatarImage(f); SqlSession session = (SqlSession) servletRequest.getAttribute(SESSION_VAR_SQLSESSION); int rowsUpdated = session.update("io.starter.dao.UserMapper.updateByPrimaryKey", u); u = UserData.getUserObjectByID(u.getId(), servletRequest, servletResponse); u.setAvatarImage(f); session.commit(); if (rowsUpdated < 1) throw new ServletException("UserData.upload() could not setAvatarImage()"); } // return Response.status(200).entity(output).build(); // return the JSON result JSONObject j = new JSONObject(); String fnamey = uploadedFileLocation.substring(0, uploadedFileLocation.lastIndexOf(".")); String fnamex = uploadedFileLocation.substring(uploadedFileLocation.lastIndexOf(".")); String fna = "/" + fnamey + "/Standard" + fnamex; fna = fnamey + fnamex; j.put("filename", fna); j.put("mimeType", servletRequest.getSession().getServletContext().getMimeType(fna)); return j.toString(); } /** * * @param servletRequest * @param servletResponse * @return * @throws JSONException * @throws IOException * @throws ServletException */ @DELETE @Path("delete") public void delete(@PathParam("contentId") int id, @Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse) throws IOException, ServletException { // TODO: checkaccess // Content cxdel = getContentObject(servletRequest, servletResponse); // String contentToDelete = cxdel.getUrl(); // TODO: S3FS is our friend // S3FS s3fs = new S3FS(); // s3fs.deleteFile(S3_STARTER_MEDIA_BUCKET,); SqlSession session = (SqlSession) servletRequest.getAttribute(SESSION_VAR_SQLSESSION); try { // delete content acls AclExample a = new AclExample(); Criteria c = a.createCriteria(); c.andTargetIdEqualTo(id); c.andTargetTypeEqualTo(SystemConstants.SECURITY_TARGET_TYPE_CONTENT); session.delete("io.starter.dao.AclMapper.deleteByExample", a); session.commit(); // delete content record session.delete("io.starter.dao.ContentMapper.deleteByPrimaryKey", id); session.commit(); } catch (Exception e) { // if there are cascading FK constraints then we need to mark this // content item deleted (not actually delete it) // this way we preserve the integrity of the system // TODO: discuss handling deletion of content in re: orphan data Content cxdel = getContentObject(servletRequest, id); session = (SqlSession) servletRequest.getAttribute(SESSION_VAR_SQLSESSION); try { cxdel.setFlag(FLAG_DELETED); session.update("io.starter.dao.ContentMapper.updateByPrimaryKey", cxdel); session.commit(); } catch (Exception x) { Logger.error("Total failure in ContentData.delete trying to mark content item as deleted: " + x.toString()); // hmmm total failure } } super.deleteds.add(id); // update caches super.removeContentFromCaches(id, servletRequest); } /** * make the content item private and only accessible to the content owner * and administrators * * @param id * @param servletRequest * @param servletResponse * @return * @throws IOException * @throws ServletException */ @PUT @Path("makeprivate") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public String makeprivate(@PathParam("contentId") int id, @Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse) throws IOException, ServletException { return resetAclsForContent(OPTYPE_SET_PRIVATE, servletRequest, id); } /** * make the content item public and accessible read-only to all users and * anonymous viewers * * @param id * @param servletRequest * @param servletResponse * @return * @throws IOException * @throws ServletException */ @PUT @Path("makepublic") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public String makepublic(@PathParam("contentId") int id, @Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse) throws IOException, ServletException { return resetAclsForContent(OPTYPE_SET_PUBLIC, servletRequest, id); } /** * do the work of deleting all existing acls for content, inserting a new * owner acl, and optionally inserting necessary new ACL(s) based on the * OP_TYPE * * @param optype * @param servletRequest * @param id * @return * @throws ServletException */ private String resetAclsForContent(int optype, ServletRequest servletRequest, Integer id) throws ServletException { // DELETE all ACLs except the User's OWNER ACL Object u = servletRequest.getAttribute(SESSION_VAR_USER); if (u == null) throw new ServletException("No User in Request -- Anonymous users cannot modify content permissions."); User user = (User) u; int uid = user.getId(); user.clearCachedAuthorizationForAllUsers(); SqlSession session = (SqlSession) servletRequest.getAttribute(SESSION_VAR_SQLSESSION); int rowsDeleted = 0; // delete content acls AclExample ax = new AclExample(); Criteria c = ax.createCriteria(); c.andTargetIdEqualTo(id); c.andTargetTypeEqualTo(SECURITY_TARGET_TYPE_CONTENT); session.delete("io.starter.dao.AclMapper.deleteByExample", ax); session.commit(); Acl a = new Acl(); // give permission to current session user -- only one allowed to do // this a.setPrincipleId(user.getId()); a.setPrincipleType(SECURITY_PRINCIPAL_TYPE_USER); // allow them to a.setPermission(SECURITY_ACL_OWNER); // to this thing a.setTargetId(id); a.setTargetType(SECURITY_TARGET_TYPE_CONTENT); int rowsInserted = session.insert("io.starter.dao.AclMapper.insert", a); if (rowsInserted < 1) throw new ServletException("Could not make Content object private: setting Owner ACL failed."); if (optype == OPTYPE_SET_PUBLIC) { // make public Acl ae = new Acl(); // give permission to current session user -- only one allowed // to do // this ae.setPrincipleId(SECURITY_ROLE_EVERYONE); ae.setPrincipleType(SECURITY_PRINCIPAL_TYPE_ROLE); // allow them to ae.setPermission(SystemConstants.SECURITY_ACL_APPEND); // required // to allow // comments/rating // to this thing ae.setTargetId(id); ae.setTargetType(SECURITY_TARGET_TYPE_CONTENT); rowsInserted = session.insert("io.starter.dao.AclMapper.insert", ae); session.commit(); ae = new Acl(); ae.setPrincipleId(SECURITY_ROLE_EVERYONE); ae.setPrincipleType(SECURITY_PRINCIPAL_TYPE_ROLE); // allow them to ae.setPermission(SystemConstants.SECURITY_ACL_READ); // need to see // to this thing ae.setTargetId(id); ae.setTargetType(SECURITY_TARGET_TYPE_CONTENT); rowsInserted += session.insert("io.starter.dao.AclMapper.insert", ae); session.commit(); if (rowsInserted < 2) throw new ServletException( "Could not make Content object private: setting Everyone READ-ONLY and APPEND ACLs failed."); } else if (optype == OPTYPE_SET_TAKEOVER_OWNERSHIP) { // take over // ownership // (administrators) if (!user.isAdmin()) throw new ServletException( "Could not take over Content object ownership: Only Administrators can do this."); Acl ax1 = new Acl(); // give permission to current session user -- only one allowed // to do // this ax1.setPrincipleId(1); ax1.setPrincipleType(SECURITY_PRINCIPAL_TYPE_USER); // allow them to ax1.setPermission(SECURITY_ACL_OWNER); // to this thing ax1.setTargetId(id); ax1.setTargetType(SECURITY_TARGET_TYPE_CONTENT); rowsInserted = session.insert("io.starter.dao.AclMapper.insert", ax1); if (rowsInserted < 1) throw new ServletException( "Could not take over Content object ownership: setting Owner ACL failed."); } session.commit(); // return the result return "true"; } /** * create a new content item in the system * * @param author * @param device * @param copyright * @param description * @param url * @param categories * @param servletRequest * @param servletResponse * @param longitude * @param latitude * @param width * @param height * @return * @throws IOException * @throws ServletException * @throws JSONException * @throws org.json.JSONException */ @PUT @Path("create") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public String create(@FormParam("author") int author, @FormParam("device") int device, @FormParam("copyright") String copyright, @FormParam("description") String description, @FormParam("url") String url, @FormParam("categories") String categories, @Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse, @FormParam("longitude") Double longitude, @FormParam("latitude") Double latitude, @FormParam("mimeType") String mimeType, @FormParam("width") Long width, @FormParam("height") Long height) throws IOException, ServletException, JSONException, org.json.JSONException { Object u = servletRequest.getAttribute(SESSION_VAR_USER); if (u == null) throw new ServletException("No User in Request -- Cannot create anonymously owned content."); User user = (User) u; int uid = user.getId(); url = fixContentURLs(url); user.getSubject().getSession(true); Content content = new Content(); content.setUserId(uid); content.setAuthor(author); content.setAuthorDevice(device); content.setCopyright(copyright); content.setDescription(description); content.setLongitude(longitude); content.setLatitude(latitude); content.setWidth(width); content.setHeight(height); content.setUrl(url); content.setMimeType(mimeType); content.setFlag(FLAG_NONE); content.setPostDate(new Date(System.currentTimeMillis())); content.setLicense( "Content has been uploaded by end-users and is provided for personal non-commercial viewing under fair use laws of the United States, and additionally as satirical works protected speech under the First Amendment."); SqlSession session = (SqlSession) servletRequest.getAttribute(SESSION_VAR_SQLSESSION); int rowsInserted = 0; rowsInserted = session.insert("io.starter.dao.ContentMapper.insert", content); session.commit(); if (rowsInserted > 0) { ContentData.setContentOwnerPermissions(content, user, session); String dq = "userId=" + user.getId(); removeCachedContentList(dq, servletRequest); } // set the categories for the object.. setCategories(content.getId(), categories, session); content = this.getContentObject(servletRequest, content.getId()); // return the JSON result JSONObject j = new JSONObject(content); // handle ownership here. if ((content.getUserId() == uid) || (user.isAdmin())) j.put("isowner", true); else j.put("isowner", false); return j.toString(); } /** * helper method to 'improve' random webclip URLS, ie: YouTube embeds * * @param url * @return */ public static String fixContentURLs(String url) { // handle youtube webclips... use the proper URL for best display... String youEmbed = "http://www.youtube-nocookie.com/embed/"; if (url.toLowerCase().contains(youEmbed)) // good! return url; youEmbed = "http://www.youtube.com/embed/"; if (url.toLowerCase().contains(youEmbed)) // good! return url; String youBroken = "http://youtu.be/"; // bad String youBroken2 = "http://m.youtube.com/"; // bad if (url.toLowerCase().contains(youBroken)) { // ok replace! url = url.substring(youBroken.length()); } else if (url.toLowerCase().contains(youBroken2)) { // ok replace! url = url.substring(url.indexOf("v=") + 2); url = url.substring(0, 11); } else { return url; } // matched a youtube url url = youEmbed + url; return url; } /** * handle the details of ownership ACLs and cache reset * * @param content * @param user * @param session * @throws ServletException */ public static void setContentOwnerPermissions(Content content, User user, SqlSession session) throws ServletException { // share a content item with the share group Acl a = new Acl(); // give permission to a.setPrincipleId(user.getId()); a.setPrincipleType(SECURITY_PRINCIPAL_TYPE_USER); // allow them to a.setPermission(SECURITY_ACL_OWNER); // to this thing a.setTargetId(content.getId()); a.setTargetType(SECURITY_TARGET_TYPE_CONTENT); int rowsInserted = session.insert("io.starter.dao.AclMapper.insert", a); session.commit(); if (rowsInserted > 0) { ; } else { throw new ServletException( "Null rows inserted in ACL could not assign Ownership ACL to new Content object."); } user.clearCachedAuthorization(); WildcardPermission owner = new WildcardPermission(SystemConstants.SECURITY_TARGET_TYPE_CONTENT + ":" + SystemConstants.SECURITY_ACL_OWNER + ":" + content.getId()); assert (user.checkAccess(owner)); // return content; } /** * assign categories to an item * * @param obj * @param cats * @throws ServletException */ public static void setCategories(Integer objId, String cats, SqlSession session) throws ServletException { int rowsInserted = 0; StringTokenizer toker = new StringTokenizer(cats, ","); while (toker.hasMoreElements()) { String st = toker.nextElement().toString(); if (st.contains("[")) { st = st.substring(1); } if (st.contains("]")) { st = st.substring(0, st.length() - 1); } Integer categoryId = Integer.parseInt(st); ContentCategoryIdx cat = new ContentCategoryIdx(); cat.setCategoryId(categoryId); cat.setContentId(objId); rowsInserted = session.insert("io.starter.dao.ContentCategoryIdxMapper.insert", cat); session.commit(); } if (rowsInserted > 0) { ; } else { throw new ServletException( "Null rows inserted in ContentCategory IDX -- could not assign categories to Content object."); } } // save uploaded file to new location private File[] saveToFile(InputStream uploadedInputStream, String uploadedFileLocation, int userId) throws ServiceException, IOException { uploadedFileLocation = S3_STARTER_MEDIA_FOLDER + "/" + userId + "/" + uploadedFileLocation; Logger.log("ContentData saveToFile. bucket:" + S3_STARTER_MEDIA_BUCKET + " file: " + uploadedFileLocation); // S3FS is our friend S3FS s3fs = new S3FS(); s3fs.uploadToBucket(S3_STARTER_MEDIA_BUCKET, new DataInputStream(uploadedInputStream), uploadedFileLocation); // do special file ninja kungfu // add back the slash uploadedFileLocation = "/" + uploadedFileLocation; return saveStarterFile(uploadedFileLocation, userId); } /** * rate the content item * * @param flag * @param raterId * @param value * @param review * @param url * @param servletRequest * @param servletResponse * @throws IOException * @throws JSONException * @PUT * @Path("rate") * @Produces(MediaType.APPLICATION_JSON) * @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public String * rate(@PathParam( * "contentId") int id, * @FormParam("flag") int flag, @FormParam("raterId") int raterId, * @FormParam("rating") int value, @FormParam("review") String review, * @FormParam("url") String url, * @Context HttpServletRequest servletRequest, * @Context HttpServletResponse servletResponse) throws IOException, * JSONException { * * ContentRating contentRating = new ContentRating(); * contentRating.setFlag(flag); * contentRating.setContentId(Integer.valueOf(id)); * contentRating.setReview(review); contentRating.setType(1); * contentRating.setRaterId(raterId); contentRating.setValue((long) * value); * * SqlSession session = (SqlSession) servletRequest * .getAttribute(SESSION_VAR_SQLSESSION); * * session.insert("io.starter.dao.ContentRatingMapper.insert", * contentRating); * * Content content = getContentObject(servletRequest, * servletResponse, id); * * JSONObject ret = new JSONObject(); ret.put("rating", * this.getAverageRating(id, session)); * * // return the updated rating for the content object return * ret.toString(); } */ /** * returns the average rating for the content item * * this is the content "score" * * @param id * @param servletRequest * @throws IOException * @throws JSONException * @throws ServletException * @throws org.json.JSONException */ @GET @Path("rating") @Produces(MediaType.APPLICATION_JSON) public String getRating(@PathParam("contentId") int id, @Context HttpServletRequest servletRequest) throws IOException, JSONException, ServletException, org.json.JSONException { SqlSession session = (SqlSession) servletRequest.getAttribute(SESSION_VAR_SQLSESSION); Content content = session.selectOne("io.starter.dao.ContentMapper.selectObjByPrimaryKey", id); JSONObject job = new JSONObject(); job.put("rating", content.getRating()); return job.toString(); } /** * show the content * * @param contentId * @throws Exception */ @GET @Path("get") @Produces(MediaType.APPLICATION_JSON) public String get(@PathParam("contentId") int id, @Context HttpServletResponse servletResponse, @Context HttpServletRequest servletRequest) throws Exception { Content c = getContentObject(servletRequest, id); // replace with full-throated user object // TODO: check whether mybatis should lose this object map int uid = c.getUserId(); User uxx = UserData.getUserObjectByID(uid, servletRequest, servletResponse); uxx.setPassword(null); uxx.setPasswordSalt(null); uxx.setEmail(null); c.setUser(uxx); JSONObject job = new JSONObject(c); SqlSession session = (SqlSession) servletRequest.getAttribute(SESSION_VAR_SQLSESSION); Object u = servletRequest.getAttribute(SESSION_VAR_USER); if (u == null) throw new ServletException("No User in Request - ContentData.get()"); // get ratings for content in there float rtr = c.getRating(); String rval = String.valueOf(rtr); job.put("rating", rval); // set pretty date SimpleDateFormat sdf1 = new SimpleDateFormat(PRETTY_DATE_FORMAT); String postPrettyDate = sdf1.format(c.getPostDate()); job.put("prettyDate", postPrettyDate); // content display wrapper job.put("showWrapper", ContentData.getWrapper(id, session)); User user = (User) u; int uidx = user.getId(); if ((uid == uidx) || (user.isAdmin())) job.put("isowner", true); else job.put("isowner", false); job.put("isdeleted", (c.getFlag() == FLAG_DELETED)); return job.toString(); } /** * TODO: figure out if this approach makes sense. * * password protection of upload directory vs. this type of stream handling. * * Could not fix this error: * * May 15, 2013 4:49:57 PM com.sun.jersey.spi.container.ContainerRequest * getEntity SEVERE: A message body reader for Java class * javax.servlet.http.HttpServletResponse, and Java type interface * javax.servlet.http.HttpServletResponse, and MIME media type * application/octet-stream was not found. The registered message body * readers compatible with the MIME media type are: application/octet-stream * -> com.sun.jersey.core.impl.provider.entity.ByteArrayProvider * com.sun.jersey.core.impl.provider.entity.FileProvider * com.sun.jersey.core.impl.provider.entity.InputStreamProvider * com.sun.jersey.core.impl.provider.entity.DataSourceProvider * com.sun.jersey.core.impl.provider.entity.RenderedImageProvider * * returns the media file * * @param image * @param servletRequest * @return * @throws IOException * @GET * @Path("media/{imagename ") public void getMedia(@PathParam("imagename") * String image, HttpServletResponse * servletResponse, HttpServletRequest * servletRequest) throws IOException { if * (!isSafeToOpenFile(image)) { throw new * IllegalArgumentException * ("Cannot open the media file."); } * * String mediadir = (String) * servletRequest.getSession() * .getServletContext().getInitParameter * ("media.dir"); String uploadedFileLocation = * mediadir + image; File f = new * File(uploadedFileLocation); if (!f.exists()) { * throw new WebApplicationException(404); } * * BufferedOutputStream bot = new * BufferedOutputStream( * servletResponse.getOutputStream()); bot.write(new * FileInputStream(f).read()); bot.flush(); * bot.close(); * * } */ /** * show the content * * @param contentId * @throws IOException * @throws ServletException */ @GET @Path("description") @Produces(MediaType.TEXT_PLAIN) public String getDescription(@PathParam("contentId") int id, @Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse) throws IOException, ServletException { Content content = getContentObject(servletRequest, id); String ret = "NO CONTENTO"; String desc = content.getDescription(); if (desc != null) ret = desc; return ret; } /** * Get a Content object from this request * * @param servletRequest * @param id * @return * @throws IOException * @throws ServletException */ static Content getContentObject(HttpServletRequest servletRequest, int id) throws IOException, ServletException { // get cached Content content = getCachedContent(id, servletRequest); if (content == null) { Logger.debug("Content Object Cache Miss for content id: " + id); // apply some filters SqlSession session = (SqlSession) servletRequest.getAttribute(SESSION_VAR_SQLSESSION); content = session.selectOne("io.starter.dao.ContentMapper.selectObjByPrimaryKey", id); // add to cache addContentToCaches(id, content, servletRequest); } else { Logger.debug("Content Object Cache Hit for content id: " + id); } return content; } /** * determine whether to show a wrapper and if so, which one * * currently we only have NSFW implemented as it is core * * 'Rated G' : 0 'Rated PG' : -1 'Rated R' : -2 'N.S.F.W.' : -3 'Rated X' : * -4 * * * @param session * * @return */ public static String getWrapper(int id, SqlSession session) { try { List<Category> results = session.selectList("io.starter.dao.ContentMapper.getCategoriesForContent", id); Iterator its = results.iterator(); while (its.hasNext()) { Category cat = (Category) its.next(); int rating = cat.getSuitabilityRating(); if (rating < -2) return "true"; // TODO: in the future implement custom } } catch (NullPointerException e) { ; // no categories } return "false"; } /** * AWESOME IMAGE UTILS AREA */ /** * returns 3 versions of an input image: * * TRY THESE: 0: standardized 'medium' filesize 400w scaled 1: image blurred * 512 w back 2: image sharp 157@2x thumb 3: image tiny 64@2x thumb * * * @param input * @return * @throws IOException * @throws ServiceException */ public static File[] getStarterPics(Content c) throws ServiceException, IOException { // get image String uploadedFileLocation = c.getUrl(); int userId = c.getUserId(); return saveStarterFile(uploadedFileLocation, userId); } /** * the heavy lifting * * * @param uploadedFileLocation * @param userId * @return * @throws ServiceException * @throws IOException */ public static File[] saveStarterFile(String uploadedFileLocation, int userId) throws ServiceException, IOException { final S3FS s3fs = new S3FS(); File fx = new File(SystemConstants.S3_STARTER_SERVICE + SystemConstants.S3_STARTER_MEDIA_BUCKET + "/" + uploadedFileLocation); File[] modfiles = null; // intercept and process the incoming IMAGE files if (uploadedFileLocation.toLowerCase().endsWith(".png") || uploadedFileLocation.toLowerCase().endsWith(".jpg") || uploadedFileLocation.toLowerCase().endsWith(".gif") || uploadedFileLocation.toLowerCase().endsWith(".jpeg")) { uploadedFileLocation = S3_STARTER_SERVICE + S3_STARTER_MEDIA_BUCKET + uploadedFileLocation; fx = new File(uploadedFileLocation); modfiles = ImageUtils.getStarterPics(fx, userId); // upload with nice names for (File modfile : modfiles) { fx = new File(uploadedFileLocation); String fnstart = modfile.getPath().substring(modfile.getPath().lastIndexOf("/")); String fnamx = fx.getName(); fnamx = fnamx.substring(0, fnamx.lastIndexOf(".")); fnstart = S3_STARTER_MEDIA_FOLDER + "/" + userId + "/" + fnamx + fnstart; s3fs.uploadToBucket(S3_STARTER_MEDIA_BUCKET, new DataInputStream(new FileInputStream(modfile)), fnstart); Logger.log("ContentData saveToFile. saved Starter modified image files:" + S3_STARTER_MEDIA_BUCKET + " file: " + fnstart); } } else { // non image content... folderize String fnend = uploadedFileLocation; fnend = fnend.substring(fnend.lastIndexOf(".")); // mimetype String fnamx = uploadedFileLocation; fnamx = fnamx.substring(fnamx.lastIndexOf("/") + 1); // filename fnamx = fnamx.substring(0, fnamx.lastIndexOf(".")); if (((fnend.toLowerCase().endsWith(".mov")) || (fnend.toLowerCase().endsWith(".html")) || (fnend.toLowerCase().endsWith(".m4a")))) { File fin = File.createTempFile("ck-", fnend); fx = ImageUtils.readFromUrl(fx.getPath(), fin); fin.deleteOnExit(); modfiles = new File[1]; modfiles[0] = fin; } String fnstart = uploadedFileLocation.substring(0, uploadedFileLocation.lastIndexOf(".") - 1); fnstart = S3_STARTER_MEDIA_FOLDER + "/" + userId + "/" + fnamx; uploadedFileLocation = fnstart + "/" + "Standard" + fnend; s3fs.uploadToBucket(S3_STARTER_MEDIA_BUCKET, new DataInputStream(new FileInputStream(fx)), uploadedFileLocation); Logger.log("ContentData saveToFile. saved Starter modified image files:" + S3_STARTER_MEDIA_BUCKET + " file: " + uploadedFileLocation); } return modfiles; } }