@@ -13,7 +13,7 @@ | |||
package ro.fortsoft.pf4j; | |||
import java.io.File; | |||
import java.io.FilenameFilter; | |||
import java.io.FileFilter; | |||
import java.io.IOException; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
@@ -24,11 +24,14 @@ import java.util.Map; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import ro.fortsoft.pf4j.util.AndFileFilter; | |||
import ro.fortsoft.pf4j.util.CompoundClassLoader; | |||
import ro.fortsoft.pf4j.util.DirectoryFilter; | |||
import ro.fortsoft.pf4j.util.DirectoryFileFilter; | |||
import ro.fortsoft.pf4j.util.FileUtils; | |||
import ro.fortsoft.pf4j.util.HiddenFilter; | |||
import ro.fortsoft.pf4j.util.NotFileFilter; | |||
import ro.fortsoft.pf4j.util.Unzip; | |||
import ro.fortsoft.pf4j.util.ZipFilter; | |||
import ro.fortsoft.pf4j.util.ZipFileFilter; | |||
/** | |||
* Default implementation of the PluginManager interface. | |||
@@ -200,9 +203,9 @@ public class DefaultPluginManager implements PluginManager { | |||
} | |||
// expand all plugin archives | |||
FilenameFilter zipFilter = new ZipFilter(); | |||
String[] zipFiles = pluginsDirectory.list(zipFilter); | |||
for (String zipFile : zipFiles) { | |||
FileFilter zipFilter = new ZipFileFilter(); | |||
File[] zipFiles = pluginsDirectory.listFiles(zipFilter); | |||
for (File zipFile : zipFiles) { | |||
try { | |||
expandPluginArchive(zipFile); | |||
} catch (IOException e) { | |||
@@ -211,15 +214,18 @@ public class DefaultPluginManager implements PluginManager { | |||
} | |||
// check for no plugins | |||
FilenameFilter directoryFilter = new DirectoryFilter(); | |||
String[] directories = pluginsDirectory.list(directoryFilter); | |||
List<FileFilter> filterList = new ArrayList<FileFilter>(); | |||
filterList.add(new DirectoryFileFilter()); | |||
filterList.add(new NotFileFilter(createHiddenPluginFilter())); | |||
FileFilter pluginsFilter = new AndFileFilter(filterList); | |||
File[] directories = pluginsDirectory.listFiles(pluginsFilter); | |||
if (directories.length == 0) { | |||
log.info("No plugins"); | |||
return; | |||
} | |||
// load any plugin from plugins directory | |||
for (String directory : directories) { | |||
for (File directory : directories) { | |||
try { | |||
loadPlugin(directory); | |||
} catch (PluginException e) { | |||
@@ -268,15 +274,36 @@ public class DefaultPluginManager implements PluginManager { | |||
return null; | |||
} | |||
private void loadPlugin(String fileName) throws PluginException { | |||
// test for plugin directory | |||
File pluginDirectory = new File(pluginsDirectory, fileName); | |||
if (!pluginDirectory.isDirectory()) { | |||
return; | |||
} | |||
/** | |||
* Add the possibility to override the PluginDescriptorFinder. | |||
*/ | |||
protected PluginDescriptorFinder createPluginDescriptorFinder() { | |||
return new DefaultPluginDescriptorFinder(); | |||
} | |||
/** | |||
* Add the possibility to override the ExtensionFinder. | |||
*/ | |||
protected ExtensionFinder createExtensionFinder() { | |||
return new DefaultExtensionFinder(compoundClassLoader); | |||
} | |||
protected boolean isPluginDisabled(String pluginId) { | |||
if (enabledPlugins.isEmpty()) { | |||
return disabledPlugins.contains(pluginId); | |||
} | |||
return !enabledPlugins.contains(pluginId); | |||
} | |||
protected FileFilter createHiddenPluginFilter() { | |||
return new HiddenFilter(); | |||
} | |||
private void loadPlugin(File pluginDirectory) throws PluginException { | |||
// try to load the plugin | |||
String pluginPath = "/".concat(fileName); | |||
String pluginName = pluginDirectory.getName(); | |||
String pluginPath = "/".concat(pluginName); | |||
// test for plugin duplication | |||
if (plugins.get(pathToIdMap.get(pluginPath)) != null) { | |||
@@ -318,37 +345,15 @@ public class DefaultPluginManager implements PluginManager { | |||
pluginClassLoaders.put(pluginId, pluginClassLoader); | |||
} | |||
/** | |||
* Add the possibility to override the PluginDescriptorFinder. | |||
*/ | |||
protected PluginDescriptorFinder createPluginDescriptorFinder() { | |||
return new DefaultPluginDescriptorFinder(); | |||
} | |||
/** | |||
* Add the possibility to override the ExtensionFinder. | |||
*/ | |||
protected ExtensionFinder createExtensionFinder() { | |||
return new DefaultExtensionFinder(compoundClassLoader); | |||
} | |||
protected boolean isPluginDisabled(String pluginId) { | |||
if (enabledPlugins.isEmpty()) { | |||
return disabledPlugins.contains(pluginId); | |||
} | |||
return !enabledPlugins.contains(pluginId); | |||
} | |||
private void expandPluginArchive(String fileName) throws IOException { | |||
File pluginArchiveFile = new File(pluginsDirectory, fileName); | |||
private void expandPluginArchive(File pluginArchiveFile) throws IOException { | |||
String fileName = pluginArchiveFile.getName(); | |||
long pluginArchiveDate = pluginArchiveFile.lastModified(); | |||
String pluginName = fileName.substring(0, fileName.length() - 4); | |||
File pluginDirectory = new File(pluginsDirectory, pluginName); | |||
// check if exists directory or the '.zip' file is "newer" than directory | |||
if (!pluginDirectory.exists() || (pluginArchiveDate > pluginDirectory.lastModified())) { | |||
log.debug("Expand plugin archive '{}' in '{}'", pluginArchiveFile, pluginDirectory); | |||
// create directorie for plugin | |||
// create directory for plugin | |||
pluginDirectory.mkdirs(); | |||
// expand '.zip' file |
@@ -13,15 +13,15 @@ | |||
package ro.fortsoft.pf4j; | |||
import java.io.File; | |||
import java.io.FilenameFilter; | |||
import java.io.FileFilter; | |||
import java.net.MalformedURLException; | |||
import java.util.Vector; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import ro.fortsoft.pf4j.util.DirectoryFilter; | |||
import ro.fortsoft.pf4j.util.JarFilter; | |||
import ro.fortsoft.pf4j.util.DirectoryFileFilter; | |||
import ro.fortsoft.pf4j.util.JarFileFilter; | |||
/** | |||
* Load all informations needed by a plugin. | |||
@@ -77,20 +77,20 @@ class PluginLoader { | |||
return loadClasses() && loadJars(); | |||
} | |||
private void getJars(Vector<String> v, File file) { | |||
FilenameFilter jarFilter = new JarFilter(); | |||
FilenameFilter directoryFilter = new DirectoryFilter(); | |||
private void getJars(Vector<File> bucket, File file) { | |||
FileFilter jarFilter = new JarFileFilter(); | |||
FileFilter directoryFilter = new DirectoryFileFilter(); | |||
if (file.exists() && file.isDirectory() && file.isAbsolute()) { | |||
String[] jars = file.list(jarFilter); | |||
File[] jars = file.listFiles(jarFilter); | |||
for (int i = 0; (jars != null) && (i < jars.length); ++i) { | |||
v.addElement(jars[i]); | |||
bucket.addElement(jars[i]); | |||
} | |||
String[] directoryList = file.list(directoryFilter); | |||
for (int i = 0; (directoryList != null) && (i < directoryList.length); ++i) { | |||
File directory = new File(file, directoryList[i]); | |||
getJars(v, directory); | |||
File[] directories = file.listFiles(directoryFilter); | |||
for (int i = 0; (directories != null) && (i < directories.length); ++i) { | |||
File directory = directories[i]; | |||
getJars(bucket, directory); | |||
} | |||
} | |||
} | |||
@@ -122,13 +122,12 @@ class PluginLoader { | |||
// make 'jarDirectory' absolute | |||
libDirectory = libDirectory.getAbsoluteFile(); | |||
Vector<String> jars = new Vector<String>(); | |||
Vector<File> jars = new Vector<File>(); | |||
getJars(jars, libDirectory); | |||
for (String jar : jars) { | |||
File jarFile = new File(libDirectory, jar); | |||
for (File jar : jars) { | |||
try { | |||
pluginClassLoader.addURL(jarFile.toURI().toURL()); | |||
log.debug("Added '{}' to the class loader path", jarFile); | |||
pluginClassLoader.addURL(jar.toURI().toURL()); | |||
log.debug("Added '{}' to the class loader path", jar); | |||
} catch (MalformedURLException e) { | |||
e.printStackTrace(); | |||
log.error(e.getMessage(), e); |
@@ -0,0 +1,76 @@ | |||
/* | |||
* Copyright 2013 Decebal Suiu | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with | |||
* the License. You may obtain a copy of the License in the LICENSE file, or at: | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | |||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | |||
* specific language governing permissions and limitations under the License. | |||
*/ | |||
package ro.fortsoft.pf4j.util; | |||
import java.io.File; | |||
import java.io.FileFilter; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
/** | |||
* This filter providing conditional AND logic across a list of | |||
* file filters. This filter returns <code>true</code> if all filters in the | |||
* list return <code>true</code>. Otherwise, it returns <code>false</code>. | |||
* Checking of the file filter list stops when the first filter returns | |||
* <code>false</code>. | |||
* | |||
* @author Decebal Suiu | |||
*/ | |||
public class AndFileFilter implements FileFilter { | |||
/** The list of file filters. */ | |||
private List<FileFilter> fileFilters; | |||
public AndFileFilter() { | |||
this.fileFilters = new ArrayList<FileFilter>(); | |||
} | |||
public AndFileFilter(List<FileFilter> fileFilters) { | |||
this.fileFilters = new ArrayList<FileFilter>(fileFilters); | |||
} | |||
public void addFileFilter(FileFilter fileFilter) { | |||
fileFilters.add(fileFilter); | |||
} | |||
public List<FileFilter> getFileFilters() { | |||
return Collections.unmodifiableList(fileFilters); | |||
} | |||
public boolean removeFileFilter(FileFilter fileFilter) { | |||
return fileFilters.remove(fileFilter); | |||
} | |||
public void setFileFilters(List<FileFilter> fileFilters) { | |||
this.fileFilters = new ArrayList<FileFilter>(fileFilters); | |||
} | |||
@Override | |||
public boolean accept(File file) { | |||
if (this.fileFilters.size() == 0) { | |||
return false; | |||
} | |||
for (Iterator<FileFilter> iter = this.fileFilters.iterator(); iter.hasNext();) { | |||
FileFilter fileFilter = (FileFilter) iter.next(); | |||
if (!fileFilter.accept(file)) { | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
} |
@@ -14,22 +14,17 @@ package ro.fortsoft.pf4j.util; | |||
import java.io.File; | |||
import java.io.FileFilter; | |||
import java.io.FilenameFilter; | |||
/** | |||
* Filter accepts files that are directories. | |||
* | |||
* @author Decebal Suiu | |||
*/ | |||
public class DirectoryFilter implements FileFilter, FilenameFilter { | |||
public class DirectoryFileFilter implements FileFilter { | |||
/** | |||
* Accepts any file ending in .jar. The case of the filename is ignored. | |||
*/ | |||
@Override | |||
public boolean accept(File file) { | |||
return file.isDirectory(); | |||
} | |||
public boolean accept(File dir, String name) { | |||
return accept(new File(dir, name)); | |||
} | |||
} |
@@ -13,30 +13,25 @@ | |||
package ro.fortsoft.pf4j.util; | |||
import java.io.File; | |||
import java.io.FilenameFilter; | |||
import java.io.FileFilter; | |||
/** | |||
* Filter accepts any file ending in extension. The case of the filename is ignored. | |||
* | |||
* @author Decebal Suiu | |||
*/ | |||
public class ExtensionFilter implements FilenameFilter { | |||
public class ExtensionFileFilter implements FileFilter { | |||
private String extension; | |||
public ExtensionFilter(String extension) { | |||
public ExtensionFileFilter(String extension) { | |||
this.extension = extension; | |||
} | |||
/** | |||
* Accepts any file ending in extension. The case of the filename is ignored. | |||
*/ | |||
@Override | |||
public boolean accept(File file) { | |||
// perform a case insensitive check. | |||
return file.getName().toUpperCase().endsWith(extension.toUpperCase()); | |||
} | |||
@Override | |||
public boolean accept(File dir, String name) { | |||
return accept(new File(dir, name)); | |||
} | |||
} |
@@ -0,0 +1,30 @@ | |||
/* | |||
* Copyright 2013 Decebal Suiu | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with | |||
* the License. You may obtain a copy of the License in the LICENSE file, or at: | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | |||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | |||
* specific language governing permissions and limitations under the License. | |||
*/ | |||
package ro.fortsoft.pf4j.util; | |||
import java.io.File; | |||
import java.io.FileFilter; | |||
/** | |||
* Filter that only accepts hidden files. | |||
* | |||
* @author decebal.suiu | |||
*/ | |||
public class HiddenFilter implements FileFilter { | |||
@Override | |||
public boolean accept(File file) { | |||
return file.isHidden(); | |||
} | |||
} |
@@ -18,14 +18,14 @@ package ro.fortsoft.pf4j.util; | |||
* | |||
* @author Decebal Suiu | |||
*/ | |||
public class JarFilter extends ExtensionFilter { | |||
public class JarFileFilter extends ExtensionFileFilter { | |||
/** | |||
* The extension that this filter will search for. | |||
*/ | |||
private static final String JAR_EXTENSION = ".JAR"; | |||
public JarFilter() { | |||
public JarFileFilter() { | |||
super(JAR_EXTENSION); | |||
} | |||
@@ -0,0 +1,36 @@ | |||
/* | |||
* Copyright 2013 Decebal Suiu | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with | |||
* the License. You may obtain a copy of the License in the LICENSE file, or at: | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | |||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | |||
* specific language governing permissions and limitations under the License. | |||
*/ | |||
package ro.fortsoft.pf4j.util; | |||
import java.io.File; | |||
import java.io.FileFilter; | |||
/** | |||
* This filter produces a logical NOT of the filters specified. | |||
* | |||
* @author Decebal Suiu | |||
*/ | |||
public class NotFileFilter implements FileFilter { | |||
private FileFilter filter; | |||
public NotFileFilter(FileFilter filter) { | |||
this.filter = filter; | |||
} | |||
@Override | |||
public boolean accept(File file) { | |||
return !filter.accept(file); | |||
} | |||
} |
@@ -18,14 +18,14 @@ package ro.fortsoft.pf4j.util; | |||
* | |||
* @author Decebal Suiu | |||
*/ | |||
public class ZipFilter extends ExtensionFilter { | |||
public class ZipFileFilter extends ExtensionFileFilter { | |||
/** | |||
* The extension that this filter will search for. | |||
*/ | |||
private static final String ZIP_EXTENSION = ".ZIP"; | |||
public ZipFilter() { | |||
public ZipFileFilter() { | |||
super(ZIP_EXTENSION); | |||
} | |||