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.activemq.util;
018    
019    import java.io.File;
020    import java.io.FileInputStream;
021    import java.io.FileNotFoundException;
022    import java.io.FileOutputStream;
023    import java.io.IOException;
024    import java.io.InputStream;
025    import java.io.OutputStream;
026    
027    /**
028     * @version $Revision: 661435 $
029     */
030    public final class IOHelper {
031        protected static final int MAX_DIR_NAME_LENGTH;
032        protected static final int MAX_FILE_NAME_LENGTH;
033        private static final int DEFAULT_BUFFER_SIZE = 4096;
034        private IOHelper() {
035        }
036    
037        public static String getDefaultDataDirectory() {
038            return getDefaultDirectoryPrefix() + "activemq-data";
039        }
040    
041        public static String getDefaultStoreDirectory() {
042            return getDefaultDirectoryPrefix() + "amqstore";
043        }
044    
045        /**
046         * Allows a system property to be used to overload the default data
047         * directory which can be useful for forcing the test cases to use a target/
048         * prefix
049         */
050        public static String getDefaultDirectoryPrefix() {
051            try {
052                return System.getProperty("org.apache.activemq.default.directory.prefix", "");
053            } catch (Exception e) {
054                return "";
055            }
056        }
057    
058        /**
059         * Converts any string into a string that is safe to use as a file name.
060         * The result will only include ascii characters and numbers, and the "-","_", and "." characters.
061         *
062         * @param name
063         * @return
064         */
065        public static String toFileSystemDirectorySafeName(String name) {
066            return toFileSystemSafeName(name, true, MAX_DIR_NAME_LENGTH);
067        }
068        
069        public static String toFileSystemSafeName(String name) {
070            return toFileSystemSafeName(name, false, MAX_FILE_NAME_LENGTH);
071        }
072        
073        /**
074         * Converts any string into a string that is safe to use as a file name.
075         * The result will only include ascii characters and numbers, and the "-","_", and "." characters.
076         *
077         * @param name
078         * @param dirSeparators 
079         * @param maxFileLength 
080         * @return
081         */
082        public static String toFileSystemSafeName(String name,boolean dirSeparators,int maxFileLength) {
083            int size = name.length();
084            StringBuffer rc = new StringBuffer(size * 2);
085            for (int i = 0; i < size; i++) {
086                char c = name.charAt(i);
087                boolean valid = c >= 'a' && c <= 'z';
088                valid = valid || (c >= 'A' && c <= 'Z');
089                valid = valid || (c >= '0' && c <= '9');
090                valid = valid || (c == '_') || (c == '-') || (c == '.') || (c=='#')
091                        ||(dirSeparators && ( (c == '/') || (c == '\\')));
092    
093                if (valid) {
094                    rc.append(c);
095                } else {
096                    // Encode the character using hex notation
097                    rc.append('#');
098                    rc.append(HexSupport.toHexFromInt(c, true));
099                }
100            }
101            String result = rc.toString();
102            if (result.length() > maxFileLength) {
103                result = result.substring(result.length()-maxFileLength,result.length());
104            }
105            return result;
106        }
107        
108        public static boolean deleteFile(File fileToDelete) {
109            if (fileToDelete == null || !fileToDelete.exists()) {
110                return true;
111            }
112            boolean result = deleteChildren(fileToDelete);
113            result &= fileToDelete.delete();
114            return result;
115        }
116        
117        public static boolean deleteChildren(File parent) {
118            if (parent == null || !parent.exists()) {
119                return false;
120            }
121            boolean result = true;
122            if (parent.isDirectory()) {
123                File[] files = parent.listFiles();
124                if (files == null) {
125                    result = false;
126                } else {
127                    for (int i = 0; i < files.length; i++) {
128                        File file = files[i];
129                        if (file.getName().equals(".")
130                                || file.getName().equals("..")) {
131                            continue;
132                        }
133                        if (file.isDirectory()) {
134                            result &= deleteFile(file);
135                        } else {
136                            result &= file.delete();
137                        }
138                    }
139                }
140            }
141           
142            return result;
143        }
144        
145        
146        public static void moveFile(File src, File targetDirectory) throws IOException {
147            if (!src.renameTo(new File(targetDirectory, src.getName()))) {
148                throw new IOException("Failed to move " + src + " to " + targetDirectory);
149            }
150        }
151        
152        public static void copyFile(File src, File dest) throws IOException {
153            FileInputStream fileSrc = new FileInputStream(src);
154            FileOutputStream fileDest = new FileOutputStream(dest);
155            copyInputStream(fileSrc, fileDest);
156        }
157        
158        public static void copyInputStream(InputStream in, OutputStream out) throws IOException {
159            byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
160            int len = in.read(buffer);
161            while (len >= 0) {
162                out.write(buffer, 0, len);
163                len = in.read(buffer);
164            }
165            in.close();
166            out.close();
167        }
168        
169        static {
170            MAX_DIR_NAME_LENGTH = Integer.valueOf(System.getProperty("MaximumDirNameLength","200")).intValue();  
171            MAX_FILE_NAME_LENGTH = Integer.valueOf(System.getProperty("MaximumFileNameLength","64")).intValue();             
172        }
173    
174        
175        public static void mkdirs(File dir) throws IOException {
176            if (dir.exists()) {
177                if (!dir.isDirectory()) {
178                    throw new IOException("Failed to create directory '" + dir +"', regular file already existed with that name");
179                }
180                
181            } else {
182                if (!dir.mkdirs()) {
183                    throw new IOException("Failed to create directory '" + dir+"'");
184                }
185            }
186        }
187    }