/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.visualvm.application.options;
import com.sun.tools.visualvm.application.Application;
import com.sun.tools.visualvm.application.jvm.Jvm;
import com.sun.tools.visualvm.application.jvm.JvmFactory;
import com.sun.tools.visualvm.core.datasource.DataSourceContainer;
import com.sun.tools.visualvm.core.datasupport.DataChangeEvent;
import com.sun.tools.visualvm.core.datasupport.DataChangeListener;
import com.sun.tools.visualvm.core.ui.DataSourceWindowManager;
import com.sun.tools.visualvm.host.Host;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.swing.Timer;
import org.netbeans.api.sendopts.CommandException;
import org.netbeans.spi.sendopts.Env;
import org.netbeans.spi.sendopts.Option;
import org.netbeans.spi.sendopts.OptionProcessor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.NbBundle;
/**
* Handling of --openpid and --openid commandline option
*
* @author Tomas Hurka
*/
public final class Open extends OptionProcessor {
private Option openpid = Option.requiredArgument(Option.NO_SHORT_NAME,"openpid"); // NOI18N
private Option openid = Option.requiredArgument(Option.NO_SHORT_NAME,"openid"); // NOI18N
private static final int TIMEOUT = 5000;
private static final String ID = "visualvm.id"; // NOI18N
public Open() {
openpid = Option.shortDescription(openpid,"com.sun.tools.visualvm.application.options.Bundle","MSG_OPENPID"); // NOI18N
openid = Option.shortDescription(openid,"com.sun.tools.visualvm.application.options.Bundle","MSG_OPENID"); // NOI18N
}
protected Set<Option> getOptions() {
Set<Option> options = new HashSet();
options.add(openpid);
options.add(openid);
return options;
}
protected void process(Env env, Map<Option, String[]> optionValues) throws CommandException {
Integer pid = null;
String id = null;
String[] pids = optionValues.get(openpid);
String[] ids = optionValues.get(openid);
Integer viewIndex = null;
if (pids != null && pids.length>0) {
String pidStr = pids[0];
int idx = pidStr.indexOf('@'); // NOI18N
if (idx > -1) {
try {
viewIndex = Integer.valueOf(pidStr.substring(idx + 1));
} catch (NumberFormatException e) {
throw new CommandException(0, NbBundle.getMessage(Open.class,"MSG_VIEWIDX_FAILED",new Object[] {e.toString()})); // NOI18N
}
pidStr = pidStr.substring(0, idx);
}
try {
pid = Integer.valueOf(pidStr);
} catch (NumberFormatException e) {
throw new CommandException(0, NbBundle.getMessage(Open.class,"MSG_PID_FAILED",new Object[] {e.toString()})); // NOI18N
}
}
if (ids != null && ids.length>0) {
String idStr = ids[0];
int idx = idStr.indexOf('@'); // NOI18N
if (idx > -1) {
try {
viewIndex = Integer.valueOf(idStr.substring(idx + 1));
} catch (NumberFormatException e) {
throw new CommandException(0, NbBundle.getMessage(Open.class,"MSG_VIEWIDX_FAILED",new Object[] {e.toString()})); // NOI18N
}
idStr = idStr.substring(0, idx);
}
id = "-D"+ID+"="+idStr; // NOI18N
}
DataSourceContainer container = Host.LOCALHOST.getRepository();
Set<Application> apps = container.getDataSources(Application.class);
if (openApplication(id, pid, viewIndex, apps)) {
return;
}
Listener l = new Listener(id, pid, viewIndex, container);
container.addDataChangeListener(l,Application.class);
}
private boolean openApplication(final String id, final Integer pid, final Integer viewIndex, final Set<Application> apps) {
for (Application app : apps) {
if (pid != null && app.getPid() == pid.intValue()) {
int index = viewIndex != null ? viewIndex.intValue() - 1 : 0;
DataSourceWindowManager.sharedInstance().openDataSource(app, true, index);
return true;
}
if (id != null) {
Jvm jvm = JvmFactory.getJVMFor(app);
if (jvm.isBasicInfoSupported()) {
String args = jvm.getJvmArgs();
if (args != null && args.contains(id)) {
int index = viewIndex != null ? viewIndex.intValue() - 1 : 0;
DataSourceWindowManager.sharedInstance().openDataSource(app, true, index);
return true;
}
}
}
}
return false;
}
private class Listener implements DataChangeListener<Application>, ActionListener {
private final Integer pid;
private final String id;
private final Integer viewIndex;
private final DataSourceContainer container;
private volatile boolean removed;
private final Timer timer;
private Listener(String i,Integer p,Integer x,DataSourceContainer c) {
id = i;
pid = p;
viewIndex = x;
container = c;
timer = new Timer(TIMEOUT,this);
timer.start();
}
public synchronized void dataChanged(DataChangeEvent<Application> event) {
Set<Application> added = event.getAdded();
if (openApplication(id,pid,viewIndex,added)) {
if (!removed) {
container.removeDataChangeListener(this);
removed = true;
timer.stop();
}
}
}
public synchronized void actionPerformed(ActionEvent e) {
if (!removed) {
container.removeDataChangeListener(this);
removed = true;
String msg = ""; // NOI18N
if (pid != null) {
msg = NbBundle.getMessage(Open.class,"MSG_NO_APP_PID",new Object[] {Integer.toString(pid)}); // NOI18N
}
if (id != null) {
msg = NbBundle.getMessage(Open.class,"MSG_NO_APP_ID"); // NOI18N
}
NotifyDescriptor desc = new NotifyDescriptor.Message(msg,NotifyDescriptor.WARNING_MESSAGE);
DialogDisplayer.getDefault().notifyLater(desc);
}
}
}
}