Browse Source

Refactoring to make PluginDescriptor more usable (#180)

pull/186/head
Josiah Haswell 7 years ago committed by Decebal Suiu
parent
commit
5b192003f4
  1. 211
      pf4j/src/main/java/org/pf4j/DefaultPluginDescriptor.java
  2. 6
      pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java
  3. 154
      pf4j/src/main/java/org/pf4j/PluginDescriptor.java
  4. 6
      pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java
  5. 4
      pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java
  6. 20
      pf4j/src/test/java/org/pf4j/DependencyResolverTest.java
  7. 82
      pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java

211
pf4j/src/main/java/org/pf4j/DefaultPluginDescriptor.java

@ -0,0 +1,211 @@
/*
* Copyright 2012 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 java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* A plugin descriptor contains information about a plug-in obtained
* from the manifest (META-INF) file.
*
* @author Decebal Suiu
*/
public class DefaultPluginDescriptor implements PluginDescriptor {
private String pluginId;
private String pluginDescription;
private String pluginClass;
private String version;
private String requires = "*"; // SemVer format
private String provider;
private List<PluginDependency> dependencies;
private String license;
public DefaultPluginDescriptor() {
dependencies = new ArrayList<>();
}
/**
* @param pluginId
* @param pluginDescription
* @param pluginClass
* @param version
* @param requires
* @param provider
* @param license
*/
public DefaultPluginDescriptor(String pluginId, String pluginDescription, String pluginClass, String version, String requires, String provider, String license) {
this();
this.pluginId = pluginId;
this.pluginDescription = pluginDescription;
this.pluginClass = pluginClass;
this.version = version;
this.requires = requires;
this.provider = provider;
this.license = license;
}
public void addDependency(PluginDependency dependency) {
this.dependencies.add(dependency);
}
/**
* Returns the unique identifier of this plugin.
*/
@Override
public String getPluginId() {
return pluginId;
}
/**
* Returns the description of this plugin.
*/
@Override
public String getPluginDescription() {
return pluginDescription;
}
/**
* Returns the name of the class that implements Plugin interface.
*/
@Override
public String getPluginClass() {
return pluginClass;
}
/**
* Returns the version of this plugin.
*/
@Override
public String getVersion() {
return version;
}
/**
* Returns string version of requires
*
* @return String with requires expression on SemVer format
*/
@Override
public String getRequires() {
return requires;
}
/**
* Returns the provider name of this plugin.
*/
@Override
public String getProvider() {
return provider;
}
/**
* Returns the legal license of this plugin, e.g. "Apache-2.0", "MIT" etc
*/
@Override
public String getLicense() {
return license;
}
/**
* Returns all dependencies declared by this plugin.
* Returns an empty array if this plugin does not declare any require.
*/
@Override
public List<PluginDependency> getDependencies() {
return dependencies;
}
@Override
public String toString() {
return "PluginDescriptor [pluginId=" + pluginId + ", pluginClass="
+ pluginClass + ", version=" + version + ", provider="
+ provider + ", dependencies=" + dependencies + ", description="
+ pluginDescription + ", requires=" + requires + ", license="
+ license + "]";
}
protected DefaultPluginDescriptor setPluginId(String pluginId) {
this.pluginId = pluginId;
return this;
}
protected PluginDescriptor setPluginDescription(String pluginDescription) {
this.pluginDescription = pluginDescription;
return this;
}
protected PluginDescriptor setPluginClass(String pluginClassName) {
this.pluginClass = pluginClassName;
return this;
}
protected DefaultPluginDescriptor setPluginVersion(String version) {
this.version = version;
return this;
}
protected PluginDescriptor setProvider(String provider) {
this.provider = provider;
return this;
}
protected PluginDescriptor setRequires(String requires) {
this.requires = requires;
return this;
}
protected PluginDescriptor setDependencies(String dependencies) {
if (dependencies != null) {
dependencies = dependencies.trim();
if (dependencies.isEmpty()) {
this.dependencies = Collections.emptyList();
} else {
this.dependencies = new ArrayList<>();
String[] tokens = dependencies.split(",");
for (String dependency : tokens) {
dependency = dependency.trim();
if (!dependency.isEmpty()) {
this.dependencies.add(new PluginDependency(dependency));
}
}
if (this.dependencies.isEmpty()) {
this.dependencies = Collections.emptyList();
}
}
} else {
this.dependencies = Collections.emptyList();
}
return this;
}
public PluginDescriptor setLicense(String license) {
this.license = license;
return this;
}
}

6
pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java

@ -88,7 +88,7 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder {
} }
protected PluginDescriptor createPluginDescriptor(Manifest manifest) { protected PluginDescriptor createPluginDescriptor(Manifest manifest) {
PluginDescriptor pluginDescriptor = createPluginDescriptorInstance(); DefaultPluginDescriptor pluginDescriptor = createPluginDescriptorInstance();
// TODO validate !!! // TODO validate !!!
Attributes attributes = manifest.getMainAttributes(); Attributes attributes = manifest.getMainAttributes();
@ -125,8 +125,8 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder {
return pluginDescriptor; return pluginDescriptor;
} }
protected PluginDescriptor createPluginDescriptorInstance() { protected DefaultPluginDescriptor createPluginDescriptorInstance() {
return new PluginDescriptor(); return new DefaultPluginDescriptor();
} }
} }

