Java tutorial
package io.starter.datamodel; /* * --------- BEGIN COPYRIGHT NOTICE --------- * Copyright 2012-2014 Starter Inc. * * This file is part of Starter. * * Starter is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Starter 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 Lesser General Public License for more details. * * You should have received a copy of the GNU General Public License along with Starter. * * If not, see <http://www.gnu.org/licenses/>. * * ---------- END COPYRIGHT NOTICE ---------- */ import io.starter.messaging.SNSMobilePush; import io.starter.messaging.tools.NotificationMessageGenerator; import io.starter.model.Device; import io.starter.model.Syslog; import io.starter.model.User; import io.starter.security.dao.MyBatisConnectionFactory; import io.starter.util.Logger; import io.starter.util.SystemConstants; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.concurrent.CountDownLatch; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.servlet.ServletException; 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; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; /** * System handling * * fetch system log fetch statistics edit/delete users, groups, content send * system messages * * * @author John McMahon Copyright 2013 Starter Inc., all rights reserved. * */ @Path("/system") public class Sys implements SystemConstants { private final String txt = "starter"; private Map counters = new HashMap(); /** * add a counter to the system stats * * @param name * @param ct */ public void incrementCounter(String name, Object ct) { Object existing = counters.get(name); if (existing != null) { // attempt to treat as a number, fail to String try { if (existing instanceof Float) { float fnf = Float.parseFloat(existing.toString()); float fnadd = Float.parseFloat(ct.toString()); // increment by new value fnf += fnadd; // update the counter counters.put(name, new Float(fnf)); } else if (existing instanceof Integer) { int fni = Integer.parseInt(existing.toString()); int fnadd = Integer.parseInt(ct.toString()); // increment by new value fni += fnadd; // update the counter counters.put(name, new Integer(fni)); } // is it an integer or a real float? } catch (NumberFormatException xf) { // cannot be "added", if it's a string append or replace? counters.put(name, ct); } } else { counters.put(name, ct); } } /** * Get the /1.0/application.wadl * * TODO: implement extended WADL Apply XSLT to the WADL output to generate * human-readable api docs per: https://wikis.oracle.com/display/Jersey/WADL * * * @return * @throws IOException * @throws TransformerException */ @GET @Path("apidocs") @Produces(MediaType.TEXT_HTML) public String getWADL(@Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse) throws IOException, TransformerException { servletResponse.addHeader("Access-Control-Allow-Origin", "*"); // Transform the WADL to HTML using XSLT TransformerFactory factory = TransformerFactory.newInstance(); // Make a URL to the XML String iserv = servletRequest.getScheme() + "://" + servletRequest.getServerName() + ":" + servletRequest.getServerPort() + "/" + SystemConstants.REST_BASE_PATH + "/"; URL url = new URL(iserv + WADL_SOURCE_URL); URLConnection con = url.openConnection(); con.setDoOutput(true); Source text = new StreamSource(con.getInputStream()); // path to the XSLT URL urlx = new URL(SystemConstants.REST_API_SERVER_HOST + "/wadl_html_doc.xslt"); HttpURLConnection urlConnection = (HttpURLConnection) urlx.openConnection(); InputStream is = null; is = new BufferedInputStream(urlConnection.getInputStream()); Source xslt = new StreamSource(is); Transformer transformer = factory.newTransformer(xslt); servletResponse.setContentType("text/html"); OutputStream ous = servletResponse.getOutputStream(); transformer.transform(text, new StreamResult(ous)); ous.flush(); ous.close(); return "ok"; } /** * this method checks things and sends back a 200 if all is OK otherwise an * error code is sent * * used for system monitoring * * @param query * @param servletRequest * @param servletResponse * @return * @throws IOException * @throws ServletException * @throws JSONException * @throws SQLException */ @GET @Path("systemcheck") @Produces(MediaType.APPLICATION_JSON) public String getSystemCheck(@Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse) throws IOException, ServletException, JSONException, SQLException { JSONObject ret = new JSONObject(); try { SqlSession session = (SqlSession) servletRequest.getAttribute(SESSION_VAR_SQLSESSION); Connection connection = session.getConnection(); ret.put("MyBatis DB Connection Status", connection.isValid(10000)); return ret.toString(); } catch (Exception e) { servletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return null; } } /** * this method returns a JSON string with a summarized set of data for the * entire starter system * * includes: * * Top Content Leader board System-wide Alliances * * @param query * @param servletRequest * @param servletResponse * @return * @throws IOException * @throws ServletException * @throws JSONException * @throws SQLException */ @GET @Path("stats") @Produces(MediaType.APPLICATION_JSON) public String getStats(@Context HttpServletRequest servletRequest, @Context HttpServletResponse servletResponse) throws IOException, ServletException, JSONException, SQLException { String jsonStr = ""; Map namevals = new HashMap(); // System-wide eazy squeezy User u = (User) servletRequest.getSession(true).getAttribute(SESSION_VAR_USER); SqlSession session = (SqlSession) servletRequest.getAttribute(SESSION_VAR_SQLSESSION); Connection connection = session.getConnection(); try { namevals.put("system.totalusers", this.getValueFromDB("SELECT COUNT(id) as ct FROM user", connection)); namevals.put("system.totalcontent", this.getValueFromDB("SELECT COUNT(id) as ct FROM content", connection)); namevals.put("system.totalalliances", this.getValueFromDB("SELECT COUNT(id) as ct FROM role WHERE id > 100", connection)); namevals.put("system.totalshares", this.getValueFromDB( "SELECT COUNT(id) FROM acl WHERE target_type = 2 AND principle_id = 2 AND principle_type = 1 AND permission = 3", connection)); namevals.put("system.totalsocialshares", this.getValueFromDB( "SELECT COUNT(syslog.id) as CT FROM syslog WHERE ( event_type = 25 OR event_type = 26) AND syslog.description LIKE '%OK [%' ORDER BY CT desc", connection)); namevals.put("system.totalratings", this.getValueFromDB("SELECT COUNT(id) as CT FROM content_rating", connection)); namevals.put("system.totalcategories", this.getValueFromDB("SELECT COUNT(id) as CT FROM category", connection)); namevals.put("system.totallogins", this.getValueFromDB( "SELECT COUNT(syslog.id) as CT FROM syslog WHERE event_type = 0 AND syslog.description LIKE '%OK [%' ORDER BY CT desc", connection)); // Top Content -- the easiest ContentData cdx = new ContentData(); String lx = cdx.list("top", servletRequest, servletResponse); JSONArray jaray = new JSONArray(lx); for (int t = 0; t < jaray.length(); t++) { namevals.put("topcontent." + t, jaray.get(t)); } // Leader board // Top Content -- the easiest if (servletRequest.getParameter("leaderboard") != null) { try { lx = UserData.list("leaders", servletRequest, servletResponse); jaray = new JSONArray(lx); int lx1 = jaray.length() - 1; for (int t = 0; t < jaray.length(); t++) { namevals.put("leader." + t, jaray.get(lx1 - t)); } } catch (Exception e) { ; // couldn't get leaderboard } } // Alliances try { lx = RoleData.list("top", servletRequest, servletResponse); jaray = new JSONArray(lx); for (int t = 0; t < jaray.length(); t++) { namevals.put("alliance." + t, jaray.get(t)); } } catch (Exception e) { ; // couldn't get alliances } // JSONify jsonStr = new JSONObject(namevals).toString(); // oh yes, record it for posterity... this is going to come in // handy... Syslog logEntry = new Syslog(); logEntry.setDescription("OK [ ANONYMOUS -1 ], [GET] [stats " + jsonStr.substring(0, 100) + "]"); logEntry.setEventType(SystemConstants.LOG_EVENT_TYPE_SYSTEM_CONTENT); logEntry.setSourceId(-1); logEntry.setSourceType(SystemConstants.TARGET_TYPE_SYSTEM); logEntry.setTimestamp(new java.util.Date(System.currentTimeMillis())); session.insert("io.starter.dao.SyslogMapper.insert", logEntry); session.commit(); } catch (Exception x) { Logger.log("Getting System Stats Failed: " + x.toString()); } return jsonStr; } private Object getValueFromDB(String query, Connection connection) throws SQLException { float ret = -1; Logger.debug("Sys: Executing query [ " + query + " ] took:"); long start = System.currentTimeMillis(); java.sql.Statement st = connection.createStatement(); ResultSet rs = st.executeQuery(query); rs.next(); ret = rs.getFloat(1); // limited valid queries rs.close(); st.close(); long end = System.currentTimeMillis(); long duration = (end - start); Logger.debug(duration + " milliseconds"); return ret; } // This method is called if TEXT_PLAIN is request @GET @Produces(MediaType.TEXT_PLAIN) public String getTextLog() { return txt; } // This method is called if XML is request @GET @Produces(MediaType.TEXT_XML) public String getXMLLog() { return "<?xml version=\"1.0\"?><system>" + txt + ":" + "</system>"; } // This method is called if HTML is request @GET @Produces(MediaType.TEXT_HTML) public String getHTMLLog() { return "<html> " + "<title>" + txt + "</title>" + "<body><h1>" + txt + "<br/><br/>System:<br/>" + "</body></h1>" + "</html> "; } /** * * @param params * @throws Exception * * */ public static void sendEmail(String url, final User from, String toEmail, Map params, SqlSession session, CountDownLatch latch) throws Exception { final CountDownLatch ltc = latch; if (from == null) { throw new ServletException("Sys.sendEmail cannot have a null FROM User."); } String fromEmail = from.getEmail(); final String fro = fromEmail; final String to = toEmail; final Map p = params; final String u = url; final SqlSession sr = session; // TODO: check message sender/recipient validity if (!checkEmailValidity(fromEmail)) { throw new RuntimeException( fromEmail + " is not a valid email address. SENDING MESSAGE TO " + toEmail + " FAILED"); } // TODO: check mail server if it's a valid message if (!checkEmailValidity(toEmail)) { throw new RuntimeException( toEmail + " is not a valid email address. SENDING MESSAGE TO " + toEmail + " FAILED"); } // message.setSubject("Testing Email From Starter.io"); // Send the actual HTML message, as big as you like // fetch the content final String content = getText(u); new Thread(new Runnable() { @Override public void run() { // Sender's email ID needs to be mentioned // String sendAccount = "$EMAIL_USER_NAME$"; // final String username = "$EMAIL_USER_NAME$", password = // "hum0rm3"; // Assuming you are sending email from localhost // String host = "gator3083.hostgator.com"; String sendAccount = "$EMAIL_USER_NAME$"; final String username = "$EMAIL_USER_NAME$", password = "$EMAIL_USER_PASS$"; // Assuming you are sending email from localhost String host = SystemConstants.EMAIL_SERVER; // Get system properties Properties props = System.getProperties(); // Setup mail server props.setProperty("mail.smtp.host", host); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.smtp.port", "587"); // Get the default Session object. Session session = Session.getInstance(props, new javax.mail.Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(username, password); } }); try { // Create a default MimeMessage object. MimeMessage message = new MimeMessage(session); // Set From: header field of the header. message.setFrom(new InternetAddress(sendAccount)); // Set To: header field of the header. message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(sendAccount)); // Set Subject: header field Object o = p.get("MESSAGE_SUBJECT"); message.setSubject(o.toString()); String ctx = new String(content.toString()); // TODO: String Rep on the params ctx = stringRep(ctx, p); message.setContent(ctx, "text/html; charset=utf-8"); // message.setContent(new Multipart()); // Send message Transport.send(message); Logger.log("Sending message to:" + to + " SUCCESS"); } catch (MessagingException mex) { // mex.printStackTrace(); Logger.log("Sending message to:" + to + " FAILED"); Logger.error("Sys.sendEmail() failed to send message. Messaging Exception: " + mex.toString()); } // log the data Syslog logEntry = new Syslog(); logEntry.setDescription("OK [ email sent from: " + fro + " to: " + to + "]"); logEntry.setUserId(from.getId()); logEntry.setEventType(SystemConstants.LOG_EVENT_TYPE_SEND_EMAIL); logEntry.setSourceId(from.getId()); // unknown logEntry.setSourceType(SystemConstants.TARGET_TYPE_USER); logEntry.setTimestamp(new java.util.Date(System.currentTimeMillis())); SqlSessionFactory sqlSessionFactory = MyBatisConnectionFactory.getSqlSessionFactory(); SqlSession sesh = sqlSessionFactory.openSession(true); sesh.insert("io.starter.dao.SyslogMapper.insert", logEntry); sesh.commit(); if (ltc != null) ltc.countDown(); // release the latch } }).start(); } /** * do checks * * @param emailAddress * @return */ public static boolean checkEmailValidity(String heck) { if (heck == null) return false; int hx = heck.indexOf("@"); if (hx < 1) // theres an @ with something in front of it return false; if (heck.lastIndexOf(".") < hx) // the dot is after the @ return false; if (heck.lastIndexOf(".") > heck.length() - 3) // not dot at the end return false; return true; } /** * search and replace the strings in the input with delimiter %XX_SOMENAME% * with the map values: * * "SOMENAME", "somevalue" * * * @param input * @param params * @return */ public static String stringRep(String input, Map<String, String> params) { if (params == null) {// unchanged Logger.warn("Sys.stringRep(): no parameters to replace. String unchanged."); return input; } Set<String> it = params.keySet(); Iterator<String> its = it.iterator(); // SEARCH AND REPLACE while (its.hasNext()) { String key = its.next(); String o = String.valueOf(params.get(key)); // transform to the replace string String find = "%" + key.toUpperCase() + "%"; input = input.replace(find, o); } return input; } /** * get cached URL text * * @param url * @return * @throws Exception */ public static String getText(String url) throws Exception { Object o = System.getProperty(url); if (o != null) { // Logger.log("System.sendEmail text cache hit for: " + url); return o.toString(); } else { Logger.log("System.sendEmail text cache MISS for: " + url); } String oldurl = url; if (url.indexOf("?") > -1) { url += "&cachebust=" + System.currentTimeMillis(); } else { url += "?cachebust=" + System.currentTimeMillis(); } URL website = new URL(url); URLConnection connection = website.openConnection(); BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); StringBuilder response = new StringBuilder(); String inputLine; while ((inputLine = in.readLine()) != null) response.append(inputLine); in.close(); String strz = response.toString(); System.setProperty(oldurl, strz); return strz; } /** * get the web content * * @param url * @return */ public String getWebEmailFromURL(String url, Map<?, ?> replacements) { return ""; } /** * send a push notification to the device * * NOTE: Uses Amazon SNS * * @param dve * @param to * @param params * @param session * @throws IOException */ public static void sendFollowPushNotification(Device dve, User to, Map params, SqlSession session) throws IOException { String msg = getStarterAppleFollowMessage(to, params); SNSMobilePush pu = new SNSMobilePush(); pu.starterAppleAppNotification(msg, dve.getDeviceId()); } /** * send a push notification when a comment submitted * * NOTE: Uses Amazon SNS * * @param dve * @param to * @param params * @param session * @throws IOException */ public static void sendCommentPushNotification(User to, String params, SqlSession session) throws IOException { // handle Push notifications List Devices = to.getDevices(); if (Devices == null) { return; } Iterator its = Devices.iterator(); while (its.hasNext()) { Device dve = (Device) its.next(); String msg = getStarterAppleCommentMessage(to, params); SNSMobilePush pu = new SNSMobilePush(); pu.starterAppleAppNotification(msg, dve.getDeviceId()); } } /** * send a push notification to the device * * NOTE: Uses Amazon SNS * * @param dve * @param to * @param params * @param session * @throws IOException */ public static void sendSharePushNotification(Device dve, User to, Map params, SqlSession session) throws IOException { String msg = getStarterAppleShareMessage(to, params); SNSMobilePush pu = new SNSMobilePush(); pu.starterAppleAppNotification(msg, dve.getDeviceId()); } public static String getStarterAppleCommentMessage(User to, String params) { Map<String, Object> appleMessageMap = new HashMap<String, Object>(); Map<String, Object> appMessageMap = new HashMap<String, Object>(); appMessageMap.put("alert", params); appMessageMap.put("badge", to.getStats().size()); // TODO hook up to // "seen" counter appMessageMap.put("sound", "default"); appleMessageMap.put("aps", appMessageMap); return NotificationMessageGenerator.jsonify(appleMessageMap); } public static String getStarterAppleShareMessage(User to, Map params) { Map<String, Object> appleMessageMap = new HashMap<String, Object>(); Map<String, Object> appMessageMap = new HashMap<String, Object>(); appMessageMap.put("alert", params.get("MESSAGE_SUBJECT")); appMessageMap.put("badge", to.getStats().size()); // TODO hook up to // "seen" counter appMessageMap.put("sound", "default"); appleMessageMap.put("aps", appMessageMap); return NotificationMessageGenerator.jsonify(appleMessageMap); } public static String getStarterAppleFollowMessage(User to, Map params) { Map<String, Object> appleMessageMap = new HashMap<String, Object>(); Map<String, Object> appMessageMap = new HashMap<String, Object>(); appMessageMap.put("alert", "Good news, " + to.getUsername() + ". " + params.get("SENDER_UN") + " is now following you on Starter!"); appMessageMap.put("badge", 5); // to.getStats().size()); // TODO hook up // to "seen" counter appMessageMap.put("sound", "default"); appleMessageMap.put("aps", appMessageMap); return NotificationMessageGenerator.jsonify(appleMessageMap); } /** * TODO: create an XLS report of System stats * * @param id * @return * @throws IOException * @throws WorkSheetNotFoundException * @throws RowNotFoundException * @throws CellNotFoundException * @throws JSONException * @throws Exception * @GET * @Path("/report/excel/{reportName /{userId}") * @Produces({ "application/vnd.ms-excel", * "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" * }) public Response exportExcel(@Context HttpServletRequest * servletRequest, * @PathParam("reportName") String reportName, * @PathParam("userId") int userId, * @Context HttpServletResponse servletResponse) throws * XmlPullParserException, IOException, WorkSheetNotFoundException, * RowNotFoundException, CellNotFoundException, JSONException { * * final WorkBookHandle wb = new WorkBookHandle(); // TODO: use // * preformatted Template WorkSheetHandle sheet = * wb.getWorkSheet(0); try { wb.getWorkSheet(1).remove(); * wb.getWorkSheet(1).remove(); } catch (Exception x) { ; } * CellHandle titlecell = sheet.add("Starter User Profile", "A1"); * titlecell.setFontWeight(Font.BOLD); titlecell.setFontSize(38); * titlecell.setFontColor(new Color(0, 0, 100)); * * sheet.add("Series", "A2"); sheet.add("Rating", "B2"); * sheet.add("Flags", "C2"); sheet.add("Takedowns", "D2"); * * SqlSession session = (SqlSession) servletRequest * .getAttribute(SESSION_VAR_SQLSESSION); * * UserExample example = new UserExample(); * io.starter.model.UserExample.Criteria criteria = * example.createCriteria(); // for now hard code ID * criteria.andIdBetween(0, 5); List<?> results = * session.selectList( "io.starter.dao.UserMapper.selectByExample", * example); * * Iterator<?> its = results.iterator(); int t = 2; while * (its.hasNext()) { * * Object o = its.next(); io.starter.model.User u = * (io.starter.model.User) o; // get rating // float score = * UserData.getRatingScore(u, servletRequest, // servletResponse); * * double score = 100 * Math.random(); * * Object[] data = { u.getUsername(), new Double(score), new * Double((int) (100 * Math.random())), new Double((int) (100 * * Math.random())), }; sheet.insertRow(t++, data); } * * sheet.setShowGridlines(false); // sheet.setProtected(protect, * password) * * EnumSet<ChartOptions> opts = EnumSet.noneOf(ChartOptions.class); * // chart-specific * * opts.add(ChartOptions.THREED); * * // ChartHandle cx = ChartHandle.createNewChart(sheet, * ChartHandle.PIE, // opts); // * cx.setTitle("Starter Humor Analysis"); * * ChartHandle cx = wb.createChart("User Stats", sheet); * cx.setChartType(ChartHandle.BAR); * * short[] cd = { 60, 60, 1000, 1000 }; cx.setCoords(cd); * * for (int z = 3; z <= t; z++) { * cx.addSeriesRange(sheet.getCell("A" + z), new * CellRange(sheet.getSheetName() + "!B2:D2", wb), new * CellRange(sheet.getSheetName() + "!B" + z + ":D" + z, wb), * null); } * * StreamingOutput stream = new StreamingOutput() { * @Override public void write(OutputStream output) throws IOException, * WebApplicationException { try { wb.write(output); } catch * (Exception e) { throw new WebApplicationException(e); } * wb.close(); } }; return Response .ok(stream) * .header("content-disposition", * "attachment; filename = export.xls").build(); } */ }