/** * Copyright (C) 2010 EdgyTech LLC. * * 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 com.edgytech.umongo; import com.edgytech.swingfast.XmlComponentUnit; import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBObject; import com.mongodb.Mongo; import com.mongodb.MongoException; import com.mongodb.gridfs.GridFS; import com.mongodb.gridfs.GridFSDBFile; import com.mongodb.gridfs.GridFSInputFile; import java.io.File; import java.io.IOException; import javax.swing.JPanel; import org.bson.types.Code; import com.edgytech.umongo.DbPanel.Item; import com.edgytech.swingfast.*; import com.mongodb.*; import java.util.ArrayList; import java.util.List; /** * * @author antoine */ public class DbPanel extends BasePanel implements EnumListener<Item> { enum Item { icon, name, queryOptions, writeConcern, readPreference, stats, getStats, refresh, dropDatabase, uploadFile, uploadFileDialog, uploadFilePath, uploadFileName, uploadContentType, uploadMetadata, downloadFile, downloadQuery, downloadFileName, downloadFilePath, listFiles, deleteFile, deleteQuery, deleteFileName, commandCmd, commandStr, commandJson, commandHelp, listCommands, eval, evalCode, evalNoLock, dbHash, readWriteOptions, authenticate, authUser, authPassword, manageUsers, userDialog, userList, addUser, removeUser, editUser, userChange, createCollection, createCollName, createCollCapped, createCollSize, createCollCount, // createCollAutoIndex, createCollUsePowerOf2Sizes, enableSharding, movePrimary, mvpToShard, shardingInfo, profile, profileLevel, profileSlowMS, analyzeProfilingData, repair, addJSFunction, addJSFunctionName, addJSFunctionCode, findJSFunction, findJSFunctionName, summarizeData } GridFS gridFS; public DbPanel() { setEnumBinding(Item.values(), this); } public GridFS getGridFS() { if (gridFS == null) { gridFS = new GridFS(getDbNode().getDb()); } return gridFS; } public DbNode getDbNode() { return (DbNode) getNode(); } @Override protected void updateComponentCustom(JPanel old) { try { DB db = getDbNode().getDb(); setStringFieldValue(Item.name, db.getName()); setStringFieldValue(Item.queryOptions, MongoUtils.queryOptionsToString(db.getOptions())); ((DocField) getBoundUnit(Item.writeConcern)).setDoc(db.getWriteConcern().getCommand()); ((DocField) getBoundUnit(Item.readPreference)).setDoc(db.getReadPreference().toDBObject()); ((CmdField) getBoundUnit(Item.stats)).updateFromCmd(db); } catch (Exception e) { UMongo.instance.showError(this.getClass().getSimpleName() + " update", e); } } public void actionPerformed(Item enm, XmlComponentUnit unit, Object src) { } public void command(final ButtonBase button) { final DB db = getDbNode().getDb(); final String scmd = getStringFieldValue(Item.commandStr); final DBObject cmd = !scmd.isEmpty() ? new BasicDBObject(scmd, 1) : ((DocBuilderField) getBoundUnit(Item.commandJson)).getDBObject(); boolean help = getBooleanFieldValue(Item.commandHelp); if (help) { cmd.put("help", true); } new DbJobCmd(db, cmd, null, button).addJob(); } public void listCommands(ButtonBase button) { new DbJobCmd(getDbNode().getDb(), "listCommands").addJob(); } public void eval(final ButtonBase button) { final DB db = getDbNode().getDb(); final String sfunc = getStringFieldValue(Item.evalCode); final boolean noLock = getBooleanFieldValue(Item.evalNoLock); final BasicDBObject cmd = new BasicDBObject("$eval", sfunc); if (noLock) { cmd.put("nolock", true); } new DbJobCmd(db, cmd, null, button).addJob(); } public void uploadFile(final ButtonBase button) { final DbNode dbNode = getDbNode(); final DB db = dbNode.getDb(); final String path = getStringFieldValue(Item.uploadFilePath); if (path.isEmpty()) { return; } final File src = new File(path); final String fileName = getStringFieldValue(Item.uploadFileName); final String contentType = getStringFieldValue(Item.uploadContentType); final DBObject metadata = ((DocBuilderField) getBoundUnit(Item.uploadMetadata)).getDBObject(); new DbJob() { @Override public Object doRun() throws IOException { final GridFSInputFile file = getGridFS().createFile(src); if (!fileName.isEmpty()) { file.setFilename(fileName); } if (!contentType.isEmpty()) { file.setContentType(contentType); } if (metadata != null) { file.setMetaData(metadata); } file.save(); return file; } @Override public String getNS() { return db.getName(); } @Override public String getShortName() { return "Upload File"; } @Override public DBObject getRoot(Object result) { return new BasicDBObject("path", path); } @Override public void wrapUp(Object res) { super.wrapUp(res); // may have new collections dbNode.structureComponent(); } @Override public ButtonBase getButton() { return button; } }.addJob(); } public void downloadFile(final ButtonBase button) { final DB db = getDbNode().getDb(); final DBObject query = ((DocBuilderField) getBoundUnit(Item.downloadQuery)).getDBObject(); final String fname = getStringFieldValue(Item.downloadFileName); final String dpath = getStringFieldValue(Item.downloadFilePath); if (dpath.isEmpty()) { return; } final File dfile = new File(dpath); new DbJob() { @Override public Object doRun() throws IOException { GridFSDBFile dbfile = null; if (query != null) { dbfile = getGridFS().findOne(query); } else { dbfile = getGridFS().findOne(fname); } if (dbfile == null) { throw new MongoException("GridFS cannot find file " + fname); } dbfile.writeTo(dfile); return dbfile; } @Override public String getNS() { return db.getName(); } @Override public String getShortName() { return "Download File"; } @Override public DBObject getRoot(Object result) { BasicDBObject obj = new BasicDBObject("filename", fname); obj.put("query", query); obj.put("path", dpath); return obj; } @Override public ButtonBase getButton() { return button; } }.addJob(); } public void listFiles(ButtonBase button) { final DB db = getDbNode().getDb(); final DBCollection col = db.getCollection("fs.files"); new DbJob() { @Override public Object doRun() throws IOException { return col.find(); } @Override public String getNS() { return col.getName(); } @Override public String getShortName() { return "List Files"; } }.addJob(); } public void deleteFile(final ButtonBase button) { final DB db = getDbNode().getDb(); final DBObject query = ((DocBuilderField) getBoundUnit(Item.downloadQuery)).getDBObject(); final String fname = getStringFieldValue(Item.downloadFileName); new DbJob() { @Override public Object doRun() throws IOException { if (query != null) { getGridFS().remove(query); } else { getGridFS().remove(fname); } return true; } @Override public String getNS() { return db.getName(); } @Override public String getShortName() { return "Delete File"; } @Override public DBObject getRoot(Object result) { BasicDBObject obj = new BasicDBObject("filename", fname); obj.put("query", query); return obj; } @Override public ButtonBase getButton() { return button; } }.addJob(); } public void dropDatabase(ButtonBase button) { final DbNode node = getDbNode(); final DB db = getDbNode().getDb(); BasicDBObject cmd = new BasicDBObject("dropDatabase", 1); new DbJobCmd(db, cmd, null, node.getMongoNode(), null).addJob(); } public void readWriteOptions(ButtonBase button) { final DB db = getDbNode().getDb(); OptionDialog od = UMongo.instance.getGlobalStore().getOptionDialog(); od.update(db.getOptions(), db.getWriteConcern(), db.getReadPreference()); if (!od.show()) { return; } db.setOptions(od.getQueryOptions()); db.setWriteConcern(od.getWriteConcern()); db.setReadPreference(od.getReadPreference()); refresh(); } public void authenticate(final ButtonBase button) { final DbNode dbNode = getDbNode(); final DB db = dbNode.getDb(); final String user = getStringFieldValue(Item.authUser); final String pass = getStringFieldValue(Item.authPassword); new DbJob() { @Override public Object doRun() { db.authenticateCommand(user, pass.toCharArray()); return null; } @Override public String getNS() { return db.getName(); } @Override public String getShortName() { return "Auth"; } @Override public void wrapUp(Object res) { super.wrapUp(res); if (dbNode.getDb().getName().equals("admin")) { // now we can list dbs, refresh whole mongo dbNode.getMongoNode().structureComponent(); } else { dbNode.structureComponent(); } } @Override public ButtonBase getButton() { return button; } }.addJob(); } void refreshUserList() { ListArea list = (ListArea) getBoundUnit(Item.userList); final DB db = getDbNode().getDb(); DBCursor cur = db.getCollection("system.users").find().sort(new BasicDBObject("user", 1)); ArrayList users = new ArrayList(); while (cur.hasNext()) { BasicDBObject user = (BasicDBObject) cur.next(); users.add(user.getString("user")); } list.items = (String[]) users.toArray(new String[users.size()]); list.structureComponent(); } public void manageUsers(ButtonBase button) { FormDialog dialog = (FormDialog) ((MenuItem) getBoundUnit(Item.manageUsers)).getDialog(); refreshUserList(); dialog.show(); } public void addUser(ButtonBase button) { final DB db = getDbNode().getDb(); final DBCollection col = db.getCollection("system.users"); UserDialog ud = (UserDialog) getBoundUnit(Item.userDialog); ud.resetForNew(); if (!ud.show()) { return; } final BasicDBObject newUser = ud.getUser(null); new DbJob() { @Override public Object doRun() throws IOException { return col.insert(newUser); } @Override public String getNS() { return "system.users"; } @Override public String getShortName() { return "Add User"; } @Override public void wrapUp(Object res) { super.wrapUp(res); refreshUserList(); } }.addJob(); } public void removeUser(ButtonBase button) { final DB db = getDbNode().getDb(); final String user = getComponentStringFieldValue(Item.userList); if (user == null) { return; } if (!((ConfirmDialog) getBoundUnit(Item.userChange)).show()) { return; } new DbJob() { @Override public Object doRun() throws IOException { return db.removeUser(user); } @Override public String getNS() { return "system.users"; } @Override public String getShortName() { return "Remove User"; } @Override public void wrapUp(Object res) { super.wrapUp(res); refreshUserList(); } }.addJob(); } public void editUser(ButtonBase button) { final DB db = getDbNode().getDb(); final DBCollection col = db.getCollection("system.users"); final String user = getComponentStringFieldValue(Item.userList); if (user == null) { return; } final BasicDBObject userObj = (BasicDBObject) col.findOne(new BasicDBObject("user", user)); UserDialog ud = (UserDialog) getBoundUnit(Item.userDialog); ud.resetForEdit(userObj); if (!ud.show()) { return; } final BasicDBObject newUser = ud.getUser(userObj); new DbJob() { @Override public Object doRun() throws IOException { return col.save(newUser); } @Override public String getNS() { return col.getName(); } @Override public String getShortName() { return "Edit User"; } @Override public void wrapUp(Object res) { super.wrapUp(res); refreshUserList(); } }.addJob(); } public void createCollection(final ButtonBase button) { final DbNode node = getDbNode(); final DB db = getDbNode().getDb(); final String name = getStringFieldValue(Item.createCollName); final boolean capped = getBooleanFieldValue(Item.createCollCapped); final int size = getIntFieldValue(Item.createCollSize); final int count = getIntFieldValue(Item.createCollCount); // final boolean autoIndexId = getBooleanFieldValue(Item.createCollAutoIndex); final boolean usePowerOf2Sizes = getBooleanFieldValue(Item.createCollUsePowerOf2Sizes); DBObject createCmd = new BasicDBObject("create", name); DBObject opt = new BasicDBObject("capped", capped); if (capped) { if (size > 0) { opt.put("size", size); } if (count > 0) { opt.put("max", count); } } // // deprecated // if (!autoIndexId) { // opt.put("autoIndexId", false); // } // usePowerOf2Sizes uses flags name :( opt.put("flags", usePowerOf2Sizes ? 1 : 0); createCmd.putAll(opt); new DbJobCmd(db, createCmd, null, node, button).addJob(); } public void getStats(ButtonBase button) { new DbJobCmd(getDbNode().getDb(), "dbstats").addJob(); } public void dbHash(ButtonBase button) { new DbJobCmd(getDbNode().getDb(), "dbHash").addJob(); } public void enableSharding(ButtonBase button) { MongoClient m = getDbNode().getMongoNode().getMongoClient(); DB admin = m.getDB("admin"); DBObject cmd = new BasicDBObject("enableSharding", getDbNode().getDb().getName()); new DbJobCmd(admin, cmd, this, null).addJob(); } public void profile(ButtonBase button) { DB db = getDbNode().getDb(); int level = getIntFieldValue(Item.profileLevel); final DBObject cmd = new BasicDBObject("profile", level); if (level == 1) { int slow = getIntFieldValue(Item.profileSlowMS); if (slow > 0) { cmd.put("slowms", slow); } } new DbJobCmd(db, cmd).addJob(); } public void analyzeProfilingData(ButtonBase button) { new DbJob() { @Override public Object doRun() throws Exception { DBCollection prof = getDbNode().getDb().getCollection("system.profile"); BasicDBObject out = new BasicDBObject(); CommandResult res = null; DocumentDeserializer dd = null; BasicDBObject aggCmd = null; // response time by operation type dd = new DocumentDeserializer(DocumentDeserializer.Format.JSON_SINGLE_DOC, null); dd.setInputStream(DbPanel.class.getResourceAsStream("/json/profOperationType.json")); aggCmd = (BasicDBObject) dd.readObject(); res = getDbNode().getDb().command(aggCmd); out.put("byOperationType", res.get("result")); dd.close(); // slowest by namespace dd = new DocumentDeserializer(DocumentDeserializer.Format.JSON_SINGLE_DOC, null); dd.setInputStream(DbPanel.class.getResourceAsStream("/json/profNamespace.json")); aggCmd = (BasicDBObject) dd.readObject(); res = getDbNode().getDb().command(aggCmd); out.put("byNamespace", res.get("result")); dd.close(); // slowest by client dd = new DocumentDeserializer(DocumentDeserializer.Format.JSON_SINGLE_DOC, null); dd.setInputStream(DbPanel.class.getResourceAsStream("/json/profClient.json")); aggCmd = (BasicDBObject) dd.readObject(); res = getDbNode().getDb().command(aggCmd); out.put("byClient", res.get("result")); dd.close(); // summary moved vs non-moved dd = new DocumentDeserializer(DocumentDeserializer.Format.JSON_SINGLE_DOC, null); dd.setInputStream(DbPanel.class.getResourceAsStream("/json/profMoved.json")); aggCmd = (BasicDBObject) dd.readObject(); res = getDbNode().getDb().command(aggCmd); out.put("movedVsNonMoved", res.get("result")); dd.close(); // response time analysis dd = new DocumentDeserializer(DocumentDeserializer.Format.JSON_SINGLE_DOC, null); dd.setInputStream(DbPanel.class.getResourceAsStream("/json/profResponseTimeAnalysis.json")); aggCmd = (BasicDBObject) dd.readObject(); res = getDbNode().getDb().command(aggCmd); out.put("responseTimeAnalysis", res.get("result")); dd.close(); return out; } @Override public String getNS() { return getDbNode().getDb().getName(); } @Override public String getShortName() { return "Analyze Profiling Data"; } }.addJob(); } public void repair(ButtonBase button) { DB db = getDbNode().getDb(); final DBObject cmd = new BasicDBObject("repairDatabase", 1); if (!UMongo.instance.getGlobalStore().confirmLockingOperation()) { return; } new DbJobCmd(db, cmd).addJob(); } public void shardingInfo(ButtonBase button) { final DB db = getDbNode().getDb(); final DB config = db.getSisterDB("config"); final DBCollection col = config.getCollection("databases"); CollectionPanel.doFind(col, new BasicDBObject("_id", db.getName())); } public void movePrimary(ButtonBase button) { FormDialog dialog = (FormDialog) ((MenuItem) getBoundUnit(Item.movePrimary)).getDialog(); ComboBox combo = (ComboBox) getBoundUnit(Item.mvpToShard); combo.value = 0; combo.items = getDbNode().getMongoNode().getShardNames(); combo.structureComponent(); if (!dialog.show()) { return; } MongoClient m = getDbNode().getMongoNode().getMongoClient(); DB admin = m.getDB("admin"); String shard = getStringFieldValue(Item.mvpToShard); DBObject cmd = new BasicDBObject("movePrimary", getDbNode().getDb().getName()); cmd.put("to", shard); new DbJobCmd(admin, cmd, this, null).addJob(); } public void findJSFunction(ButtonBase button) { final DB db = getDbNode().getDb(); final DBCollection col = db.getCollection("system.js"); final String name = getStringFieldValue(Item.findJSFunctionName); DBObject query = new BasicDBObject(); if (name != null && !name.isEmpty()) { query.put("_id", name); } CollectionPanel.doFind(col, query); } public void addJSFunction(final ButtonBase button) { final DB db = getDbNode().getDb(); final DBCollection col = db.getCollection("system.js"); final String name = getStringFieldValue(Item.addJSFunctionName); final String code = getStringFieldValue(Item.addJSFunctionCode); CollectionPanel.doFind(col, new BasicDBObject("_id", name)); new DbJob() { @Override public Object doRun() throws Exception { DBObject obj = new BasicDBObject("_id", name); obj.put("value", new Code(code)); return col.insert(obj); } @Override public String getNS() { return col.getFullName(); } @Override public String getShortName() { return "Add JS Function"; } @Override public ButtonBase getButton() { return null; } }.addJob(); } public void summarizeData(final ButtonBase button) { final DbNode dbnode = getDbNode(); new DbJob() { @Override public Object doRun() throws IOException { return dbnode.summarizeData(); } @Override public String getNS() { return dbnode.getDb().getName(); } @Override public String getShortName() { return "Summarize Data"; } }.addJob(); } }