/*
* 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.jmx;
import com.sun.tools.visualvm.application.Application;
import com.sun.tools.visualvm.core.datasource.Storage;
import com.sun.tools.visualvm.core.datasupport.Utils;
import java.util.HashMap;
import java.util.Map;
import javax.management.remote.JMXConnector;
/**
* EnvironmentProvider adding the JMXConnector.CREDENTIALS property to the JMX
* environment map.
*
* There are two subclasses of EnvironmentProvider available, typically you want
* to use the EnvironmentProvider.Custom class to provide a custom credentials
* for a JMX connection. The EnvironmentProvider.Persistent class is used for
* handling credentials for persisted connections.
*
* Note that if the credentials provided by this provider are incorrect a dialog
* requesting new credentials will be displayed by the framework. If the
* user-provided credentials are correct they will override the credentials
* defined by this provider. The user-provided credentials are never persisted.
*
* @since VisualVM 1.2
* @author Jiri Sedlacek
*/
public abstract class CredentialsProvider extends EnvironmentProvider {
private static final String PROPERTY_USERNAME = "prop_credentials_username"; // NOI18N
private static final String PROPERTY_PASSWORD = "prop_credentials_password"; // NOI18N
private static Persistent PERSISTENT_PROVIDER;
static synchronized Persistent persistent() {
if (PERSISTENT_PROVIDER == null) PERSISTENT_PROVIDER = new Persistent();
return PERSISTENT_PROVIDER;
}
/**
* Returns an unique String identifying the CredentialsProvider. Must be
* overridden to return a different identificator when subclassing the
* CredentialsProvider.
*
* @return unique String identifying the CredentialsProvider
*/
public String getId() {
return CredentialsProvider.class.getName();
}
abstract String getUsername(Storage storage);
abstract boolean hasPassword(Storage storage);
abstract boolean isPersistent(Storage storage);
/**
* CredentialsProvider to provide custom settings.
*
* @since VisualVM 1.2
* @author Jiri Sedlacek
*/
public static class Custom extends CredentialsProvider {
private final String username;
private final char[] password;
private final boolean persistent;
/**
* Creates new instance of CredentialsProvider.Custom.
*
* @param username username
* @param password password
* @param persistent true if the credentials should be persisted for another VisualVM sessions, false otherwise
*/
public Custom(String username, char[] password, boolean persistent) {
this.username = username;
this.password = encodePassword(password);
this.persistent = persistent;
}
public Map<String, ?> getEnvironment(Application application, Storage storage) {
return createMap(username, password != null ? new String(password) : null);
}
public String getEnvironmentId(Storage storage) {
if (username != null) return username;
return super.getEnvironmentId(storage);
}
public void saveEnvironment(Storage storage) {
if (!persistent) return;
storage.setCustomProperty(PROPERTY_USERNAME, username);
storage.setCustomProperty(PROPERTY_PASSWORD, new String(password));
}
String getUsername(Storage storage) { return username; }
boolean hasPassword(Storage storage) { return password != null &&
password.length > 0; }
boolean isPersistent(Storage storage) { return persistent; }
}
/**
* CredentialsProvider to provide custom settings.
*
* @since VisualVM 1.2
* @author Jiri Sedlacek
*/
public static class Persistent extends CredentialsProvider {
public Map<String, ?> getEnvironment(Application application, Storage storage) {
String username = storage.getCustomProperty(PROPERTY_USERNAME);
String password = storage.getCustomProperty(PROPERTY_PASSWORD);
return createMap(username, password);
}
public String getEnvironmentId(Storage storage) {
if (storage != null) {
String username = storage.getCustomProperty(PROPERTY_USERNAME);
if (username != null) return username;
}
return super.getEnvironmentId(storage);
}
String getUsername(Storage storage) { return storage.getCustomProperty(
PROPERTY_USERNAME); }
boolean hasPassword(Storage storage) {
String password = storage.getCustomProperty(PROPERTY_PASSWORD);
return password != null && password.length() > 0;
}
boolean isPersistent(Storage storage) {
return getUsername(storage) != null || hasPassword(storage);
}
}
// --- Private implementation ----------------------------------------------
private static Map<String, ?> createMap(String username, String password) {
Map map = new HashMap();
if (username != null && !username.isEmpty())
map.put(JMXConnector.CREDENTIALS,
new String[] { username, decodePassword(password) });
return map;
}
private static char[] encodePassword(char[] password) {
if (password == null) return null;
return Utils.encodePassword(new String(password)).toCharArray();
}
private static String decodePassword(String password) {
if (password == null) return null;
return Utils.decodePassword(password);
}
}