package com.perforce.api; import java.io.*; import java.util.*; /* * Copyright (c) 2001, Perforce Software, All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * Representation of a source control user. Each instance can store one p4 * user's information. The class methods can be used to <a * href="#getUser(java.lang.String)">get a particular user</a>. If that user * has been gotten before, their user information will not be reloaded from P4. * It is instead loaded from an internal HashDecay. * <p> * If the user information must be up to date, then the <a href="#sync()">sync()</a> * method must be called. * <p> * TBD: The current implementation does NOT handle the "reviews" information for * each user. Should User extend Mapping? * * @see HashDecay * @author <a href="mailto:david@markley.cc">David Markley</a> * @version $Date: 2002/05/16 $ $Revision: #2 $ */ public final class User extends SourceControlObject { private String id = ""; private String email = ""; private String fullname = ""; private static HashDecay users = null; /** * Default no-argument constructor. */ public User() { super(); getCache(); } /** * Constructor that accepts the id of the user. This simply creates an * instance that has the id set. No other information in the class will be * present until the <a href="#sync()">sync() method is called. * * @param id * Id for the user. */ public User(String id) { this(); this.id = id; } private static HashDecay setCache() { if(null == users) { users = new HashDecay(600000); users.start(); } return users; } public HashDecay getCache() { return setCache(); } /** * Sets the id for this user. * * @param id * Id for the user. */ public void setId(String id) { this.id = id; } /** * Returns an <code>Enumeration</code> of all <code>User</code> objects. */ public static synchronized Enumeration getUsers() { return getUsers(null); } /** * Returns an <code>Enumeration</code> of all <code>User</code> objects. */ public static synchronized Enumeration getUsers(Env env) { String l; User u; String[] cmd = { "p4", "users" }; try { P4Process p = new P4Process(env); p.exec(cmd); while(null != (l = p.readLine())) { if(l.startsWith("#")) { continue; } u = getUser(l); u.setEnv(env); } p.close(); } catch(IOException ex) { } return setCache().elements(); } /** * Gets the user information for the specified user. If that user has been * gotten before, their user information will not be reloaded from P4. It is * instead loaded from an internal HashDecay. * <p> * If the user information must be up to date, then the <a * href="#sync()">sync() method must be called. * * @deprecated Use method with Env parameter. * @param uid * User id that is requested. */ public static synchronized User getUser(String uid) { return getUser(null, uid); } /** * Gets the user information for the specified user. If that user has been * gotten before, their user information will not be reloaded from P4. It is * instead loaded from an internal HashDecay. * <p> * If the user information must be up to date, then the <a * href="#sync()">sync() method must be called. * * @param env * Source control environment to use. * @param uid * The user id of the user information to get from p4. */ public static synchronized User getUser(Env env, String uid) { if(null == uid) { return null; } if(uid.trim().equals("")) { return null; } String tid; int i, left = 0; uid = uid.trim(); if(-1 == (left = uid.indexOf("<"))) { tid = uid; } else { tid = uid.substring(0, left - 1).trim(); } User u = (User) setCache().get(uid); if(null != u) { return u; } else { u = new User(tid); } u.setEmail(tid); u.setFullName(tid); if(-1 != left) { uid = uid.substring(left + 1); char[] ch = uid.toCharArray(); left = 0; for(i = 0; i < ch.length; i++) { switch(ch[i]) { case '>': u.setEmail(new String(ch, left, i - left)); break; case '(': left = i + 1; break; case ')': u.setFullName(new String(ch, left, i - left)); break; } } } u.setEnv(env); users.put(tid, u); return u; } /** * Returns the id for this user. * * @return Id for the user. */ public String getId() { return id; } /** * Sets the e-mail address for this user. * * @param email * Email address for the user. */ public void setEmail(String email) { this.email = email; } /** * Returns the e-mail address for this user. * * @return Email address for the user. */ public String getEmail() { return email; } /** * Sets the full name of this user. * * @param fullname * The full name for the user. */ public void setFullName(String fullname) { this.fullname = fullname; } /** * Returns the full name of this user. * * @return The full name for the user. */ public String getFullName() { return fullname; } /** * TBD: The <code>commit</code> method is not working yet. */ public void commit() { } /** * Synchronizes the user information with P4. This method must be called to * ensure that this contains the latest information from p4. This form of * the method can be used to change the user Id in at the same time. * * @param id * The user id for this to synchronize from p4. */ public void sync(String id) { this.id = id; sync(); } /** * Synchronizes the user information with P4. This method must be called to * ensure that this contains the latest information from p4. */ public void sync() { if(!outOfSync(300000)) return; String l; String[] cmd = { "p4", "user", "-o", "id" }; cmd[3] = id; try { P4Process p = new P4Process(getEnv()); p.exec(cmd); while(null != (l = p.readLine())) { if(l.startsWith("#")) { continue; } if(l.startsWith("User:")) { id = l.substring(6).trim(); } else if(l.startsWith("Email:")) { email = l.substring(7).trim(); } else if(l.startsWith("FullName:")) { fullname = l.substring(10).trim(); } } p.close(); inSync(); } catch(IOException ex) { } } public String toString() { return id; } public String toXML() { StringBuffer sb = new StringBuffer("<user id=\""); sb.append(getId()); sb.append("\" fullname=\""); sb.append(getFullName()); sb.append("\" email=\""); sb.append(getEmail()); sb.append("\"/>"); return sb.toString(); } /** * Used for testing. * * @deprecated Actually in use, but this keeps it out of the docs. */ public static void main(String[] argv) { User u; Env env = new Env(); Debug.setDebugLevel(Debug.NOTICE); env.setUser("robot"); env.setPort("perforce.ma.lycos.com:1666"); Enumeration en = User.getUsers(env); while(en.hasMoreElements()) { u = (User) en.nextElement(); System.out.println("USER: " + u.getId()); } } }