private boolean resourceIsExpirable(RepoResource resource, HttpRepo repo) {
   // If the file is expirable then the expirable mechanism is responsible to update the file and
   // the properties
   String path = resource.getRepoPath().getPath();
   CacheExpiry cacheExpiry = ContextHelper.get().beanForType(CacheExpiry.class);
   return cacheExpiry.isExpirable(repo.getLocalCacheRepo(), path);
 }
 /**
  * Performs local properties update
  *
  * @param resource
  * @return success/failure
  */
 private boolean doPull(RepoResource resource) {
   log.debug("Downloading properties for artifact {}", resource);
   String repoKey = StringUtils.replaceLast(resource.getRepoPath().getRepoKey(), "-cache", "");
   HttpRepo repo = (HttpRepo) repositoryService.remoteRepositoryByKey(repoKey);
   // If file doesn't exist then do mot update properties since it will be updated during file
   // download
   if (!repositoryService.exists(resource.getRepoPath())) {
     return false;
   }
   // If properties not expire the return false, no need to get properties drom the remote repo
   if (repo == null
       || resourceIsExpirable(resource, repo)
       || !isPropertiesExpired(resource, repo)) {
     return false;
   }
   String remotePath = repo.getUrl() + "/" + resource.getRepoPath().getPath() + ":properties";
   HttpGet getMethod = new HttpGet(HttpUtils.encodeQuery(remotePath));
   try {
     CloseableHttpResponse getResponse = repo.executeMethod(getMethod);
     boolean ok = HttpStatus.SC_OK == getResponse.getStatusLine().getStatusCode();
     boolean notFound = HttpStatus.SC_NOT_FOUND == getResponse.getStatusLine().getStatusCode();
     if (ok || notFound) {
       InputStream stream = getResponse.getEntity().getContent();
       Properties properties = (Properties) InfoFactoryHolder.get().createProperties();
       if (ok && stream != null) {
         RepoRequests.logToContext("Received remote property content");
         Properties remoteProperties =
             (Properties) InfoFactoryHolder.get().getFileSystemXStream().fromXML(stream);
         for (String remotePropertyKey : remoteProperties.keySet()) {
           Set<String> values = remoteProperties.get(remotePropertyKey);
           RepoRequests.logToContext(
               "Found remote property key '{}' with values '%s'", remotePropertyKey, values);
           if (!remotePropertyKey.startsWith(ReplicationAddon.PROP_REPLICATION_PREFIX)) {
             properties.putAll(remotePropertyKey, values);
           }
         }
       }
       updateRemoteProperties(resource, properties);
     }
     repositoryService.unexpireIfExists(
         repo.getLocalCacheRepo(), resource.getRepoPath().getPath());
   } catch (IOException e) {
     log.debug("Cannot update remote properties", e);
     return false;
   }
   return true;
 }
 /**
  * Checks whether given resource's properties cache has expired
  *
  * @param resource - repo resource
  * @param repo - http repo
  * @return yes/no
  */
 private boolean isPropertiesExpired(RepoResource resource, HttpRepo repo) {
   RepoPath repoPath = resource.getRepoPath();
   long lastUpdated = repositoryService.getFileInfo(repoPath).getLastUpdated();
   long cacheAge = System.currentTimeMillis() - lastUpdated;
   long retrievalCachePeriodMillis = repo.getRetrievalCachePeriodSecs() * 1000L;
   // If cache age is less than retrieval cache period then do not update properties.
   if (cacheAge < retrievalCachePeriodMillis) {
     return false;
   }
   return true;
 }