154
pf4j/src/main/java/org/pf4j/PluginDescriptor.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 Decebal Suiu * Copyright 2015 Decebal Suiu
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -15,8 +15,6 @@
*/ */
package org.pf4j; package org.pf4j;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@ -25,153 +23,21 @@ import java.util.List;
* *
* @author Decebal Suiu * @author Decebal Suiu
*/ */
public class PluginDescriptor { public interface PluginDescriptor {
private String pluginId; String getPluginId();
private String pluginDescription;
private String pluginClass;
private String version;
private String requires = "*"; // SemVer format
private String provider;
private List<PluginDependency> dependencies;
private String license;
public PluginDescriptor() { String getPluginDescription();
dependencies = new ArrayList<>();
}
/** String getPluginClass();
* Returns the unique identifier of this plugin.
*/
public String getPluginId() {
return pluginId;
}
/** String getVersion();
* Returns the description of this plugin.
*/
public String getPluginDescription() {
return pluginDescription;
}
/** String getRequires();
* Returns the name of the class that implements Plugin interface.
*/
public String getPluginClass() {
return pluginClass;
}
/** String getProvider();
* Returns the version of this plugin.
*/
public String getVersion() {
return version;
}
/** String getLicense();
* Returns string version of requires
* @return String with requires expression on SemVer format
*/
public String getRequires() {
return requires;
}
/**
* Returns the provider name of this plugin.
*/
public String getProvider() {
return provider;
}
/**
* Returns the legal license of this plugin, e.g. "Apache-2.0", "MIT" etc
*/
public String getLicense() {
return license;
}
/**
* Returns all dependencies declared by this plugin.
* Returns an empty array if this plugin does not declare any require.
*/
public List<PluginDependency> getDependencies() {
return dependencies;
}
@Override
public String toString() {
return "PluginDescriptor [pluginId=" + pluginId + ", pluginClass="
+ pluginClass + ", version=" + version + ", provider="
+ provider + ", dependencies=" + dependencies + ", description="
+ pluginDescription + ", requires=" + requires + ", license="
+ license + "]";
}
PluginDescriptor setPluginId(String pluginId) {
this.pluginId = pluginId;
return this;
}
PluginDescriptor setPluginDescription(String pluginDescription) {
this.pluginDescription = pluginDescription;
return this;
}
PluginDescriptor setPluginClass(String pluginClassName) {
this.pluginClass = pluginClassName;
return this;
}
PluginDescriptor setPluginVersion(String version) {
this.version = version;
return this;
}
PluginDescriptor setProvider(String provider) {
this.provider = provider;
return this;
}
PluginDescriptor setRequires(String requires) {
this.requires = requires;
return this;
}
PluginDescriptor setDependencies(String dependencies) {
if (dependencies != null) {
dependencies = dependencies.trim();
if (dependencies.isEmpty()) {
this.dependencies = Collections.emptyList();
} else {
this.dependencies = new ArrayList<>();
String[] tokens = dependencies.split(",");
for (String dependency : tokens) {
dependency = dependency.trim();
if (!dependency.isEmpty()) {
this.dependencies.add(new PluginDependency(dependency));
}
}
if (this.dependencies.isEmpty()) {
this.dependencies = Collections.emptyList();
}
}
} else {
this.dependencies = Collections.emptyList();
}
return this;
}
public PluginDescriptor setLicense(String license) {
this.license = license;
return this;
}
List<PluginDependency> getDependencies();
} }

