001    /*
002     * SonarQube, open source software quality management tool.
003     * Copyright (C) 2008-2014 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * SonarQube is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Lesser General Public
008     * License as published by the Free Software Foundation; either
009     * version 3 of the License, or (at your option) any later version.
010     *
011     * SonarQube is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Lesser General Public License for more details.
015     *
016     * You should have received a copy of the GNU Lesser General Public License
017     * along with this program; if not, write to the Free Software Foundation,
018     * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019     */
020    package org.sonar.api.utils.internal;
021    
022    import org.apache.commons.io.FileUtils;
023    import org.apache.commons.lang.StringUtils;
024    import org.sonar.api.utils.TempFolder;
025    
026    import javax.annotation.Nullable;
027    
028    import java.io.File;
029    import java.io.IOException;
030    import java.text.MessageFormat;
031    
032    public class DefaultTempFolder implements TempFolder {
033    
034      /** Maximum loop count when creating temp directories. */
035      private static final int TEMP_DIR_ATTEMPTS = 10000;
036    
037      private final File tempDir;
038    
039      public DefaultTempFolder(File tempDir) {
040        this.tempDir = tempDir;
041      }
042    
043      @Override
044      public File newDir() {
045        return createTempDir(tempDir, "");
046      }
047    
048      /**
049       * Copied from guava waiting for JDK 7 Files#createTempDirectory
050       */
051      private static File createTempDir(File baseDir, String prefix) {
052        String baseName = prefix + System.currentTimeMillis() + "-";
053    
054        for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) {
055          File tempDir = new File(baseDir, baseName + counter);
056          if (tempDir.mkdir()) {
057            return tempDir;
058          }
059        }
060        throw new IllegalStateException(MessageFormat.format("Failed to create directory within {0} attempts (tried {1} to {2})", TEMP_DIR_ATTEMPTS, baseName + 0, baseName
061          + (TEMP_DIR_ATTEMPTS - 1)));
062      }
063    
064      @Override
065      public File newDir(String name) {
066        File dir = new File(tempDir, name);
067        try {
068          FileUtils.forceMkdir(dir);
069        } catch (IOException e) {
070          throw new IllegalStateException("Failed to create temp directory in " + dir, e);
071        }
072        return dir;
073      }
074    
075      @Override
076      public File newFile() {
077        return newFile(null, null);
078      }
079    
080      @Override
081      public File newFile(@Nullable String prefix, @Nullable String suffix) {
082        return createTempFile(tempDir, prefix, suffix);
083      }
084    
085      /**
086       * Inspired by guava waiting for JDK 7 Files#createTempFile
087       */
088      private static File createTempFile(File baseDir, String prefix, String suffix) {
089        String baseName = StringUtils.defaultIfEmpty(prefix, "") + System.currentTimeMillis() + "-";
090    
091        try {
092          for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) {
093            File tempFile = new File(baseDir, baseName + counter + suffix);
094            if (tempFile.createNewFile()) {
095              return tempFile;
096            }
097          }
098        } catch (IOException e) {
099          throw new IllegalStateException("Failed to create temp file", e);
100        }
101        throw new IllegalStateException(MessageFormat.format("Failed to create temp file within {0} attempts (tried {1} to {2})", TEMP_DIR_ATTEMPTS, baseName + 0 + suffix, baseName
102          + (TEMP_DIR_ATTEMPTS - 1) + suffix));
103      }
104    
105      public void clean() {
106        FileUtils.deleteQuietly(tempDir);
107      }
108    
109    }