| 1 | //  Copyright 2004-2007 Jean-Francois Poilpret | 
| 2 | // | 
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
| 4 | // you may not use this file except in compliance with the License. | 
| 5 | // You may obtain a copy of the License at | 
| 6 | // | 
| 7 | //     http://www.apache.org/licenses/LICENSE-2.0 | 
| 8 | // | 
| 9 | // Unless required by applicable law or agreed to in writing, software | 
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | 
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
| 12 | // See the License for the specific language governing permissions and | 
| 13 | // limitations under the License. | 
| 14 |   | 
| 15 | package net.sourceforge.hiveboard.business; | 
| 16 |   | 
| 17 | import java.util.HashMap; | 
| 18 | import java.util.Map; | 
| 19 |   | 
| 20 | import org.apache.commons.logging.Log; | 
| 21 |   | 
| 22 | import org.apache.hivemind.Resource; | 
| 23 | import org.apache.hivemind.events.RegistryShutdownListener; | 
| 24 |   | 
| 25 | import net.sf.ehcache.Cache; | 
| 26 | import net.sf.ehcache.CacheException; | 
| 27 | import net.sf.ehcache.CacheManager; | 
| 28 |   | 
| 29 | import net.sourceforge.hiveboard.Board; | 
| 30 | import net.sourceforge.hiveboard.dao.BoardDAO; | 
| 31 | import net.sourceforge.hiveutils.service.ObjectTools; | 
| 32 |   | 
| 33 | /** | 
| 34 |  * Implementation of the Board Repository service. | 
| 35 |  * The repository is initalized from the database at construction time. | 
| 36 |  * | 
| 37 |  * @author Jean-Francois Poilpret | 
| 38 |  */ | 
| 39 | public class BoardRepositoryImpl implements BoardRepository, RegistryShutdownListener | 
| 40 | { | 
| 41 |         public BoardRepositoryImpl(        Log                        logger, | 
| 42 |                                                                 BoardDAO        dao, | 
| 43 |                                                                 ObjectTools        objectTools, | 
| 44 |                                                                 Resource        cacheConfig, | 
| 45 |                                                                 long                updateImageTime) | 
| 46 |                 throws CacheException | 
| 47 |         { | 
| 48 |                 _logger = logger; | 
| 49 |                 _dao = dao; | 
| 50 |                 _objectTools = objectTools; | 
| 51 |                 // Read all Boards (except images) | 
| 52 |                 _boards = _dao.selectActiveBoards(); | 
| 53 |                 _maxDiscriminator = dao.selectMaxDiscriminator(); | 
| 54 |                 _manager = CacheManager.create(cacheConfig.getResourceURL()); | 
| 55 |                 _cache = _manager.getCache("BoardImageCache"); | 
| 56 |                 _updateImageTime = updateImageTime; | 
| 57 |                 _imageUpdater = new Thread(new Runnable() | 
| 58 |                 { | 
| 59 |                         public void        run() | 
| 60 |                         { | 
| 61 |                                 loopImageUpdate(); | 
| 62 |                         } | 
| 63 |                 }); | 
| 64 |                 _imageUpdater.start(); | 
| 65 |         } | 
| 66 |          | 
| 67 |         synchronized private void        loopImageUpdate() | 
| 68 |         { | 
| 69 |                 while (!_stopped) | 
| 70 |                 { | 
| 71 |                         try | 
| 72 |                         { | 
| 73 |                                 wait(_updateImageTime); | 
| 74 |                         } | 
| 75 |                         catch (InterruptedException e) | 
| 76 |                         { | 
| 77 |                                 _logger.error("loopImageUpdate()", e); | 
| 78 |                         } | 
| 79 |                         saveAllImages(); | 
| 80 |                 } | 
| 81 |         } | 
| 82 |          | 
| 83 |         public void        registryDidShutdown() | 
| 84 |         { | 
| 85 |                 synchronized (this) | 
| 86 |                 { | 
| 87 |                         // Stop image saving thread | 
| 88 |                         // (this will force save of all Images to DB) | 
| 89 |                         _stopped = true; | 
| 90 |                         notifyAll(); | 
| 91 |                 } | 
| 92 |                 waitEndImageUpdaterThread(); | 
| 93 |         } | 
| 94 |          | 
| 95 |         private void        waitEndImageUpdaterThread() | 
| 96 |         { | 
| 97 |                 try | 
| 98 |                 { | 
| 99 |                         // Wait until thread has finished saving all images | 
| 100 |                         _imageUpdater.join(); | 
| 101 |                         _logger.debug("waitEndImageUpdaterThread() ImageUpdater Thread joined"); | 
| 102 |                 } | 
| 103 |                 catch (InterruptedException e) | 
| 104 |                 { | 
| 105 |                         _logger.error("waitEndImageUpdaterThread()", e); | 
| 106 |                 } | 
| 107 |         } | 
| 108 |          | 
| 109 |         synchronized private void        saveAllImages() | 
| 110 |         { | 
| 111 |                 _logger.debug("saveAllImages()"); | 
| 112 |                 for (BoardImageHolder holder: _holders.values()) | 
| 113 |                 { | 
| 114 |                         holder.save(); | 
| 115 |                 } | 
| 116 |         } | 
| 117 |          | 
| 118 |         synchronized public Board        getBoard(int id, boolean clone) | 
| 119 |         { | 
| 120 |                 Board board = _boards.get(id); | 
| 121 |                 if (board == null) | 
| 122 |                 { | 
| 123 |                         return null; | 
| 124 |                 } | 
| 125 |                 if (clone) | 
| 126 |                 { | 
| 127 |                         return board.copy(); | 
| 128 |                 } | 
| 129 |                 else | 
| 130 |                 { | 
| 131 |                         return board; | 
| 132 |                 } | 
| 133 |         } | 
| 134 |          | 
| 135 |         synchronized public void        changeBoard(Board board) | 
| 136 |         { | 
| 137 |                 if (board == null) | 
| 138 |                 { | 
| 139 |                         return; | 
| 140 |                 } | 
| 141 |                 _boards.put(board.getId(), board); | 
| 142 |         } | 
| 143 |          | 
| 144 |         synchronized public void        addBoard(Board board) | 
| 145 |         { | 
| 146 |                 if (board == null) | 
| 147 |                 { | 
| 148 |                         return; | 
| 149 |                 } | 
| 150 |                 _boards.put(board.getId(), board); | 
| 151 |         } | 
| 152 |          | 
| 153 |         synchronized public int                removeBoard(int id) | 
| 154 |         { | 
| 155 |                 _boards.remove(id); | 
| 156 |                 removeImageHolder(id); | 
| 157 |                 _maxDiscriminator++; | 
| 158 |                 return _maxDiscriminator; | 
| 159 |         } | 
| 160 |          | 
| 161 |         synchronized public Board[]        getBoards(boolean clone) | 
| 162 |         { | 
| 163 |                 Board[] boards = _boards.values().toArray(new Board[_boards.size()]); | 
| 164 |                 if (clone) | 
| 165 |                 { | 
| 166 |                         for (int i = 0; i < boards.length; i++) | 
| 167 |                         { | 
| 168 |                                 boards[i] = boards[i].copy(); | 
| 169 |                         } | 
| 170 |                 } | 
| 171 |                 return boards; | 
| 172 |         } | 
| 173 |   | 
| 174 |         public BoardImageHolder                getImageHolder(int idBoard) | 
| 175 |         { | 
| 176 |                 Board board        = getBoard(idBoard, true); | 
| 177 |                 BoardImageHolder holder = getHolder(idBoard); | 
| 178 |                 if (holder == null) | 
| 179 |                 { | 
| 180 |                         holder = new BoardImageHolderImpl(_dao, _objectTools, _cache, board); | 
| 181 |                         setHolder(idBoard, holder); | 
| 182 |                 } | 
| 183 |                 return holder; | 
| 184 |         } | 
| 185 |   | 
| 186 |         synchronized private BoardImageHolder        getHolder(int idBoard) | 
| 187 |         { | 
| 188 |                 return _holders.get(idBoard); | 
| 189 |         } | 
| 190 |   | 
| 191 |         synchronized private void        setHolder(int idBoard, BoardImageHolder holder) | 
| 192 |         { | 
| 193 |                 _holders.put(idBoard, holder); | 
| 194 |         } | 
| 195 |          | 
| 196 |         synchronized public void                removeImageHolder(int board) | 
| 197 |         { | 
| 198 |                 BoardImageHolder holder = _holders.remove(board); | 
| 199 |                 if (holder != null) | 
| 200 |                 { | 
| 201 |                         holder.save(); | 
| 202 |                         holder.dispose(); | 
| 203 |                 } | 
| 204 |         } | 
| 205 |   | 
| 206 |         private final Log                                                                _logger; | 
| 207 |         private final BoardDAO                                                        _dao; | 
| 208 |         private final ObjectTools                                                _objectTools; | 
| 209 |         private final Map<Integer, Board>                                _boards; | 
| 210 |         private int                                                                                _maxDiscriminator; | 
| 211 |         private final Map<Integer, BoardImageHolder>        _holders = | 
| 212 |                                                                                                 new HashMap<Integer, BoardImageHolder>(); | 
| 213 |         private final CacheManager                                                _manager; | 
| 214 |         private final Cache                                                                _cache; | 
| 215 |         private final long                                                                _updateImageTime; | 
| 216 |         private final Thread                                                        _imageUpdater; | 
| 217 |         private boolean                                                                        _stopped = false; | 
| 218 | } |