6
pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java

@ -95,7 +95,7 @@ public class PropertiesPluginDescriptorFinder implements PluginDescriptorFinder
} }
protected PluginDescriptor createPluginDescriptor(Properties properties) { protected PluginDescriptor createPluginDescriptor(Properties properties) {
PluginDescriptor pluginDescriptor = createPluginDescriptorInstance(); DefaultPluginDescriptor pluginDescriptor = createPluginDescriptorInstance();
// TODO validate !!! // TODO validate !!!
String id = properties.getProperty("plugin.id"); String id = properties.getProperty("plugin.id");
@ -132,8 +132,8 @@ public class PropertiesPluginDescriptorFinder implements PluginDescriptorFinder
return pluginDescriptor; return pluginDescriptor;
} }
protected PluginDescriptor createPluginDescriptorInstance() { protected DefaultPluginDescriptor createPluginDescriptorInstance() {
return new PluginDescriptor(); return new DefaultPluginDescriptor();
} }
} }

4
pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java

@ -27,13 +27,13 @@ import static org.junit.Assert.assertTrue;
public class DefaultPluginManagerTest { public class DefaultPluginManagerTest {
private PluginDescriptor pd1 = null; private DefaultPluginDescriptor pd1 = null;
private DefaultPluginManager pluginManager = new DefaultPluginManager(); private DefaultPluginManager pluginManager = new DefaultPluginManager();
private PluginWrapper pw1; private PluginWrapper pw1;
@Before @Before
public void init() throws IOException { public void init() throws IOException {
pd1 = new PluginDescriptor(); pd1 = new DefaultPluginDescriptor();
pd1.setPluginId("myPlugin"); pd1.setPluginId("myPlugin");
pd1.setPluginVersion("1.2.3"); pd1.setPluginVersion("1.2.3");
pd1.setPluginClass("foo"); pd1.setPluginClass("foo");

20
pf4j/src/test/java/org/pf4j/DependencyResolverTest.java

@ -40,11 +40,11 @@ public class DependencyResolverTest {
@Test @Test
public void sortedPlugins() { public void sortedPlugins() {
// create incomplete plugin descriptor (ignore some attributes) // create incomplete plugin descriptor (ignore some attributes)
PluginDescriptor pd1 = new PluginDescriptor() PluginDescriptor pd1 = new DefaultPluginDescriptor()
.setPluginId("p1") .setPluginId("p1")
.setDependencies("p2"); .setDependencies("p2");
PluginDescriptor pd2 = new PluginDescriptor() PluginDescriptor pd2 = new DefaultPluginDescriptor()
.setPluginId("p2") .setPluginId("p2")
.setPluginVersion("0.0.0"); // needed in "checkDependencyVersion" method .setPluginVersion("0.0.0"); // needed in "checkDependencyVersion" method
@ -60,7 +60,7 @@ public class DependencyResolverTest {
@Test @Test
public void notFoundDependencies() throws Exception { public void notFoundDependencies() throws Exception {
PluginDescriptor pd1 = new PluginDescriptor() PluginDescriptor pd1 = new DefaultPluginDescriptor()
.setPluginId("p1") .setPluginId("p1")
.setDependencies("p2, p3"); .setDependencies("p2, p3");
@ -75,17 +75,17 @@ public class DependencyResolverTest {
@Test @Test
public void cyclicDependencies() { public void cyclicDependencies() {
PluginDescriptor pd1 = new PluginDescriptor() PluginDescriptor pd1 = new DefaultPluginDescriptor()
.setPluginId("p1") .setPluginId("p1")
.setPluginVersion("0.0.0") .setPluginVersion("0.0.0")
.setDependencies("p2"); .setDependencies("p2");
PluginDescriptor pd2 = new PluginDescriptor() PluginDescriptor pd2 = new DefaultPluginDescriptor()
.setPluginId("p2") .setPluginId("p2")
.setPluginVersion("0.0.0") .setPluginVersion("0.0.0")
.setDependencies("p3"); .setDependencies("p3");
PluginDescriptor pd3 = new PluginDescriptor() PluginDescriptor pd3 = new DefaultPluginDescriptor()
.setPluginId("p3") .setPluginId("p3")
.setPluginVersion("0.0.0") .setPluginVersion("0.0.0")
.setDependencies("p1"); .setDependencies("p1");
@ -102,12 +102,12 @@ public class DependencyResolverTest {
@Test @Test
public void wrongDependencyVersion() { public void wrongDependencyVersion() {
PluginDescriptor pd1 = new PluginDescriptor() PluginDescriptor pd1 = new DefaultPluginDescriptor()
.setPluginId("p1") .setPluginId("p1")
// .setDependencies("p2@2.0.0"); // simple version // .setDependencies("p2@2.0.0"); // simple version
.setDependencies("p2@>=1.5.0 & <1.6.0"); // range version .setDependencies("p2@>=1.5.0 & <1.6.0"); // range version
PluginDescriptor pd2 = new PluginDescriptor() PluginDescriptor pd2 = new DefaultPluginDescriptor()
.setPluginId("p2") .setPluginId("p2")
.setPluginVersion("1.4.0"); .setPluginVersion("1.4.0");
@ -122,11 +122,11 @@ public class DependencyResolverTest {
@Test @Test
public void goodDependencyVersion() { public void goodDependencyVersion() {
PluginDescriptor pd1 = new PluginDescriptor() PluginDescriptor pd1 = new DefaultPluginDescriptor()
.setPluginId("p1") .setPluginId("p1")
.setDependencies("p2@2.0.0"); .setDependencies("p2@2.0.0");
PluginDescriptor pd2 = new PluginDescriptor() PluginDescriptor pd2 = new DefaultPluginDescriptor()
.setPluginId("p2") .setPluginId("p2")
.setPluginVersion("2.0.0"); .setPluginVersion("2.0.0");

82
pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java

@ -0,0 +1,82 @@
/*
* 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.processor;
import org.junit.Test;
import javax.annotation.processing.Filer;
import javax.tools.FileObject;
import javax.tools.StandardLocation;
import java.io.IOException;
import java.io.StringReader;
import java.util.*;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
/**
* @author Josiah Haswell
*/
public class ServiceProviderExtensionStorageTest {
@Test
public void ensureServiceProviderExtensionStorageReadWorks() throws IOException {
final StringReader file = new StringReader("#hello\n World");
final Set<String> entries = new HashSet<>();
ServiceProviderExtensionStorage.read(file, entries);
assertThat(entries.size(), is(1));
assertThat(entries.contains("World"), is(true));
}
@Test
public void ensureReadingExtensionsProducesCorrectListOfExtensions() {
final StringReader file = new StringReader("#hello\n World");
final ExtensionAnnotationProcessor processor = mock(ExtensionAnnotationProcessor.class);
final Map<String, Set<String>> extensions = new HashMap<>();
extensions.put("hello", Collections.singleton("world"));
given(processor.getExtensions()).willReturn(extensions);
ServiceProviderExtensionStorage extensionStorage = new ServiceProviderExtensionStorage(processor) {
@Override
protected Filer getFiler() {
try {
Filer filer = mock(Filer.class);
FileObject fileObject = mock(FileObject.class);
given(fileObject.openReader(true)).willReturn(file);
given(filer.getResource(
any(StandardLocation.class),
any(String.class),
any(String.class)
)).willReturn(fileObject);
return filer;
} catch(IOException ex) {
throw new IllegalStateException("Shouldn't have gotten here");
}
}
};
Map<String, Set<String>> read = extensionStorage.read();
assertThat(read.containsKey("hello"), is(true));
assertThat(read.get("hello"), is(Collections.singleton("World")));
}
}
Loading…
Cancel
Save