001/*
002 * Copyright (c) 2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2012-08-03 16:30:04 +0000 (Fri, 03 Aug 2012) $' 
007 * '$Revision: 30343 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.kepler.util;
031
032import java.io.BufferedInputStream;
033import java.io.BufferedReader;
034import java.io.File;
035import java.io.FileInputStream;
036import java.io.FileOutputStream;
037import java.io.IOException;
038import java.io.InputStream;
039import java.io.InputStreamReader;
040import java.io.OutputStream;
041import java.net.URI;
042import java.net.URISyntaxException;
043import java.net.URL;
044
045import org.kepler.build.modules.Module;
046import org.kepler.build.modules.ModuleTree;
047
048/**
049 * A place to keep some useful file processing static utility methods.
050 * @author Aaron Schultz
051 */
052public class FileUtil {
053
054
055        /**
056         * Return the highest ranked (i.e. top override) of the given
057         * relative file path.
058         * 
059         * @param relativePath
060         * @return
061         */
062        public static File getHighestRankedFile(String relativePath) {
063                for (Module module : ModuleTree.instance()) {
064                        File file = new File(module.getDir(), relativePath);
065                        if (file.exists()) {
066                                return file;
067                        }
068                }
069
070                // System.out.println("Could not find file: " + relativePath);
071                return null;
072        }
073        
074        /**
075         * Get a File object from a resource on the classpath using the 
076         * ClassLoader that loaded the given object.
077         * 
078         * @param relativeTo
079         * @param relativePath
080         * @return
081         */
082        public static File getResourceAsFile(Object relativeTo, String relativePath) {
083                ClassLoader cl = relativeTo.getClass().getClassLoader();
084                URL url = cl.getResource(relativePath);
085                URI uri;
086                try {
087                        uri = url.toURI();
088                        File f = new File(uri);
089                        return f;
090                } catch (URISyntaxException e) {
091                        e.printStackTrace();
092                }
093                return null;
094        }
095
096        /**
097         * Read in a file as a string.
098         * 
099         * @param f
100         * @return
101         * @throws java.io.IOException
102         */
103        public static String readFileAsString(File file) throws java.io.IOException {
104                int fLength = (int) file.length();
105            byte[] buffer = new byte[fLength];
106            FileInputStream fis = new FileInputStream(file);
107            BufferedInputStream f = new BufferedInputStream(fis);
108            f.read(buffer);
109            f.close();
110            return new String(buffer);
111        }
112        
113        /*
114         * Convert the InputStream to a String.
115         */
116        public static String convertStreamToString(InputStream is) throws IOException {
117                if (is != null) {
118                        StringBuilder sb = new StringBuilder();
119                        String line;
120
121                        try {
122                                BufferedReader reader = new BufferedReader(
123                                                new InputStreamReader(is, "UTF-8"));
124                                while ((line = reader.readLine()) != null) {
125                                        sb.append(line).append("\n");
126                                }
127                        } finally {
128                                is.close();
129                        }
130                        return sb.toString();
131                } else {
132                        return "";
133                }
134        }
135        
136        public static String appendNewLine(String s) {
137                s += System.getProperty("line.separator");
138                return s;
139        }
140        
141        /**
142         * @param base
143         * @param sub
144         * @return true if sub is a subdirectory of base
145         * @throws IOException 
146         */
147        public static boolean isSubdirectory(File base, File sub) throws IOException {
148                String[] basePaths = pathRep(base);
149                String[] subPaths = pathRep(sub);
150                if (basePaths.length >= subPaths.length) {
151                        return false;
152                } else {
153                        boolean sameRoot = true;
154                        for (int i = 0; i < basePaths.length; i++) {
155                                if (!basePaths[i].equals(subPaths[i])) {
156                                        sameRoot = false;
157                                }
158                        }
159                        return sameRoot;
160                }
161        }
162        
163        /**
164         * Return a string array representation of the file path.
165         * 
166         * @param f
167         * @return
168         * @throws IOException
169         */
170        public static String[] pathRep(File f) throws IOException {
171                String a = clean(f);
172                String[] paths = a.split("/");
173                return paths;
174        }
175        
176        /**
177         * Always return the true unique string representation of 
178         * a file with no trailing separators.
179         * 
180         * @param f
181         * @return
182         * @throws IOException
183         */
184        public static String clean(File f) throws IOException {
185                String s = f.getCanonicalFile().toURI().getPath();
186                if (s.endsWith("/")) {
187                        s = s.substring(0,s.length()-1);
188                }
189                return s;
190        }
191        
192        /**
193         * Return filename without extension.
194         * @param filename
195         * @return
196         */
197        public static String getFileNameWithoutExtension(String filename) {
198                // filename without the extension
199                String choppedFilename;
200
201                // extension without the dot
202                //String ext;
203
204                int dotPlace = filename.lastIndexOf('.');
205
206                if (dotPlace >= 0) {
207                        // possibly empty
208                        choppedFilename = filename.substring(0, dotPlace);
209
210                        // possibly empty
211                        //ext = filename.substring(dotPlace + 1);
212                } else {
213                        // was no extension
214                        choppedFilename = filename;
215                        //ext = "";
216                }
217                
218                return choppedFilename;
219        }
220
221        
222        /*
223         * Get the extension of a file.
224         */
225        public static String getExtension(File f) {
226                String ext = "";
227                String s = f.getName();
228                int i = s.lastIndexOf('.');
229
230                if (i > 0 && i < s.length() - 1) {
231                        ext = s.substring(i + 1).toLowerCase();
232                }
233                return ext;
234        }
235        
236        /** Copy a file or directory to another. If the source is a directory,
237         *  the contents are recursively copied.
238         * @param sourceLocation the source
239         * @param targetLocation the destination
240         * @param overwrite If true, overwrite files in the targetLocation
241         * @throws IOException
242         */
243        public static void copyDirectory(File sourceLocation , File targetLocation,
244                boolean overwrite) throws IOException {
245         
246            if (sourceLocation.isDirectory()) {
247                if (!targetLocation.exists()) {
248                    boolean created = targetLocation.mkdirs();
249                    if (!created){
250                        System.out.println("FileUtil copyDirectory ERROR couldn't mkdirs:" + targetLocation);
251                        // if we couldn't create the directories, stop copying
252                        return;
253                    }
254                }
255         
256                String[] children = sourceLocation.list();
257                for (int i=0; i<children.length; i++) {
258                    copyDirectory(new File(sourceLocation, children[i]),
259                            new File(targetLocation, children[i]), overwrite);
260                }
261            } else if(overwrite || !targetLocation.exists()) {
262                InputStream in = new FileInputStream(sourceLocation);
263                OutputStream out = new FileOutputStream(targetLocation);
264         
265                // Copy the bits from instream to outstream
266                byte[] buf = new byte[1024];
267                int len;
268                while ((len = in.read(buf)) > 0) {
269                    out.write(buf, 0, len);
270                }
271                in.close();
272                out.close();
273                
274                //set executable property
275                if (sourceLocation.canExecute())
276                        targetLocation.setExecutable(true);
277            }
278        }
279        
280}