Clover Coverage Report - Subsonic-Android Coverage Report
Coverage timestamp: ven dic 19 2014 17:57:13 EST
../../../../../img/srcFileCovDistChart8.png 45% of files have more coverage
113   301   53   5,38
50   212   0,47   21
21     2,52  
1    
This report was generated with an evaluation server license. Purchase Clover or configure your license.
 
  FileUtil       Line # 43 113 53 78,3% 0.7826087
 
No Tests
 
1    /*
2    This file is part of Subsonic.
3   
4    Subsonic is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8   
9    Subsonic is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12    GNU General Public License for more details.
13   
14    You should have received a copy of the GNU General Public License
15    along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
16   
17    Copyright 2009 (C) Sindre Mehus
18    */
19    package net.sourceforge.subsonic.androidapp.util;
20   
21    import java.io.File;
22    import java.io.FileInputStream;
23    import java.io.FileOutputStream;
24    import java.io.ObjectInputStream;
25    import java.io.ObjectOutputStream;
26    import java.io.Serializable;
27    import java.util.Arrays;
28    import java.util.SortedSet;
29    import java.util.TreeSet;
30    import java.util.Iterator;
31    import java.util.List;
32   
33    import android.content.Context;
34    import android.graphics.Bitmap;
35    import android.graphics.BitmapFactory;
36    import android.os.Environment;
37    import android.util.Log;
38    import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
39   
40    /**
41    * @author Sindre Mehus
42    */
 
43    public class FileUtil {
44   
45    private static final String TAG = FileUtil.class.getSimpleName();
46    private static final String[] FILE_SYSTEM_UNSAFE = {"/", "\\", "..", ":", "\"", "?", "*", "<", ">"};
47    private static final String[] FILE_SYSTEM_UNSAFE_DIR = {"\\", "..", ":", "\"", "?", "*", "<", ">"};
48    private static final List<String> MUSIC_FILE_EXTENSIONS = Arrays.asList("mp3", "ogg", "aac", "flac", "m4a", "wav", "wma");
49    private static final File DEFAULT_MUSIC_DIR = createDirectory("music");
50   
 
51  164 toggle public static File getSongFile(Context context, MusicDirectory.Entry song) {
52  164 File dir = getAlbumDirectory(context, song);
53   
54  164 StringBuilder fileName = new StringBuilder();
55  164 Integer track = song.getTrack();
56  164 if (track != null) {
57  93 if (track < 10) {
58  83 fileName.append("0");
59    }
60  93 fileName.append(track).append("-");
61    }
62   
63  164 fileName.append(fileSystemSafe(song.getTitle())).append(".");
64   
65  164 if (song.getTranscodedSuffix() != null) {
66  0 fileName.append(song.getTranscodedSuffix());
67    } else {
68  164 fileName.append(song.getSuffix());
69    }
70   
71  164 return new File(dir, fileName.toString());
72    }
73   
 
74  171 toggle public static File getAlbumArtFile(Context context, MusicDirectory.Entry entry) {
75  171 File albumDir = getAlbumDirectory(context, entry);
76  171 return getAlbumArtFile(albumDir);
77    }
78   
 
79  180 toggle public static File getAlbumArtFile(File albumDir) {
80  180 File albumArtDir = getAlbumArtDirectory();
81  180 return new File(albumArtDir, Util.md5Hex(albumDir.getPath()) + ".jpeg");
82    }
83   
 
84  67 toggle public static Bitmap getAlbumArtBitmap(Context context, MusicDirectory.Entry entry, int size) {
85  67 File albumArtFile = getAlbumArtFile(context, entry);
86  67 if (albumArtFile.exists()) {
87  30 Bitmap bitmap = BitmapFactory.decodeFile(albumArtFile.getPath());
88  30 return bitmap == null ? null : Bitmap.createScaledBitmap(bitmap, size, size, true);
89    }
90  37 return null;
91    }
92   
 
93  180 toggle public static File getAlbumArtDirectory() {
94  180 File albumArtDir = new File(getSubsonicDirectory(), "artwork");
95  180 ensureDirectoryExistsAndIsReadWritable(albumArtDir);
96  180 ensureDirectoryExistsAndIsReadWritable(new File(albumArtDir, ".nomedia"));
97  180 return albumArtDir;
98    }
99   
 
100  335 toggle private static File getAlbumDirectory(Context context, MusicDirectory.Entry entry) {
101  335 File dir;
102  335 if (entry.getPath() != null) {
103  314 File f = new File(fileSystemSafeDir(entry.getPath()));
104  314 dir = new File(getMusicDirectory(context).getPath() + "/" + (entry.isDirectory() ? f.getPath() : f.getParent()));
105    } else {
106  21 String artist = fileSystemSafe(entry.getArtist());
107  21 String album = fileSystemSafe(entry.getAlbum());
108  21 dir = new File(getMusicDirectory(context).getPath() + "/" + artist + "/" + album);
109    }
110  335 return dir;
111    }
112   
 
113  21 toggle public static void createDirectoryForParent(File file) {
114  21 File dir = file.getParentFile();
115  21 if (!dir.exists()) {
116  11 if (!dir.mkdirs()) {
117  0 Log.e(TAG, "Failed to create directory " + dir);
118    }
119    }
120    }
121   
 
122  1 toggle private static File createDirectory(String name) {
123  1 File dir = new File(getSubsonicDirectory(), name);
124  1 if (!dir.exists() && !dir.mkdirs()) {
125  0 Log.e(TAG, "Failed to create " + name);
126    }
127  1 return dir;
128    }
129   
 
130  184 toggle public static File getSubsonicDirectory() {
131  184 return new File(Environment.getExternalStorageDirectory(), "subsonic");
132    }
133   
 
134  1 toggle public static File getDefaultMusicDirectory() {
135  1 return DEFAULT_MUSIC_DIR;
136    }
137   
 
138  450 toggle public static File getMusicDirectory(Context context) {
139  450 String path = Util.getPreferences(context).getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, DEFAULT_MUSIC_DIR.getPath());
140  450 File dir = new File(path);
141  450 return ensureDirectoryExistsAndIsReadWritable(dir) ? dir : getDefaultMusicDirectory();
142    }
143   
 
