Java tutorial
/******************************************************************************* * Copyright (c) 2014, 2017 IBM Corporation, Carnegie Mellon University and others * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. *******************************************************************************/ package hulop.hokoukukan.utils; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.security.KeyStore; import java.security.SecureRandom; import java.security.cert.CertificateFactory; import java.util.ArrayList; import java.util.Base64; import java.util.List; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; import org.apache.wink.json4j.JSONArray; import org.apache.wink.json4j.JSONException; import org.apache.wink.json4j.JSONObject; import com.mongodb.AggregationOptions; import com.mongodb.BasicDBObject; import com.mongodb.Cursor; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.mongodb.MongoClient; import com.mongodb.MongoClientOptions; import com.mongodb.MongoClientURI; import com.mongodb.gridfs.GridFS; import com.mongodb.gridfs.GridFSDBFile; public class MongoAdapter implements DBAdapter { private final DB db; private final GridFS mFS; private final MongoClient client; private final MongoClientURI mongoURI; private final DBCollection mapCol, userCol, logCol, fileCol, entryCol; private final List<DBObject> insertList = new ArrayList<DBObject>(); private final List<DBObject> insertLogList = new ArrayList<DBObject>(); private JSONArray resultList = new JSONArray(); private int insertCount = 0; public MongoAdapter(String url) throws Exception { this(url, null, null); } public MongoAdapter(String url, String dbName, String cert) throws Exception { mongoURI = cert != null ? new MongoClientURI(url, optionsBuilder(cert)) : new MongoClientURI(url); client = new MongoClient(mongoURI); db = client.getDB(dbName != null ? dbName : mongoURI.getDatabase()); mFS = new GridFS(db); System.out.println(db.getCollectionNames()); mapCol = db.getCollection("maps"); userCol = db.getCollection("users"); logCol = db.getCollection("logs"); fileCol = db.getCollection("files"); entryCol = db.getCollection("entries"); mapCol.createIndex(new BasicDBObject("geometry", "2dsphere")); } @Override public void prepare(File file) { if (file != null) { mapCol.remove(new BasicDBObject("properties.file", file.getPath())); } resultList = new JSONArray(); insertCount = 0; } @Override public void insert(String json) { synchronized (insertList) { insertList.add(BasicDBObject.parse(json)); } if (insertList.size() >= 1000) { flush(); } } @Override public void update(String json) { mapCol.save(BasicDBObject.parse(json)); } @Override public void setOBJ(JSONObject obj) { mapCol.save(BasicDBObject.parse(obj.toString())); } @Override public void remove(JSONArray array) { List<String> idList = new ArrayList<String>(); for (int i = 0; i < array.length(); i++) { try { JSONObject obj = array.getJSONObject(i); if (obj.has("_id")) { idList.add(obj.getString("_id")); } } catch (Exception e) { e.printStackTrace(); } } mapCol.remove(new BasicDBObject("_id", new BasicDBObject("$in", idList))); } @Override public void flush() { synchronized (insertList) { if (insertList.size() > 0) { try { mapCol.insert(insertList); insertCount += insertList.size(); } catch (Exception e) { e.printStackTrace(); String error = e.getMessage(); for (Object obj : insertList) { String id = ((DBObject) obj).get("_id").toString(); try { resultList.add(new JSONObject().put("_id", id).put("error", error)); } catch (JSONException e1) { e1.printStackTrace(); } } } insertList.clear(); } } List<DBObject> flushList = null; synchronized (insertLogList) { if (insertLogList.size() > 0) { flushList = new ArrayList<DBObject>(insertLogList); insertLogList.clear(); } } if (flushList != null) { try { logCol.insert(flushList); insertCount += flushList.size(); } catch (Exception e) { e.printStackTrace(); } } } @Override public int getInsertCount() { return insertCount; } @Override public JSONArray getResult() { return resultList; } @Override public void dropDB() { db.dropDatabase(); } @Override public void getGeometry(double[] center, double radius, JSONObject nodeMap, JSONArray features) { DBObject query = new BasicDBObject().append("geometry", new BasicDBObject("$near", new BasicDBObject("$geometry", new BasicDBObject("type", "Point").append("coordinates", center)) .append("$maxDistance", radius))); System.out.println(query.toString()); DBCursor cursor = mapCol.find(query/* , new BasicDBObject("_id", 0) */); try { while (cursor.hasNext()) { JSONObject json = new JSONObject(cursor.next().toString()); JSONObject properties = json.getJSONObject("properties"); if (properties.has("ID")) { nodeMap.put(properties.getString("ID"), json); } else { features.add(json); } } } catch (JSONException e) { e.printStackTrace(); } } @Override public String findNearestNode(double[] point, List<Object> floors) { BasicDBObject query = new BasicDBObject().append("geometry", new BasicDBObject("$near", new BasicDBObject("$geometry", new BasicDBObject("type", "Point").append("coordinates", point)))); query.put("properties.ID", new BasicDBObject("$exists", true)); if (floors != null) { query.put("properties.?", new BasicDBObject("$in", floors)); } DBObject obj = mapCol.findOne(query, new BasicDBObject("_id", 0)); if (obj instanceof DBObject) { DBObject properties = (DBObject) obj.get("properties"); if (properties != null) { return (String) properties.get("ID"); } } return null; } @Override public JSONObject find(String id) { return find(mapCol, id); } @Override public List<String> listFiles() { return mapCol.distinct("properties.file"); } private JSONObject find(DBCollection col, String id) { try { DBObject obj = col.findOne(new BasicDBObject("_id", id)); if (obj != null) { return new JSONObject(obj.toString()); } } catch (JSONException e) { e.printStackTrace(); } return null; } @Override public JSONObject findUser(String id) { return find(userCol, id); } @Override public JSONArray listUsers() { JSONArray users = new JSONArray(); DBCursor cursor = userCol.find(); try { while (cursor.hasNext()) { users.add(new JSONObject(cursor.next().toString())); } } catch (JSONException e) { e.printStackTrace(); } return users; } @Override public void insertUser(String json) { updateUser(json); } @Override public void updateUser(String json) { userCol.save(BasicDBObject.parse(json)); } @Override public void removeUser(JSONObject obj) { try { if (obj.has("_id")) { userCol.remove(new BasicDBObject("_id", obj.getString("_id"))); } } catch (Exception e) { e.printStackTrace(); } } @Override public void insertLog(String json) { synchronized (insertLogList) { insertLogList.add(BasicDBObject.parse(json)); } if (insertLogList.size() >= 1000) { flush(); } } @Override public JSONArray getLogStats(String event) { List<DBObject> pipeline = new ArrayList<DBObject>(); if (event != null) { pipeline.add(new BasicDBObject("$match", new BasicDBObject("event", event))); } pipeline.add( new BasicDBObject("$project", new BasicDBObject("client", 1).append("timestamp", "$timestamp"))); pipeline.add(new BasicDBObject("$group", new BasicDBObject().append("_id", new BasicDBObject("client", "$client")) .append("count", new BasicDBObject("$sum", 1)) .append("min", new BasicDBObject("$min", "$timestamp")) .append("max", new BasicDBObject("$max", "$timestamp")))); // Iterator<DBObject> it = logCol.aggregate(pipeline).results().iterator(); Cursor it = logCol.aggregate(pipeline, AggregationOptions.builder().build()); JSONArray result = new JSONArray(); while (it.hasNext()) { try { DBObject elm = it.next(); result.add(new JSONObject().put("clientId", ((DBObject) elm.get("_id")).get("client")).put("stats", new JSONObject().put("count", elm.get("count")).put("min", elm.get("min")).put("max", elm.get("max")))); } catch (JSONException e) { e.printStackTrace(); } } return result; } @Override public JSONArray getLogs(String clientId, String start, String end, String skip, String limit, String event) { BasicDBObject query = new BasicDBObject(); if (clientId != null) { query.append("client", clientId); } new BasicDBObject("Date", new BasicDBObject("$gt", start).append("$lte", end)); BasicDBObject timeRange = new BasicDBObject(); if (start != null) { timeRange.append("$gte", Long.parseLong(start)); } if (end != null) { timeRange.append("$lt", Long.parseLong(end)); } if (timeRange.size() > 0) { query.append("timestamp", timeRange); } if (event != null) { query.append("event", event); } System.out.println(query.toString()); DBCursor cursor = logCol.find(query); if (skip != null) { cursor = cursor.skip(Integer.parseInt(skip)); } if (limit != null) { cursor = cursor.limit(Integer.parseInt(limit)); } JSONArray result = new JSONArray(); try { while (cursor.hasNext()) { result.add(new JSONObject(cursor.next().toString())); } } catch (JSONException e) { e.printStackTrace(); } return result; } @Override public void saveAttachment(String path, InputStream is) { OutputStream os = getFileOutputStream(path); if (os != null) { try { byte data[] = new byte[16 * 1024]; int len = 0; while ((len = is.read(data, 0, data.length)) > 0) { os.write(data, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Override public InputStream getAttachment(String path) { GridFSDBFile file = getFile(path); return file != null ? file.getInputStream() : null; } @Override public List<String> listAttachment() { List<String> files = new ArrayList<String>(); for (DBCursor cursor = mFS.getFileList(); cursor.hasNext();) { DBObject obj = cursor.next(); files.add(obj.get("filename").toString()); } return files; } @Override public void deleteAttachment(String path) { if (getFile(path) != null) { mFS.remove(path); } } private GridFSDBFile getFile(String id) { return mFS.findOne(id); } private OutputStream getFileOutputStream(String id) { try { deleteAttachment(id); return mFS.createFile(id).getOutputStream(); } catch (Exception e) { e.printStackTrace(); } return null; } @Override public JSONObject getEntry(String id) { return find(entryCol, id); } @Override public void setEntry(JSONObject entry) { entryCol.save(BasicDBObject.parse(entry.toString())); } @Override public JSONArray getAgreements() { JSONArray agreements = new JSONArray(); DBCursor cursor = entryCol.find(new BasicDBObject().append("agreed", new BasicDBObject("$exists", true))); try { while (cursor.hasNext()) { agreements.add(new JSONObject(cursor.next().toString())); } } catch (JSONException e) { e.printStackTrace(); } return agreements; } @Override public JSONArray getAnswers(String deviceId) { JSONArray answers = new JSONArray(); DBCursor cursor = entryCol.find(new BasicDBObject().append("device_id", deviceId)); try { while (cursor.hasNext()) { answers.add(new JSONObject(cursor.next().toString())); } } catch (JSONException e) { e.printStackTrace(); } return answers; } private static MongoClientOptions.Builder optionsBuilder(String cert) throws Exception { if (!cert.startsWith("-----BEGIN CERTIFICATE-----")) { cert = new String(Base64.getDecoder().decode(cert)); } KeyStore keystore = KeyStore.getInstance("PKCS12"); keystore.load(null); CertificateFactory cf = CertificateFactory.getInstance("X.509"); BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(cert.getBytes())); for (int i = 0; bis.available() > 0; i++) { try { keystore.setCertificateEntry("alias" + i, cf.generateCertificate(bis)); } catch (Exception e) { e.printStackTrace(); } } bis.close(); String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keystore); SSLContext sc = SSLContext.getInstance("TLSv1.2"); sc.init(null, tmf.getTrustManagers(), new SecureRandom()); return MongoClientOptions.builder().socketFactory(sc.getSocketFactory()).socketKeepAlive(true); // return MongoClientOptions.builder().sslEnabled(true).sslContext(sc); } @Override public void dumpLogs(OutputStream os) { dump(logCol, os); } @Override public void dumpEntries(OutputStream os) { dump(entryCol, os); } private void dump(DBCollection col, OutputStream os) { try (PrintWriter out = new PrintWriter(os)) { DBCursor cursor = col.find(); out.print("["); boolean first = true; while (cursor.hasNext()) { if (first) { first = false; } else { out.print(","); } out.print(new JSONObject(cursor.next().toString())); } out.print("]"); } catch (JSONException e) { e.printStackTrace(); } } }