usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/AppLoginHistory.java
changeset 598 90e364205db8
child 599 cb942db607b7
equal deleted inserted replaced
597:150dd4e7a4ae 598:90e364205db8
       
     1 /*
       
     2  * CDDL HEADER START
       
     3  *
       
     4  * The contents of this file are subject to the terms of the
       
     5  * Common Development and Distribution License (the "License").
       
     6  * You may not use this file except in compliance with the License.
       
     7  *
       
     8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
     9  * or http://www.opensolaris.org/os/licensing.
       
    10  * See the License for the specific language governing permissions
       
    11  * and limitations under the License.
       
    12  *
       
    13  * When distributing Covered Code, include this CDDL HEADER in each
       
    14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
    15  * If applicable, add the following below this CDDL HEADER, with the
       
    16  * fields enclosed by brackets "[]" replaced with your own identifying
       
    17  * information: Portions Copyright [yyyy] [name of copyright owner]
       
    18  *
       
    19  * CDDL HEADER END
       
    20  */
       
    21 
       
    22 /*
       
    23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
       
    24  */
       
    25 
       
    26 package org.opensolaris.os.vp.client.swing;
       
    27 
       
    28 import java.beans.*;
       
    29 import java.io.*;
       
    30 import java.net.*;
       
    31 import java.util.*;
       
    32 import java.util.logging.*;
       
    33 import javax.swing.event.*;
       
    34 import org.opensolaris.os.vp.client.common.ConnectionManager;
       
    35 import org.opensolaris.os.vp.panel.common.*;
       
    36 import org.opensolaris.os.vp.util.misc.NetUtil;
       
    37 import org.opensolaris.os.vp.util.swing.event.ChangeListeners;
       
    38 
       
    39 public class AppLoginHistory implements LoginHistory {
       
    40     //
       
    41     // Instance data
       
    42     //
       
    43 
       
    44     // The only instance of this class.
       
    45     private static AppLoginHistory instance = null;
       
    46 
       
    47     // Used to format logins as host:user:role
       
    48     private static final String LOGIN_DELIMITER = ":";
       
    49 
       
    50     // File used to persist login history.
       
    51     private File loginFile = new File(App.VP_USER_DIR, "history");
       
    52 
       
    53     // The size of persisted login history.
       
    54     private static final int LOGINS_SIZE = 5;
       
    55 
       
    56     // Array used to maintain login history.
       
    57     private Stack<LoginInfo> logins = new Stack<LoginInfo>();
       
    58 
       
    59     // ConnectionManager used for logins.
       
    60     private ConnectionManager connManager = null;
       
    61 
       
    62     // login history listeners.
       
    63     private ChangeListeners listeners = new ChangeListeners();
       
    64 
       
    65     // ConnectionManager listener.
       
    66     private ConnectionListListener connListener =
       
    67 	new ConnectionListListener() {
       
    68 	    @Override
       
    69 	    public void connectionRemoved(ConnectionEvent event) {
       
    70 		// Don't clear history when connections are removed.
       
    71 	    }
       
    72 
       
    73 	    @Override
       
    74 	    public void connectionAdded(ConnectionEvent event) {
       
    75 		LoginInfo info = (LoginInfo) event.getConnectionInfo();
       
    76 
       
    77 		if (info != null) {
       
    78 		    // Push to top of stack.
       
    79 		    if (!updateLogin(info)) {
       
    80 			pushLogin(info);
       
    81 			writeLogins();
       
    82 			fireStateChanged();
       
    83 		    }
       
    84 		}
       
    85 	    }
       
    86 	};
       
    87 
       
    88     //
       
    89     // Constructors
       
    90     //
       
    91 
       
    92     // There is only one instance of this class.
       
    93     private AppLoginHistory(ConnectionManager connManager) {
       
    94 	this.connManager = connManager;
       
    95 	if (connManager != null) {
       
    96 	    connManager.addConnectionListListener(connListener);
       
    97 	}
       
    98 	readLogins();
       
    99     }
       
   100 
       
   101     //
       
   102     // LoginHistory methods
       
   103     //
       
   104 
       
   105     @Override
       
   106     public void clearLogins() {
       
   107 	logins.clear();
       
   108 	loginFile.delete();
       
   109 	fireStateChanged();
       
   110     }
       
   111 
       
   112     @Override
       
   113     public List<LoginInfo> getLogins() {
       
   114 	return new ArrayList<LoginInfo>(logins);
       
   115     }
       
   116 
       
   117     //
       
   118     // AppLoginHistory methods
       
   119     //
       
   120 
       
   121     /**
       
   122      * Get {@code AppLoginHistory} instance.
       
   123      */
       
   124     public static AppLoginHistory getInstance(ConnectionManager connManager) {
       
   125 	if (instance == null) {
       
   126 	    instance = new AppLoginHistory(connManager);
       
   127 	}
       
   128 	return instance;
       
   129     }
       
   130 
       
   131     /**
       
   132      * Adds a {@code ChangeListener} to be notified upon changes in state.
       
   133      */
       
   134     public void addChangeListener(ChangeListener listener) {
       
   135 	listeners.add(listener);
       
   136     }
       
   137 
       
   138     /**
       
   139      * Removes a {@code ChangeListener} from notification.
       
   140      */
       
   141     public void removeChangeListener(ChangeListener listener) {
       
   142 	listeners.remove(listener);
       
   143     }
       
   144 
       
   145     //
       
   146     // Private methods
       
   147     //
       
   148 
       
   149     // Fire property change event.
       
   150     private void fireStateChanged() {
       
   151 	listeners.stateChanged(new ChangeEvent(this));
       
   152     }
       
   153 
       
   154     // Push logins to top of stack.
       
   155     private void pushLogin(LoginInfo info) {
       
   156 	logins.push(info);
       
   157 	if (logins.size() > LOGINS_SIZE) {
       
   158 	    logins.remove(0);
       
   159 	}
       
   160     }
       
   161 
       
   162     // Update existing login. Returns true if a match was found.
       
   163     private boolean updateLogin(LoginInfo info) {
       
   164 	boolean match = false;
       
   165 	for (int i = 0; i < logins.size(); i++) {
       
   166 	    LoginInfo oldInfo = logins.elementAt(i);
       
   167 
       
   168 	    // Don't display dup localhost for matching host name.
       
   169 	    if (oldInfo.matches(info)) {
       
   170 		match = true;
       
   171 	    } else if (NetUtil.isLoopbackAddress(info.getHost())) {
       
   172 		// localhost given as host.
       
   173 		if (oldInfo.matches(NetUtil.getHostName(), info.getUser(),
       
   174 			info.getRole())) {
       
   175 		    match = true;
       
   176 		}
       
   177 	    } else if (NetUtil.isLoopbackAddress(oldInfo.getHost())) {
       
   178 		// localhost found in stack.
       
   179 		if (info.matches(NetUtil.getHostName(), oldInfo.getUser(),
       
   180 			oldInfo.getRole())) {
       
   181 		    match = true;
       
   182 		}
       
   183 	    }
       
   184 
       
   185 	    // Replace login info created from history file.
       
   186 	    if (match) {
       
   187 		logins.setElementAt(info, i);
       
   188 		break;
       
   189 	    }
       
   190 	}
       
   191 	return match;
       
   192     }
       
   193 
       
   194     // Read persistent login history.
       
   195     private void readLogins() {
       
   196 	// Ensure file exists.
       
   197 	if (!loginFile.canRead()) {
       
   198 	    String message = "Cannot read login history: " +
       
   199 		loginFile.getAbsolutePath();
       
   200 	    Logger.getLogger(getClass().getName()).log(
       
   201 		Level.WARNING, message);
       
   202 	    return;
       
   203 	}
       
   204 
       
   205 	try {
       
   206 	    BufferedReader reader = new BufferedReader(
       
   207 		new FileReader(loginFile));
       
   208 
       
   209 	    int i = 0;
       
   210 	    String line = null;
       
   211 
       
   212 	    // Read login history
       
   213 	    while ((line = reader.readLine()) != null
       
   214 		    && i < LOGINS_SIZE) {
       
   215 		StringTokenizer st = new StringTokenizer(line, LOGIN_DELIMITER);
       
   216 
       
   217 		// Login history formated as host:user:role
       
   218 		String host = null;
       
   219 		if (st.hasMoreTokens()) {
       
   220 		    host = st.nextToken();
       
   221 		}
       
   222 		String user = null;
       
   223 		if (st.hasMoreTokens()) {
       
   224 		    user = st.nextToken();
       
   225 		}
       
   226 		String role = null;
       
   227 		if (st.hasMoreTokens()) {
       
   228 		    role = st.nextToken();
       
   229 		}
       
   230 
       
   231 		// Populate logins history.
       
   232 		if (host != null && host.length() > 0
       
   233 			&& user != null && user.length() > 0) {
       
   234 		    ConnectionInfo info = new ConnectionInfo(
       
   235 			host, user, role, null);
       
   236 		    if (!updateLogin(info)) {
       
   237 			pushLogin(info);
       
   238 		    }
       
   239 		}
       
   240 	    }
       
   241 	    reader.close();
       
   242 	} catch (IOException e) {
       
   243 	    String message = "Cannot obtain login history";
       
   244 	    Logger.getLogger(getClass().getName()).log(
       
   245 		Level.WARNING, message, e);
       
   246 	}
       
   247     }
       
   248 
       
   249     // Write persistent login history.
       
   250     private void writeLogins() {
       
   251 	File loginDir = loginFile.getParentFile();
       
   252 
       
   253 	// Ensure directory exists.
       
   254 	if (!loginDir.exists()) {
       
   255 	    if (!loginDir.mkdirs()) {
       
   256 		String message = "Cannot create login history directory: " +
       
   257 		    loginDir.getAbsolutePath();
       
   258 		Logger.getLogger(getClass().getName()).log(
       
   259 		    Level.WARNING, message);
       
   260 		return;
       
   261 	    }
       
   262 	}
       
   263 
       
   264 	try {
       
   265 	    // Write new file.
       
   266 	    File tmpFile = File.createTempFile(loginFile.getName(), ".tmp",
       
   267 		loginDir);
       
   268 	    BufferedWriter writer = new BufferedWriter(new FileWriter(tmpFile));
       
   269 
       
   270 	    // Format logins as host:user:role
       
   271 	    for (LoginInfo info : logins) {
       
   272 		if (info.getRole() != null && info.getRole().length() > 0) {
       
   273 		    writer.write(info.getHost() + LOGIN_DELIMITER +
       
   274 			info.getUser() + LOGIN_DELIMITER + info.getRole());
       
   275 		} else {
       
   276 		    writer.write(info.getHost() + LOGIN_DELIMITER +
       
   277 			info.getUser());
       
   278 		}
       
   279 		writer.newLine();
       
   280 	    }
       
   281 	    tmpFile.renameTo(loginFile);
       
   282 	    writer.close();
       
   283 	} catch (IOException e) {
       
   284 	    String message = "Cannot persist login history";
       
   285 	    Logger.getLogger(getClass().getName()).log(
       
   286 		Level.WARNING, message, e);
       
   287 	}
       
   288     }
       
   289 }