Issue 134308: Provide API that allows other modules to register actions on a database node
diff --git a/db.mysql/src/org/netbeans/modules/db/mysql/impl/MySQLActionProvider.java b/db.mysql/src/org/netbeans/modules/db/mysql/impl/MySQLActionProvider.java
--- a/db.mysql/src/org/netbeans/modules/db/mysql/impl/MySQLActionProvider.java
+++ b/db.mysql/src/org/netbeans/modules/db/mysql/impl/MySQLActionProvider.java
@@ -43,7 +43,7 @@
import java.util.ArrayList;
import java.util.List;
import javax.swing.Action;
-import org.netbeans.modules.db.api.explorer.ActionProvider;
+import org.netbeans.modules.db.api.explorer.RootNodeActionProvider;
import org.openide.util.actions.SystemAction;
/**
@@ -52,7 +52,7 @@
*
* @author David Van Couvering
*/
-public class MySQLActionProvider implements ActionProvider {
+public class MySQLActionProvider implements RootNodeActionProvider {
private static final MySQLActionProvider DEFAULT = new MySQLActionProvider();
private final ArrayList actions = new ArrayList();
diff --git a/db.mysql/src/org/netbeans/modules/db/mysql/layer.xml b/db.mysql/src/org/netbeans/modules/db/mysql/layer.xml
--- a/db.mysql/src/org/netbeans/modules/db/mysql/layer.xml
+++ b/db.mysql/src/org/netbeans/modules/db/mysql/layer.xml
@@ -49,10 +49,10 @@
-
+
-
+
diff --git a/db/apichanges.xml b/db/apichanges.xml
--- a/db/apichanges.xml
+++ b/db/apichanges.xml
@@ -105,6 +105,20 @@
+
+
+ Add ability to register actions with database connection nodes
+
+
+
+
+
+ With this change modules can register actions with database connection nodes.
+ The action is registered for all nodes, but can be selectively enabled/disabled
+ as needed.
+
+
+
Add ability to get the underlying JDBC Driver instance for a JDBCDriver
diff --git a/db/arch.xml b/db/arch.xml
--- a/db/arch.xml
+++ b/db/arch.xml
@@ -367,6 +367,52 @@
SQLIdentifiers.Quoter class is provided for this.
+
+
+ This feature allows modules to provide useful features to users by registering
+ one or more actions with a Database Explorer connection node.
+
+
+ The module registers an implementation of
+ ConnectionActionProvider in its layer file under the folder
+ Databases/ConnectionActionProvider
. The provider's
+
+ getActions()
+ method is invoked by the Database Explorer whenever a connection node needs to know what actions
+ to display. This method is passed in the
+ DatabaseConnection
+ for the current selected connection, and you can choose which actions, if any,
+ you want to make available for this connection.
+
+
+ Here is an example registration of an ActionProvider:
+
+
+ <folder name="Databases">
+ <folder name="ConnectionActionProvider">
+ <file name="MyConnectionActionProvider.instance">
+ <attr name="instanceCreate" methodvalue="org.netbeans.testdriver.MyConnectionActionProvider.getDefault"/>
+ <attr name="instanceOf" stringvalue="org.netbeans.api.db.explorer.ConnectionActionProvider"/>
+ </file>
+ </folder>
+ </folder>
+
+
+ The action can obtain the current
+ DatabaseConnection
+ by implementing
+ CookieAction and
+ specifying DatbaseConnection.class
in the
+ cookieClasses() method.
+ Then in the
+ enable()
+ and
+ performAction()
+ methods of the action, you can call
+ Node.getCookie(DatabaseConnection.class)
+ to get the DatabaseConnection.
+
+
diff --git a/db/src/org/netbeans/api/db/explorer/ConnectionActionProvider.java b/db/src/org/netbeans/api/db/explorer/ConnectionActionProvider.java
new file mode 100644
--- /dev/null
+++ b/db/src/org/netbeans/api/db/explorer/ConnectionActionProvider.java
@@ -0,0 +1,76 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2008 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.api.db.explorer;
+
+import java.util.List;
+import javax.swing.Action;
+
+/**
+ * A module that wants to provide one or more actions to a DatabaseConnection
+ * node should implement this interface and then register the provider in
+ * the layer file under the folder "Databases/ConnectionActionProvider".
+ *
+ * For example:
+ *
+
+
+
+
+
+
+
+ *
+ *
+ *
+ * The enable() method of the action can get the active DatabaseConnection(s)
+ * from the active Node(s) using Node.getCookie()
and use this information to decide
+ * whether or not the action should be enabled. For example, if you only want
+ * your action to be available for MySQL connections, you can call
+ * DatabaseConnection.getDriverClass() and see if it is the driver for MySQL.
+ *
+ * @author David Van Couvering
+ * @since 1.30
+ */
+public interface ConnectionActionProvider {
+ /**
+ * @return the list of actions provided
+ */
+ public List getActions(DatabaseConnection dbconn);
+}
diff --git a/db/src/org/netbeans/api/db/explorer/DatabaseConnection.java b/db/src/org/netbeans/api/db/explorer/DatabaseConnection.java
--- a/db/src/org/netbeans/api/db/explorer/DatabaseConnection.java
+++ b/db/src/org/netbeans/api/db/explorer/DatabaseConnection.java
@@ -44,6 +44,7 @@
import java.sql.Connection;
import org.netbeans.modules.db.explorer.ConnectionList;
import org.netbeans.modules.db.explorer.DatabaseConnectionAccessor;
+import org.openide.nodes.Node;
/**
* Encapsulates a database connection. Each DatabaseConnection instance
@@ -64,7 +65,7 @@
*
* @see ConnectionManager
*/
-public final class DatabaseConnection {
+public final class DatabaseConnection implements Node.Cookie {
private org.netbeans.modules.db.explorer.DatabaseConnection delegate;
diff --git a/db/src/org/netbeans/modules/db/explorer/DbActionLoader.java b/db/src/org/netbeans/modules/db/explorer/RootNodeActionLoader.java
rename from db/src/org/netbeans/modules/db/explorer/DbActionLoader.java
rename to db/src/org/netbeans/modules/db/explorer/RootNodeActionLoader.java
--- a/db/src/org/netbeans/modules/db/explorer/DbActionLoader.java
+++ b/db/src/org/netbeans/modules/db/explorer/RootNodeActionLoader.java
@@ -54,7 +54,7 @@
*
* @author David Van Couvering
*/
-public interface DbActionLoader {
+public interface RootNodeActionLoader {
/**
* Get all the registered actions
*/
diff --git a/db/src/org/netbeans/modules/db/explorer/DbActionLoaderSupport.java b/db/src/org/netbeans/modules/db/explorer/RootNodeActionLoaderSupport.java
rename from db/src/org/netbeans/modules/db/explorer/DbActionLoaderSupport.java
rename to db/src/org/netbeans/modules/db/explorer/RootNodeActionLoaderSupport.java
--- a/db/src/org/netbeans/modules/db/explorer/DbActionLoaderSupport.java
+++ b/db/src/org/netbeans/modules/db/explorer/RootNodeActionLoaderSupport.java
@@ -49,20 +49,20 @@
import org.openide.util.Lookup;
/**
- * Supporting methods to work with the registered implementation of ActionLoader
+ * Supporting methods to work with the registered implementation of RootNodeActionLoader
*
* @author David Van Couvering
*/
-public class DbActionLoaderSupport {
+public class RootNodeActionLoaderSupport {
- private DbActionLoaderSupport() {
+ private RootNodeActionLoaderSupport() {
}
public static List getAllActions() {
List actions = new ArrayList();
- Collection loaders = Lookup.getDefault().lookupAll(DbActionLoader.class);
+ Collection loaders = Lookup.getDefault().lookupAll(RootNodeActionLoader.class);
for (Iterator i = loaders.iterator(); i.hasNext();) {
- actions.addAll(((DbActionLoader)i.next()).getAllActions());
+ actions.addAll(((RootNodeActionLoader)i.next()).getAllActions());
}
return actions;
diff --git a/db/src/org/netbeans/modules/db/explorer/infos/ConnectionNodeInfo.java b/db/src/org/netbeans/modules/db/explorer/infos/ConnectionNodeInfo.java
--- a/db/src/org/netbeans/modules/db/explorer/infos/ConnectionNodeInfo.java
+++ b/db/src/org/netbeans/modules/db/explorer/infos/ConnectionNodeInfo.java
@@ -48,9 +48,15 @@
import java.sql.DatabaseMetaData;
import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.swing.Action;
+import org.netbeans.api.db.explorer.ConnectionActionProvider;
import org.netbeans.lib.ddl.DBConnection;
import org.netbeans.lib.ddl.DatabaseProductNotFoundException;
import org.netbeans.lib.ddl.impl.DriverSpecification;
@@ -68,6 +74,7 @@
//import org.netbeans.modules.db.explorer.PointbasePlus;
import org.openide.util.Exceptions;
//import org.openide.nodes.Node;
+import org.openide.util.lookup.Lookups;
//import org.netbeans.modules.db.explorer.nodes.ConnectionNode;
@@ -318,8 +325,39 @@
}
-
-
+
+ @Override
+ public Vector getActions() {
+ Vector actions = super.getActions();
+ List registeredActions = getRegisteredActions(getDatabaseConnection());
+
+ if (registeredActions == null || registeredActions.size() == 0) {
+ return actions;
+ }
+
+ // Add a delimiter
+ actions.add(null);
+
+ actions.addAll(registeredActions);
+
+ return actions;
+ }
+
+ private static final String ACTION_PROVIDER_PATH = "Databases/ConnectionActionProvider";
+ private List getRegisteredActions(DatabaseConnection dbconn) {
+ List actions = new ArrayList();
+ Collection providers = (Collection)
+ Lookups.forPath(ACTION_PROVIDER_PATH).lookupAll(ConnectionActionProvider.class);
+
+ for (ConnectionActionProvider provider : providers) {
+ List actionList = provider.getActions(dbconn.getDatabaseConnection());
+ if (actionList != null) {
+ actions.addAll(actionList);
+ }
+ }
+
+ return actions;
+ }
private void connect(String dbsys) throws DatabaseException {
String drvurl = getDriver();
diff --git a/db/src/org/netbeans/modules/db/explorer/infos/RootNodeInfo.java b/db/src/org/netbeans/modules/db/explorer/infos/RootNodeInfo.java
--- a/db/src/org/netbeans/modules/db/explorer/infos/RootNodeInfo.java
+++ b/db/src/org/netbeans/modules/db/explorer/infos/RootNodeInfo.java
@@ -59,7 +59,7 @@
import org.netbeans.modules.db.explorer.DatabaseConnection;
import org.netbeans.modules.db.explorer.ConnectionList;
import org.netbeans.modules.db.explorer.DatabaseOption;
-import org.netbeans.modules.db.explorer.DbActionLoaderSupport;
+import org.netbeans.modules.db.explorer.RootNodeActionLoaderSupport;
import org.netbeans.modules.db.explorer.DbNodeLoader;
import org.netbeans.modules.db.explorer.DbNodeLoaderSupport;
import org.netbeans.modules.db.explorer.nodes.*;
@@ -197,7 +197,7 @@
public Vector getActions() {
Vector actions = super.getActions();
- List loadedActions = DbActionLoaderSupport.getAllActions();
+ List loadedActions = RootNodeActionLoaderSupport.getAllActions();
Vector allActions = new Vector();
diff --git a/db/src/org/netbeans/modules/db/explorer/nodes/ConnectionNode.java b/db/src/org/netbeans/modules/db/explorer/nodes/ConnectionNode.java
--- a/db/src/org/netbeans/modules/db/explorer/nodes/ConnectionNode.java
+++ b/db/src/org/netbeans/modules/db/explorer/nodes/ConnectionNode.java
@@ -44,11 +44,18 @@
import java.awt.datatransfer.Transferable;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.swing.Action;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
+import org.netbeans.api.db.explorer.ConnectionActionProvider;
import org.netbeans.modules.db.explorer.DatabaseConnection;
import org.netbeans.api.db.explorer.DatabaseMetaDataTransfer;
import org.netbeans.modules.db.explorer.ConnectionList;
@@ -62,6 +69,7 @@
import org.openide.util.RequestProcessor;
import org.openide.util.WeakListeners;
import org.openide.util.datatransfer.ExTransferable;
+import org.openide.util.lookup.Lookups;
/**
* Node representing open or closed connection to database.
@@ -99,8 +107,16 @@
private void setPropSupport(boolean value) {
createPropSupport = value;
}
-
-
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Node.Cookie getCookie(Class cls) {
+ if (cls == org.netbeans.api.db.explorer.DatabaseConnection.class) {
+ return (Node.Cookie)info.getDatabaseConnection().getDatabaseConnection();
+ } else {
+ return super.getCookie(cls);
+ }
+ }
private void update() {
RequestProcessor.getDefault().post(new Runnable() {
diff --git a/dbapi/src/META-INF/services/org.netbeans.modules.db.explorer.DbActionLoader b/dbapi/src/META-INF/services/org.netbeans.modules.db.explorer.DbActionLoader
--- a/dbapi/src/META-INF/services/org.netbeans.modules.db.explorer.DbActionLoader
+++ b/dbapi/src/META-INF/services/org.netbeans.modules.db.explorer.DbActionLoader
@@ -1,1 +1,1 @@
-org.netbeans.modules.dbapi.DbActionLoaderImpl
+org.netbeans.modules.dbapi.RootNodeActionLoaderImpl
diff --git a/dbapi/src/org/netbeans/modules/db/api/explorer/ActionProvider.java b/dbapi/src/org/netbeans/modules/db/api/explorer/RootNodeActionProvider.java
rename from dbapi/src/org/netbeans/modules/db/api/explorer/ActionProvider.java
rename to dbapi/src/org/netbeans/modules/db/api/explorer/RootNodeActionProvider.java
--- a/dbapi/src/org/netbeans/modules/db/api/explorer/ActionProvider.java
+++ b/dbapi/src/org/netbeans/modules/db/api/explorer/RootNodeActionProvider.java
@@ -52,7 +52,7 @@
*
* @author David Van Couvering
*/
-public interface ActionProvider {
+public interface RootNodeActionProvider {
/**
* @return the list of actions provided
*/
diff --git a/dbapi/src/org/netbeans/modules/dbapi/DbActionLoaderImpl.java b/dbapi/src/org/netbeans/modules/dbapi/RootNodeActionLoaderImpl.java
rename from dbapi/src/org/netbeans/modules/dbapi/DbActionLoaderImpl.java
rename to dbapi/src/org/netbeans/modules/dbapi/RootNodeActionLoaderImpl.java
--- a/dbapi/src/org/netbeans/modules/dbapi/DbActionLoaderImpl.java
+++ b/dbapi/src/org/netbeans/modules/dbapi/RootNodeActionLoaderImpl.java
@@ -46,8 +46,8 @@
import java.util.Iterator;
import java.util.List;
import javax.swing.Action;
-import org.netbeans.modules.db.api.explorer.ActionProvider;
-import org.netbeans.modules.db.explorer.DbActionLoader;
+import org.netbeans.modules.db.api.explorer.RootNodeActionProvider;
+import org.netbeans.modules.db.explorer.RootNodeActionLoader;
import org.openide.util.lookup.Lookups;
/**
@@ -56,20 +56,20 @@
*
* @author David Van Couvering
*/
-public class DbActionLoaderImpl implements DbActionLoader {
+public class RootNodeActionLoaderImpl implements RootNodeActionLoader {
/**
* Not private because used in the tests.
*/
- static final String ACTION_PROVIDER_PATH = "Databases/ActionProviders"; // NOI18N
+ static final String ACTION_PROVIDER_PATH = "Databases/RootNodeActionProvider"; // NOI18N
public List getAllActions() {
List actions = new ArrayList();
Collection providers = Lookups.forPath(ACTION_PROVIDER_PATH).
- lookupAll(ActionProvider.class);
+ lookupAll(RootNodeActionProvider.class);
for (Iterator i = providers.iterator(); i.hasNext();) {
- ActionProvider provider = (ActionProvider)i.next();
+ RootNodeActionProvider provider = (RootNodeActionProvider)i.next();
List actionList = provider.getActions();
if (actionList != null) {
actions.addAll(actionList);