001 package org.hackystat.projectbrowser; 002 003 import java.util.ArrayList; 004 import java.util.Collections; 005 import java.util.Comparator; 006 import java.util.List; 007 import java.util.logging.Logger; 008 009 import org.apache.wicket.PageParameters; 010 import org.apache.wicket.Request; 011 import org.apache.wicket.Session; 012 import org.apache.wicket.protocol.http.WebSession; 013 import org.hackystat.dailyprojectdata.client.DailyProjectDataClient; 014 import org.hackystat.projectbrowser.page.dailyprojectdata.DailyProjectDataSession; 015 import org.hackystat.projectbrowser.page.projectportfolio.ProjectPortfolioSession; 016 import org.hackystat.projectbrowser.page.projects.ProjectsSession; 017 import org.hackystat.projectbrowser.page.sensordata.SensorDataSession; 018 import org.hackystat.projectbrowser.page.telemetry.TelemetrySession; 019 import org.hackystat.projectbrowser.page.trajectory.TrajectorySession; 020 import org.hackystat.sensorbase.client.SensorBaseClient; 021 import org.hackystat.sensorbase.client.SensorBaseClientException; 022 import org.hackystat.sensorbase.resource.projects.jaxb.Project; 023 import org.hackystat.sensorbase.resource.projects.jaxb.ProjectIndex; 024 import org.hackystat.sensorbase.resource.projects.jaxb.ProjectRef; 025 import org.hackystat.telemetry.service.client.TelemetryClient; 026 import org.hackystat.utilities.logger.HackystatLogger; 027 import org.hackystat.utilities.tstamp.Tstamp; 028 029 /** 030 * Provides a session instance that holds authentication credentials. 031 * @author Philip Johnson 032 * 033 */ 034 public class ProjectBrowserSession extends WebSession { 035 /** Support serialization. */ 036 private static final long serialVersionUID = 1L; 037 /** The email used to connect to the SensorBase. */ 038 private String email = null; 039 /** The password for the SensorBase. */ 040 private String password = null; 041 /** The SensorBase client for this user. */ 042 // Need to make this class serializable if we want to keep it in the session and not 043 // make a new one each request. 044 //private SensorBaseClient client = null; 045 /** The current signinFeedback message to display. */ 046 private String signinFeedback = ""; 047 /** The current registerFeedback message to display. */ 048 private String registerFeedback = ""; 049 /** If this user has been authenticated against the Sensorbase during this session. */ 050 private boolean isAuthenticated = false; 051 /** The collection of Projects that this user has. */ 052 //private Map<String, Project> projectMap = null; 053 /** The collection of Projects that this user has. */ 054 private List<Project> projectList = null; 055 /** The analysis list. */ 056 public List<String> analysisList = new ArrayList<String>(); 057 058 /** The separator for parameter values. */ 059 public static final String PARAMETER_VALUE_SEPARATOR = ","; 060 /** The separator between project name and its onwer. */ 061 public static final String PROJECT_NAME_OWNER_SEPARATR = "::"; 062 063 /** The SensorDataSession that holds page state for SensorData page. */ 064 private SensorDataSession sensorDataSession = new SensorDataSession(); 065 /** The DailyProjectDataSession that holds page state for DailyProjectData page. */ 066 private DailyProjectDataSession dailyProjectDataSession = new DailyProjectDataSession(); 067 /** The TelemetrySession that holds page state for Telemetry page. */ 068 private TelemetrySession telemetrySession = new TelemetrySession(); 069 /** ProjectPortfolioSession that holds page state for Project Portfolio page. */ 070 private ProjectPortfolioSession projectPortfolioSession = new ProjectPortfolioSession(); 071 /** ProjectBrowserSession that holds the page state for the Project page. */ 072 private ProjectsSession projectsSession = new ProjectsSession(); 073 /** Trajectory session - holds the page state for the Trajectory page. */ 074 private TrajectorySession trajectorySession = new TrajectorySession(); 075 076 077 /** 078 * Provide a constructor that initializes WebSession. 079 * @param request The request object. 080 */ 081 public ProjectBrowserSession(Request request) { 082 super(request); 083 //analysisList.add("Build"); 084 analysisList.add("Unit Test"); 085 analysisList.add("Coverage"); 086 //analysisList.add("Complexity"); 087 //analysisList.add("Coupling"); 088 } 089 090 /** 091 * Obtain the current session. 092 * @return The current ProjectBrowserSession. 093 */ 094 public static ProjectBrowserSession get() { 095 return (ProjectBrowserSession) Session.get(); 096 } 097 098 /** 099 * Returns true if the user has been authenticated in this session. 100 * @return True if the user has supplied a valid email and password for this sensorbase. 101 */ 102 public boolean isAuthenticated() { 103 return this.isAuthenticated; 104 } 105 106 /** 107 * Used by the Signin form to provide the SensorBase authentication credentials to this session. 108 * @param user The user. 109 * @param password The password. 110 */ 111 public void setCredentials(String user, String password) { 112 this.email = user; 113 this.password = password; 114 } 115 116 /** 117 * Returns the string to be displayed in the SigninFeedback label. 118 * @return A signin feedback string. 119 */ 120 public String getSigninFeedback() { 121 return this.signinFeedback; 122 } 123 124 /** 125 * Allows other components to set the feedback string for the signin form. 126 * @param signinFeedback The message to be displayed. 127 */ 128 public void setSigninFeedback(String signinFeedback) { 129 this.signinFeedback = signinFeedback; 130 } 131 132 /** 133 * Allows other components to set the feedback string for the register form. 134 * @param registerFeedback The message to be displayed. 135 */ 136 public void setRegisterFeedback(String registerFeedback) { 137 this.registerFeedback = registerFeedback; 138 } 139 140 /** 141 * Returns the string to be displayed in the registerFeedback label. 142 * @return A register feedback string. 143 */ 144 public String getRegisterFeedback() { 145 return this.registerFeedback; 146 } 147 148 /** 149 * Returns true if this email/password combination is valid for this sensorbase. 150 * @param email The email. 151 * @param password The password. 152 * @return True if valid for this sensorbase. 153 */ 154 public boolean signin(String email, String password) { 155 try { 156 String host = ((ProjectBrowserApplication)getApplication()).getSensorBaseHost(); 157 int timeout = 1000 * 60 * 60; 158 //HACK! This shouldn't be required! I'm doing it because I get a timeout in SensorData 159 // when trying to retrieve Hackystat data summaries for a month. 160 System.getProperties().setProperty("sensorbaseclient.timeout", String.valueOf(timeout)); 161 SensorBaseClient client = new SensorBaseClient(host, email, password); 162 // Set timeout to 60 minutes. 163 client.setTimeout(timeout); 164 client.authenticate(); 165 this.email = email; 166 this.password = password; 167 this.isAuthenticated = true; 168 return true; 169 } 170 catch (Exception e) { 171 this.isAuthenticated = false; 172 return false; 173 } 174 } 175 176 /** 177 * Returns a SensorBaseClient instance for this user and session. 178 * @return The SensorBaseClient instance. 179 */ 180 public SensorBaseClient getSensorBaseClient() { 181 String host = ((ProjectBrowserApplication)getApplication()).getSensorBaseHost(); 182 return new SensorBaseClient(host, this.email, this.password); 183 } 184 185 /** 186 * Returns a TelemetryClient instance for this user and session. 187 * @return The TelemetryClient instance. 188 */ 189 public TelemetryClient getTelemetryClient() { 190 String host = ((ProjectBrowserApplication)getApplication()).getTelemetryHost(); 191 return new TelemetryClient(host, this.email, this.password); 192 } 193 194 /** 195 * Returns a DailyProjectDataClient instance for this user and session. 196 * @return The DailyProjectDataClient instance. 197 */ 198 public DailyProjectDataClient getDailyProjectDataClient() { 199 String host = ((ProjectBrowserApplication)getApplication()).getDailyProjectDataHost(); 200 return new DailyProjectDataClient(host, this.email, this.password); 201 } 202 203 /** 204 * Gets the user's email associated with this session. 205 * @return The user. 206 */ 207 public String getUserEmail() { 208 return this.email; 209 } 210 211 /** 212 * Returns the list of project names associated with this user. 213 * @return The list of project names. 214 */ 215 /* 216 public List<String> getProjectNames() { 217 List<String> projectNames = new ArrayList<String>(); 218 projectNames.addAll(getProjects().keySet()); 219 Collections.sort(projectNames); 220 return projectNames; 221 } 222 */ 223 224 /** 225 * Return a map of project names to project instances associated with this user. 226 * If the map has not yet been built, get it from the SensorBase and cache it. 227 * @return The map of Project instances. 228 */ 229 /* 230 public Map<String, Project> getProjects() { 231 if (this.projectMap == null) { 232 this.projectMap = new HashMap<String, Project>(); 233 try { 234 SensorBaseClient sensorBaseClient = ProjectBrowserSession.get().getSensorBaseClient(); 235 ProjectIndex projectIndex = sensorBaseClient.getProjectIndex(this.email); 236 Set<String> duplicatedProjectNames = new TreeSet<String>(); 237 for (ProjectRef projectRef : projectIndex.getProjectRef()) { 238 Project project = sensorBaseClient.getProject(projectRef); 239 Project temp = projectMap.put(project.getName(), project); 240 if (temp != null) { 241 duplicatedProjectNames.add(project.getName()); 242 projectMap.put(temp.getName() + " - " + temp.getOwner(), temp); 243 projectMap.put(project.getName() + " - " + project.getOwner(), project); 244 } 245 } 246 for (String duplicatedProjectName : duplicatedProjectNames) { 247 projectMap.remove(duplicatedProjectName); 248 } 249 } 250 catch (SensorBaseClientException e) { 251 Logger logger = ((ProjectBrowserApplication)getApplication()).getLogger(); 252 logger.warning("Error getting projects for " + this.email + StackTrace.toString(e)); 253 } 254 } 255 return this.projectMap; 256 } 257 */ 258 259 /** 260 * Returns a Project instance that available to current user and 261 * is matched to the given project name and project owner. 262 * @param projectName the given project name. 263 * @param projectOwner the given project owner. 264 * @return the Project instance. null if no matching project is found, 265 * which may means either the project name or project owner is null or there is no Project for 266 * this user with the same project name and owner as the given ones. 267 */ 268 public Project getProject(String projectName, String projectOwner) { 269 if (projectName == null) { 270 return null; 271 } 272 for (Project project : getProjectList()) { 273 if (projectName.equals(project.getName()) && 274 (projectOwner == null || projectOwner.equals(project.getOwner()))) { 275 return project; 276 } 277 } 278 return null; 279 } 280 281 282 /** 283 * Returns a single String represents a list of the projects, separated by comma. 284 * @param projects a list of selected projects. 285 * @return a String. 286 */ 287 public static String convertProjectListToString(List<Project> projects) { 288 StringBuffer projectList = new StringBuffer(); 289 for (int i = 0; i < projects.size(); ++i) { 290 Project project = projects.get(i); 291 if (project == null) { 292 continue; 293 } 294 projectList.append(project.getName()); 295 projectList.append(PROJECT_NAME_OWNER_SEPARATR); 296 projectList.append(project.getOwner()); 297 if (i < projects.size() - 1) { 298 projectList.append(PARAMETER_VALUE_SEPARATOR); 299 } 300 } 301 return projectList.toString(); 302 } 303 304 /** 305 * Returns the string that represents the given date in standard formatted. 306 * e.g. 2008-08-08T08:08:08+08:00, 307 * the +08:00 in the end means the time zone of this time stamp is +08:00 308 * @param date the given date 309 * @return a String 310 */ 311 public static String getFormattedDateString(long date) { 312 return Tstamp.makeTimestamp(date).toString(); 313 } 314 315 /** 316 * Return the project associated with the given id. 317 * Id is usually the project name. In case of projects with the same name, the id will become 318 * projectName - projectOwner 319 * @param projectNameId the given id 320 * @return the result project, null if not found. 321 */ 322 /* 323 public Project getProjectByNameId(String projectNameId) { 324 return this.projectMap.get(projectNameId); 325 } 326 */ 327 328 /** 329 * Clear project list. 330 */ 331 public void clearProjectList() { 332 if (this.projectList != null) { 333 this.projectList.clear(); 334 } 335 } 336 337 /** 338 * Returns the list of Projects associated with this user. 339 * @return The list of Projects. 340 */ 341 public List<Project> getProjectList() { 342 if (this.projectList == null || this.projectList.size() <= 0) { 343 projectList = new ArrayList<Project>(); 344 try { 345 SensorBaseClient sensorBaseClient = ProjectBrowserSession.get().getSensorBaseClient(); 346 ProjectIndex projectIndex = sensorBaseClient.getProjectIndex(this.email); 347 for (ProjectRef projectRef : projectIndex.getProjectRef()) { 348 projectList.add(sensorBaseClient.getProject(projectRef)); 349 } 350 Collections.sort(projectList, new Comparator<Project>() { 351 public int compare(final Project project1, final Project project2) { 352 int result = project1.getName().compareTo(project2.getName()); 353 if (result == 0) { 354 result = project1.getOwner().compareTo(project2.getOwner()); 355 } 356 return result; 357 } 358 }); 359 } 360 catch (SensorBaseClientException e) { 361 Logger logger = ((ProjectBrowserApplication)getApplication()).getLogger(); 362 logger.warning("Error getting projects for " + this.email + ": " + e.getMessage()); 363 } 364 } 365 return projectList; 366 } 367 368 369 /** 370 * @return the Default project. 371 */ 372 public Project getDefaultProject() { 373 for (Project project : this.getProjectList()) { 374 if ("Default".equals(project.getName())) { 375 return project; 376 } 377 } 378 return null; 379 } 380 381 /** 382 * Returns the SensorDataSession instance. 383 * @return The session state for the sensor data page. 384 */ 385 public SensorDataSession getSensorDataSession() { 386 return this.sensorDataSession; 387 } 388 389 /** 390 * Returns the DailyProjectDataSession instance. 391 * @return The session state for the daily project data page. 392 */ 393 public DailyProjectDataSession getDailyProjectDataSession() { 394 return this.dailyProjectDataSession; 395 } 396 397 /** 398 * Returns the TelemetrySession instance. 399 * @return The session state for the telemetry page. 400 */ 401 public TelemetrySession getTelemetrySession() { 402 return this.telemetrySession; 403 } 404 405 /** 406 * Returns the ProjectsDataSession instance. 407 * @return The session state for the projects data page. 408 */ 409 public ProjectsSession getProjectsSession() { 410 return this.projectsSession; 411 } 412 413 /** 414 * @return the password 415 */ 416 public String getPassword() { 417 return password; 418 } 419 420 /** 421 * @return the email 422 */ 423 public String getEmail() { 424 return email; 425 } 426 427 /** 428 * @return the projectPortfolioSession 429 */ 430 public ProjectPortfolioSession getProjectPortfolioSession() { 431 return projectPortfolioSession; 432 } 433 434 /** 435 * Log the user usage to special file. 436 * @param log the log message 437 */ 438 public void logUsage(String log) { 439 if (((ProjectBrowserApplication)getApplication()).isLoggingUserUsage()) { 440 Logger logger = 441 HackystatLogger.getLogger("org.hackystat.projectbrowser.usage", "projectbrowser"); 442 logger.info("[" + email + "]" + " " + log); 443 } 444 } 445 446 /** 447 * Print the indexed page parameters in format of /parameter0/parameter1/.../. 448 * @param parameters the indexed page parameter 449 * @return the result string. 450 */ 451 public String printPageParameters(PageParameters parameters) { 452 StringBuffer paramString = new StringBuffer(); 453 int i = 0; 454 boolean end = false; 455 while (!end) { 456 String key = String.valueOf(i); 457 if (parameters.containsKey(key)) { 458 paramString.append('/'); 459 paramString.append(parameters.get(key).toString()); 460 ++i; 461 } 462 else { 463 end = true; 464 } 465 } 466 return paramString.toString(); 467 } 468 469 /** 470 * @return the logger that associated to this web application. 471 */ 472 public Logger getLogger() { 473 return ((ProjectBrowserApplication)ProjectBrowserApplication.get()).getLogger(); 474 } 475 476 /** 477 * Returns the TrajectorySession instance. 478 * @return The session state for the trajectory page. 479 */ 480 public TrajectorySession getTrajectorySession() { 481 return this.trajectorySession; 482 } 483 }