1 17 18 19 20 package org.apache.lenya.ac.file; 21 22 import java.io.File ; 23 import java.io.FileFilter ; 24 import java.io.IOException ; 25 import java.util.ArrayList ; 26 import java.util.HashMap ; 27 import java.util.HashSet ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.Map ; 31 import java.util.Set ; 32 33 import org.apache.avalon.framework.configuration.Configuration; 34 import org.apache.avalon.framework.configuration.ConfigurationException; 35 import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; 36 import org.apache.lenya.ac.AccessControlException; 37 import org.apache.lenya.ac.Group; 38 import org.apache.lenya.ac.Groupable; 39 import org.apache.lenya.ac.Item; 40 import org.apache.lenya.ac.ItemManagerListener; 41 import org.apache.lenya.ac.impl.ItemConfiguration; 42 import org.apache.log4j.Category; 43 44 47 public abstract class FileItemManager { 48 private static final Category log = Category.getInstance(FileItemManager.class); 49 50 public static final String PATH = "config" + File.separator + "ac" + File.separator + "passwd"; 51 52 private Map items = new HashMap (); 53 private File configurationDirectory; 54 private DirectoryChangeNotifier notifier; 55 56 62 protected FileItemManager(File configurationDirectory) throws AccessControlException { 63 assert configurationDirectory != null; 64 65 if (!configurationDirectory.exists() || !configurationDirectory.isDirectory()) { 66 throw new AccessControlException( 67 "The directory [" + configurationDirectory.getAbsolutePath() + "] does not exist!"); 68 } 69 70 this.configurationDirectory = configurationDirectory; 71 notifier = new DirectoryChangeNotifier(configurationDirectory, getFileFilter()); 72 loadItems(); 73 } 74 75 79 protected void loadItems() throws AccessControlException { 80 81 boolean changed; 82 try { 83 changed = notifier.hasChanged(); 84 } catch (IOException e) { 85 throw new AccessControlException(e); 86 } 87 88 if (changed) { 89 90 if (log.isDebugEnabled()) { 91 log.debug("Item configuration has changed - reloading."); 92 } 93 94 File [] addedFiles = notifier.getAddedFiles(); 95 96 for (int i = 0; i < addedFiles.length; i++) { 97 Item item = loadItem(addedFiles[i]); 98 add(item); 99 } 100 101 File [] removedFiles = notifier.getRemovedFiles(); 102 for (int i = 0; i < removedFiles.length; i++) { 103 String fileName = removedFiles[i].getName(); 104 String id = fileName.substring(0, fileName.length() - getSuffix().length()); 105 106 Item item = (Item) items.get(id); 107 108 if (item != null) { 109 110 if (item instanceof Groupable) { 111 ((Groupable) item).removeFromAllGroups(); 112 } 113 if (item instanceof Group) { 114 ((Group) item).removeAllMembers(); 115 } 116 117 remove(item); 118 } 119 } 120 121 File [] changedFiles = notifier.getChangedFiles(); 122 for (int i = 0; i < changedFiles.length; i++) { 123 Item item = loadItem(changedFiles[i]); 124 update(item); 125 } 126 127 } 128 129 } 130 131 137 protected Item loadItem(File file) throws AccessControlException { 138 Configuration config = getItemConfiguration(file); 139 140 String fileName = file.getName(); 141 String id = fileName.substring(0, fileName.length() - getSuffix().length()); 142 Item item = (Item) items.get(id); 143 144 String klass = getItemClass(config); 145 if (item == null) { 146 try { 147 item = (Item) Class.forName(klass).newInstance(); 148 } catch (Exception e) { 149 String errorMsg = 150 "Exception when trying to instanciate: " 151 + klass 152 + " with exception: " 153 + e.fillInStackTrace(); 154 155 log.error(errorMsg); 158 throw new AccessControlException(errorMsg, e); 159 } 160 item.setConfigurationDirectory(configurationDirectory); 161 } 162 163 try { 164 item.configure(config); 165 } catch (ConfigurationException e) { 166 String errorMsg = "Exception when trying to configure: " + klass; 167 throw new AccessControlException(errorMsg, e); 168 } 169 return item; 170 } 171 172 178 protected String getItemClass(Configuration config) throws AccessControlException { 179 String klass = null; 180 181 try { 182 klass = config.getAttribute(ItemConfiguration.CLASS_ATTRIBUTE); 183 } catch (ConfigurationException e) { 184 String errorMsg = 185 "Exception when extracting class name from identity file: " 186 + klass 187 + config.getAttributeNames(); 188 log.error(errorMsg); 189 throw new AccessControlException(errorMsg, e); 190 } 191 return klass; 192 } 193 194 200 protected Configuration getItemConfiguration(File file) throws AccessControlException { 201 DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder(); 202 Configuration config = null; 203 204 try { 205 assert file.exists(); 206 config = builder.buildFromFile(file); 207 } catch (Exception e) { 208 String errorMsg = 209 "Exception when reading the configuration from file: " + file.getName(); 210 211 log.error(errorMsg); 214 throw new AccessControlException(errorMsg, e); 215 } 216 return config; 217 } 218 219 protected void removeItem(File file) { 220 } 221 222 227 public Item getItem(String id) { 228 try { 229 loadItems(); 230 } catch (AccessControlException e) { 231 throw new IllegalStateException (e.getMessage()); 232 } 233 return (Item) items.get(id); 234 } 235 236 241 public Item[] getItems() { 242 try { 243 loadItems(); 244 } catch (AccessControlException e) { 245 throw new IllegalStateException (e.getMessage()); 246 } 247 return (Item[]) items.values().toArray(new Item[items.values().size()]); 248 } 249 250 256 public void add(Item item) throws AccessControlException { 257 assert item != null; 258 items.put(item.getId(), item); 259 if (log.isDebugEnabled()) { 260 log.debug("Item [" + item + "] added."); 261 } 262 notifyAdded(item); 263 } 264 265 270 public void remove(Item item) throws AccessControlException { 271 items.remove(item.getId()); 272 if (log.isDebugEnabled()) { 273 log.debug("Item [" + item + "] removed."); 274 } 275 notifyRemoved(item); 276 } 277 278 283 public void update(Item newItem) throws AccessControlException { 284 items.remove(newItem.getId()); 285 items.put(newItem.getId(), newItem); 286 if (log.isDebugEnabled()) { 287 log.debug("Item [" + newItem + "] updated."); 288 } 289 } 290 291 296 public boolean contains(Item item) { 297 try { 298 loadItems(); 299 } catch (AccessControlException e) { 300 throw new IllegalStateException (e.getMessage()); 301 } 302 return items.containsValue(item); 303 } 304 305 310 public File getConfigurationDirectory() { 311 return configurationDirectory; 312 } 313 314 318 protected FileFilter getFileFilter() { 319 FileFilter filter = new FileFilter () { 320 public boolean accept(File pathname) { 321 return (pathname.getName().endsWith(getSuffix())); 322 } 323 }; 324 325 return filter; 326 } 327 328 332 protected abstract String getSuffix(); 333 334 private List itemManagerListeners = new ArrayList (); 335 336 340 public void addItemManagerListener(ItemManagerListener listener) { 341 log.debug("Adding listener: [" + listener + "]"); 342 if (!itemManagerListeners.contains(listener)) { 343 itemManagerListeners.add(listener); 344 } 345 } 346 347 351 public void removeItemManagerListener(ItemManagerListener listener) { 352 log.debug("Removing listener: [" + listener + "]"); 353 itemManagerListeners.remove(listener); 354 } 355 356 361 protected void notifyAdded(Item item) throws AccessControlException { 362 log.debug("Item was added: [" + item + "]"); 363 List clone = new ArrayList (itemManagerListeners); 364 for (Iterator i = clone.iterator(); i.hasNext();) { 365 ItemManagerListener listener = (ItemManagerListener) i.next(); 366 listener.itemAdded(item); 367 } 368 } 369 370 375 protected void notifyRemoved(Item item) throws AccessControlException { 376 log.debug("Item was removed: [" + item + "]"); 377 List clone = new ArrayList (itemManagerListeners); 378 for (Iterator i = clone.iterator(); i.hasNext();) { 379 ItemManagerListener listener = (ItemManagerListener) i.next(); 380 log.debug("Notifying listener: [" + listener + "]"); 381 listener.itemRemoved(item); 382 } 383 } 384 385 388 public static class DirectoryChangeNotifier { 389 390 395 public DirectoryChangeNotifier(File directory, FileFilter filter) { 396 this.directory = directory; 397 this.filter = filter; 398 } 399 400 private File directory; 401 private FileFilter filter; 402 private Map canonicalPath2LastModified = new HashMap (); 403 private static final Category log = Category.getInstance(DirectoryChangeNotifier.class); 404 405 private Set addedFiles = new HashSet (); 406 private Set removedFiles = new HashSet (); 407 private Set changedFiles = new HashSet (); 408 409 414 public boolean hasChanged() throws IOException { 415 416 addedFiles.clear(); 417 removedFiles.clear(); 418 changedFiles.clear(); 419 420 File [] files = directory.listFiles(filter); 421 422 Set newPathSet = new HashSet (); 423 424 for (int i = 0; i < files.length; i++) { 425 String canonicalPath = files[i].getCanonicalPath(); 426 newPathSet.add(canonicalPath); 427 428 if (!canonicalPath2LastModified.containsKey(canonicalPath)) { 429 addedFiles.add(new File (canonicalPath)); 430 431 if (log.isDebugEnabled()) { 432 log.debug("New file: [" + canonicalPath + "]"); 433 } 434 435 } else { 436 Long lastModifiedObject = (Long ) canonicalPath2LastModified.get(canonicalPath); 437 long lastModified = lastModifiedObject.longValue(); 438 if (lastModified < files[i].lastModified()) { 439 changedFiles.add(files[i]); 440 if (log.isDebugEnabled()) { 441 log.debug("File has changed: [" + canonicalPath + "]"); 442 } 443 } 444 } 445 Long lastModified = new Long (files[i].lastModified()); 446 canonicalPath2LastModified.put(canonicalPath, lastModified); 447 } 448 449 Set oldPathSet = canonicalPath2LastModified.keySet(); 450 String [] oldPaths = (String []) oldPathSet.toArray(new String [oldPathSet.size()]); 451 for (int i = 0; i < oldPaths.length; i++) { 452 if (!newPathSet.contains(oldPaths[i])) { 453 removedFiles.add(new File (oldPaths[i])); 454 canonicalPath2LastModified.remove(oldPaths[i]); 455 if (log.isDebugEnabled()) { 456 log.debug("File removed: [" + oldPaths[i] + "]"); 457 } 458 } 459 } 460 461 return !addedFiles.isEmpty() || !removedFiles.isEmpty() || !changedFiles.isEmpty(); 462 } 463 464 468 public File [] getAddedFiles() { 469 return (File []) addedFiles.toArray(new File [addedFiles.size()]); 470 } 471 472 476 public File [] getRemovedFiles() { 477 return (File []) removedFiles.toArray(new File [removedFiles.size()]); 478 } 479 480 484 public File [] getChangedFiles() { 485 return (File []) changedFiles.toArray(new File [changedFiles.size()]); 486 } 487 488 } 489 490 } 491 | Popular Tags |