usr/src/java/vpanels/client/org/opensolaris/os/vp/client/common/LoginHistoryManager.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/vpanels/client/org/opensolaris/os/vp/client/common/LoginHistoryManager.java Mon Nov 22 10:50:58 2010 -0500
@@ -0,0 +1,269 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+package org.opensolaris.os.vp.client.common;
+
+import java.beans.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.util.logging.*;
+import javax.swing.event.*;
+import org.opensolaris.os.vp.client.common.ConnectionManager;
+import org.opensolaris.os.vp.panel.common.*;
+import org.opensolaris.os.vp.util.misc.NetUtil;
+import org.opensolaris.os.vp.util.swing.event.ChangeListeners;
+
+public class LoginHistoryManager implements LoginHistory {
+ //
+ // Instance data
+ //
+
+ // Used to format logins as host:user:role
+ private static final String LOGIN_DELIMITER = ":";
+
+ // File used to persist login history.
+ private File loginFile;
+
+ // The size of persisted login history.
+ // Note: Current login not displayed.
+ private static final int LOGINS_SIZE = 6;
+
+ // Array used to maintain login history.
+ private Stack<LoginInfo> logins = new Stack<LoginInfo>();
+
+ // ConnectionManager used for logins.
+ private ConnectionManager connManager = null;
+
+ // login history listeners.
+ private ChangeListeners listeners = new ChangeListeners();
+
+ // ConnectionManager listener.
+ private ConnectionListListener connListener =
+ new ConnectionListListener() {
+ @Override
+ public void connectionRemoved(ConnectionEvent event) {
+ // Nothing to do here.
+ }
+
+ @Override
+ public void connectionAdded(ConnectionEvent event) {
+ connectionChanged(event);
+ }
+
+ @Override
+ public void connectionSelected(ConnectionEvent event) {
+ connectionChanged(event);
+ }
+
+ private void connectionChanged(ConnectionEvent event) {
+ LoginInfo info = (LoginInfo) event.getConnectionInfo();
+ addLogin(info);
+ writeLogins();
+ fireStateChanged();
+ }
+ };
+
+ //
+ // Constructors
+ //
+
+ /**
+ * Create an instance of this class.
+ *
+ * @param connManager The {@code ConnectionManager} associated with logins.
+ * @param loginFile The {@code File} used to persist login history.
+ */
+ public LoginHistoryManager(ConnectionManager connManager, File loginFile) {
+ this.loginFile = loginFile;
+ this.connManager = connManager;
+ connManager.addConnectionListListener(connListener);
+ readLogins();
+ }
+
+ //
+ // LoginHistory methods
+ //
+
+ @Override
+ public void clearLogins() {
+ logins.clear();
+ loginFile.delete();
+ fireStateChanged();
+ }
+
+ @Override
+ public List<LoginInfo> getLogins() {
+ return new ArrayList<LoginInfo>(logins);
+ }
+
+ //
+ // LoginHistoryManager methods
+ //
+
+ /**
+ * Adds a {@code ChangeListener} to be notified upon changes in state.
+ */
+ public void addChangeListener(ChangeListener listener) {
+ listeners.add(listener);
+ }
+
+ /**
+ * Removes a {@code ChangeListener} from notification.
+ */
+ public void removeChangeListener(ChangeListener listener) {
+ listeners.remove(listener);
+ }
+
+ //
+ // Private methods
+ //
+
+ // Add logins in FIFO order.
+ private void addLogin(LoginInfo info) {
+ removeLogin(info);
+ logins.insertElementAt(info, 0);
+ if (logins.size() > LOGINS_SIZE) {
+ logins.remove(LOGINS_SIZE - 1);
+ }
+ }
+
+ // Fire property change event.
+ private void fireStateChanged() {
+ listeners.stateChanged(new ChangeEvent(this));
+ }
+
+ // Push logins in LIFO order.
+ private void pushLogin(LoginInfo info) {
+ removeLogin(info);
+ logins.push(info);
+ if (logins.size() > LOGINS_SIZE) {
+ logins.remove(0);
+ }
+ }
+
+ // Remove existing login.
+ private void removeLogin(LoginInfo info) {
+ for (int i = 0; i < logins.size(); i++) {
+ LoginInfo login = logins.elementAt(i);
+ if (info.matches(login)) {
+ logins.removeElementAt(i);
+ return;
+ }
+ }
+ }
+
+ // Read persistent login history.
+ private void readLogins() {
+ // Ensure file exists.
+ if (loginFile.exists() && !loginFile.canRead()) {
+ String message = "Cannot read login history: " +
+ loginFile.getAbsolutePath();
+ Logger.getLogger(getClass().getName()).log(
+ Level.WARNING, message);
+ return;
+ }
+
+ try {
+ BufferedReader reader = new BufferedReader(
+ new FileReader(loginFile));
+
+ int i = 0;
+ String line = null;
+
+ // Read login history
+ while ((line = reader.readLine()) != null
+ && i < LOGINS_SIZE) {
+ StringTokenizer st = new StringTokenizer(line, LOGIN_DELIMITER);
+
+ // Login history formated as host:user:role
+ String host = null;
+ if (st.hasMoreTokens()) {
+ host = st.nextToken();
+ }
+ String user = null;
+ if (st.hasMoreTokens()) {
+ user = st.nextToken();
+ }
+ String role = null;
+ if (st.hasMoreTokens()) {
+ role = st.nextToken();
+ }
+
+ // Populate logins history.
+ if (host != null && host.length() > 0
+ && user != null && user.length() > 0) {
+ ConnectionInfo info = new ConnectionInfo(
+ host, user, role, null);
+ pushLogin(info);
+ }
+ }
+ reader.close();
+ } catch (IOException e) {
+ String message = "Cannot obtain login history";
+ Logger.getLogger(getClass().getName()).log(
+ Level.WARNING, message, e);
+ }
+ }
+
+ // Write persistent login history.
+ private void writeLogins() {
+ File loginDir = loginFile.getParentFile();
+
+ // Ensure directory exists.
+ if (!loginDir.exists() && !loginDir.mkdirs()) {
+ String message = "Cannot create login history directory: " +
+ loginDir.getAbsolutePath();
+ Logger.getLogger(getClass().getName()).log(
+ Level.WARNING, message);
+ return;
+ }
+
+ try {
+ // Write new file.
+ File tmpFile = File.createTempFile(loginFile.getName(), ".tmp",
+ loginDir);
+ BufferedWriter writer = new BufferedWriter(new FileWriter(tmpFile));
+
+ // Format logins as host:user:role
+ for (LoginInfo login : logins) {
+ if (login.getRole() != null && login.getRole().length() > 0) {
+ writer.write(login.getHost() + LOGIN_DELIMITER +
+ login.getUser() + LOGIN_DELIMITER + login.getRole());
+ } else {
+ writer.write(login.getHost() + LOGIN_DELIMITER +
+ login.getUser());
+ }
+ writer.newLine();
+ }
+ tmpFile.renameTo(loginFile);
+ writer.close();
+ } catch (IOException e) {
+ String message = "Cannot persist login history";
+ Logger.getLogger(getClass().getName()).log(
+ Level.WARNING, message, e);
+ }
+ }
+}