mirror of https://github.com/pf4j/pf4j.git
Decebal Suiu
11 years ago
8 changed files with 326 additions and 188 deletions
@ -0,0 +1,102 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012 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; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.FileInputStream; |
||||||
|
import java.io.FileNotFoundException; |
||||||
|
import java.io.IOException; |
||||||
|
import java.util.jar.Attributes; |
||||||
|
import java.util.jar.Manifest; |
||||||
|
|
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
|
||||||
|
import ro.fortsoft.pf4j.util.StringUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Read the plugin descriptor from the manifest file. |
||||||
|
* |
||||||
|
* @author Decebal Suiu |
||||||
|
*/ |
||||||
|
public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder { |
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ManifestPluginDescriptorFinder.class); |
||||||
|
|
||||||
|
private PluginClasspath pluginClasspath; |
||||||
|
|
||||||
|
public ManifestPluginDescriptorFinder(PluginClasspath pluginClasspath) { |
||||||
|
this.pluginClasspath = pluginClasspath; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public PluginDescriptor find(File pluginRepository) throws PluginException { |
||||||
|
// TODO it's ok with first classes directory? Another idea is to specify in PluginClasspath the folder.
|
||||||
|
String classes = pluginClasspath.getClassesDirectories().get(0); |
||||||
|
File manifestFile = new File(pluginRepository, classes + "/META-INF/MANIFEST.MF"); |
||||||
|
log.debug("Lookup plugin descriptor in '{}'", manifestFile); |
||||||
|
if (!manifestFile.exists()) { |
||||||
|
throw new PluginException("Cannot find '" + manifestFile + "' file"); |
||||||
|
} |
||||||
|
|
||||||
|
FileInputStream input = null; |
||||||
|
try { |
||||||
|
input = new FileInputStream(manifestFile); |
||||||
|
} catch (FileNotFoundException e) { |
||||||
|
// not happening
|
||||||
|
} |
||||||
|
|
||||||
|
Manifest manifest = null; |
||||||
|
try { |
||||||
|
manifest = new Manifest(input); |
||||||
|
} catch (IOException e) { |
||||||
|
throw new PluginException(e.getMessage(), e); |
||||||
|
} finally { |
||||||
|
try { |
||||||
|
input.close(); |
||||||
|
} catch (IOException e) { |
||||||
|
throw new PluginException(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
PluginDescriptor pluginDescriptor = new PluginDescriptor(); |
||||||
|
|
||||||
|
// TODO validate !!!
|
||||||
|
Attributes attrs = manifest.getMainAttributes(); |
||||||
|
String id = attrs.getValue("Plugin-Id"); |
||||||
|
if (StringUtils.isEmpty(id)) { |
||||||
|
throw new PluginException("Plugin-Id cannot be empty"); |
||||||
|
} |
||||||
|
pluginDescriptor.setPluginId(id); |
||||||
|
|
||||||
|
String clazz = attrs.getValue("Plugin-Class"); |
||||||
|
if (StringUtils.isEmpty(clazz)) { |
||||||
|
throw new PluginException("Plugin-Class cannot be empty"); |
||||||
|
} |
||||||
|
pluginDescriptor.setPluginClass(clazz); |
||||||
|
|
||||||
|
String version = attrs.getValue("Plugin-Version"); |
||||||
|
if (StringUtils.isEmpty(version)) { |
||||||
|
throw new PluginException("Plugin-Version cannot be empty"); |
||||||
|
} |
||||||
|
pluginDescriptor.setPluginVersion(PluginVersion.createVersion(version)); |
||||||
|
|
||||||
|
String provider = attrs.getValue("Plugin-Provider"); |
||||||
|
pluginDescriptor.setProvider(provider); |
||||||
|
String dependencies = attrs.getValue("Plugin-Dependencies"); |
||||||
|
pluginDescriptor.setDependencies(dependencies); |
||||||
|
|
||||||
|
return pluginDescriptor; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
/* |
||||||
|
* 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; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* The classpath of the plugin after it was unpacked. |
||||||
|
* It contains classes directories and lib directories (directories that contains jars). |
||||||
|
* All directories are relativ to plugin repository. |
||||||
|
* The default values are "classes" and "lib". |
||||||
|
* |
||||||
|
* @author Decebal Suiu |
||||||
|
*/ |
||||||
|
public class PluginClasspath { |
||||||
|
|
||||||
|
private static final String DEFAULT_CLASSES_DIRECTORY = "classes"; |
||||||
|
private static final String DEFAULT_LIB_DIRECTORY = "lib"; |
||||||
|
|
||||||
|
private List<String> classesDirectories; |
||||||
|
private List<String> libDirectories; |
||||||
|
|
||||||
|
public PluginClasspath() { |
||||||
|
classesDirectories = new ArrayList<String>(); |
||||||
|
libDirectories = new ArrayList<String>(); |
||||||
|
|
||||||
|
// add defaults
|
||||||
|
classesDirectories.add(DEFAULT_CLASSES_DIRECTORY); |
||||||
|
libDirectories.add(DEFAULT_LIB_DIRECTORY); |
||||||
|
} |
||||||
|
|
||||||
|
public List<String> getClassesDirectories() { |
||||||
|
return classesDirectories; |
||||||
|
} |
||||||
|
|
||||||
|
public void setClassesDirectories(List<String> classesDirectories) { |
||||||
|
this.classesDirectories = classesDirectories; |
||||||
|
} |
||||||
|
|
||||||
|
public List<String> getLibDirectories() { |
||||||
|
return libDirectories; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLibDirectories(List<String> libDirectories) { |
||||||
|
this.libDirectories = libDirectories; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,80 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012 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; |
||||||
|
|
||||||
|
import java.lang.reflect.AnnotatedElement; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
|
||||||
|
import net.java.sezpoz.Index; |
||||||
|
import net.java.sezpoz.IndexItem; |
||||||
|
|
||||||
|
/** |
||||||
|
* Using Sezpoz(http://sezpoz.java.net/) for extensions discovery.
|
||||||
|
* |
||||||
|
* @author Decebal Suiu |
||||||
|
*/ |
||||||
|
public class SezpozExtensionFinder implements ExtensionFinder { |
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SezpozExtensionFinder.class); |
||||||
|
|
||||||
|
private volatile List<IndexItem<Extension, Object>> indices; |
||||||
|
private ClassLoader classLoader; |
||||||
|
|
||||||
|
public SezpozExtensionFinder(ClassLoader classLoader) { |
||||||
|
this.classLoader = classLoader; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public <T> List<ExtensionWrapper<T>> find(Class<T> type) { |
||||||
|
log.debug("Find extensions for {}", type); |
||||||
|
List<ExtensionWrapper<T>> result = new ArrayList<ExtensionWrapper<T>>(); |
||||||
|
getIndices(); |
||||||
|
// System.out.println("indices = "+ indices);
|
||||||
|
for (IndexItem<Extension, Object> item : indices) { |
||||||
|
try { |
||||||
|
AnnotatedElement element = item.element(); |
||||||
|
Class<?> extensionType = (Class<?>) element; |
||||||
|
log.debug("Checking extension type {}", extensionType); |
||||||
|
if (type.isAssignableFrom(extensionType)) { |
||||||
|
Object instance = item.instance(); |
||||||
|
if (instance != null) { |
||||||
|
log.debug("Added extension {}", extensionType); |
||||||
|
result.add(new ExtensionWrapper<T>(type.cast(instance), item.annotation().ordinal())); |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (InstantiationException e) { |
||||||
|
log.error(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
private List<IndexItem<Extension, Object>> getIndices() { |
||||||
|
if (indices == null) { |
||||||
|
indices = new ArrayList<IndexItem<Extension, Object>>(); |
||||||
|
Iterator<IndexItem<Extension, Object>> it = Index.load(Extension.class, Object.class, classLoader).iterator(); |
||||||
|
while (it.hasNext()) { |
||||||
|
indices.add(it.next()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return indices; |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue