Author: gnodet Date: Mon Oct 12 09:18:33 2009 New Revision: 824270 URL: http://svn.apache.org/viewvc?rev=824270&view=rev Log: FELIX-1628: fileinstall should load configurations as soon as config admin is available
Modified: felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/FileInstall.java felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/Scanner.java Modified: felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java URL: http://svn.apache.org/viewvc/felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java?rev=824270&r1=824269&r2=824270&view=diff ============================================================================== --- felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java (original) +++ felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java Mon Oct 12 09:18:33 2009 @@ -77,6 +77,7 @@ public final static String TMPDIR = "felix.fileinstall.tmpdir"; public final static String FILTER = "felix.fileinstall.filter"; public final static String START_NEW_BUNDLES = "felix.fileinstall.bundles.new.start"; + public final static String NO_INITIAL_DELAY = "felix.fileinstall.noInitialDelay"; File watchedDirectory; File tmpDir; @@ -86,6 +87,7 @@ String filter; BundleContext context; String originatingFileName; + boolean noInitialDelay; // Map of all installed artifacts Map/* <File, Artifact> */ currentManagedArtifacts = new HashMap/* <File, Artifact> */(); @@ -111,6 +113,7 @@ tmpDir = getFile(properties, TMPDIR, new File("./tmp")); startBundles = getBoolean(properties, START_NEW_BUNDLES, true); // by default, we start bundles. filter = (String) properties.get(FILTER); + noInitialDelay = getBoolean(properties, NO_INITIAL_DELAY, false); FilenameFilter flt; if (filter != null && filter.length() > 0) @@ -127,6 +130,18 @@ flt = null; } scanner = new Scanner(watchedDirectory, flt); + + if (noInitialDelay) + { + log("Starting initial scan", null); + initializeCurrentManagedBundles(); + scanner.initialize(currentManagedArtifacts.keySet()); + Set/*<File>*/ files = scanner.scan(true); + if (files != null) + { + process(files); + } + } } /** @@ -143,175 +158,187 @@ + TMPDIR + " = " + tmpDir + ", " + FILTER + " = " + filter + "}", null); - initializeCurrentManagedBundles(); - - scanner.initialize(currentManagedArtifacts.keySet()); + if (!noInitialDelay) + { + initializeCurrentManagedBundles(); + scanner.initialize(currentManagedArtifacts.keySet()); + } while (!interrupted()) { try { - Set/*<File>*/ files = scanner.scan(); + Set/*<File>*/ files = scanner.scan(false); // Check that there is a result. If not, this means that the directory can not be listed, // so it's presumably not a valid directory (it may have been deleted by someone). // In such case, just sleep if (files == null) { - Thread.sleep(poll); + synchronized (this) + { + wait(poll); + } continue; } - List/*<ArtifactListener>*/ listeners = FileInstall.getListeners(); - List/*<Artifact>*/ deleted = new ArrayList/*<Artifact>*/(); - List/*<Artifact>*/ modified = new ArrayList/*<Artifact>*/(); - List/*<Artifact>*/ created = new ArrayList/*<Artifact>*/(); - - // Try to process again files that could not be processed - files.addAll(processingFailures); - processingFailures.clear(); - - for (Iterator it = files.iterator(); it.hasNext();) - { - File file = (File) it.next(); - boolean exists = file.exists(); - Artifact artifact = (Artifact) currentManagedArtifacts.get(file); - // File has been deleted - if (!exists && artifact != null) + process(files); + + synchronized (this) + { + wait(poll); + } + } + catch (InterruptedException e) + { + return; + } + catch (Throwable e) + { + log("In main loop, we have serious trouble", e); + } + } + } + + private void process(Set files) { + List/*<ArtifactListener>*/ listeners = FileInstall.getListeners(); + List/*<Artifact>*/ deleted = new ArrayList/*<Artifact>*/(); + List/*<Artifact>*/ modified = new ArrayList/*<Artifact>*/(); + List/*<Artifact>*/ created = new ArrayList/*<Artifact>*/(); + + // Try to process again files that could not be processed + files.addAll(processingFailures); + processingFailures.clear(); + + for (Iterator it = files.iterator(); it.hasNext();) + { + File file = (File) it.next(); + boolean exists = file.exists(); + Artifact artifact = (Artifact) currentManagedArtifacts.get(file); + // File has been deleted + if (!exists && artifact != null) + { + deleteJaredDirectory(artifact); + deleteTransformedFile(artifact); + deleted.add(artifact); + } + else + { + File jar = file; + // Jar up the directory if needed + if (file.isDirectory()) + { + prepareDir(tmpDir); + try { - deleteJaredDirectory(artifact); - deleteTransformedFile(artifact); - deleted.add(artifact); + jar = new File(tmpDir, file.getName() + ".jar"); + Util.jarDir(file, jar); + } - else + catch (IOException e) { - File jar = file; - // Jar up the directory if needed - if (file.isDirectory()) + log("Unable to create jar for: " + file.getAbsolutePath(), e); + continue; + } + } + // File has been modified + if (exists && artifact != null) + { + // Check the last modified date against + // the artifact last modified date if available. This will loose + // the possibility of the jar being replaced by an older one + // or the content changed without the date being modified, but + // else, we'd have to reinstall all the deployed bundles on restart. + if (artifact.getLastModified() > Util.getLastModified(file)) + { + continue; + } + // If there's no listener, this is because this artifact has been installed before + // fileinstall has been restarted. In this case, try to find a listener. + if (artifact.getListener() == null) + { + ArtifactListener listener = findListener(jar, listeners); + // If no listener can handle this artifact, we need to defer the + // processing for this artifact until one is found + if (listener == null) { - prepareDir(tmpDir); - try - { - jar = new File(tmpDir, file.getName() + ".jar"); - Util.jarDir(file, jar); - - } - catch (IOException e) - { - log("Unable to create jar for: " + file.getAbsolutePath(), e); - continue; - } + processingFailures.add(file); + continue; } - // File has been modified - if (exists && artifact != null) + artifact.setListener(listener); + } + // If the listener can not handle this file anymore, + // uninstall the artifact and try as if is was new + if (!listeners.contains(artifact.getListener()) || !artifact.getListener().canHandle(jar)) + { + deleted.add(artifact); + artifact = null; + } + // The listener is still ok + else + { + deleteTransformedFile(artifact); + artifact.setJaredDirectory(jar); + if (transformArtifact(artifact)) { - // Check the last modified date against - // the artifact last modified date if available. This will loose - // the possibility of the jar being replaced by an older one - // or the content changed without the date being modified, but - // else, we'd have to reinstall all the deployed bundles on restart. - if (artifact.getLastModified() > Util.getLastModified(file)) - { - continue; - } - // If there's no listener, this is because this artifact has been installed before - // fileinstall has been restarted. In this case, try to find a listener. - if (artifact.getListener() == null) - { - ArtifactListener listener = findListener(jar, listeners); - // If no listener can handle this artifact, we need to defer the - // processing for this artifact until one is found - if (listener == null) - { - processingFailures.add(file); - continue; - } - artifact.setListener(listener); - } - // If the listener can not handle this file anymore, - // uninstall the artifact and try as if is was new - if (!listeners.contains(artifact.getListener()) || !artifact.getListener().canHandle(jar)) - { - deleted.add(artifact); - artifact = null; - } - // The listener is still ok - else - { - deleteTransformedFile(artifact); - artifact.setJaredDirectory(jar); - if (transformArtifact(artifact)) - { - modified.add(artifact); - } - else - { - deleteJaredDirectory(artifact); - deleted.add(artifact); - } - continue; - } + modified.add(artifact); } - // File has been added - if (exists && artifact == null) + else { - // Find the listener - ArtifactListener listener = findListener(jar, listeners); - // If no listener can handle this artifact, we need to defer the - // processing for this artifact until one is found - if (listener == null) - { - processingFailures.add(file); - continue; - } - // Create the artifact - artifact = new Artifact(); - artifact.setPath(file); - artifact.setJaredDirectory(jar); - artifact.setListener(listener); - if (transformArtifact(artifact)) - { - created.add(artifact); - } - else - { - deleteJaredDirectory(artifact); - } + deleteJaredDirectory(artifact); + deleted.add(artifact); } + continue; } } - // Handle deleted artifacts - // We do the operations in the following order: - // uninstall, update, install, refresh & start. - Collection uninstalledBundles = uninstall(deleted); - Collection updatedBundles = update(modified); - Collection installedBundles = install(created); - if (uninstalledBundles.size() > 0 || updatedBundles.size() > 0) - { - // Refresh if any bundle got uninstalled or updated. - // This can lead to restart of recently updated bundles, but - // don't worry about that at this point of time. - refresh(); - } - - if (startBundles) + // File has been added + if (exists && artifact == null) { - // Try to start all the bundles that are not persistently stopped - startAllBundles(); - // Try to start newly installed bundles - start(installedBundles); + // Find the listener + ArtifactListener listener = findListener(jar, listeners); + // If no listener can handle this artifact, we need to defer the + // processing for this artifact until one is found + if (listener == null) + { + processingFailures.add(file); + continue; + } + // Create the artifact + artifact = new Artifact(); + artifact.setPath(file); + artifact.setJaredDirectory(jar); + artifact.setListener(listener); + if (transformArtifact(artifact)) + { + created.add(artifact); + } + else + { + deleteJaredDirectory(artifact); + } } - - Thread.sleep(poll); - } - catch (InterruptedException e) - { - return; - } - catch (Throwable e) - { - log("In main loop, we have serious trouble", e); } } + // Handle deleted artifacts + // We do the operations in the following order: + // uninstall, update, install, refresh & start. + Collection uninstalledBundles = uninstall(deleted); + Collection updatedBundles = update(modified); + Collection installedBundles = install(created); + if (uninstalledBundles.size() > 0 || updatedBundles.size() > 0) + { + // Refresh if any bundle got uninstalled or updated. + // This can lead to restart of recently updated bundles, but + // don't worry about that at this point of time. + refresh(); + } + + if (startBundles) + { + // Try to start all the bundles that are not persistently stopped + startAllBundles(); + // Try to start newly installed bundles + start(installedBundles); + } } ArtifactListener findListener(File artifact, List/* <ArtifactListener> */ listeners) Modified: felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/FileInstall.java URL: http://svn.apache.org/viewvc/felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/FileInstall.java?rev=824270&r1=824269&r2=824270&view=diff ============================================================================== --- felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/FileInstall.java (original) +++ felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/FileInstall.java Mon Oct 12 09:18:33 2009 @@ -115,6 +115,7 @@ set(ht, DirectoryWatcher.FILTER); set(ht, DirectoryWatcher.TMPDIR); set(ht, DirectoryWatcher.START_NEW_BUNDLES); + set(ht, DirectoryWatcher.NO_INITIAL_DELAY); updated("initial", ht); } @@ -135,12 +136,17 @@ public void stop(BundleContext context) throws Exception { - for (Iterator w = watchers.values().iterator(); w.hasNext();) + List /*<DirectoryWatcher>*/ toClose = new ArrayList /*<DirectoryWatcher>*/(); + synchronized (watchers) + { + toClose.addAll(watchers.values()); + watchers.clear(); + } + for (Iterator w = toClose.iterator(); w.hasNext();) { try { DirectoryWatcher dir = (DirectoryWatcher) w.next(); - w.remove(); dir.close(); } catch (Exception e) @@ -155,7 +161,11 @@ public void deleted(String pid) { - DirectoryWatcher watcher = (DirectoryWatcher) watchers.remove(pid); + DirectoryWatcher watcher; + synchronized (watchers) + { + watcher = (DirectoryWatcher) watchers.remove(pid); + } if (watcher != null) { watcher.close(); @@ -184,6 +194,7 @@ { listeners.add(listener); } + notifyWatchers(); } private void removeListener(ArtifactListener listener) @@ -192,6 +203,24 @@ { listeners.remove(listener); } + notifyWatchers(); + } + + private void notifyWatchers() + { + List /*<DirectoryWatcher>*/ toNotify = new ArrayList /*<DirectoryWatcher>*/(); + synchronized (watchers) + { + toNotify.addAll(watchers.values()); + } + for (Iterator w = toNotify.iterator(); w.hasNext();) + { + DirectoryWatcher dir = (DirectoryWatcher) w.next(); + synchronized (dir) + { + dir.notifyAll(); + } + } } static List getListeners() Modified: felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/Scanner.java URL: http://svn.apache.org/viewvc/felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/Scanner.java?rev=824270&r1=824269&r2=824270&view=diff ============================================================================== --- felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/Scanner.java (original) +++ felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/Scanner.java Mon Oct 12 09:18:33 2009 @@ -95,9 +95,10 @@ * Upon restart, such checksums are not known so that all files will * be reported as modified. * + * @param reportImmediately report all files immediately without waiting for the checksum to be stable * @return a list of changes on the files included in the directory */ - public Set/*<File>*/ scan() + public Set/*<File>*/ scan(boolean reportImmediately) { File[] list = directory.listFiles(filter); if (list == null) @@ -114,7 +115,7 @@ long newChecksum = checksum(file); lastChecksums.put(file, Long.valueOf(newChecksum)); // Only handle file when it does not change anymore and it has changed since last reported - if (newChecksum == lastChecksum && newChecksum != storedChecksum) + if ((newChecksum == lastChecksum || reportImmediately) && newChecksum != storedChecksum) { storedChecksums.put(file, Long.valueOf(newChecksum)); files.add(file);