View Javadoc
1   package fr.ifremer.tutti.persistence;
2   
3   /*
4    * #%L
5    * Tutti :: Persistence
6    * %%
7    * Copyright (C) 2012 - 2014 Ifremer
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as
11   * published by the Free Software Foundation, either version 3 of the 
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Public 
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/gpl-3.0.html>.
22   * #L%
23   */
24  
25  import com.google.common.base.Preconditions;
26  import com.google.common.base.Predicate;
27  import com.google.common.base.Predicates;
28  import com.google.common.collect.Lists;
29  import org.apache.commons.io.FileUtils;
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.nuiton.jaxx.application.ApplicationIOUtil;
33  import org.nuiton.jaxx.application.ApplicationTechnicalException;
34  
35  import java.io.File;
36  import java.io.IOException;
37  import java.net.URL;
38  import java.net.URLClassLoader;
39  import java.util.Enumeration;
40  import java.util.List;
41  
42  import static org.nuiton.i18n.I18n.t;
43  
44  /**
45   * A class loader that search first in a given directory before in parent
46   * class loader.
47   *
48   * @author Tony Chemit - chemit@codelutin.com
49   * @since 0.3
50   */
51  public class RessourceClassLoader extends ClassLoader {
52  
53      /** Logger. */
54      private static final Log log =
55              LogFactory.getLog(RessourceClassLoader.class);
56  
57      public static final URL[] EMPTY_URL_ARRAY = new URL[0];
58  
59      protected URLClassLoader loader;
60  
61      protected Predicate<String> searchInDirectoriesPredicate;
62  
63      protected final List<File> directories;
64  
65      public RessourceClassLoader(ClassLoader parent) {
66          super(parent);
67  
68          // by default try in directories if there is some
69          this.searchInDirectoriesPredicate = new Predicate<String>() {
70              @Override
71              public boolean apply(String input) {
72                  return !directories.isEmpty();
73              }
74          };
75          directories = Lists.newArrayList();
76          loader = URLClassLoader.newInstance(EMPTY_URL_ARRAY);
77      }
78  
79      public void addDirectory(File... directories) {
80          for (File directory : directories) {
81              if (!this.directories.contains(directory)) {
82                  this.directories.add(directory);
83  
84                  // force to create directory
85                  ApplicationIOUtil.forceMkdir(directory, t("tutti.io.mkDir.error", directory));
86              }
87          }
88          loader = null;
89      }
90  
91      public void removeDirectory(File... directories) {
92          for (File directory : directories) {
93              this.directories.remove(directory);
94          }
95          loader = null;
96      }
97  
98      public Predicate<String> getSearchInDirectoriesPredicate() {
99          return searchInDirectoriesPredicate;
100     }
101 
102     public void addSearchInDirectoriesPredicate(Predicate<String> predicate) {
103         Preconditions.checkNotNull(predicate,
104                                    "search predicate can not be null");
105         this.searchInDirectoriesPredicate =
106                 Predicates.and(searchInDirectoriesPredicate, predicate);
107     }
108 
109     public void setSearchInDirectoriesPredicate(Predicate<String> searchInDirectoriesPredicate) {
110         Preconditions.checkNotNull(searchInDirectoriesPredicate,
111                                    "search predicate can not be null");
112         this.searchInDirectoriesPredicate = searchInDirectoriesPredicate;
113     }
114 
115     @Override
116     public URL findResource(String name) {
117         URL result = null;
118         if (searchInDirectoriesPredicate.apply(name)) {
119             if (log.isDebugEnabled()) {
120                 log.debug("findResource [" + name + "] in " + directories);
121             }
122             result = getLoader().findResource(name);
123         }
124         if (result == null) {
125             result = super.findResource(name);
126         }
127         return result;
128     }
129 
130     @Override
131     public Enumeration<URL> findResources(String name) throws IOException {
132         Enumeration<URL> result = null;
133         if (searchInDirectoriesPredicate.apply(name)) {
134             if (log.isDebugEnabled()) {
135                 log.debug("findResources [" + name + "] in " + directories);
136             }
137             result = getLoader().findResources(name);
138         }
139         if (result == null || !result.hasMoreElements()) {
140             result = super.findResources(name);
141         }
142         return result;
143     }
144 
145     @Override
146     public URL getResource(String name) {
147         URL result = null;
148         if (searchInDirectoriesPredicate.apply(name)) {
149             if (log.isDebugEnabled()) {
150                 log.debug("getResource [" + name + "] in " +
151                           directories);
152             }
153             result = getLoader().getResource(name);
154         }
155         if (result == null) {
156             result = super.getResource(name);
157         }
158         return result;
159     }
160 
161     @Override
162     public Enumeration<URL> getResources(String name) throws IOException {
163         Enumeration<URL> result = null;
164         if (searchInDirectoriesPredicate.apply(name)) {
165             if (log.isDebugEnabled()) {
166                 log.debug("getResources [" + name + "] in " + directories);
167             }
168             result = getLoader().getResources(name);
169         }
170         if (result == null || !result.hasMoreElements()) {
171             result = super.getResources(name);
172         }
173         return result;
174     }
175 
176     protected URLClassLoader getLoader() {
177         if (loader == null) {
178             try {
179                 URL[] urls = FileUtils.toURLs(
180                         directories.toArray(new File[directories.size()]));
181                 loader = URLClassLoader.newInstance(urls, null);
182             } catch (IOException e) {
183                 throw new ApplicationTechnicalException(t("tutti.persistence.loader.error", directories), e);
184             }
185         }
186         return loader;
187     }
188 }