001 package org.hackystat.dailyprojectdata.resource.dailyprojectdata; 002 003 import java.util.Date; 004 import java.util.Map; 005 006 import org.hackystat.dailyprojectdata.server.Server; 007 import org.hackystat.sensorbase.client.SensorBaseClient; 008 import org.restlet.Context; 009 import org.restlet.data.CharacterSet; 010 import org.restlet.data.Language; 011 import org.restlet.data.MediaType; 012 import org.restlet.data.Request; 013 import org.restlet.data.Response; 014 import org.restlet.data.Status; 015 import org.restlet.resource.Representation; 016 import org.restlet.resource.Resource; 017 import org.restlet.resource.StringRepresentation; 018 import org.restlet.resource.Variant; 019 import static 020 org.hackystat.dailyprojectdata.server.Authenticator.AUTHENTICATOR_SENSORBASECLIENTS_KEY; 021 022 /** 023 * An abstract superclass for all DailyProjectData resources that supplies common 024 * initialization processing. 025 * This includes: 026 * <ul> 027 * <li> Extracting the authenticated user identifier (when authentication available) 028 * <li> Extracting the user email from the URI (when available) 029 * <li> Declares that the TEXT/XML representational variant is supported. 030 * </ul> 031 * 032 * @author Philip Johnson 033 * 034 */ 035 public abstract class DailyProjectDataResource extends Resource { 036 037 /** To be retrieved from the URL as the 'email' template parameter, or null. */ 038 protected String uriUser = null; 039 040 /** To be retrieved from the URL as the 'project' template parameter, or null. */ 041 protected String project = null; 042 043 /** To be retrieved from the URL as the 'timestamp' template parameter, or null. */ 044 protected String timestamp = null; 045 046 /** The authenticated user, retrieved from the ChallengeResponse, or null. */ 047 protected String authUser = null; 048 049 /** The server. */ 050 protected Server server; 051 052 /** The standard error message returned from invalid authentication. */ 053 protected String badAuth = "User is not admin and authenticated user does not not match URI user"; 054 055 /** Records the time at which each HTTP request was initiated. */ 056 protected long requestStartTime = new Date().getTime(); 057 058 protected String uriString; 059 060 /** 061 * Provides the following representational variants: TEXT_XML. 062 * @param context The context. 063 * @param request The request object. 064 * @param response The response object. 065 */ 066 public DailyProjectDataResource(Context context, Request request, Response response) { 067 super(context, request, response); 068 if (request.getChallengeResponse() != null) { 069 this.authUser = request.getChallengeResponse().getIdentifier(); 070 } 071 this.server = (Server)getContext().getAttributes().get("DailyProjectDataServer"); 072 this.uriUser = (String) request.getAttributes().get("user"); 073 this.project = (String) request.getAttributes().get("project"); 074 this.timestamp = (String) request.getAttributes().get("timestamp"); 075 this.uriString = this.getRequest().getResourceRef().toString(); 076 getVariants().clear(); // copied from BookmarksResource.java, not sure why needed. 077 getVariants().add(new Variant(MediaType.TEXT_XML)); 078 } 079 080 /** 081 * The Restlet getRepresentation method which must be overridden by all concrete Resources. 082 * @param variant The variant requested. 083 * @return The Representation. 084 */ 085 @Override 086 public abstract Representation represent(Variant variant); 087 088 /** 089 * Creates and returns a new Restlet StringRepresentation built from xmlData. 090 * The xmlData will be prefixed with a processing instruction indicating UTF-8 and version 1.0. 091 * @param xmlData The xml data as a string. 092 * @return A StringRepresentation of that xmldata. 093 */ 094 public StringRepresentation getStringRepresentation(String xmlData) { 095 return new StringRepresentation(xmlData, MediaType.TEXT_XML, Language.ALL, CharacterSet.UTF_8); 096 } 097 098 /** 099 * Returns a SensorBaseClient instance associated with the User in this request. 100 * @return The SensorBaseClient instance. 101 */ 102 @SuppressWarnings("unchecked") 103 public SensorBaseClient getSensorBaseClient() { 104 Map<String, SensorBaseClient> userClientMap = 105 (Map<String, SensorBaseClient>)this.server.getContext() 106 .getAttributes().get(AUTHENTICATOR_SENSORBASECLIENTS_KEY); 107 return userClientMap.get(this.authUser); 108 } 109 110 /** 111 * Generates a log message indicating the type of request, the elapsed time required, 112 * the user who requested the data, and the day. 113 * @param requestType The type of DPD request, such as "Commit", "FileMetric", etc. 114 */ 115 protected void logRequest(String requestType) { 116 logRequest(requestType, ""); 117 } 118 119 /** 120 * Generates a log message indicating the type of request, the elapsed time required, 121 * the user who requested the data, and the day. 122 * @param requestType The type of DPD request, such as "Commit", "FileMetric", etc. 123 * @param optionalParams Any additional parameters to the request. 124 */ 125 protected void logRequest(String requestType, String... optionalParams) { 126 long elapsed = new Date().getTime() - requestStartTime; 127 String sp = " "; 128 StringBuffer msg = new StringBuffer(20); 129 msg.append(elapsed).append(" ms: ").append(requestType).append(sp).append(uriUser).append(sp); 130 msg.append(project).append(sp).append(timestamp); 131 for (String param : optionalParams) { 132 msg.append(sp).append(param); 133 } 134 server.getLogger().info(msg.toString()); 135 } 136 137 /** 138 * Called when an error resulting from an exception is caught during processing. 139 * @param msg A description of the error. 140 * @param e A chained exception. 141 */ 142 protected void setStatusError (String msg, Exception e) { 143 String responseMsg = String.format("%s:%n Request: %s %s%n Caused by: %s", 144 msg, 145 this.getRequest().getMethod().getName(), 146 this.getRequest().getResourceRef().toString(), 147 e.getMessage()); 148 this.getLogger().info(responseMsg); 149 getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST, 150 responseMsg.replace(System.getProperty("line.separator"), " ")); 151 } 152 153 /** 154 * Called when an error resulting from an exception is caught during processing. 155 * @param msg A description of the error. 156 */ 157 protected void setStatusError (String msg) { 158 String responseMsg = String.format("%s:%n Request: %s %s%n", 159 msg, 160 this.getRequest().getMethod().getName(), 161 this.getRequest().getResourceRef().toString()); 162 this.getLogger().info(responseMsg); 163 getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST, 164 responseMsg.replace(System.getProperty("line.separator"), " ")); 165 } 166 167 }