001 package org.hackystat.dailyprojectdata.resource.unittest; 002 003 import static org.hackystat.dailyprojectdata.server.ServerProperties.SENSORBASE_FULLHOST_KEY; 004 005 import java.io.StringWriter; 006 import java.util.logging.Logger; 007 008 import javax.xml.bind.JAXBContext; 009 import javax.xml.bind.Marshaller; 010 import javax.xml.datatype.XMLGregorianCalendar; 011 import javax.xml.parsers.DocumentBuilder; 012 import javax.xml.parsers.DocumentBuilderFactory; 013 import javax.xml.transform.Transformer; 014 import javax.xml.transform.TransformerFactory; 015 import javax.xml.transform.dom.DOMSource; 016 import javax.xml.transform.stream.StreamResult; 017 018 import org.hackystat.dailyprojectdata.resource.dailyprojectdata.DailyProjectDataResource; 019 import org.hackystat.dailyprojectdata.resource.unittest.jaxb.MemberData; 020 import org.hackystat.dailyprojectdata.resource.unittest.jaxb.UnitTestDailyProjectData; 021 import org.hackystat.sensorbase.client.SensorBaseClient; 022 import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorDataIndex; 023 import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorDataRef; 024 import org.hackystat.utilities.tstamp.Tstamp; 025 import org.restlet.Context; 026 import org.restlet.data.MediaType; 027 import org.restlet.data.Request; 028 import org.restlet.data.Response; 029 import org.restlet.resource.Representation; 030 import org.restlet.resource.Variant; 031 import org.w3c.dom.Document; 032 033 /** 034 * Implements the Resource for processing GET {host}/unittest/{user}/{projectname}/{timestamp} 035 * requests. 036 * 037 * Authenticated user must be the uriUser, or Admin, or project member. 038 * 039 * @author Pavel Senin, Philip Johnson 040 */ 041 042 public class UnitTestResource extends DailyProjectDataResource { 043 044 /** 045 * The standard constructor. 046 * 047 * @param context The context. 048 * @param request The request object. 049 * @param response The response object. 050 */ 051 public UnitTestResource(Context context, Request request, Response response) { 052 super(context, request, response); 053 } 054 055 /** 056 * Returns an UnitTestDailyProjectData instance. 057 * 058 * @param variant The representational variant requested. 059 * @return The representation. 060 */ 061 @Override 062 public Representation represent(Variant variant) { 063 Logger logger = this.server.getLogger(); 064 logger.fine("UnitTest DPD: Starting"); 065 if (variant.getMediaType().equals(MediaType.TEXT_XML)) { 066 try { 067 // [1] get the SensorBaseClient for the user making this request. 068 SensorBaseClient client = super.getSensorBaseClient(); 069 // [2] Check the front side cache and return if the DPD is found and is OK to access. 070 String cachedDpd = this.server.getFrontSideCache().get(uriUser, project, uriString); 071 if ((cachedDpd != null) && client.inProject(uriUser, project)) { 072 return super.getStringRepresentation(cachedDpd); 073 } 074 // [2] get a SensorDataIndex of UnitTest sensor data for this Project on the requested day. 075 XMLGregorianCalendar startTime = Tstamp.makeTimestamp(this.timestamp); 076 XMLGregorianCalendar endTime = Tstamp.incrementDays(startTime, 1); 077 logger.fine("UnitTest DPD: Requesting index: " + uriUser + " " + project); 078 SensorDataIndex index = client.getProjectSensorData(uriUser, project, startTime, endTime, 079 "UnitTest"); 080 // [3] Update the counter with this data. 081 logger.fine("UnitTest DPD: Got index. " + index.getSensorDataRef().size() + " instances"); 082 UnitTestCounter counter = new UnitTestCounter(); 083 for (SensorDataRef ref : index.getSensorDataRef()) { 084 counter.add(client.getSensorData(ref)); 085 } 086 logger.fine("UnitTest DPD: Finished retrieving instances. "); 087 088 // return resulting data 089 UnitTestDailyProjectData unitTestDPD = new UnitTestDailyProjectData(); 090 // create the individual MemberData elements. 091 String sensorBaseHost = this.server.getServerProperties().get(SENSORBASE_FULLHOST_KEY); 092 for (String member : counter.getMembers()) { 093 MemberData memberData = new MemberData(); 094 memberData.setMemberUri(sensorBaseHost + "users/" + member); 095 memberData.setSuccess(counter.getPassCount(member)); 096 memberData.setFailure(counter.getFailCount(member)); 097 unitTestDPD.getMemberData().add(memberData); 098 } 099 100 unitTestDPD.setOwner(uriUser); 101 unitTestDPD.setProject(project); 102 unitTestDPD.setStartTime(startTime); 103 unitTestDPD.setUriPattern("**"); // we don't support UriPatterns yet. 104 105 String xmlData = makeUnitTestDPD(unitTestDPD); 106 if (!Tstamp.isTodayOrLater(startTime)) { 107 this.server.getFrontSideCache().put(uriUser, project, uriString, xmlData); 108 } 109 logRequest("UnitTest"); 110 return super.getStringRepresentation(xmlData); 111 112 } 113 catch (Exception e) { 114 setStatusError("Error creating UnitTest DPD.", e); 115 return null; 116 } 117 } 118 return null; 119 } 120 121 /** 122 * Returns the passed UnitTestDPD instance as a String encoding of its XML representation. 123 * 124 * @param data The UnitTestDPD instance. 125 * @return The XML String representation. 126 * @throws Exception If problems occur during translation. 127 */ 128 private String makeUnitTestDPD(UnitTestDailyProjectData data) throws Exception { 129 JAXBContext unitTestJAXB = (JAXBContext) this.server.getContext().getAttributes().get( 130 "UnitTestJAXB"); 131 Marshaller marshaller = unitTestJAXB.createMarshaller(); 132 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 133 dbf.setNamespaceAware(true); 134 DocumentBuilder documentBuilder = dbf.newDocumentBuilder(); 135 Document doc = documentBuilder.newDocument(); 136 marshaller.marshal(data, doc); 137 DOMSource domSource = new DOMSource(doc); 138 StringWriter writer = new StringWriter(); 139 StreamResult result = new StreamResult(writer); 140 TransformerFactory tf = TransformerFactory.newInstance(); 141 Transformer transformer = tf.newTransformer(); 142 transformer.transform(domSource, result); 143 return writer.toString(); 144 } 145 }