/* * JBoss, Home of Professional Open Source * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors * as indicated by the @author tags. All rights reserved. * See the copyright.txt in the distribution for a * full listing of individual contributors. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License, v. 2.1. * This program is distributed in the hope that it will be useful, but WITHOUT A * 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 Lesser General Public License, * v.2.1 along with this distribution; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ package org.jboss.as.cli.gui; import static java.security.AccessController.doPrivileged; import java.awt.BorderLayout; import java.awt.Component; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.io.IOException; import java.security.PrivilegedAction; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import javax.management.MBeanServerConnection; import javax.swing.ImageIcon; import javax.swing.JInternalFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.SwingWorker; import org.jboss.as.cli.CliInitializationException; import org.jboss.as.cli.CommandContext; import org.jboss.as.cli.CommandContextFactory; import org.jboss.as.controller.client.ModelControllerClient; import org.jboss.as.controller.client.impl.ExistingChannelModelControllerClient; import org.jboss.remoting3.Channel; import org.jboss.remoting3.Connection; import org.jboss.remotingjmx.RemotingMBeanServerConnection; import org.jboss.threads.JBossThreadFactory; import org.xnio.IoFuture; import org.xnio.OptionMap; import com.sun.tools.jconsole.JConsoleContext; import com.sun.tools.jconsole.JConsolePlugin; /** * * @author Stan Silvert ssilvert@redhat.com (C) 2012 Red Hat Inc. */ public class JConsoleCLIPlugin extends JConsolePlugin { private static final String MSG_CANNOT_ESTABLISH_CONNECTION = "Cannot establish a remote connection to the application server"; private static final int DEFAULT_MAX_THREADS = 6; private static final String LABEL = "WildFly CLI"; // Global count of created pools private static final AtomicInteger executorCount = new AtomicInteger(); private ConnectDialog dialog; CliGuiContext cliGuiCtx; private JPanel jconsolePanel; private boolean initComplete = false; private boolean isConnected = false; private ComponentListener doConnectListener; @Override public Map<String,JPanel> getTabs() { Map<String, JPanel> panelMap = new HashMap<String, JPanel>(); this.jconsolePanel = new JPanel(new BorderLayout()); this.dialog = new ConnectDialog(this, this.jconsolePanel); doConnectListener = new ComponentListener() { @Override public void componentShown(ComponentEvent arg0) { try { if(!isConnected) connect(); } catch (Exception e) { throw new RuntimeException("Error connecting to JBoss AS.", e); } } @Override public void componentResized(ComponentEvent arg0) { } @Override public void componentMoved(ComponentEvent arg0) { } @Override public void componentHidden(ComponentEvent arg0) { if(dialog.isStarted()){ dialog.stop(); } } }; jconsolePanel.addComponentListener(doConnectListener); panelMap.put(LABEL, jconsolePanel); return panelMap; } private void connect() throws Exception { JConsoleContext jcCtx = this.getContext(); MBeanServerConnection mbeanServerConn = jcCtx.getMBeanServerConnection(); if (mbeanServerConn instanceof RemotingMBeanServerConnection) { final CommandContext cmdCtx = CommandContextFactory.getInstance().newCommandContext(); if(connectUsingRemoting(cmdCtx, (RemotingMBeanServerConnection)mbeanServerConn)) { init(cmdCtx); } else { JOptionPane.showInternalMessageDialog(jconsolePanel, MSG_CANNOT_ESTABLISH_CONNECTION); } } else { //show dialog dialog.start(); } } private boolean connectUsingRemoting(CommandContext cmdCtx, RemotingMBeanServerConnection rmtMBeanSvrConn) throws IOException, CliInitializationException { Connection conn = rmtMBeanSvrConn.getConnection(); Channel channel; final IoFuture<Channel> futureChannel = conn.openChannel("management", OptionMap.EMPTY); IoFuture.Status result = futureChannel.await(5, TimeUnit.SECONDS); if (result == IoFuture.Status.DONE) { channel = futureChannel.get(); } else { futureChannel.cancel(); return false; } ModelControllerClient modelCtlrClient = ExistingChannelModelControllerClient.createReceiving(channel, createExecutor()); cmdCtx.bindClient(modelCtlrClient); return true; } private ExecutorService createExecutor() { final ThreadGroup group = new ThreadGroup("management-client-thread"); final ThreadFactory threadFactory = doPrivileged(new PrivilegedAction<JBossThreadFactory>() { public JBossThreadFactory run() { return new JBossThreadFactory(group, Boolean.FALSE, null, "%G " + executorCount.incrementAndGet() + "-%t", null, null); } }); return new ThreadPoolExecutor(2, DEFAULT_MAX_THREADS, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory); } @Override public SwingWorker<?, ?> newSwingWorker() { if (!initComplete && isConnected) { initComplete = true; configureMyJInternalFrame(); } return null; } /** * @param cmdCtx */ public void init(CommandContext cmdCtx) { //TODO: add checks cliGuiCtx = GuiMain.startEmbedded(cmdCtx); final JPanel cliGuiPanel = cliGuiCtx.getMainPanel(); jconsolePanel.setVisible(false); dialog.stop(); jconsolePanel.add(GuiMain.makeMenuBar(cliGuiCtx), BorderLayout.NORTH); jconsolePanel.add(cliGuiPanel, BorderLayout.CENTER); jconsolePanel.setVisible(true); jconsolePanel.repaint(); isConnected = true; } private void configureMyJInternalFrame() { ImageIcon icon = new ImageIcon(GuiMain.getJBossIcon()); Component component = jconsolePanel; while (component != null) { component = component.getParent(); if (component instanceof JInternalFrame) { JInternalFrame frame = (JInternalFrame)component; frame.setFrameIcon(icon); return; } } } }