(no commit message)
[utils] / mythtv / src / main / java / org / wamblee / mythtv / LinkStructure.java
1 /*
2  * Copyright 2006 the original author or authors.
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.wamblee.mythtv;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.text.SimpleDateFormat;
22 import java.util.HashMap;
23 import java.util.Map;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.wamblee.io.SimpleProcess;
28 import org.wamblee.io.DirectoryMonitor.Listener;
29
30 /**
31  * Link structure.
32  */
33 public class LinkStructure implements Listener {
34
35     private static final Log LOG = LogFactory.getLog(LinkStructure.class);
36
37     private String _monitorDir = "/mnt/vcr";
38
39     private File _linkDir;
40
41     private RecordingDatabase _database;
42
43     private SimpleDateFormat _format;
44     
45     private Map<File,Recording> _recordings; 
46
47     public LinkStructure(String aMonitorDir, File aLinkDir,
48             RecordingDatabase aDatabase) {
49         _monitorDir = aMonitorDir + "/";
50         _linkDir = aLinkDir;
51         _database = aDatabase;
52         _format = new SimpleDateFormat("yyyy-MM-dd-HH:mm");
53         _recordings = new HashMap<File,Recording>();
54     }
55
56     /*
57      * (non-Javadoc)
58      * 
59      * @see org.wamblee.io.DirectoryMonitor.Listener#fileChanged(java.io.File)
60      */
61     public void fileChanged(File aFile) {
62         LOG.debug("file changed " + aFile);
63
64         // Re-assess file type
65         Recording recording = _recordings.get(aFile);
66         LOG.debug("Recording changed " + recording);
67         String dir = getDirectory(recording);
68         FileType type = getFileType(aFile);
69         String path = dir + "/" + getFilename(recording, type);
70
71         if (exists(dir + "/" + getFilename(recording, type))) {
72             // Nothing to do.
73         } else {
74             mkdir(dir);
75             for (FileType t : FileType.values()) {
76                 rmlink(dir + "/" + getFilename(recording, t));
77             }
78             createSymLink(_monitorDir + aFile.getName(), dir + "/"
79                     + getFilename(recording, type));
80         }
81     }
82
83     /*
84      * (non-Javadoc)
85      * 
86      * @see org.wamblee.io.DirectoryMonitor.Listener#fileCreated(java.io.File)
87      */
88     public void fileCreated(File aFile) {
89         LOG.debug("file created " + aFile);
90         Recording recording = _database.findRecording(aFile.getName());
91         _recordings.put(aFile, recording);
92         LOG.info("New recording detected " + aFile + " "
93                 + recording);
94       
95         recording.setFilesize(aFile.length());
96         _database.update(recording);
97         String dir = getDirectory(recording);
98         mkdir(dir);
99         createSymLink(_monitorDir + aFile.getName(), dir + "/"
100                 + getFilename(recording, getFileType(aFile)));
101     }
102
103     /*
104      * (non-Javadoc)
105      * 
106      * @see org.wamblee.io.DirectoryMonitor.Listener#fileDeleted(java.io.File)
107      */
108     public void fileDeleted(File aFile) {
109         LOG.debug("file deleted " + aFile);
110         Recording recording = _recordings.get(aFile);
111         _recordings.remove(recording);
112         LOG.info("recording deleted " + recording);
113         String dir = getDirectory(recording);
114         for (FileType t: FileType.values()) {
115             rmlink(dir + "/" + getFilename(recording, t));
116         }
117         rmdir(dir);
118     }
119
120     private String getDirectory(Recording aRecording) {
121         return aRecording.getTitle();
122     }
123
124     private FileType getFileType(File aFile) {
125         SimpleProcess process = new SimpleProcess(new File(_monitorDir), new String[] {
126                 "file", aFile.getName() });
127         try {
128             process.run();
129             if (process.getStdout().contains("RIFF")) {
130                 return FileType.AVI;
131             } else {
132                 return FileType.MPG;
133             }
134         } catch (IOException e) {
135             LOG.error("Determining filetype for " + aFile + " failed", e);
136             return FileType.MPG;
137         }
138     }
139
140     private String getFilename(Recording aRecording, FileType aType) {
141         return _format.format(aRecording.getProgstart()) + "-"
142                 + aRecording.getSubtitle() + "-"
143                 + aRecording.getChannel().getName() + "."
144                 + aType.toString().toLowerCase();
145     }
146
147     private boolean exists(String aPath) {
148         LOG.debug("exists " + aPath);
149         return new File(_linkDir, aPath).exists();
150     }
151
152     private void rmlink(String aPath) {
153         LOG.debug("rmlink " + aPath);
154         File link = new File(_linkDir, aPath);
155         //if ( !link.exists()) { 
156         //    return; 
157        // }
158         if (!link.delete()) {
159             LOG.warn("Delete failed: " + aPath);
160         } else { 
161             LOG.info("Removed link " + link);
162         }
163     }
164
165     private void mkdir(String aDir) {
166         LOG.debug("mkdir " + aDir);
167         File dir = new File(_linkDir, aDir);
168         if ( dir.isDirectory()) { 
169             return; 
170         }
171         if (!dir.mkdirs()) {
172             LOG.warn("Could not create directory path: " + aDir);
173         } else { 
174             LOG.info("Created directory " + dir);
175         }
176     }
177
178     private void rmdir(String aDir) {
179         LOG.debug("rmdir " + aDir);
180         File dir = new File(_linkDir, aDir);
181         if (!dir.delete()) {
182             LOG.warn("Directory not deleted (still recordings left): " + aDir);
183         } else { 
184             LOG.info("Directory " + dir + " deleted.");
185         }
186     }
187
188     private void createSymLink(String aTarget, String aSource) {
189         try {
190             SimpleProcess process = new SimpleProcess(_linkDir, new String[] {
191                     "ln", "-s", aTarget, aSource });
192             process.run();
193             LOG.info("Created symlink " + aSource + " -> " + aTarget);
194         } catch (IOException e) {
195             LOG.error(
196                     "Could not create symlink: " + aTarget + " <- " + aSource,
197                     e);
198         }
199     }
200
201 }