001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.servicemix.jbi.util;
018    
019    import java.io.File;
020    import java.io.IOException;
021    
022    import org.apache.commons.logging.Log;
023    import org.apache.commons.logging.LogFactory;
024    
025    /**
026     * Supports a simple versioning scheme using the file system
027     * 
028     * @version $Revision: 564607 $
029     */
030    public final class FileVersionUtil {
031        
032        private static final Log LOG = LogFactory.getLog(FileVersionUtil.class);
033    
034        private static final String VERSION_PREFIX = "version_";
035    
036        private static final String[] RESERVED = {VERSION_PREFIX };
037        
038        private FileVersionUtil() {
039        }
040    
041        /**
042         * Get the latest version number for a directory
043         * 
044         * @param rootDirectory
045         * @return the version number
046         */
047        public static int getLatestVersionNumber(File rootDirectory) {
048            int result = -1;
049            if (isVersioned(rootDirectory)) {
050                File[] files = rootDirectory.listFiles();
051                for (int i = 0; i < files.length; i++) {
052                    int version = getVersionNumber(files[i].getName());
053                    if (version > result) {
054                        result = version;
055                    }
056                }
057            }
058            return result;
059        }
060    
061        /**
062         * Get the latest versioned directory
063         * 
064         * @param rootDirectory
065         * @return the directory
066         * @throws IOException
067         */
068        public static File getLatestVersionDirectory(File rootDirectory) {
069            File result = null;
070            int highestVersion = -1;
071            if (rootDirectory != null && isVersioned(rootDirectory)) {
072                File[] files = rootDirectory.listFiles();
073                for (int i = 0; i < files.length; i++) {
074                    int version = getVersionNumber(files[i].getName());
075                    if (version > highestVersion) {
076                        highestVersion = version;
077                        result = files[i];
078                    }
079                }
080            }
081            return result;
082        }
083    
084        /**
085         * Create a new version directory
086         * 
087         * @param rootDirectory
088         * @return the created version directory
089         * @throws IOException
090         */
091        public static File createNewVersionDirectory(File rootDirectory) throws IOException {
092            File result = getNewVersionDirectory(rootDirectory);
093            if (!FileUtil.buildDirectory(result)) {
094                throw new IOException("Failed to build version directory: " + result);
095            }
096            return result;
097        }
098    
099        /**
100         * get's the new version file - without creating the directory
101         * 
102         * @param rootDirectory
103         * @return the version directory
104         * @throws IOException
105         */
106        public static File getNewVersionDirectory(File rootDirectory) throws IOException {
107            File result = null;
108            if (FileUtil.buildDirectory(rootDirectory)) {
109                String versionDirectoryName = VERSION_PREFIX;
110                if (isVersioned(rootDirectory)) {
111                    int versionNumber = getLatestVersionNumber(rootDirectory);
112                    versionNumber = versionNumber > 0 ? versionNumber + 1 : 1;
113                    versionDirectoryName += versionNumber;
114                } else {
115                    versionDirectoryName += 1;
116                }
117                result = FileUtil.getDirectoryPath(rootDirectory, versionDirectoryName);
118            } else {
119                throw new IOException("Cannot build parent directory: " + rootDirectory);
120            }
121            return result;
122        }
123    
124        /**
125         * Used to move non-version files/directories to versioned
126         * 
127         * @param rootDirectory
128         * @throws IOException
129         */
130        public static void initializeVersionDirectory(File rootDirectory) throws IOException {
131            if (!isVersioned(rootDirectory)) {
132                File newRoot = createNewVersionDirectory(rootDirectory);
133                File[] files = rootDirectory.listFiles();
134                for (int i = 0; i < files.length; i++) {
135                    if (!isReserved(files[i].getName())) {
136                        LOG.info(rootDirectory.getPath() + ": moving non-versioned file " + files[i].getName() + " to " + newRoot.getName());
137                        File moveTo = FileUtil.getDirectoryPath(newRoot, files[i].getName());
138                        FileUtil.moveFile(files[i], moveTo);
139                    }
140                }
141            }
142        }
143    
144        private static boolean isVersioned(File rootDirectory) {
145            boolean result = false;
146            if (rootDirectory.exists() && rootDirectory.isDirectory()) {
147                File[] files = rootDirectory.listFiles();
148                result = files == null || files.length == 0;
149                if (!result) {
150                    for (int i = 0; i < files.length; i++) {
151                        if (isReserved(files[i].getName())) {
152                            result = true;
153                            break;
154                        }
155                    }
156                }
157            }
158            return result;
159        }
160    
161        private static boolean isReserved(String name) {
162            boolean result = false;
163            if (name != null) {
164                for (int i = 0; i < RESERVED.length; i++) {
165                    if (name.startsWith(RESERVED[i])) {
166                        result = true;
167                        break;
168                    }
169                }
170            }
171            return result;
172        }
173    
174        private static int getVersionNumber(String name) {
175            int result = -1;
176            if (name != null && name.startsWith(VERSION_PREFIX)) {
177                String number = name.substring(VERSION_PREFIX.length());
178                result = Integer.parseInt(number);
179            }
180            return result;
181        }
182    }