/** * 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.Application; import com.edgytech.swingfast.ConfirmDialog; import com.edgytech.swingfast.Frame; import com.edgytech.swingfast.MenuItem; import com.edgytech.swingfast.Scroller; import com.edgytech.swingfast.TabbedDiv; import com.edgytech.swingfast.Tree; import com.edgytech.swingfast.XmlJComponentUnit; import com.mongodb.DBObject; import com.mongodb.MongoClient; import com.mongodb.MongoException; import java.awt.event.WindowEvent; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.jar.JarFile; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.SwingUtilities; import org.xml.sax.SAXException; /** * * @author antoine */ public class UMongo extends Application implements Runnable { enum Item { workspace, workspaceScroll, tree, treeScroll, mainMenu, mainToolBar, frame, globalStore, docViewDialog, docTree, tabbedResult, jobBar, } public final static UMongo instance = new UMongo(); private ArrayList<MongoNode> mongos = new ArrayList<MongoNode>(); boolean stopped = false; BaseTreeNode node = null; FileWriter activityLogWriter = null; boolean activityLogFirstResult = false; Handler applicationLogHandler = null; String pluginFolder = null; BinaryDecoder binaryDecoder = null; public UMongo() { super(true); setEnumBinding(Item.values(), null); } Frame getFrame() { return (Frame) getBoundUnit(Item.frame); } Workspace getWorkspace() { return (Workspace) getBoundUnit(Item.workspace); } Scroller getWorkspaceScroll() { return (Scroller) getBoundUnit(Item.workspaceScroll); } Tree getTree() { return (Tree) getBoundUnit(Item.tree); } MainMenu getMainMenu() { return (MainMenu) getBoundUnit(Item.mainMenu); } PreferencesDialog getPreferences() { return getMainMenu().getPreferences(); } MainToolBar getMainToolBar() { return (MainToolBar) getBoundUnit(Item.mainToolBar); } public void load() throws IOException, SAXException { xmlLoad(Resource.getXmlDir(), Resource.File.umongo, null); } public void loadSettings() throws IOException, SAXException { try { xmlLoad(Resource.getConfDir(), Resource.File.umongo, null); } catch (FileNotFoundException e) { // means no custom setting } } public void saveSettings() { try { xmlSave(Resource.getConfDir(), Resource.File.umongo, null); } catch (Exception ex) { getLogger().log(Level.SEVERE, ex.getMessage(), ex); } } @Override public void initialize() { try { load(); loadSettings(); } catch (Exception ex) { getLogger().log(Level.SEVERE, null, ex); } Thread maintenance = new Thread(this); maintenance.setDaemon(true); maintenance.start(); } @Override public void wrapUp() { saveSettings(); } public void start() { getLogger().log(Level.INFO, "UMONGO STARTING"); } public void stop() { getLogger().log(Level.INFO, "UMONGO STOPPING"); stopped = true; } public static void main(String[] args) { // LogManager.getLogManager().getLogger("").setLevel(Level.FINE); instance.launch(); } GlobalStore getGlobalStore() { return (GlobalStore) getBoundUnit(Item.globalStore); } void addMongoClient(MongoClient mongo, List<String> dbs) throws MongoException, UnknownHostException { MongoNode node = new MongoNode(mongo, dbs); getTree().addChild(node); mongos.add(node); getTree().structureComponent(); getTree().expandNode(node); getTree().selectNode(node); } void disconnect(MongoNode node) { mongos.remove(node); node.removeNode(); MongoClient mongo = ((MongoNode) node).getMongoClient(); mongo.close(); if (mongos.size() > 0) { MongoNode other = mongos.get(0); getTree().expandNode(other); getTree().selectNode(other); } else { displayElement(null); } } public ArrayList<MongoNode> getMongos() { return mongos; } void displayElement(XmlJComponentUnit unit) { getWorkspace().setContent(unit); } void showError(String in, Exception ex) { ErrorDialog dia = getGlobalStore().getErrorDialog(); dia.setException(ex, in); dia.show(); } TabbedDiv getTabbedResult() { return (TabbedDiv) getBoundUnit(Item.tabbedResult); } void removeAllTabs() { TabbedDiv tabs = getTabbedResult(); tabs.removeAllChildren(); tabs.structureComponent(); } JobBar getJobBar() { return (JobBar) getBoundUnit(Item.jobBar); } public void displayNode(BaseTreeNode node) { this.node = node; BasePanel panel = null; if (node instanceof MongoNode) { panel = getGlobalStore().getMongoPanel(); } else if (node instanceof DbNode) { panel = getGlobalStore().getDbPanel(); } else if (node instanceof CollectionNode) { panel = getGlobalStore().getCollectionPanel(); } else if (node instanceof IndexNode) { panel = getGlobalStore().getIndexPanel(); } else if (node instanceof ServerNode) { panel = getGlobalStore().getServerPanel(); } else if (node instanceof RouterNode) { panel = getGlobalStore().getRouterPanel(); } else if (node instanceof ReplSetNode) { panel = getGlobalStore().getReplSetPanel(); } panel.setNode(node); // cant load checkpoint here, means all dialogs get reset // panel.xmlLoadCheckpoint(); displayElement(panel); } public BaseTreeNode getNode() { return node; } public void runJob(DbJob job) { getJobBar().addJob(job); job.start(); } public void removeJob(DbJob job) { getJobBar().removeJob(job); } long _nextTreeUpdate = System.currentTimeMillis(); ConcurrentLinkedQueue<BaseTreeNode> nodesToRefresh = new ConcurrentLinkedQueue<BaseTreeNode>(); void addNodeToRefresh(BaseTreeNode node) { nodesToRefresh.add(node); } public void run() { while (!stopped) { try { long now = System.currentTimeMillis(); int treeRate = getPreferences().getTreeUpdateRate(); if (treeRate > 0 && _nextTreeUpdate < now) { _nextTreeUpdate = now + treeRate; SwingUtilities.invokeAndWait(new Runnable() { public void run() { long start = System.currentTimeMillis(); // need structure here, to trigger refresh() getTree().structureComponent(); getLogger().log(Level.FINE, "Tree update took " + (System.currentTimeMillis() - start)); // getTree().structureComponent(); } }); } BaseTreeNode node = null; while ((node = nodesToRefresh.poll()) != null) { node.refresh(); final BaseTreeNode fnode = node; SwingUtilities.invokeAndWait(new Runnable() { public void run() { fnode.updateComponent(false); } }); } } catch (Exception ex) { getLogger().log(Level.SEVERE, null, ex); } try { Thread.sleep(100); } catch (InterruptedException ex) { getLogger().log(Level.SEVERE, null, ex); } } } @Override public void windowClosing(WindowEvent e) { if (getJobBar().hasChildren()) { String text = "There are jobs running, force exit?"; ConfirmDialog confirm = new ConfirmDialog(null, "Confirm Exit", null, text); if (!confirm.show()) { return; } } super.windowClosing(e); } void updateLogging() { synchronized (this) { try { Handler handler = getPreferences().getApplicationLogHandler(); if (handler == null) { if (applicationLogHandler != null) { Logger.getLogger("").removeHandler(applicationLogHandler); } } else { if (applicationLogHandler == null) { Logger.getLogger("").addHandler(handler); } else if (!applicationLogHandler.equals(handler)) { Logger.getLogger("").removeHandler(applicationLogHandler); Logger.getLogger("").addHandler(handler); } } applicationLogHandler = handler; String logFile = getPreferences().getActivityLogFile(); if (logFile != null) { if (activityLogWriter != null) { activityLogWriter.close(); } activityLogWriter = new FileWriter(logFile, true); activityLogFirstResult = getPreferences().getActivityLogFirstResult(); } else { if (activityLogWriter != null) { activityLogWriter.close(); } activityLogWriter = null; } } catch (IOException ex) { getLogger().log(Level.WARNING, null, ex); } } } boolean isLoggingOn() { return activityLogWriter != null; } boolean isLoggingFirstResultOn() { return activityLogFirstResult; } void logActivity(DBObject obj) { synchronized (this) { try { if ("Auth".equals(obj.get("name"))) { // dont log auth return; } activityLogWriter.write(MongoUtils.getJSON(obj)); activityLogWriter.write("\n"); activityLogWriter.flush(); } catch (Exception ex) { getLogger().log(Level.WARNING, null, ex); } } } void updatePlugins() { String folder = getPreferences().getPluginFolder(); if (folder != null && folder.equals(pluginFolder)) { return; } pluginFolder = folder; resetPlugins(); if (folder == null) { return; } // System.setSecurityManager(new PluginSecurityManager(pluginFolder)); //System.getProperty("user.dir") File dir = new File(pluginFolder); PluginClassLoader cl = new PluginClassLoader(dir); if (dir.exists() && dir.isDirectory()) { // we'll only load classes directly in this directory - // no subdirectories, and no classes in packages are recognized File[] files = dir.listFiles(); for (int i = 0; i < files.length; i++) { try { List<Class> classes = null; File file = files[i]; if (file.getPath().endsWith(".jar")) { getLogger().info("Attempting to load plugin " + file.getPath()); JarFile jar = new JarFile(file); classes = cl.loadClasses(jar); } /* // only consider files ending in ".class" if (!files[i].endsWith(".class")) { continue; } getLogger().info("Attempting to load plugin " + files[i]); Class c = cl.loadClass(files[i].substring(0, files[i].indexOf("."))); */ for (Class c : classes) { Class[] intf = c.getInterfaces(); for (int j = 0; j < intf.length; j++) { if (intf[j].getName().equals("com.edgytech.umongo.BinaryDecoder")) { getLogger().info("Detected BinaryDecoder plugin in " + c.getCanonicalName()); // the following line assumes that PluginFunction has a no-argument constructor BinaryDecoder bd = (BinaryDecoder) c.newInstance(); binaryDecoder = bd; } } } } catch (Exception ex) { getLogger().log(Level.WARNING, null, ex); } } } } void resetPlugins() { binaryDecoder = null; } BinaryDecoder getBinaryDecoder() { return binaryDecoder; } @Override public void handleMacAbout() { ((MenuItem)getMainMenu().getBoundUnit(MainMenu.Item.about)).getButton().doClick(); } }