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.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036 037/** 038 * Manages access to a properties file. 039 */ 040@Singleton 041@Named 042public final class DefaultTrackingFileManager implements TrackingFileManager { 043 private static final Logger LOGGER = LoggerFactory.getLogger(DefaultTrackingFileManager.class); 044 045 @Override 046 public Properties read(File file) { 047 Path filePath = file.toPath(); 048 if (Files.isReadable(filePath)) { 049 try (InputStream stream = Files.newInputStream(filePath)) { 050 Properties props = new Properties(); 051 props.load(stream); 052 return props; 053 } catch (IOException e) { 054 LOGGER.warn("Failed to read tracking file '{}'", file, e); 055 throw new UncheckedIOException(e); 056 } 057 } 058 return null; 059 } 060 061 @Override 062 public Properties update(File file, Map<String, String> updates) { 063 Path filePath = file.toPath(); 064 Properties props = new Properties(); 065 066 try { 067 Files.createDirectories(filePath.getParent()); 068 } catch (IOException e) { 069 LOGGER.warn("Failed to create tracking file parent '{}'", file, e); 070 throw new UncheckedIOException(e); 071 } 072 073 try { 074 if (Files.isReadable(filePath)) { 075 try (InputStream stream = Files.newInputStream(filePath)) { 076 props.load(stream); 077 } 078 } 079 080 for (Map.Entry<String, String> update : updates.entrySet()) { 081 if (update.getValue() == null) { 082 props.remove(update.getKey()); 083 } else { 084 props.setProperty(update.getKey(), update.getValue()); 085 } 086 } 087 088 try (OutputStream stream = Files.newOutputStream(filePath)) { 089 LOGGER.debug("Writing tracking file '{}'", file); 090 props.store( 091 stream, 092 "NOTE: This is a Maven Resolver internal implementation file" 093 + ", its format can be changed without prior notice."); 094 } 095 } catch (IOException e) { 096 LOGGER.warn("Failed to write tracking file '{}'", file, e); 097 throw new UncheckedIOException(e); 098 } 099 100 return props; 101 } 102}