Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
   *
   * Licensed under the Apache License, Version 2.0 (the "License").
   * You may not use this file except in compliance with the License.
   * A copy of the License is located at
   *
   *  http://aws.amazon.com/apache2.0
   *
  * or in the "license" file accompanying this file. This file is distributed
  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  * express or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
 package com.amazonaws.auth.profile;
 
 import java.io.File;
 import java.io.Writer;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 
 
The class for creating and modifying the credential profiles file.
 
 public class ProfilesConfigFileWriter {
 
     private static final Log LOG = LogFactory.getLog(ProfilesConfigFileWriter.class);

    
Write all the credential profiles to a file. Note that this method will clobber the existing content in the destination file if it's in the overwrite mode. Use modifyOrInsertProfiles(java.io.File,com.amazonaws.auth.profile.internal.Profile[]) instead, if you want to perform in-place modification on your existing credentials file.

Parameters:
destination The destination file where the credentials will be written to.
overwrite If true, this method If false, this method will throw exception if the file already exists.
profiles All the credential profiles to be written.
 
     public static void dumpToFile(File destinationboolean overwriteProfile... profiles) {
         if (destination.exists() && !overwrite) {
             throw new AmazonClientException(
                     "The destination file already exists. " +
                     "Set overwrite=true if you want to clobber the existing " +
                     "content and completely re-write the file.");
         }
 
         FileWriter writer;
         try {
             writer = new FileWriter(destinationfalse); // append=false
         } catch (IOException ioe) {
             throw new AmazonClientException(
                     "Unable to open the destination file."ioe);
         }
 
         try {
             final Map<StringProfilemodifications = new LinkedHashMap<StringProfile>();
             for (Profile profile : profiles) {
                 modifications.put(profile.getProfileName(), profile);
             }
             ProfilesConfigFileWriterHelper writerHelper = new ProfilesConfigFileWriterHelper(writermodifications);
 
             writerHelper.writeWithoutExistingContent();
         } finally {
             try { writer.close(); } catch (IOException ioe) {}
         }
 
     }

    
Modify or insert new profiles into an existing credentials file by in-place modification. Only the properties of the affected profiles will be modified; all the unaffected profiles and comment lines will remain the same. This method does not support renaming a profile.

Parameters:
destination The destination file to modify
profiles All the credential profiles to be written.
    public static void modifyOrInsertProfiles(File destinationProfile... profiles) {
        final Map<StringProfilemodifications = new LinkedHashMap<StringProfile>();
        for (Profile profile : profiles) {
            modifications.put(profile.getProfileName(), profile);
        }
        modifyProfiles(destinationmodifications);
    }

    
Modify one profile in the existing credentials file by in-place modification. This method will rename the existing profile if the specified Profile has a different name.

Parameters:
destination The destination file to modify
profileName The name of the existing profile to be modified
newProfile The new Profile object.
    public static void modifyOneProfile(File destinationString profileNameProfile newProfile) {
        final Map<StringProfilemodifications = Collections.singletonMap(profileNamenewProfile);
        modifyProfiles(destinationmodifications);
    }

    
Remove one or more profiles from the existing credentials file by in-place modification.

Parameters:
destination The destination file to modify
profileNames The names of all the profiles to be deleted.
    public static void deleteProfiles(File destinationString... profileNames) {
        final Map<StringProfilemodifications = new LinkedHashMap<StringProfile>();
        for (String profileName : profileNames) {
            modifications.put(profileNamenull); // null value indicates a deletion
        }
        modifyProfiles(destinationmodifications);
    }

    
A package-private method that supports all kinds of profile modification, including renaming or deleting one or more profiles.

Parameters:
modifications Use null key value to indicate a profile that is to be deleted.
    static void modifyProfiles(File destinationMap<StringProfilemodifications) {
        final boolean inPlaceModify = destination.exists();
        File stashLocation = null;
        // Stash the original file, before we apply the changes
        if (inPlaceModify) {
            boolean stashed = false;
            try {
                // We can't use File.createTempFile, since it will always create
                // that file no matter what, and File.reNameTo does not allow
                // the destination to be an existing file
                stashLocation = new File(destination.getParentFile(),
                        destination.getName() + ".bak."
                                + UUID.randomUUID().toString());
                stashed = destination.renameTo(stashLocation);
                if (.isDebugEnabled()) {
                    .debug(String
                            .format("The original credentials file is stashed to loaction (%s).",
                                    stashLocation.getAbsolutePath()));
                }
            } finally {
                if (!stashed) {
                    throw new AmazonClientException(
                            "Failed to stash the existing credentials file " +
                            "before applying the changes.");
                }
            }
        }
        FileWriter writer = null;
        try {
            writer = new FileWriter(destination);
            ProfilesConfigFileWriterHelper writerHelper = new ProfilesConfigFileWriterHelper(writermodifications);
            if (inPlaceModify) {
                Scanner existingContent = new Scanner(stashLocation);
                writerHelper.writeWithExistingContent(existingContent);
            } else {
                writerHelper.writeWithoutExistingContent();
            }
            // Make sure the output is valid and can be loaded by the loader
            new ProfilesConfigFile(destination);
            if ( inPlaceModify && !stashLocation.delete() ) {
                if (.isDebugEnabled()) {
                    .debug(String
                            .format("Successfully modified the credentials file. But failed to " +
                                    "delete the stashed copy of the original file (%s).",
                                    stashLocation.getAbsolutePath()));
                }
            }
        } catch (Exception e) {
            // Restore the stashed file
            if (inPlaceModify) {
                boolean restored = false;
                try {
                    // We don't really care about what destination.delete()
                    // returns, since the file might not have been created when
                    // the error occurred.
                    if ( !destination.delete() ) {
                        .debug("Unable to remove the credentials file "
                                + "before restoring the original one.");
                    }
                    restored = stashLocation.renameTo(destination);
                } finally {
                    if (!restored) {
                        throw new AmazonClientException(
                                "Unable to restore the original credentials file. " +
                                "File content stashed in " + stashLocation.getAbsolutePath());
                    }
                }
            }
            throw new AmazonClientException(
                    "Unable to modify the credentials file. " +
                    "(The original file has been restored.)",
                    e);
        } finally {
            try {
                if (writer != nullwriter.close();
            } catch (IOException e) {}
        }
    }

    
Implementation of AbstractProfilesConfigFileScanner, which reads the content from an existing credentials file (if any) and then modifies some of the profile properties in place.
    private static class ProfilesConfigFileWriterHelper extends AbstractProfilesConfigFileScanner {

        
The writer where the modified profiles will be output to
        private final Writer writer;

        
Map of all the profiles to be modified, keyed by profile names
        private final Map<StringProfilenewProfiles = new LinkedHashMap<StringProfile>();

        
Map of the names of all the profiles to be deleted
        private final Set<StringdeletedProfilesnew HashSet<String>();
        private final StringBuilder buffer = new StringBuilder();
        private final Map<StringSet<String>> existingProfileProperties = new HashMap<StringSet<String>>();

        
Creates ProfilesConfigFileWriterHelper with the specified new profiles.

Parameters:
writer The writer where the modified content is output to.
modifications A map of all the new profiles, keyed by the profile name. If a profile name is associated with a null value, it's profile content will be removed.
        public ProfilesConfigFileWriterHelper(Writer writerMap<StringProfilemodifications) {
            this. = writer;
            for (Entry<StringProfileentry : modifications.entrySet()) {
                String profileName = entry.getKey();
                Profile profile    = entry.getValue();
                if (profile == null) {
                    .add(profileName);
                } else {
                    .put(profileNameprofile);
                }
            }
        }

        
Append the new profiles to the writer, by reading from empty content.
        public void writeWithoutExistingContent() {
            .setLength(0);
            .clear();
            // Use empty String as input, since we are bootstrapping a new file.
            run(new Scanner(""));
        }

        
Read the existing content of a credentials file, and then make in-place modification according to the new profiles specified in this class.
        public void writeWithExistingContent(Scanner existingContent) {
            .setLength(0);
            .clear();
            run(existingContent);
        }
        @Override
        protected void onEmptyOrCommentLine(String profileNameString line) {
            /*
             * Buffer the line until we reach the next property line or the end
             * of the profile. We do this so that new properties could be
             * inserted at more appropriate location. For example:
             *
             * [default]
             * # access key
             * aws_access_key_id=aaa
             * # secret key
             * aws_secret_access_key=sss
             * # We want new properties to be inserted before this line
             * # instead of after the following empty line
             *
             * [next profile]
             * ...
             */
            if (profileName == null || !.contains(profileName)) {
                buffer(line);
            }
        }
        @Override
        protected void onProfileStartingLine(String profileNameString line) {
            .put(profileNamenew HashSet<String>());
            // Copy the line after flush the buffer
            flush();
            if (.contains(profileName))
                return;
            // If the profile name is changed
            if (.get(profileName) != null) {
                String newProfileName = .get(profileName).getProfileName();
                if ( !newProfileName.equals(profileName) ) {
                    line = "[" + newProfileName + "]";
                }
            }
            writeLine(line);
        }
        @Override
        protected void onProfileEndingLine(String prevProfileName) {
            // Check whether we need to insert new properties into this profile
            Profile modifiedProfile = .get(prevProfileName);
            if (modifiedProfile != null) {
                for (Entry<StringStringentry : modifiedProfile.getProperties().entrySet()) {
                    String propertyKey   = entry.getKey();
                    String propertyValue = entry.getValue();
                    if ( !.get(prevProfileName).contains(propertyKey) ) {
                        writeProperty(propertyKeypropertyValue);
                    }
                }
            }
            // flush all the buffered comments and empty lines
            flush();
        }
        @Override
        protected void onProfileProperty(String profileName,
                String propertyKeyString propertyValue,
                boolean isSupportedPropertyString line) {
            // Record that this property key has been declared for this profile
            if (.get(profileName) == null) {
                .put(profileNamenew HashSet<String>());
            }
            .get(profileName).add(propertyKey);
            if (.contains(profileName))
                return;
            // Keep the unsupported properties
            if ( !isSupportedProperty ) {
                writeLine(line);
                return;
            }
            // flush all the buffered comments and empty lines before this property line
            flush();
            // Modify the property value
            if (.containsKey(profileName)) {
                String newValue = .get(profileName)
                        .getPropertyValue(propertyKey);
                if (newValue != null) {
                    writeProperty(propertyKeynewValue);
                }
                // else remove that line
            } else {
                writeLine(line);
            }
        }
        @Override
        protected void onEndOfFile() {
            // Append profiles that don't exist in the original file
            for (Entry<StringProfileentry : .entrySet()) {
                String profileName = entry.getKey();
                Profile profile    = entry.getValue();
                if ( !.containsKey(profileName) ) {
                    // The profile name is not found in the file
                    // Append the profile properties
                    writeProfile(profile);
                    writeLine("");
                }
            }
            // Flush the "real" writer
            try {
                .flush();
            } catch (IOException ioe) {
                throw new AmazonClientException(
                        "Unable to write to the target file to persist the profile credentials.",
                        ioe);
            }
        }
        /* Private interface */
        private void writeProfile(Profile profile) {
            writeProfileName(profile.getProfileName());
            for (Entry<StringStringentry : profile.getProperties().entrySet()) {
                writeProperty(entry.getKey(), entry.getValue());
            }
        }
        private void writeProfileName(String profileName) {
            writeLine(String.format("[%s]"profileName));
        }
        private void writeProperty(String propertyKeyString propertyValue) {
            writeLine(String.format("%s=%s"propertyKeypropertyValue));
        }
        private void writeLine(String line) {
            append(String.format("%s%n"line));
        }

        
This method handles IOException that occurs when calling the append method on the writer.
        private void append(String str) {
            try {
                .append(str);
            } catch (IOException ioe) {
                throw new AmazonClientException(
                        "Unable to write to the target file to persist the profile credentials.",
                        ioe);
            }
        }
        private void flush() {
            if (.length() != 0) {
                append(.toString());
                .setLength(0);
            }
        }
        private void buffer(String line) {
            .append(String.format("%s%n"line));
        }
    }
New to GrepCode? Check out our FAQ X