usr/src/java/vpanels/client/org/opensolaris/os/vp/client/common/LoginHistoryManager.java
changeset 603 71a20acea802
parent 602 c60ad6a81113
child 605 c5fc1a2832c4
--- /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);
+	}
+    }
+}