144  810 toggle public static boolean ensureDirectoryExistsAndIsReadWritable(File dir) {
145  810 if (dir == null) {
146  0 return false;
147    }
148   
149  810 if (dir.exists()) {
150  810 if (!dir.isDirectory()) {
151  0 Log.w(TAG, dir + " exists but is not a directory.");
152  0 return false;
153    }
154    } else {
155  0 if (dir.mkdirs()) {
156  0 Log.i(TAG, "Created directory " + dir);
157    } else {
158  0 Log.w(TAG, "Failed to create directory " + dir);
159  0 return false;
160    }
161    }
162   
163  810 if (!dir.canRead()) {
164  0 Log.w(TAG, "No read permission for directory " + dir);
165  0 return false;
166    }
167   
168  810 if (!dir.canWrite()) {
169  0 Log.w(TAG, "No write permission for directory " + dir);
170  0 return false;
171    }
172  810 return true;
173    }
174   
175    /**
176    * Makes a given filename safe by replacing special characters like slashes ("/" and "\")
177    * with dashes ("-").
178    *
179    * @param filename The filename in question.
180    * @return The filename with special characters replaced by hyphens.
181    */
 
182  206 toggle private static String fileSystemSafe(String filename) {
183  206 if (filename == null || filename.trim().length() == 0) {
184  22 return "unnamed";
185    }
186   
187  184 for (String s : FILE_SYSTEM_UNSAFE) {
188  1656 filename = filename.replace(s, "-");
189    }
190  184 return filename;
191    }
192   
193    /**
194    * Makes a given filename safe by replacing special characters like colons (":")
195    * with dashes ("-").
196    *
197    * @param path The path of the directory in question.
198    * @return The the directory name with special characters replaced by hyphens.
199    */
 
