001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.internal.impl; 020 021import javax.inject.Named; 022import javax.inject.Singleton; 023 024import java.io.File; 025import java.io.IOException; 026import java.io.InputStream; 027import java.io.OutputStream; 028import java.io.UncheckedIOException; 029import java.nio.file.Files; 030import java.nio.file.Path; 031import java.util.Map; 032import java.util.Properties; 033 034import org.eclipse.aether.util.FileUtils; 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 037 038/** 039 * Manages access to a properties file. 040 */ 041@Singleton 042@Named 043public final class DefaultTrackingFileManager implements TrackingFileManager { 044 private static final Logger LOGGER = LoggerFactory.getLogger(DefaultTrackingFileManager.class); 045 046 @Override 047 public Properties read(File file) { 048 Path filePath = file.toPath(); 049 if (Files.isRegularFile(filePath)) { 050 try (InputStream stream = Files.newInputStream(filePath)) { 051 Properties props = new Properties(); 052 props.load(stream); 053 return props; 054 } catch (IOException e) { 055 LOGGER.warn("Failed to read tracking file '{}'", file, e); 056 throw new UncheckedIOException(e); 057 } 058 } 059 return null; 060 } 061 062 @Override 063 public Properties update(File file, Map<String, String> updates) { 064 Path filePath = file.toPath(); 065 Properties props = new Properties(); 066 067 try { 068 Files.createDirectories(filePath.getParent()); 069 } catch (IOException e) { 070 LOGGER.warn("Failed to create tracking file parent '{}'", file, e); 071 throw new UncheckedIOException(e); 072 } 073 074 try { 075 if (Files.isReadable(filePath)) { 076 try (InputStream stream = Files.newInputStream(filePath)) { 077 props.load(stream); 078 } 079 } 080 081 for (Map.Entry<String, String> update : updates.entrySet()) { 082 if (update.getValue() == null) { 083 props.remove(update.getKey()); 084 } else { 085 props.setProperty(update.getKey(), update.getValue()); 086 } 087 } 088 089 FileUtils.writeFile(filePath, p -> { 090 try (OutputStream stream = Files.newOutputStream(p)) { 091 LOGGER.debug("Writing tracking file '{}'", file); 092 props.store( 093 stream, 094 "NOTE: This is a Maven Resolver internal implementation file" 095 + ", its format can be changed without prior notice."); 096 } 097 }); 098 } catch (IOException e) { 099 LOGGER.warn("Failed to write tracking file '{}'", file, e); 100 throw new UncheckedIOException(e); 101 } 102 103 return props; 104 } 105}