001 package org.hackystat.dailyprojectdata.client; 002 003 import java.io.StringReader; 004 import java.util.Date; 005 import java.util.logging.Logger; 006 007 import javax.xml.bind.JAXBContext; 008 import javax.xml.bind.JAXBException; 009 import javax.xml.bind.Unmarshaller; 010 import javax.xml.datatype.XMLGregorianCalendar; 011 012 import org.hackystat.dailyprojectdata.resource.build.jaxb.BuildDailyProjectData; 013 import org.hackystat.dailyprojectdata.resource.codeissue.jaxb.CodeIssueDailyProjectData; 014 import org.hackystat.dailyprojectdata.resource.commit.jaxb.CommitDailyProjectData; 015 import org.hackystat.dailyprojectdata.resource.complexity.jaxb.ComplexityDailyProjectData; 016 import org.hackystat.dailyprojectdata.resource.coupling.jaxb.CouplingDailyProjectData; 017 import org.hackystat.dailyprojectdata.resource.coverage.jaxb.CoverageDailyProjectData; 018 import org.hackystat.dailyprojectdata.resource.devtime.jaxb.DevTimeDailyProjectData; 019 import org.hackystat.dailyprojectdata.resource.filemetric.jaxb.FileMetricDailyProjectData; 020 import org.hackystat.dailyprojectdata.resource.issue.jaxb.IssueDailyProjectData; 021 import org.hackystat.dailyprojectdata.resource.issuechange.jaxb.IssueChangeDailyProjectData; 022 import org.hackystat.dailyprojectdata.resource.unittest.jaxb.UnitTestDailyProjectData; 023 import org.hackystat.utilities.logger.HackystatLogger; 024 import org.hackystat.utilities.tstamp.Tstamp; 025 import org.hackystat.utilities.uricache.UriCache; 026 import org.restlet.Client; 027 import org.restlet.data.ChallengeResponse; 028 import org.restlet.data.ChallengeScheme; 029 import org.restlet.data.MediaType; 030 import org.restlet.data.Method; 031 import org.restlet.data.Preference; 032 import org.restlet.data.Protocol; 033 import org.restlet.data.Reference; 034 import org.restlet.data.Request; 035 import org.restlet.data.Response; 036 import org.restlet.data.Status; 037 import org.restlet.resource.Representation; 038 039 /** 040 * Provides a client to support access to the DailyProjectData service. 041 * 042 * @author Philip Johnson 043 */ 044 public class DailyProjectDataClient { 045 046 /** Holds the userEmail to be associated with this client. */ 047 private String userEmail; 048 /** Holds the password to be associated with this client. */ 049 private String password; 050 /** 051 * The DailyProjectData host, such as "http://localhost:9877/dailyprojectdata". 052 */ 053 private String dailyProjectDataHost; 054 /** The Restlet Client instance used to communicate with the server. */ 055 private Client client; 056 /** DevTime JAXBContext. */ 057 private JAXBContext devTimeJAXB; 058 /** FileMetric JAXBContext. */ 059 private JAXBContext fileMetricJAXB; 060 /** UnitTest JAXBContext. */ 061 private JAXBContext unitTestJAXB; 062 /** CodeIssue JAXBContext. */ 063 private JAXBContext codeIssueJAXB; 064 /** CodeIssue JAXBContext. */ 065 private JAXBContext coverageJAXB; 066 /** Commit JAXBContext. */ 067 private JAXBContext commitJAXB; 068 /** Build JAXB Context. */ 069 private JAXBContext buildJAXB; 070 /** Complexity JAXB Context. */ 071 private JAXBContext complexityJAXB; 072 /** Coupling JAXB Context. */ 073 private JAXBContext couplingJAXB; 074 /** Issue JAXB Context. */ 075 private JAXBContext issueJAXB; 076 /** IssueChange JAXB Context. */ 077 private JAXBContext issuechangeJAXB; 078 /** The http authentication approach. */ 079 private ChallengeScheme scheme = ChallengeScheme.HTTP_BASIC; 080 /** The preferred representation type. */ 081 private Preference<MediaType> xmlMedia = new Preference<MediaType>(MediaType.TEXT_XML); 082 /** To facilitate debugging of problems using this system. */ 083 private boolean isTraceEnabled = false; 084 /** For logging. */ 085 private Logger logger; 086 /** The System property key used to retrieve the default timeout value in milliseconds. */ 087 public static final String DAILYPROJECTDATACLIENT_TIMEOUT_KEY = "dailyprojectdataclient.timeout"; 088 089 090 /** An associated UriCache to improve responsiveness. */ 091 private UriCache uriCache; 092 093 /** Indicates whether or not cache is enabled. */ 094 private boolean isCacheEnabled = false; 095 096 /** 097 * Initializes a new DailyProjectDataClient, given the host, userEmail, and password. Note that 098 * the userEmail and password refer to the underlying SensorBase client associated with this 099 * DailyProjectData service. This service does not keep its own independent set of userEmails and 100 * passwords. Authentication is not actually performed in this constructor. Use the authenticate() 101 * method to explicitly check the authentication credentials. 102 * 103 * @param host The host, such as 'http://localhost:9877/dailyprojectdata'. 104 * @param email The user's email used for authentication. 105 * @param password The password used for authentication. 106 */ 107 public DailyProjectDataClient(String host, String email, String password) { 108 this.logger = HackystatLogger.getLogger( 109 "org.hackystat.dailyprojectdata.client.DailyProjectDataClient", "dailyprojectdata", false); 110 this.logger.info("Instantiating client for: " + host + " " + email); 111 validateArg(host); 112 validateArg(email); 113 validateArg(password); 114 this.userEmail = email; 115 this.password = password; 116 this.dailyProjectDataHost = host; 117 if (!this.dailyProjectDataHost.endsWith("/")) { 118 this.dailyProjectDataHost = this.dailyProjectDataHost + "/"; 119 } 120 if (this.isTraceEnabled) { 121 System.out.println("DailyProjectDataClient Tracing: INITIALIZE " + "host='" + host 122 + "', email='" + email + "', password='" + password + "'"); 123 } 124 this.client = new Client(Protocol.HTTP); 125 setTimeoutFromSystemProperty(); 126 try { 127 this.devTimeJAXB = JAXBContext 128 .newInstance(org.hackystat.dailyprojectdata.resource.devtime.jaxb.ObjectFactory.class); 129 this.unitTestJAXB = JAXBContext 130 .newInstance(org.hackystat.dailyprojectdata.resource.unittest.jaxb.ObjectFactory.class); 131 this.fileMetricJAXB = JAXBContext 132 .newInstance(org.hackystat.dailyprojectdata.resource.filemetric.jaxb.ObjectFactory.class); 133 this.codeIssueJAXB = JAXBContext 134 .newInstance(org.hackystat.dailyprojectdata.resource.codeissue.jaxb.ObjectFactory.class); 135 this.coverageJAXB = JAXBContext 136 .newInstance(org.hackystat.dailyprojectdata.resource.coverage.jaxb.ObjectFactory.class); 137 this.buildJAXB = JAXBContext 138 .newInstance(org.hackystat.dailyprojectdata.resource.build.jaxb.ObjectFactory.class); 139 this.commitJAXB = JAXBContext 140 .newInstance(org.hackystat.dailyprojectdata.resource.commit.jaxb.ObjectFactory.class); 141 this.complexityJAXB = JAXBContext 142 .newInstance(org.hackystat.dailyprojectdata.resource.complexity.jaxb.ObjectFactory.class); 143 this.couplingJAXB = JAXBContext 144 .newInstance(org.hackystat.dailyprojectdata.resource.coupling.jaxb.ObjectFactory.class); 145 this.issueJAXB = JAXBContext 146 .newInstance(org.hackystat.dailyprojectdata.resource.issue.jaxb.ObjectFactory.class); 147 this.issuechangeJAXB = JAXBContext 148 .newInstance(org.hackystat.dailyprojectdata.resource.issuechange.jaxb.ObjectFactory.class); 149 } 150 catch (Exception e) { 151 throw new RuntimeException("Couldn't create JAXB context instances.", e); 152 } 153 } 154 155 /** 156 * Throws an unchecked illegal argument exception if the arg is null or empty. 157 * 158 * @param arg The String that must be non-null and non-empty. 159 */ 160 private void validateArg(String arg) { 161 if ((arg == null) || ("".equals(arg))) { 162 throw new IllegalArgumentException(arg + " cannot be null or the empty string."); 163 } 164 } 165 166 /** 167 * Sets the timeout value for this client. 168 * 169 * @param milliseconds The number of milliseconds to wait before timing out. 170 */ 171 public final synchronized void setTimeout(int milliseconds) { 172 client.getContext().getParameters().removeAll("connectTimeout"); 173 client.getContext().getParameters().add("connectTimeout", String.valueOf(milliseconds)); 174 // For the Apache Commons client. 175 client.getContext().getParameters().removeAll("readTimeout"); 176 client.getContext().getParameters().add("readTimeout", String.valueOf(milliseconds)); 177 client.getContext().getParameters().removeAll("connectionManagerTimeout"); 178 client.getContext().getParameters().add("connectionManagerTimeout", 179 String.valueOf(milliseconds)); 180 } 181 182 /** 183 * Sets the timeout for this client if the system property 184 * dailyprojectdataclient.timeout is set 185 * and if it can be parsed to an integer. 186 */ 187 private void setTimeoutFromSystemProperty() { 188 String systemTimeout = System.getProperty(DAILYPROJECTDATACLIENT_TIMEOUT_KEY); 189 // if not set, then return immediately. 190 if (systemTimeout == null) { 191 return; 192 } 193 // systemTimeout has a value, so set it if we can. 194 try { 195 int timeout = Integer.parseInt(systemTimeout); 196 setTimeout(timeout); 197 this.logger.info("DdpClient timeout set to: " + timeout + " milliseconds"); 198 } 199 catch (Exception e) { 200 this.logger.warning("dailyprojectdataclient.timeout has non integer value: " + systemTimeout); 201 } 202 } 203 204 /** 205 * Does the housekeeping for making HTTP requests to the SensorBase by a test or admin user. 206 * 207 * @param method The type of Method. 208 * @param requestString A string, such as "users". No preceding slash. 209 * @param entity The representation to be sent with the request, or null if not needed. 210 * @return The Response instance returned from the server. 211 */ 212 private Response makeRequest(Method method, String requestString, Representation entity) { 213 Reference reference = new Reference(this.dailyProjectDataHost + requestString); 214 Request request = (entity == null) ? new Request(method, reference) : new Request(method, 215 reference, entity); 216 request.getClientInfo().getAcceptedMediaTypes().add(xmlMedia); 217 ChallengeResponse authentication = new ChallengeResponse(scheme, this.userEmail, this.password); 218 request.setChallengeResponse(authentication); 219 if (this.isTraceEnabled) { 220 System.out.println("DailyProjectDataClient Tracing: " + method + " " + reference); 221 if (entity != null) { 222 try { 223 System.out.println(entity.getText()); 224 } 225 catch (Exception e) { 226 System.out.println(" Problems with getText() on entity."); 227 } 228 } 229 } 230 Response response = this.client.handle(request); 231 if (this.isTraceEnabled) { 232 Status status = response.getStatus(); 233 System.out.println(" => " + status.getCode() + " " + status.getDescription()); 234 } 235 return response; 236 } 237 238 /** 239 * Takes a String encoding of a DevTimeDailyProjectData in XML format and converts it. 240 * 241 * @param xmlString The XML string representing a DevTimeDailyProjectData. 242 * @return The corresponding DevTimeDailyProjectData instance. 243 * @throws Exception If problems occur during unmarshalling. 244 */ 245 private DevTimeDailyProjectData makeDevTimeDailyProjectData(String xmlString) throws Exception { 246 Unmarshaller unmarshaller = this.devTimeJAXB.createUnmarshaller(); 247 return (DevTimeDailyProjectData) unmarshaller.unmarshal(new StringReader(xmlString)); 248 } 249 250 /** 251 * Authenticates this user and password with this DailyProjectData service, throwing a 252 * DailyProjectDataException if the user and password associated with this instance are not valid 253 * credentials. Note that authentication is performed by checking these credentials with the 254 * SensorBase; this service does not keep its own independent set of usernames and passwords. 255 * 256 * @return This DailyProjectDataClient instance. 257 * @throws DailyProjectDataClientException If authentication is not successful. 258 */ 259 public synchronized DailyProjectDataClient authenticate() throws DailyProjectDataClientException { 260 // Performs authentication by invoking ping with user and password as form 261 // params. 262 String uri = "ping?user=" + this.userEmail + "&password=" + this.password; 263 Response response = makeRequest(Method.GET, uri, null); 264 if (!response.getStatus().isSuccess()) { 265 throw new DailyProjectDataClientException(response.getStatus()); 266 } 267 String responseString; 268 try { 269 responseString = response.getEntity().getText(); 270 } 271 catch (Exception e) { 272 throw new DailyProjectDataClientException("Bad response", e); 273 } 274 if (!"DailyProjectData authenticated".equals(responseString)) { 275 throw new DailyProjectDataClientException("Authentication failed"); 276 } 277 return this; 278 } 279 280 /** 281 * Returns a DevTimeDailyProjectData instance from this server, or throws a DailyProjectData 282 * exception if problems occurred. 283 * 284 * @param user The user that owns the project. 285 * @param project The project owned by user. 286 * @param timestamp The Timestamp indicating the start of the 24 hour period of DevTime. 287 * @return A DevTimeDailyProjectData instance. 288 * @throws DailyProjectDataClientException If the credentials associated with this instance are 289 * not valid, or if the underlying SensorBase service cannot be reached, or if one or more 290 * of the supplied user, password, or timestamp is not valid. 291 */ 292 public synchronized DevTimeDailyProjectData getDevTime(String user, String project, 293 XMLGregorianCalendar timestamp) throws DailyProjectDataClientException { 294 Date startTime = new Date(); 295 DevTimeDailyProjectData devTime; 296 String uri = "devtime/" + user + "/" + project + "/" + timestamp; 297 // Check the cache, and return the instance from it if available. 298 if (this.isCacheEnabled) { 299 devTime = (DevTimeDailyProjectData) this.uriCache.getFromGroup(uri, user + project); 300 if (devTime != null) { 301 return devTime; 302 } 303 } 304 // Otherwise get it from the DPD service. 305 Response response = makeRequest(Method.GET, uri, null); 306 if (!response.getStatus().isSuccess()) { 307 throw new DailyProjectDataClientException(response.getStatus()); 308 } 309 try { 310 String xmlData = response.getEntity().getText(); 311 devTime = makeDevTimeDailyProjectData(xmlData); 312 // Add it to the cache if we're using one. 313 if (this.isCacheEnabled && !Tstamp.isTodayOrLater(timestamp)) { 314 this.uriCache.putInGroup(uri, user + project, devTime); 315 } 316 } 317 catch (Exception e) { 318 logElapsedTime(uri, startTime, e); 319 throw new DailyProjectDataClientException(response.getStatus(), e); 320 } 321 logElapsedTime(uri, startTime); 322 return devTime; 323 } 324 325 /** 326 * Returns a UnitTestDailyProjectData instance from this server, or throws a DailyProjectData 327 * exception if problems occurred. 328 * 329 * @param user The user that owns the project. 330 * @param project The project owned by user. 331 * @param timestamp The Timestamp indicating the start of the 24 hour period of DevTime. 332 * @return A DevTimeDailyProjectData instance. 333 * @throws DailyProjectDataClientException If the credentials associated with this instance are 334 * not valid, or if the underlying SensorBase service cannot be reached, or if one or more 335 * of the supplied user, password, or timestamp is not valid. 336 */ 337 public synchronized UnitTestDailyProjectData getUnitTest(String user, String project, 338 XMLGregorianCalendar timestamp) throws DailyProjectDataClientException { 339 Date startTime = new Date(); 340 String uri = "unittest/" + user + "/" + project + "/" + timestamp; 341 UnitTestDailyProjectData unitDPD; 342 // Check the cache, and return the instance from it if available. 343 if (this.isCacheEnabled) { 344 unitDPD = (UnitTestDailyProjectData) this.uriCache.getFromGroup(uri, user + project); 345 if (unitDPD != null) { 346 return unitDPD; 347 } 348 } 349 Response response = makeRequest(Method.GET, uri, null); 350 if (!response.getStatus().isSuccess()) { 351 throw new DailyProjectDataClientException(response.getStatus()); 352 } 353 try { 354 String xmlData = response.getEntity().getText(); 355 unitDPD = makeUnitTestDailyProjectData(xmlData); 356 // Add it to the cache if we're using one. 357 if (this.isCacheEnabled && !Tstamp.isTodayOrLater(timestamp)) { 358 this.uriCache.putInGroup(uri, user + project, unitDPD); 359 } 360 } 361 catch (Exception e) { 362 logElapsedTime(uri, startTime, e); 363 throw new DailyProjectDataClientException(response.getStatus(), e); 364 } 365 logElapsedTime(uri, startTime); 366 return unitDPD; 367 } 368 369 /** 370 * Takes a String encoding of a UnitTestDailyProjectData in XML format and converts it. 371 * 372 * @param xmlString The XML string representing a UnitTestDailyProjectData. 373 * @return The corresponding UnitTestDailyProjectData instance. 374 * @throws Exception If problems occur during unmarshalling. 375 */ 376 private UnitTestDailyProjectData makeUnitTestDailyProjectData(String xmlString) throws Exception { 377 Unmarshaller unmarshaller = this.unitTestJAXB.createUnmarshaller(); 378 return (UnitTestDailyProjectData) unmarshaller.unmarshal(new StringReader(xmlString)); 379 } 380 381 /** 382 * Returns true if the passed host is a DailyProjectData host. 383 * 384 * @param host The URL of a DailyProjectData host, "http://localhost:9876/dailyprojectdata". 385 * @return True if this URL responds as a DailyProjectData host. 386 */ 387 public static boolean isHost(String host) { 388 // All sensorbase hosts use the HTTP protocol. 389 if (!host.startsWith("http://")) { 390 return false; 391 } 392 // Create the host/register URL. 393 try { 394 String registerUri = host.endsWith("/") ? host + "ping" : host + "/ping"; 395 Request request = new Request(); 396 request.setResourceRef(registerUri); 397 request.setMethod(Method.GET); 398 Client client = new Client(Protocol.HTTP); 399 Response response = client.handle(request); 400 String pingText = response.getEntity().getText(); 401 return (response.getStatus().isSuccess() && "DailyProjectData".equals(pingText)); 402 } 403 catch (Exception e) { 404 return false; 405 } 406 } 407 408 /** 409 * Returns a FileMetricDailyProjectData instance from this server, or throws a DailyProjectData 410 * exception if problems occurred. 411 * 412 * @param user The user that owns the project. 413 * @param project The project owned by user. 414 * @param timestamp The Timestamp indicating the start of the 24 hour period of DevTime. 415 * @param sizeMetric The size metric to be retrieved. 416 * @return A FileMetricDailyProjectData instance. 417 * @throws DailyProjectDataClientException If the credentials associated with this instance are 418 * not valid, or if the underlying SensorBase service cannot be reached, or if one or more 419 * of the supplied user, password, or timestamp is not valid. 420 */ 421 public synchronized FileMetricDailyProjectData getFileMetric(String user, String project, 422 XMLGregorianCalendar timestamp, String sizeMetric) throws DailyProjectDataClientException { 423 return getFileMetric(user, project, timestamp, sizeMetric, null); 424 } 425 426 /** 427 * Returns a FileMetricDailyProjectData instance from this server, or throws a DailyProjectData 428 * exception if problems occurred. 429 * 430 * @param user The user that owns the project. 431 * @param project The project owned by user. 432 * @param timestamp The Timestamp indicating the start of the 24 hour period of DevTime. 433 * @param sizeMetric The size metric to be retrieved. 434 * @param tool The tool whose data is to be retrieved, or null for no tool. 435 * @return A FileMetricDailyProjectData instance. 436 * @throws DailyProjectDataClientException If the credentials associated with this instance are 437 * not valid, or if the underlying SensorBase service cannot be reached, or if one or more 438 * of the supplied user, password, or timestamp is not valid. 439 */ 440 public synchronized FileMetricDailyProjectData getFileMetric(String user, String project, 441 XMLGregorianCalendar timestamp, String sizeMetric, String tool) 442 throws DailyProjectDataClientException { 443 Date startTime = new Date(); 444 FileMetricDailyProjectData fileMetric; 445 String param = (tool == null) ? "" : "?Tool=" + tool; 446 String uri = "filemetric/" + user + "/" + project + "/" + timestamp + "/" + sizeMetric + param; 447 // Check the cache, and return the instance from it if available. 448 if (this.isCacheEnabled) { 449 fileMetric = (FileMetricDailyProjectData) this.uriCache.getFromGroup(uri, user + project); 450 if (fileMetric != null) { 451 return fileMetric; 452 } 453 } 454 Response response = makeRequest(Method.GET, uri, null); 455 if (!response.getStatus().isSuccess()) { 456 System.err.println("filemetric/" + user + "/" + project + "/" + timestamp + "/" + sizeMetric); 457 throw new DailyProjectDataClientException(response.getStatus()); 458 } 459 try { 460 String xmlData = response.getEntity().getText(); 461 fileMetric = makeFileMetricDailyProjectData(xmlData); 462 // Add it to the cache if we're using one. 463 if (this.isCacheEnabled && !Tstamp.isTodayOrLater(timestamp)) { 464 this.uriCache.putInGroup(uri, user + project, fileMetric); 465 } 466 } 467 catch (Exception e) { 468 logElapsedTime(uri, startTime, e); 469 throw new DailyProjectDataClientException(response.getStatus(), e); 470 } 471 logElapsedTime(uri, startTime); 472 return fileMetric; 473 } 474 475 /** 476 * Returns a ComplexityDailyProjectData instance from this server, or throws a DailyProjectData 477 * exception if problems occurred. 478 * 479 * @param user The user that owns the project. 480 * @param project The project owned by user. 481 * @param timestamp The Timestamp indicating the start of the 24 hour period of DevTime. 482 * @param type The type of complexity, such as "Cyclometric". 483 * @param tool The tool that provided the complexity data, such as "JavaNCSS". 484 * @return A ComplexityDailyProjectData instance. 485 * @throws DailyProjectDataClientException If the credentials associated with this instance are 486 * not valid, or if the underlying SensorBase service cannot be reached, or if one or more 487 * of the supplied user, password, or timestamp is not valid. 488 */ 489 public synchronized ComplexityDailyProjectData getComplexity(String user, String project, 490 XMLGregorianCalendar timestamp, String type, String tool) 491 throws DailyProjectDataClientException { 492 Date startTime = new Date(); 493 ComplexityDailyProjectData complexity; 494 String uri = "complexity/" + user + "/" + project + "/" + timestamp + "/" + type + "?Tool=" 495 + tool; 496 // Check the cache, and return the instance from it if available. 497 if (this.isCacheEnabled) { 498 complexity = (ComplexityDailyProjectData) this.uriCache.getFromGroup(uri, user + project); 499 if (complexity != null) { 500 return complexity; 501 } 502 } 503 Response response = makeRequest(Method.GET, uri, null); 504 if (!response.getStatus().isSuccess()) { 505 System.err.println("complexity/" + user + "/" + project + "/" + timestamp + "/" + type); 506 throw new DailyProjectDataClientException(response.getStatus()); 507 } 508 try { 509 String xmlData = response.getEntity().getText(); 510 complexity = makeComplexityDailyProjectData(xmlData); 511 // Add it to the cache if we're using one. 512 if (this.isCacheEnabled && !Tstamp.isTodayOrLater(timestamp)) { 513 this.uriCache.putInGroup(uri, user + project, complexity); 514 } 515 } 516 catch (Exception e) { 517 logElapsedTime(uri, startTime, e); 518 throw new DailyProjectDataClientException(response.getStatus(), e); 519 } 520 logElapsedTime(uri, startTime); 521 return complexity; 522 } 523 524 /** 525 * Returns a CouplingDailyProjectData instance from this server, or throws a DailyProjectData 526 * exception if problems occurred. 527 * 528 * @param user The user that owns the project. 529 * @param project The project owned by user. 530 * @param timestamp The Timestamp indicating the start of the 24 hour period of DevTime. 531 * @param type The type of coupling, such as "class". 532 * @param tool The tool that provided the coupling data, such as "DependencyFinder". 533 * @return A CouplingDailyProjectData instance. 534 * @throws DailyProjectDataClientException If the credentials associated with this instance are 535 * not valid, or if the underlying SensorBase service cannot be reached, or if one or more 536 * of the supplied user, password, or timestamp is not valid. 537 */ 538 public synchronized CouplingDailyProjectData getCoupling(String user, String project, 539 XMLGregorianCalendar timestamp, String type, String tool) 540 throws DailyProjectDataClientException { 541 Date startTime = new Date(); 542 CouplingDailyProjectData coupling; 543 String uri = "coupling/" + user + "/" + project + "/" + timestamp + "/" + type + "?Tool=" 544 + tool; 545 // Check the cache, and return the instance from it if available. 546 if (this.isCacheEnabled) { 547 coupling = (CouplingDailyProjectData) this.uriCache.getFromGroup(uri, user + project); 548 if (coupling != null) { 549 return coupling; 550 } 551 } 552 Response response = makeRequest(Method.GET, uri, null); 553 if (!response.getStatus().isSuccess()) { 554 System.err.println("coupling/" + user + "/" + project + "/" + timestamp + "/" + type); 555 throw new DailyProjectDataClientException(response.getStatus()); 556 } 557 try { 558 String xmlData = response.getEntity().getText(); 559 coupling = makeCouplingDailyProjectData(xmlData); 560 // Add it to the cache if we're using one. 561 if (this.isCacheEnabled && !Tstamp.isTodayOrLater(timestamp)) { 562 this.uriCache.putInGroup(uri, user + project, coupling); 563 } 564 } 565 catch (Exception e) { 566 logElapsedTime(uri, startTime, e); 567 throw new DailyProjectDataClientException(response.getStatus(), e); 568 } 569 logElapsedTime(uri, startTime); 570 return coupling; 571 } 572 573 /** 574 * Takes a String encoding of a FileMetricDailyProjectData in XML format and converts it. 575 * 576 * @param xmlString The XML string representing a DevTimeDailyProjectData. 577 * @return The corresponding DevTimeDailyProjectData instance. 578 * @throws Exception If problems occur during unmarshalling. 579 */ 580 private FileMetricDailyProjectData makeFileMetricDailyProjectData(String xmlString) 581 throws Exception { 582 Unmarshaller unmarshaller = this.fileMetricJAXB.createUnmarshaller(); 583 return (FileMetricDailyProjectData) unmarshaller.unmarshal(new StringReader(xmlString)); 584 } 585 586 /** 587 * Takes a String encoding of a ComplexityDailyProjectData in XML format and converts it. 588 * 589 * @param xmlString The XML string representing a ComplexityDailyProjectData. 590 * @return The corresponding ComplexityDailyProjectData instance. 591 * @throws Exception If problems occur during unmarshalling. 592 */ 593 private ComplexityDailyProjectData makeComplexityDailyProjectData(String xmlString) 594 throws Exception { 595 Unmarshaller unmarshaller = this.complexityJAXB.createUnmarshaller(); 596 return (ComplexityDailyProjectData) unmarshaller.unmarshal(new StringReader(xmlString)); 597 } 598 599 /** 600 * Takes a String encoding of a CouplingDailyProjectData in XML format and converts it. 601 * 602 * @param xmlString The XML string representing a CouplingDailyProjectData. 603 * @return The corresponding CouplingDailyProjectData instance. 604 * @throws Exception If problems occur during unmarshalling. 605 */ 606 private CouplingDailyProjectData makeCouplingDailyProjectData(String xmlString) throws Exception { 607 Unmarshaller unmarshaller = this.couplingJAXB.createUnmarshaller(); 608 return (CouplingDailyProjectData) unmarshaller.unmarshal(new StringReader(xmlString)); 609 } 610 611 /** 612 * Returns a CodeIssueDailyProjectData instance from this server, or throws a DailyProjectData 613 * exception if problems occurred. 614 * 615 * @param user The user that owns the project. 616 * @param project The project owned by user. 617 * @param timestamp The Timestamp indicating the start of the 24 hour period of CodeIssue data. 618 * @param tool An optional tool for matching CodeIssue data. 619 * @param type An optional type for matching CodeIssue types. 620 * @return A CodeIssueDailyProjectData instance. 621 * @throws DailyProjectDataClientException If the credentials associated with this instance are 622 * not valid, or if the underlying SensorBase service cannot be reached, or if one or more 623 * of the supplied user, password, or timestamp is not valid. 624 */ 625 public synchronized CodeIssueDailyProjectData getCodeIssue(String user, String project, 626 XMLGregorianCalendar timestamp, String tool, String type) 627 throws DailyProjectDataClientException { 628 CodeIssueDailyProjectData codeIssue; 629 Date startTime = new Date(); 630 StringBuilder requestStringBuilder = new StringBuilder("codeissue/"); 631 requestStringBuilder.append(user); 632 requestStringBuilder.append("/"); 633 requestStringBuilder.append(project); 634 requestStringBuilder.append("/"); 635 requestStringBuilder.append(timestamp); 636 637 boolean questionMarkAppended = false; 638 if (tool != null) { 639 requestStringBuilder.append("?"); 640 requestStringBuilder.append("Tool="); 641 requestStringBuilder.append(tool); 642 questionMarkAppended = true; 643 } 644 if (type != null) { 645 if (questionMarkAppended) { 646 requestStringBuilder.append("&"); 647 } 648 else { 649 requestStringBuilder.append("?"); 650 } 651 requestStringBuilder.append("Type="); 652 requestStringBuilder.append(type); 653 } 654 String uri = requestStringBuilder.toString(); 655 // Check the cache, and return the instance from it if available. 656 if (this.isCacheEnabled) { 657 codeIssue = (CodeIssueDailyProjectData) this.uriCache.getFromGroup(uri, user + project); 658 if (codeIssue != null) { 659 return codeIssue; 660 } 661 } 662 Response response = makeRequest(Method.GET, uri, null); 663 664 if (!response.getStatus().isSuccess()) { 665 logElapsedTime(uri, startTime); 666 throw new DailyProjectDataClientException(response.getStatus()); 667 } 668 try { 669 String xmlData = response.getEntity().getText(); 670 codeIssue = makeCodeIssueDailyProjectData(xmlData); 671 // Add it to the cache if we're using one. 672 if (this.isCacheEnabled && !Tstamp.isTodayOrLater(timestamp)) { 673 this.uriCache.putInGroup(uri, user + project, codeIssue); 674 } 675 } 676 catch (Exception e) { 677 logElapsedTime(uri, startTime, e); 678 throw new DailyProjectDataClientException(response.getStatus(), e); 679 } 680 logElapsedTime(uri, startTime); 681 return codeIssue; 682 } 683 684 /** 685 * Returns a CoverageDailyProjectData instance from this server, or throws a DailyProjectData 686 * exception if problems occurred. 687 * 688 * @param user The user that owns the project. 689 * @param project The project owned by user. 690 * @param timestamp The Timestamp indicating the start of the 24 hour period of CodeIssue data. 691 * @param granularity the granularity of the coverage data. 692 * @return A CoverageDailyProjectData instance. 693 * @throws DailyProjectDataClientException If the credentials associated with this instance are 694 * not valid, or if the underlying SensorBase service cannot be reached, or if one or more 695 * of the supplied user, password, or timestamp is not valid. 696 */ 697 public synchronized CoverageDailyProjectData getCoverage(String user, String project, 698 XMLGregorianCalendar timestamp, String granularity) throws DailyProjectDataClientException { 699 Date startTime = new Date(); 700 StringBuilder requestStringBuilder = new StringBuilder("coverage/"); 701 requestStringBuilder.append(user); 702 requestStringBuilder.append("/"); 703 requestStringBuilder.append(project); 704 requestStringBuilder.append("/"); 705 requestStringBuilder.append(timestamp); 706 707 if (granularity != null) { 708 requestStringBuilder.append("/"); 709 requestStringBuilder.append(granularity); 710 } 711 712 String uri = requestStringBuilder.toString(); 713 CoverageDailyProjectData coverage; 714 // Check the cache, and return the instance from it if available. 715 if (this.isCacheEnabled) { 716 coverage = (CoverageDailyProjectData) this.uriCache.getFromGroup(uri, user + project); 717 if (coverage != null) { 718 return coverage; 719 } 720 } 721 Response response = makeRequest(Method.GET, uri, null); 722 723 if (!response.getStatus().isSuccess()) { 724 logElapsedTime(uri, startTime); 725 throw new DailyProjectDataClientException(response.getStatus()); 726 } 727 try { 728 String xmlData = response.getEntity().getText(); 729 coverage = makeCoverageDailyProjectData(xmlData); 730 // Add it to the cache if we're using one. 731 if (this.isCacheEnabled && !Tstamp.isTodayOrLater(timestamp)) { 732 this.uriCache.putInGroup(uri, user + project, coverage); 733 } 734 } 735 catch (Exception e) { 736 logElapsedTime(uri, startTime, e); 737 throw new DailyProjectDataClientException(response.getStatus(), e); 738 } 739 logElapsedTime(uri, startTime); 740 return coverage; 741 } 742 743 /** 744 * Takes a String encoding of a CoverageDailyProjectData in XML format and converts it. 745 * 746 * @param xmlString The XML string representing a CoverageDailyProjectData. 747 * @return The corresponding CoverageDailyProjectData instance. 748 * @throws Exception If problems occur during unmarshalling. 749 */ 750 private CoverageDailyProjectData makeCoverageDailyProjectData(String xmlString) throws Exception { 751 Unmarshaller unmarshaller = this.coverageJAXB.createUnmarshaller(); 752 return (CoverageDailyProjectData) unmarshaller.unmarshal(new StringReader(xmlString)); 753 } 754 755 /** 756 * Returns a CommitDailyProjectData instance from this server, or throws a DailyProjectData 757 * exception if problems occurred. 758 * 759 * @param user The user that owns the project. 760 * @param project The project owned by user. 761 * @param timestamp The Timestamp indicating the start of the 24 hour period of CodeIssue data. 762 * @return A CommitDailyProjectData instance. 763 * @throws DailyProjectDataClientException If the credentials associated with this instance are 764 * not valid, or if the underlying SensorBase service cannot be reached, or if one or more 765 * of the supplied user, password, or timestamp is not valid. 766 */ 767 public synchronized CommitDailyProjectData getCommit(String user, String project, 768 XMLGregorianCalendar timestamp) throws DailyProjectDataClientException { 769 Date startTime = new Date(); 770 StringBuilder requestStringBuilder = new StringBuilder("commit/"); 771 requestStringBuilder.append(user); 772 requestStringBuilder.append("/"); 773 requestStringBuilder.append(project); 774 requestStringBuilder.append("/"); 775 requestStringBuilder.append(timestamp); 776 777 String uri = requestStringBuilder.toString(); 778 CommitDailyProjectData commit; 779 // Check the cache, and return the instance from it if available. 780 if (this.isCacheEnabled) { 781 commit = (CommitDailyProjectData) this.uriCache.getFromGroup(uri, user + project); 782 if (commit != null) { 783 return commit; 784 } 785 } 786 Response response = makeRequest(Method.GET, uri, null); 787 788 if (!response.getStatus().isSuccess()) { 789 logElapsedTime(uri, startTime); 790 throw new DailyProjectDataClientException(response.getStatus()); 791 } 792 try { 793 String xmlData = response.getEntity().getText(); 794 commit = makeCommitDailyProjectData(xmlData); 795 // Add it to the cache if we're using one. 796 // Since CM sensors typically run on yesterday's data, don't cache unless 2 days or older. 797 if (this.isCacheEnabled && !Tstamp.isYesterdayOrLater(timestamp)) { 798 this.uriCache.putInGroup(uri, user + project, commit); 799 } 800 } 801 catch (Exception e) { 802 logElapsedTime(uri, startTime, e); 803 throw new DailyProjectDataClientException(response.getStatus(), e); 804 } 805 logElapsedTime(uri, startTime); 806 return commit; 807 } 808 809 /** 810 * Takes a String encoding of a CommitDailyProjectData in XML format and converts it. 811 * 812 * @param xmlString The XML string representing a CommitDailyProjectData. 813 * @return The corresponding CommitsDailyProjectData instance. 814 * @throws Exception If problems occur during unmarshalling. 815 */ 816 private CommitDailyProjectData makeCommitDailyProjectData(String xmlString) throws Exception { 817 Unmarshaller unmarshaller = this.commitJAXB.createUnmarshaller(); 818 return (CommitDailyProjectData) unmarshaller.unmarshal(new StringReader(xmlString)); 819 } 820 821 /** 822 * Takes a String encoding of a CodeIssueDailyProjectData in XML format and converts it. 823 * 824 * @param xmlString The XML string representing a CodeIssueDailyProjectData. 825 * @return The corresponding CodeIssueDailyProjectData instance. 826 * @throws Exception If problems occur during unmarshalling. 827 */ 828 private CodeIssueDailyProjectData makeCodeIssueDailyProjectData(String xmlString) 829 throws Exception { 830 Unmarshaller unmarshaller = this.codeIssueJAXB.createUnmarshaller(); 831 return (CodeIssueDailyProjectData) unmarshaller.unmarshal(new StringReader(xmlString)); 832 } 833 834 /** 835 * Returns a BuildDailyProjectData instance from this server, or throws a DailyProjectData 836 * exception if problems occurred. 837 * 838 * @param user The user that owns the project. 839 * @param project The project owned by user. 840 * @param timestamp The Timestamp indicating the start of the 24 hour period of build data. 841 * @param type The type of build to retrieve data for. 842 * @return A BuildDailyProjectData instance. 843 * @throws DailyProjectDataClientException If the credentials associated with this instance are 844 * not valid, or if the underlying SensorBase service cannot be reached, or if one or more 845 * of the supplied user, password, or timestamp is not valid. 846 */ 847 public synchronized BuildDailyProjectData getBuild(String user, String project, 848 XMLGregorianCalendar timestamp, String type) throws DailyProjectDataClientException { 849 Date startTime = new Date(); 850 851 StringBuilder requestStringBuilder = new StringBuilder("build/"); 852 requestStringBuilder.append(user); 853 requestStringBuilder.append("/"); 854 requestStringBuilder.append(project); 855 requestStringBuilder.append("/"); 856 requestStringBuilder.append(timestamp); 857 858 if (type != null) { 859 requestStringBuilder.append("?"); 860 requestStringBuilder.append("Type="); 861 requestStringBuilder.append(type); 862 } 863 864 BuildDailyProjectData build; 865 String uri = requestStringBuilder.toString(); 866 // Check the cache, and return the instance from it if available. 867 if (this.isCacheEnabled) { 868 build = (BuildDailyProjectData) this.uriCache.getFromGroup(uri, user + project); 869 if (build != null) { 870 return build; 871 } 872 } 873 Response response = makeRequest(Method.GET, uri, null); 874 875 if (!response.getStatus().isSuccess()) { 876 logElapsedTime(uri, startTime); 877 throw new DailyProjectDataClientException(response.getStatus()); 878 } 879 try { 880 String xmlData = response.getEntity().getText(); 881 build = makeBuildDailyProjectData(xmlData); 882 // Add it to the cache if we're using one. 883 if (this.isCacheEnabled && !Tstamp.isTodayOrLater(timestamp)) { 884 this.uriCache.putInGroup(uri, user + project, build); 885 } 886 } 887 catch (Exception e) { 888 logElapsedTime(uri, startTime, e); 889 throw new DailyProjectDataClientException(response.getStatus(), e); 890 } 891 logElapsedTime(uri, startTime); 892 return build; 893 } 894 895 /** 896 * Returns a BuildDailyProjectData instance from this server, or throws a DailyProjectData 897 * exception if problems occurred. 898 * 899 * @param user The user that owns the project. 900 * @param project The project owned by user. 901 * @param timestamp The Timestamp indicating the start of the 24 hour period of build data. 902 * @return A BuildDailyProjectData instance. 903 * @throws DailyProjectDataClientException If the credentials associated with this instance are 904 * not valid, or if the underlying SensorBase service cannot be reached, or if one or more 905 * of the supplied user, password, or timestamp is not valid. 906 */ 907 public synchronized BuildDailyProjectData getBuild(String user, String project, 908 XMLGregorianCalendar timestamp) throws DailyProjectDataClientException { 909 return getBuild(user, project, timestamp, null); 910 } 911 912 /** 913 * Takes a String encoding of a BuildDailyProjectData in XML format and converts it. 914 * 915 * @param xmlString The XML string representing a DevTimeDailyProjectData. 916 * @return The corresponding BuildDailyProjectData instance. 917 * @throws Exception If problems occur during unmarshalling. 918 */ 919 private BuildDailyProjectData makeBuildDailyProjectData(String xmlString) throws Exception { 920 Unmarshaller unmarshaller = this.buildJAXB.createUnmarshaller(); 921 return (BuildDailyProjectData) unmarshaller.unmarshal(new StringReader(xmlString)); 922 } 923 924 /** 925 * Returns a IssueDailyProjectData instance from this server, or throws a DailyProjectData 926 * exception if problems occurred. 927 * @param user The user that owns the project. 928 * @param project The project owned by user. 929 * @param timestamp The Timestamp indicating the start of the 24 hour period of build data. 930 * @param status The status of the issue, open or closed, 931 * or a specified status such as "Accepted" or "Fixed" 932 * @return A IssueDailyProjectData instance. 933 * @throws DailyProjectDataClientException If the credentials associated with this instance are 934 * not valid, or if the underlying SensorBase service cannot be reached, or if one or more 935 * of the supplied user, password, or timestamp is not valid. 936 */ 937 public synchronized IssueDailyProjectData getIssue(String user, String project, 938 XMLGregorianCalendar timestamp, String status) throws DailyProjectDataClientException { 939 Date startTime = new Date(); 940 941 StringBuilder requestStringBuilder = new StringBuilder("issue/"); 942 requestStringBuilder.append(user); 943 requestStringBuilder.append("/"); 944 requestStringBuilder.append(project); 945 requestStringBuilder.append("/"); 946 requestStringBuilder.append(timestamp); 947 948 if (status != null) { 949 requestStringBuilder.append("?"); 950 requestStringBuilder.append("Status="); 951 requestStringBuilder.append(status); 952 } 953 954 IssueDailyProjectData issue; 955 String uri = requestStringBuilder.toString(); 956 // Check the cache, and return the instance from it if available. 957 if (this.isCacheEnabled) { 958 issue = (IssueDailyProjectData) this.uriCache.getFromGroup(uri, user + project); 959 if (issue != null) { 960 return issue; 961 } 962 } 963 Response response = makeRequest(Method.GET, uri, null); 964 965 if (!response.getStatus().isSuccess()) { 966 logElapsedTime(uri, startTime); 967 throw new DailyProjectDataClientException(response.getStatus()); 968 } 969 try { 970 String xmlData = response.getEntity().getText(); 971 issue = makeIssueDailyProjectData(xmlData); 972 // Add it to the cache if we're using one. 973 if (this.isCacheEnabled && !Tstamp.isTodayOrLater(timestamp)) { 974 this.uriCache.putInGroup(uri, user + project, issue); 975 } 976 } 977 catch (Exception e) { 978 logElapsedTime(uri, startTime, e); 979 throw new DailyProjectDataClientException(response.getStatus(), e); 980 } 981 logElapsedTime(uri, startTime); 982 return issue; 983 } 984 /** 985 * Returns a IssueDailyProjectData instance from this server, or throws a DailyProjectData 986 * exception if problems occurred. 987 * @param user The user that owns the project. 988 * @param project The project owned by user. 989 * @param timestamp The Timestamp indicating the start of the 24 hour period of build data. 990 * @return A IssueDailyProjectData instance. 991 * @throws DailyProjectDataClientException If the credentials associated with this instance are 992 * not valid, or if the underlying SensorBase service cannot be reached, or if one or more 993 * of the supplied user, password, or timestamp is not valid. 994 */ 995 public synchronized IssueDailyProjectData getIssue(String user, String project, 996 XMLGregorianCalendar timestamp) throws DailyProjectDataClientException { 997 return getIssue(user, project, timestamp, null); 998 } 999 /** 1000 * Takes a String encoding of a IssueDailyProjectData in XML format and converts it. 1001 * 1002 * @param xmlData The XML string representing a DevTimeDailyProjectData. 1003 * @return The corresponding IssueDailyProjectData instance. 1004 * @throws JAXBException If problems occur during unmarshalling. 1005 */ 1006 private IssueDailyProjectData makeIssueDailyProjectData(String xmlData) throws JAXBException { 1007 Unmarshaller unmarshaller = this.issueJAXB.createUnmarshaller(); 1008 return (IssueDailyProjectData) unmarshaller.unmarshal(new StringReader(xmlData)); 1009 } 1010 1011 1012 /** 1013 * Returns a IssueDailyProjectData instance from this server, or throws a DailyProjectData 1014 * exception if problems occurred. 1015 * @param user The user that owns the project. 1016 * @param project The project owned by user. 1017 * @param timestamp The Timestamp indicating the start of the 24 hour period of build data. 1018 * @return A IssueDailyProjectData instance. 1019 * @throws DailyProjectDataClientException If the credentials associated with this instance are 1020 * not valid, or if the underlying SensorBase service cannot be reached, or if one or more 1021 * of the supplied user, password, or timestamp is not valid. 1022 */ 1023 public synchronized IssueChangeDailyProjectData getIssueChange(String user, String project, 1024 XMLGregorianCalendar timestamp) throws DailyProjectDataClientException { 1025 Date startTime = new Date(); 1026 1027 StringBuilder requestStringBuilder = new StringBuilder("issuechange/"); 1028 requestStringBuilder.append(user); 1029 requestStringBuilder.append("/"); 1030 requestStringBuilder.append(project); 1031 requestStringBuilder.append("/"); 1032 requestStringBuilder.append(timestamp); 1033 1034 IssueChangeDailyProjectData issue; 1035 String uri = requestStringBuilder.toString(); 1036 // Check the cache, and return the instance from it if available. 1037 if (this.isCacheEnabled) { 1038 issue = (IssueChangeDailyProjectData) this.uriCache.getFromGroup(uri, user + project); 1039 } 1040 Response response = makeRequest(Method.GET, uri, null); 1041 1042 if (!response.getStatus().isSuccess()) { 1043 logElapsedTime(uri, startTime); 1044 throw new DailyProjectDataClientException(response.getStatus()); 1045 } 1046 try { 1047 String xmlData = response.getEntity().getText(); 1048 issue = makeIssueChangeDailyProjectData(xmlData); 1049 // Add it to the cache if we're using one. 1050 if (this.isCacheEnabled && !Tstamp.isTodayOrLater(timestamp)) { 1051 this.uriCache.putInGroup(uri, user + project, issue); 1052 } 1053 } 1054 catch (Exception e) { 1055 logElapsedTime(uri, startTime, e); 1056 throw new DailyProjectDataClientException(response.getStatus(), e); 1057 } 1058 logElapsedTime(uri, startTime); 1059 return issue; 1060 } 1061 1062 /** 1063 * Takes a String encoding of a IssueDailyProjectData in XML format and converts it. 1064 * 1065 * @param xmlData The XML string representing a DevTimeDailyProjectData. 1066 * @return The corresponding IssueDailyProjectData instance. 1067 * @throws JAXBException If problems occur during unmarshalling. 1068 */ 1069 private IssueChangeDailyProjectData makeIssueChangeDailyProjectData(String xmlData) 1070 throws JAXBException { 1071 Unmarshaller unmarshaller = this.issuechangeJAXB.createUnmarshaller(); 1072 return (IssueChangeDailyProjectData) unmarshaller.unmarshal(new StringReader(xmlData)); 1073 } 1074 1075 /** 1076 * Logs info to the logger about the elapsed time for this request. 1077 * 1078 * @param uri The URI requested. 1079 * @param startTime The startTime of the call. 1080 * @param e The exception thrown, or null if no exception. 1081 */ 1082 private void logElapsedTime(String uri, Date startTime, Exception e) { 1083 long millis = (new Date()).getTime() - startTime.getTime(); 1084 String msg = millis + " millis: " + uri + ((e == null) ? "" : " " + e); 1085 this.logger.info(msg); 1086 } 1087 1088 /** 1089 * Logs info to the logger about the elapsed time for this request. 1090 * 1091 * @param uri The URI requested. 1092 * @param startTime The startTime of the call. 1093 */ 1094 private void logElapsedTime(String uri, Date startTime) { 1095 logElapsedTime(uri, startTime, null); 1096 } 1097 1098 /** 1099 * Enables caching in this client. We do not cache DPDs for the current day, since not all data 1100 * might be have been sent yet. 1101 * 1102 * @param cacheName The name of the cache. 1103 * @param subDir The subdirectory in which the cache backend store is saved. 1104 * @param maxLife The default expiration time for cached objects in days. 1105 * @param capacity The maximum number of instances to be held in-memory. 1106 */ 1107 public synchronized void enableCaching(String cacheName, String subDir, Double maxLife, 1108 Long capacity) { 1109 this.uriCache = new UriCache(cacheName, subDir, maxLife, capacity); 1110 this.isCacheEnabled = true; 1111 } 1112 1113 /** 1114 * Delete all entries from the local cache of DailyProjectData instances associated with this 1115 * DailyProjectDataClient instance. All DPD-specific caches are cleared. If this DPDClient 1116 * instance does not have caching enabled, then this method has no effect. 1117 */ 1118 public synchronized void clearLocalCache() { 1119 if (this.uriCache != null) { 1120 this.uriCache.clearAll(); 1121 } 1122 } 1123 1124 /** 1125 * Delete all cache entries associated with the specified project and its owner. 1126 * If this DPDClient does not have caching enabled, then this has no effect. 1127 * 1128 * @param user The user. 1129 * @param project The project. 1130 */ 1131 public synchronized void clearLocalCache(String user, String project) { 1132 if (this.uriCache != null) { 1133 this.uriCache.clearGroup(user + project); 1134 } 1135 } 1136 1137 /** 1138 * Returns the number of cached entries for the given project and its owner. 1139 * If this DPDClient does not have caching enabled, then returns 0. 1140 * 1141 * @param user The owner of this project. 1142 * @param project The project. 1143 * @return The number of entries in the cache for that project. 1144 */ 1145 public synchronized int localCacheSize(String user, String project) { 1146 int size = 0; 1147 if (this.uriCache != null) { 1148 size = this.uriCache.getGroupSize(user + project); 1149 } 1150 return size; 1151 } 1152 1153 /** 1154 * Clears the (front side) DPD cache associated with this user on the DailyProjectData server 1155 * to which this DailyProjectDataClient instance is connected. 1156 * 1157 * @return True if the command succeeded. 1158 * @throws DailyProjectDataClientException If problems occur. 1159 */ 1160 public synchronized boolean clearServerCache() throws DailyProjectDataClientException { 1161 Date startTime = new Date(); 1162 String uri = "cache"; 1163 Response response = makeRequest(Method.DELETE, uri, null); 1164 if (!response.getStatus().isSuccess()) { 1165 logElapsedTime(uri, startTime); 1166 throw new DailyProjectDataClientException(response.getStatus()); 1167 } 1168 logElapsedTime(uri, startTime); 1169 return true; 1170 } 1171 1172 /** 1173 * Clears the (front side) DPD cache entries associated with the specified project and its owner 1174 * on the DailyProjectData server to which this DailyProjectDataClient instance is connected. 1175 * 1176 * @param owner The owner of the project whose entries are to be cleared. 1177 * @param project The project DPDs to be cleared on the server. 1178 * @return True if the command succeeded. 1179 * @throws DailyProjectDataClientException If problems occur. 1180 */ 1181 public synchronized boolean clearServerCache(String owner, String project) 1182 throws DailyProjectDataClientException { 1183 Date startTime = new Date(); 1184 String uri = String.format("cache/%s/%s", owner, project); 1185 Response response = makeRequest(Method.DELETE, uri, null); 1186 if (!response.getStatus().isSuccess()) { 1187 logElapsedTime(uri, startTime); 1188 throw new DailyProjectDataClientException(response.getStatus()); 1189 } 1190 logElapsedTime(uri, startTime); 1191 return true; 1192 } 1193 1194 1195 }