200  314 toggle private static String fileSystemSafeDir(String path) {
201  314 if (path == null || path.trim().length() == 0) {
202  0 return "";
203    }
204   
205  314 for (String s : FILE_SYSTEM_UNSAFE_DIR) {
206  2512 path = path.replace(s, "-");
207    }
208  314 return path;
209    }
210   
211    /**
212    * Similar to {@link File#listFiles()}, but returns a sorted set.
213    * Never returns {@code null}, instead a warning is logged, and an empty set is returned.
214    */
 
215  275 toggle public static SortedSet<File> listFiles(File dir) {
216  275 File[] files = dir.listFiles();
217  275 if (files == null) {
218  0 Log.w(TAG, "Failed to list children for " + dir.getPath());
219  0 return new TreeSet<File>();
220    }
221   
222  275 return new TreeSet<File>(Arrays.asList(files));
223    }
224   
 
225  24 toggle public static SortedSet<File> listMusicFiles(File dir) {
226  24 SortedSet<File> files = listFiles(dir);
227  24 Iterator<File> iterator = files.iterator();
228  65 while (iterator.hasNext()) {
229  41 File file = iterator.next();
230  41 if (!file.isDirectory() && !isMusicFile(file)) {
231  0 iterator.remove();
232    }
233    }
234  24 return files;
235    }
236   
 
237  19 toggle private static boolean isMusicFile(File file) {
238  19 String extension = getExtension(file.getName());
239  19 return MUSIC_FILE_EXTENSIONS.contains(extension);
240    }
241   
242    /**
243    * Returns the extension (the substring after the last dot) of the given file. The dot
244    * is not included in the returned extension.
245    *
246    * @param name The filename in question.
247    * @return The extension, or an empty string if no extension is found.
248    */
 
249  417 toggle public static String getExtension(String name) {
250  417 int index = name.lastIndexOf('.');
251  417 return index == -1 ? "" : name.substring(index + 1).toLowerCase();
252    }
253   
254    /**
255    * Returns the base name (the substring before the last dot) of the given file. The dot
256    * is not included in the returned basename.
257    *
258    * @param name The filename in question.
259    * @return The base name, or an empty string if no basename is found.
260    */
 
261  394 toggle public static String getBaseName(String name) {
262  394 int index = name.lastIndexOf('.');
263  394 return index == -1 ? name : name.substring(0, index);
264    }
265   
 
266  59 toggle public static <T extends Serializable> boolean serialize(Context context, T obj, String fileName) {
267  59 File file = new File(context.getCacheDir(), fileName);
268  59 ObjectOutputStream out = null;
269  59 try {
270  59 out = new ObjectOutputStream(new FileOutputStream(file));
271  59 out.writeObject(obj);
272  59 Log.i(TAG, "Serialized object to " + file);
273  59 return true;
274    } catch (Throwable x) {
275  0 Log.w(TAG, "Failed to serialize object to " + file);
276  0 return false;
277    } finally {
278  59 Util.close(out);
279    }
280    }
281   
 
282  5 toggle public static <T extends Serializable> T deserialize(Context context, String fileName) {
283  5 File file = new File(context.getCacheDir(), fileName);
284  5 if (!file.exists() || !file.isFile()) {
285  3 return null;
286    }
287   
288  2 ObjectInputStream in = null;
289  2 try {
290  2 in = new ObjectInputStream(new FileInputStream(file));
291  2 T result = (T) in.readObject();
292  2 Log.i(TAG, "Deserialized object from " + file);
293  2 return result;
294    } catch (Throwable x) {
295  0 Log.w(TAG, "Failed to deserialize object from " + file, x);
296  0 return null;
297    } finally {
298  2 Util.close(in);
299    }
300    }
301    }