View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.jci.listeners;
19  
20  import java.io.File;
21  import java.io.FileInputStream;
22  import java.util.Collection;
23  import java.util.HashSet;
24  import java.util.Iterator;
25  import java.util.Set;
26  
27  import org.apache.commons.io.IOUtils;
28  import org.apache.commons.jci.ReloadingClassLoader;
29  import org.apache.commons.jci.monitor.FilesystemAlterationObserver;
30  import org.apache.commons.jci.stores.MemoryResourceStore;
31  import org.apache.commons.jci.stores.ResourceStore;
32  import org.apache.commons.jci.stores.Transactional;
33  import org.apache.commons.jci.utils.ConversionUtils;
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  
37  /**
38   * This Listener waits for FAM events to trigger a reload of classes
39   * or resources.
40   * 
41   * @author tcurdt
42   */
43  public class ReloadingListener extends AbstractFilesystemAlterationListener {
44  
45      private final Log log = LogFactory.getLog(ReloadingListener.class);
46      
47      private final Set notificationListeners = new HashSet();
48      private final ResourceStore store;
49      
50      public ReloadingListener() {
51          this(new MemoryResourceStore());
52      }
53  
54      public ReloadingListener( final ResourceStore pStore ) {
55          store = pStore;
56      }
57  
58      public ResourceStore getStore() {
59          return store;
60      }
61  
62      public void addReloadNotificationListener( final ReloadNotificationListener pNotificationListener ) {
63          notificationListeners.add(pNotificationListener);
64  
65          if (pNotificationListener instanceof ReloadingClassLoader) {
66              ((ReloadingClassLoader)pNotificationListener).addResourceStore(store);
67          }
68  
69      }
70      
71      public boolean isReloadRequired( final FilesystemAlterationObserver pObserver ) {
72          boolean reload = false;
73  
74          final Collection created = getCreatedFiles();
75          final Collection changed = getChangedFiles();
76          final Collection deleted = getDeletedFiles();
77          
78          log.debug("created:" + created.size() + " changed:" + changed.size() + " deleted:" + deleted.size() + " resources");
79  
80          if (deleted.size() > 0) {
81              for (Iterator it = deleted.iterator(); it.hasNext();) {
82                  final File file = (File) it.next();
83                  final String resourceName = ConversionUtils.getResourceNameFromFileName(ConversionUtils.relative(pObserver.getRootDirectory(), file));
84                  store.remove(resourceName);
85              }
86              reload = true;
87          }
88  
89          if (created.size() > 0) {
90              for (Iterator it = created.iterator(); it.hasNext();) {
91                  final File file = (File) it.next();
92                  FileInputStream is = null;
93                  try {
94                      is = new FileInputStream(file);
95                      final byte[] bytes = IOUtils.toByteArray(is);
96                      final String resourceName = ConversionUtils.getResourceNameFromFileName(ConversionUtils.relative(pObserver.getRootDirectory(), file));
97                      store.write(resourceName, bytes);
98                  } catch(final Exception e) {
99                      log.error("could not load " + file, e);
100                 } finally {
101                     IOUtils.closeQuietly(is);
102                 }
103             }
104         }
105 
106         if (changed.size() > 0) {
107             for (Iterator it = changed.iterator(); it.hasNext();) {
108                 final File file = (File) it.next();
109                 FileInputStream is = null;
110                 try {
111                     is = new FileInputStream(file);
112                     final byte[] bytes = IOUtils.toByteArray(is);
113                     final String resourceName = ConversionUtils.getResourceNameFromFileName(ConversionUtils.relative(pObserver.getRootDirectory(), file));
114                     store.write(resourceName, bytes);
115                 } catch(final Exception e) {
116                     log.error("could not load " + file, e);
117                 } finally {
118                     IOUtils.closeQuietly(is);
119                 }
120             }
121             reload = true;
122         }
123 
124         return reload;
125     }
126     
127     public void onStop( final FilesystemAlterationObserver pObserver ) {
128         
129         
130         if (store instanceof Transactional) {
131             ((Transactional)store).onStart();
132         }
133 
134         final boolean reload = isReloadRequired(pObserver);
135 
136         if (store instanceof Transactional) {
137             ((Transactional)store).onStop();
138         }
139         
140         if (reload) {
141             notifyReloadNotificationListeners();
142         }
143         
144         super.onStop(pObserver);
145     }
146 
147     void notifyReloadNotificationListeners() {
148         
149         for (Iterator it = notificationListeners.iterator(); it.hasNext();) {
150             final ReloadNotificationListener listener = (ReloadNotificationListener) it.next();
151 
152             log.debug("notifying listener " + listener);
153 
154             listener.handleNotification();
155         }
156     }
157     
158     public void onDirectoryCreate( final File pDir ) {                
159     }
160     public void onDirectoryChange( final File pDir ) {                
161     }
162     public void onDirectoryDelete( final File pDir ) {
163     }
164 }