001    // ============================================== 
002    //                                                                                              
003    // Module-Imaging 1.0, 05-2006                  
004    // +++++++++++++++++++++++++++++++++++++                        
005    //                                                                                              
006    // Andreas Trappe       - idea, concept
007    // Chi Vu Huu           - concept, development
008    //
009    // $Revision$ $Date$ 
010    // ============================================== 
011    
012    package org.mycore.services.imaging;
013    
014    import java.awt.Dimension;
015    import java.io.IOException;
016    import java.io.InputStream;
017    import java.io.OutputStream;
018    
019    import org.apache.log4j.Logger;
020    import org.jdom.Element;
021    import org.jdom.JDOMException;
022    import org.mycore.common.MCRException;
023    import org.mycore.datamodel.ifs.MCRDirectory;
024    import org.mycore.datamodel.ifs.MCRFile;
025    import org.mycore.datamodel.ifs.MCRFilesystemNode;
026    
027    /*******************************************************************************
028     * The MCRImgCacheManager deliver the method for getting data into and out of
029     * the cache structure which lies in the IFS.<br>
030     * The cache structure is just an one level flat tree:<br>
031     * |--> [imgCache] --> [cached Image File] --> [versions of image]<br>
032     * <br>
033     * 
034     * Cached image file is a subfolder of the root node imgCache in IFS. The name
035     * is composed the following:<br>
036     * ownerID + absolute path + filename<br>
037     * in absolute path the "/" is replaced by "%20"
038     * 
039     * 
040     * @version 0.01pre 03/01/2006<br>
041     *          1.00 08/08/2006
042     * @author Vu Huu Chi
043     * 
044     */
045    
046    public class MCRImgCacheManager implements CacheManager {
047        public static final String THUMB = "Thumb";
048    
049        public static final String CACHE = "Cache";
050    
051        public static final String ORIG = "Orig";
052    
053        public static final String CACHE_FOLDER = "imgCache";
054    
055        private Logger LOGGER = Logger.getLogger(MCRImgCacheManager.class.getName());
056    
057        private static MCRDirectory cacheInIFS = null;
058    
059        private static MCRImgCacheManager cacheManager;
060    
061        public synchronized static MCRImgCacheManager instance() {
062            if (cacheManager == null)
063                cacheManager = new MCRImgCacheManager();
064    
065            return cacheManager;
066        }
067    
068        private MCRImgCacheManager() {
069            cacheInIFS = (MCRDirectory) MCRFilesystemNode.getRootNode(CACHE_FOLDER);
070            
071            if (cacheInIFS == null) {
072                LOGGER.info("Img Cache not exist, creating new one");
073                try {
074                    cacheInIFS = new MCRDirectory(CACHE_FOLDER, CACHE_FOLDER);
075                } catch (Exception e) {
076                    throw new MCRException(e.getMessage());
077                }
078            }
079        }
080    
081        public void getImage(MCRFile image, String filename, OutputStream imageData) {
082            MCRFilesystemNode cachedImg = cacheInIFS.getChildByPath(buildPath(image) + "/" + filename);
083            LOGGER.debug("Path in cache: " + cachedImg.getAbsolutePath());
084    
085            if (cachedImg != null && cachedImg instanceof MCRFile) {
086                Stopwatch timer = new Stopwatch();
087    
088                timer.start();
089                ((MCRFile) cachedImg).getContentTo(imageData);
090                timer.stop();
091                LOGGER.info("getContentTo: " + timer.getElapsedTime());
092            } else
093                throw new MCRException("Could not load " + image.getName() + "from cache!");
094        }
095    
096        public InputStream getImageAsInputStream(MCRFile image, String filename) throws IOException {
097            MCRFilesystemNode cachedImg = cacheInIFS.getChildByPath(buildPath(image) + "/" + filename);
098            LOGGER.debug("Path in cache: " + cachedImg.getAbsolutePath());
099    
100            if (cachedImg != null && cachedImg instanceof MCRFile) {
101                LOGGER.debug("Return Image from Cache as InputStream.");
102                return ((MCRFile) cachedImg).getContentAsInputStream();
103            } else {
104                LOGGER.debug("Return Null.");
105                return null;
106            }
107        }
108    
109        public void saveImage(MCRFile image, Dimension size, InputStream imageData) {
110            saveImage(image, dimToString(size), imageData);
111        }
112    
113        public void saveImage(MCRFile image, String filename, InputStream imageData) {
114    
115            MCRDirectory cachedImg = getCacheDir(image);
116    
117            if (cachedImg == null)
118                cachedImg = setCacheDir(image);
119    
120            try {
121                MCRFile cachedImgIFS = new MCRFile(filename + "lock", cachedImg);
122    
123                cachedImgIFS.setContentFrom(imageData);
124                cachedImgIFS.setName(filename);
125            } catch (Exception e) {
126                throw new MCRException("Could not save Image " + image.getName() + " as " + filename + " in cache!");
127            }
128        }
129    
130        public void deleteImage(MCRFile image, Dimension size) {
131            deleteImage(image, dimToString(size));
132        }
133    
134        public void deleteImage(MCRFile image, String filename) {
135            MCRFilesystemNode cachedImg = cacheInIFS.getChildByPath(buildPath(image) + "/" + filename);
136    
137            if (cachedImg != null && cachedImg instanceof MCRFile)
138                ((MCRFile) cachedImg).delete();
139            else
140                LOGGER.debug("Could not delete " + image.getName() + "from cache!");
141            // throw new MCRException("Could not delete " + image.getName() + "from
142            // cache!");
143    
144        }
145    
146        public void deleteImage(MCRFile image) {
147            MCRFilesystemNode cachedImg = cacheInIFS.getChildByPath(buildPath(image));
148    
149            if (cachedImg != null && cachedImg instanceof MCRDirectory) {
150                LOGGER.debug("MCRImgCacheManager - deleteImage");
151                LOGGER.debug("Delte : " + cachedImg.getName());
152                ((MCRDirectory) cachedImg).delete();
153            } else
154                LOGGER.debug("Could not delete " + image.getName() + "from cache!");
155            // throw new MCRException("Could not delete " + image.getName() + "from
156            // cache!");
157    
158        }
159    
160        public boolean existInCache(MCRFile image, String filename) {
161            MCRFilesystemNode cachedImg = cacheInIFS.getChildByPath(buildPath(image) + "/" + filename);
162    
163            if (cachedImg != null && cachedImg instanceof MCRFile) {
164    
165                return true;
166            } else
167                return false;
168        }
169    
170        public boolean existInCache(MCRFile image) {
171            return (existInCache(image, THUMB) || existInCache(image, ORIG) || existInCache(image, CACHE));
172        }
173    
174        public Dimension getImgDimension(MCRFile image) {
175            Dimension dim = new Dimension();
176            try {
177                Element addData = image.getAdditionalData("ImageMetaData");
178        
179                if (addData != null) {
180                    dim.width = Integer.parseInt(addData.getChild("imageSize").getChild("width").getText());
181                    dim.height = Integer.parseInt(addData.getChild("imageSize").getChild("height").getText());
182                }
183            } catch (Exception e) {
184                e.printStackTrace();
185            }
186            return dim;
187        }
188    
189        public int getImgWidth(MCRFile image) {
190            int width = 0;
191    
192            try {
193                Element addData = image.getAdditionalData("ImageMetaData");
194    
195                if (addData != null) {
196                    width = (new Integer(addData.getChild("imageSize").getChild("width").getText())).intValue();
197                }
198            } catch (IOException e) {
199                // TODO Auto-generated catch block
200                e.printStackTrace();
201            } catch (JDOMException e) {
202                // TODO Auto-generated catch block
203                e.printStackTrace();
204            }
205    
206            return width;
207        }
208    
209        public int getImgHeight(MCRFile image) {
210            int height = 0;
211    
212            try {
213                Element addData = image.getAdditionalData("ImageMetaData");
214    
215                if (addData != null) {
216                    height = (new Integer(addData.getChild("imageSize").getChild("height").getText())).intValue();
217                }
218            } catch (IOException e) {
219                // TODO Auto-generated catch block
220                e.printStackTrace();
221            } catch (JDOMException e) {
222                // TODO Auto-generated catch block
223                e.printStackTrace();
224            }
225    
226            return height;
227        }
228    
229        public void setImgSize(MCRFile image, int width, int height) {
230            try {
231                Element addData = image.getAdditionalData("ImageMetaData");
232                if (addData == null) {
233                    addData = new Element("ImageMetaData").addContent(new Element("imageSize"));
234                    Element elem = addData.getChild("imageSize");
235                    elem.addContent((new Element("width")).setText(String.valueOf(width)));
236                    elem.addContent((new Element("height")).setText(String.valueOf(height)));
237                    image.setAdditionalData(addData);
238    
239                    LOGGER.info("Writing additional data for " + image.getName() + " complete!");
240                } else
241                    LOGGER.info("Additional data for " + image.getName() + " allready exists!");
242            } catch (IOException e) {
243                // TODO Auto-generated catch block
244                e.printStackTrace();
245            } catch (JDOMException e) {
246                // TODO Auto-generated catch block
247                e.printStackTrace();
248            }
249        }
250    
251        /* *********************************************************************************************** */
252        /* End implement interface */
253        /* *********************************************************************************************** */
254    
255        private MCRDirectory getCacheDir(MCRFile image) {
256            String path = buildPath(image);
257            MCRFilesystemNode node = cacheInIFS.getChildByPath(path);
258            MCRDirectory cachedImg = null;
259    
260            LOGGER.info("PATH for img in Cache: " + path);
261            LOGGER.info("Node: " + node);
262            LOGGER.info("Directory: " + (node instanceof MCRDirectory));
263    
264            if (node != null && node instanceof MCRDirectory) {
265                cachedImg = (MCRDirectory) node;
266                LOGGER.debug("Path in cache found: " + cachedImg.getAbsolutePath());
267            } else {
268                // cachedImg = new MCRDirectory(path, cacheInIFS);
269                LOGGER.debug("No path in cache!" + path);
270            }
271            return cachedImg;
272        }
273    
274        private MCRDirectory setCacheDir(MCRFile image) {
275            String path = buildPath(image);
276            MCRDirectory dir = new MCRDirectory(path, cacheInIFS);
277    
278            return dir;
279        }
280    
281        private String buildPath(MCRFile image) {
282            String ownerID = image.getOwnerID();
283            String absPath = image.getAbsolutePath().replaceAll("/", "%20");
284    
285            return ownerID + absPath;
286        }
287    
288        // return 'width'x'height' as String
289        private String dimToString(Dimension size) {
290            return size.width + "x" + size.height;
291        }
292    
293        public boolean existInCache(MCRFile image, Dimension size) {
294            return existInCache(image, dimToString(size));
295        }
296    
297        public void deleteCache() {
298            MCRFilesystemNode[] children = cacheInIFS.getChildren();
299    
300            for (int i = 0; i < children.length; i++) {
301                children[i].delete();
302            }
303        }
304    }