mirror of https://github.com/pf4j/pf4j.git
Decebal Suiu
7 years ago
committed by
GitHub
21 changed files with 549 additions and 298 deletions
@ -0,0 +1,81 @@
|
||||
/* |
||||
* Copyright 2017 Decebal Suiu |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License 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 org.pf4j; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
import java.nio.file.Path; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author Decebal Suiu |
||||
*/ |
||||
public class CompoundPluginDescriptorFinder implements PluginDescriptorFinder { |
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(CompoundPluginDescriptorFinder.class); |
||||
|
||||
private List<PluginDescriptorFinder> finders = new ArrayList<>(); |
||||
|
||||
public CompoundPluginDescriptorFinder add(PluginDescriptorFinder finder) { |
||||
if (finder == null) { |
||||
throw new IllegalArgumentException("null not allowed"); |
||||
} |
||||
|
||||
finders.add(finder); |
||||
|
||||
return this; |
||||
} |
||||
|
||||
public int size() { |
||||
return finders.size(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isApplicable(Path pluginPath) { |
||||
for (PluginDescriptorFinder finder : finders) { |
||||
if (finder.isApplicable(pluginPath)) { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
@Override |
||||
public PluginDescriptor find(Path pluginPath) throws PluginException { |
||||
for (PluginDescriptorFinder finder : finders) { |
||||
if (finder.isApplicable(pluginPath)) { |
||||
log.debug("'{}' is applicable for plugin '{}'", finder, pluginPath); |
||||
try { |
||||
PluginDescriptor pluginDescriptor = finder.find(pluginPath); |
||||
if (pluginDescriptor != null) { |
||||
return pluginDescriptor; |
||||
} |
||||
} catch (Exception e) { |
||||
// log the exception and continue with the next finder
|
||||
log.error(e.getMessage()); // ?!
|
||||
} |
||||
} else { |
||||
log.debug("'{}' is not applicable for plugin '{}'", finder, pluginPath); |
||||
} |
||||
} |
||||
|
||||
throw new PluginException("No PluginDescriptorFinder for plugin '{}'", pluginPath); |
||||
} |
||||
|
||||
} |
@ -1,64 +0,0 @@
|
||||
/* |
||||
* Copyright 2013 Decebal Suiu |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License 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 org.pf4j; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.nio.file.Files; |
||||
import java.nio.file.Path; |
||||
import java.nio.file.Paths; |
||||
import java.util.jar.Manifest; |
||||
|
||||
/** |
||||
* The default implementation for {@link PluginDescriptorFinder}. |
||||
* Now, this class it's a "link" to {@link ManifestPluginDescriptorFinder}. |
||||
* |
||||
* @author Decebal Suiu |
||||
*/ |
||||
public class DefaultPluginDescriptorFinder extends ManifestPluginDescriptorFinder { |
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ManifestPluginDescriptorFinder.class); |
||||
|
||||
private PluginClasspath pluginClasspath; |
||||
|
||||
public DefaultPluginDescriptorFinder(PluginClasspath pluginClasspath) { |
||||
this.pluginClasspath = pluginClasspath; |
||||
} |
||||
|
||||
@Override |
||||
public Manifest readManifest(Path pluginPath) throws PluginException { |
||||
// TODO it's ok with first classes root? Another idea is to specify in PluginClasspath the folder.
|
||||
if (pluginClasspath.getClassesDirectories().size() == 0) { |
||||
throw new PluginException("Failed to read manifest, no classes folder in classpath"); |
||||
} |
||||
String classes = pluginClasspath.getClassesDirectories().get(0); |
||||
Path manifestPath = pluginPath.resolve(Paths.get(classes,"/META-INF/MANIFEST.MF")); |
||||
log.debug("Lookup plugin descriptor in '{}'", manifestPath); |
||||
if (Files.notExists(manifestPath)) { |
||||
throw new PluginException("Cannot find '{}' path", manifestPath); |
||||
} |
||||
|
||||
try (InputStream input = Files.newInputStream(manifestPath)) { |
||||
return new Manifest(input); |
||||
} catch (IOException e) { |
||||
throw new PluginException(e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,104 @@
|
||||
/* |
||||
* Copyright 2017 Decebal Suiu |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License 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 org.pf4j; |
||||
|
||||
import org.junit.Rule; |
||||
import org.junit.Test; |
||||
import org.junit.rules.TemporaryFolder; |
||||
import org.pf4j.plugin.PluginZip; |
||||
|
||||
import java.nio.charset.StandardCharsets; |
||||
import java.nio.file.Files; |
||||
import java.nio.file.Path; |
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
/** |
||||
* @author Decebal Suiu |
||||
*/ |
||||
public class CompoundPluginDescriptorFinderTest { |
||||
|
||||
@Rule |
||||
public TemporaryFolder testFolder = new TemporaryFolder(); |
||||
|
||||
@Test |
||||
public void add() { |
||||
CompoundPluginDescriptorFinder instance = new CompoundPluginDescriptorFinder(); |
||||
assertEquals(0, instance.size()); |
||||
|
||||
instance.add(new PropertiesPluginDescriptorFinder()); |
||||
assertEquals(1, instance.size()); |
||||
} |
||||
|
||||
@Test |
||||
public void find() throws Exception { |
||||
Path pluginPath = testFolder.newFolder("test-plugin-1").toPath(); |
||||
Files.write(pluginPath.resolve("plugin.properties"), getPlugin1Properties(), StandardCharsets.UTF_8); |
||||
|
||||
PluginDescriptorFinder instance = new CompoundPluginDescriptorFinder() |
||||
.add(new PropertiesPluginDescriptorFinder()); |
||||
|
||||
PluginDescriptor pluginDescriptor = instance.find(pluginPath); |
||||
assertNotNull(pluginDescriptor); |
||||
assertEquals("test-plugin-1", pluginDescriptor.getPluginId()); |
||||
assertEquals("0.0.1", pluginDescriptor.getVersion()); |
||||
} |
||||
|
||||
@Test |
||||
public void findInJar() throws Exception { |
||||
PluginDescriptorFinder instance = new CompoundPluginDescriptorFinder() |
||||
.add(new PropertiesPluginDescriptorFinder()); |
||||
|
||||
PluginZip pluginJar = new PluginZip.Builder(testFolder.newFile("my-plugin-1.2.3.jar"), "myPlugin") |
||||
.pluginVersion("1.2.3") |
||||
.build(); |
||||
|
||||
PluginDescriptor pluginDescriptor = instance.find(pluginJar.path()); |
||||
assertNotNull(pluginDescriptor); |
||||
assertEquals("myPlugin", pluginJar.pluginId()); |
||||
assertEquals("1.2.3", pluginJar.pluginVersion()); |
||||
} |
||||
|
||||
@Test(expected = PluginException.class) |
||||
public void testNotFound() throws Exception { |
||||
PluginDescriptorFinder instance = new CompoundPluginDescriptorFinder(); |
||||
instance.find(getPluginsRoot().resolve("test-plugin-3")); |
||||
} |
||||
|
||||
private List<String> getPlugin1Properties() { |
||||
String[] lines = new String[] { |
||||
"plugin.id=test-plugin-1\n" |
||||
+ "plugin.version=0.0.1\n" |
||||
+ "plugin.description=Test Plugin 1\n" |
||||
+ "plugin.provider=Decebal Suiu\n" |
||||
+ "plugin.class=org.pf4j.plugin.TestPlugin\n" |
||||
+ "plugin.dependencies=test-plugin-2,test-plugin-3@~1.0\n" |
||||
+ "plugin.requires=>=1\n" |
||||
+ "plugin.license=Apache-2.0\n" |
||||
+ "\n" |
||||
+ "" |
||||
}; |
||||
|
||||
return Arrays.asList(lines); |
||||
} |
||||
|
||||
private Path getPluginsRoot() { |
||||
return testFolder.getRoot().toPath(); |
||||
} |
||||
|
||||
} |
@ -1,51 +0,0 @@
|
||||
/* |
||||
* Copyright 2017 Decebal Suiu |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License 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 org.pf4j.plugin; |
||||
|
||||
import org.pf4j.DefaultPluginClasspath; |
||||
import org.pf4j.DefaultPluginDescriptorFinder; |
||||
import org.pf4j.DefaultPluginManager; |
||||
import org.pf4j.PluginDescriptorFinder; |
||||
|
||||
import java.nio.file.Path; |
||||
|
||||
/** |
||||
* Manager for testing |
||||
*/ |
||||
public class MockPluginManager extends DefaultPluginManager { |
||||
|
||||
private PluginDescriptorFinder finder = new DefaultPluginDescriptorFinder(new DefaultPluginClasspath()); |
||||
|
||||
public MockPluginManager() { |
||||
super(); |
||||
} |
||||
|
||||
public MockPluginManager(Path root, PluginDescriptorFinder finder) { |
||||
super(root); |
||||
this.finder = finder; |
||||
} |
||||
|
||||
@Override |
||||
protected PluginDescriptorFinder getPluginDescriptorFinder() { |
||||
return finder; |
||||
} |
||||
|
||||
@Override |
||||
protected PluginDescriptorFinder createPluginDescriptorFinder() { |
||||
return finder; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,107 @@
|
||||
/* |
||||
* Copyright 2015 Decebal Suiu |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License 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 org.pf4j.plugin; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileOutputStream; |
||||
import java.io.IOException; |
||||
import java.nio.file.Path; |
||||
import java.util.Properties; |
||||
import java.util.zip.ZipEntry; |
||||
import java.util.zip.ZipOutputStream; |
||||
|
||||
/** |
||||
* Represents a plugin zip/jar file. |
||||
* The "plugin.properties" file is created on the fly from the information supplied in Builder. |
||||
* |
||||
* @author Decebal Suiu |
||||
*/ |
||||
public class PluginZip { |
||||
|
||||
private final File file; |
||||
private final String pluginId; |
||||
private final String pluginVersion; |
||||
|
||||
protected PluginZip(Builder builder) { |
||||
this.file = builder.file; |
||||
this.pluginId = builder.pluginId; |
||||
this.pluginVersion = builder.pluginVersion; |
||||
} |
||||
|
||||
public File file() { |
||||
return file; |
||||
} |
||||
|
||||
public Path path() { |
||||
return file.toPath(); |
||||
} |
||||
|
||||
public String pluginId() { |
||||
return pluginId; |
||||
} |
||||
|
||||
public String pluginVersion() { |
||||
return pluginVersion; |
||||
} |
||||
|
||||
public Path unzippedPath() { |
||||
Path path = path(); |
||||
String fileName = path.getFileName().toString(); |
||||
|
||||
return path.getParent().resolve(fileName.substring(0, fileName.length() - 4)); // without ".zip" suffix
|
||||
} |
||||
|
||||
public static class Builder { |
||||
|
||||
private final File file; |
||||
private final String pluginId; |
||||
|
||||
private String pluginVersion; |
||||
|
||||
public Builder(File file, String pluginId) { |
||||
this.file = file; |
||||
this.pluginId = pluginId; |
||||
} |
||||
|
||||
public Builder pluginVersion(String pluginVersion) { |
||||
this.pluginVersion = pluginVersion; |
||||
|
||||
return this; |
||||
} |
||||
|
||||
public PluginZip build() throws IOException { |
||||
createPropertiesFile(); |
||||
|
||||
return new PluginZip(this); |
||||
} |
||||
|
||||
protected void createPropertiesFile() throws IOException { |
||||
Properties properties = new Properties(); |
||||
properties.setProperty("plugin.id", pluginId); |
||||
properties.setProperty("plugin.version", pluginVersion); |
||||
properties.setProperty("plugin.class", "org.pf4j.plugin.TestPlugin"); |
||||
|
||||
ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(file)); |
||||
ZipEntry propertiesFile = new ZipEntry("plugin.properties"); |
||||
outputStream.putNextEntry(propertiesFile); |
||||
properties.store(outputStream, ""); |
||||
outputStream.closeEntry(); |
||||
outputStream.close(); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue