Skip to content

Commit

Permalink
Relax Plugin construction (remove dependency on PluginWrapper) (pf4j#512
Browse files Browse the repository at this point in the history
)
  • Loading branch information
decebals authored Jan 30, 2023
1 parent de63736 commit 1f04209
Show file tree
Hide file tree
Showing 13 changed files with 561 additions and 346 deletions.
35 changes: 35 additions & 0 deletions demo/api/src/main/java/org/pf4j/demo/api/DemoPlugin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2012-present the original author or authors.
*
* 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.demo.api;

import org.pf4j.Plugin;

/**
* Base {@link Plugin} for all demo plugins.
*
* @author Decebal Suiu
*/
public abstract class DemoPlugin extends Plugin {

protected final PluginContext context;

protected DemoPlugin(PluginContext context) {
super();

this.context = context;
}

}
39 changes: 39 additions & 0 deletions demo/api/src/main/java/org/pf4j/demo/api/PluginContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2012-present the original author or authors.
*
* 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.demo.api;

import org.pf4j.RuntimeMode;

/**
* An instance of this class is provided to plugins in their constructor.
* It's safe for plugins to keep a reference to the instance for later use.
* This class facilitates communication with application and plugin manager.
*
* @author Decebal Suiu
*/
public class PluginContext {

private final RuntimeMode runtimeMode;

public PluginContext(RuntimeMode runtimeMode) {
this.runtimeMode = runtimeMode;
}

public RuntimeMode getRuntimeMode() {
return runtimeMode;
}

}
22 changes: 1 addition & 21 deletions demo/app/src/main/java/org/pf4j/demo/Boot.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package org.pf4j.demo;

import org.apache.commons.lang.StringUtils;
import org.pf4j.DefaultPluginManager;
import org.pf4j.PluginManager;
import org.pf4j.PluginWrapper;
import org.pf4j.demo.api.Greeting;
Expand All @@ -40,7 +39,7 @@ public static void main(String[] args) {
printLogo();

// create the plugin manager
PluginManager pluginManager = createPluginManager();
PluginManager pluginManager = new DemoPluginManager();

// load the plugins
pluginManager.loadPlugins();
Expand Down Expand Up @@ -129,23 +128,4 @@ private static void printLogo() {
log.info(StringUtils.repeat("#", 40));
}

private static PluginManager createPluginManager() {
return new DefaultPluginManager();

// use below plugin manager instance if you want to enable ServiceProviderExtensionFinder
/*
return new DefaultPluginManager() {
@Override
protected ExtensionFinder createExtensionFinder() {
DefaultExtensionFinder extensionFinder = (DefaultExtensionFinder) super.createExtensionFinder();
extensionFinder.addServiceProviderExtensionFinder(); // to activate "HowdyGreeting" extension
return extensionFinder;
}
};
*/
}

}
40 changes: 40 additions & 0 deletions demo/app/src/main/java/org/pf4j/demo/DemoPluginFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (C) 2012-present the original author or authors.
*
* 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.demo;

import org.pf4j.DefaultPluginFactory;
import org.pf4j.Plugin;
import org.pf4j.PluginWrapper;
import org.pf4j.demo.api.PluginContext;

import java.lang.reflect.Constructor;

class DemoPluginFactory extends DefaultPluginFactory {

@Override
protected Plugin createInstance(Class<?> pluginClass, PluginWrapper pluginWrapper) {
PluginContext context = new PluginContext(pluginWrapper.getRuntimeMode());
try {
Constructor<?> constructor = pluginClass.getConstructor(PluginContext.class);
return (Plugin) constructor.newInstance(context);
} catch (Exception e) {
log.error(e.getMessage(), e);
}

return null;
}

}
42 changes: 42 additions & 0 deletions demo/app/src/main/java/org/pf4j/demo/DemoPluginManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2012-present the original author or authors.
*
* 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.demo;

import org.pf4j.DefaultExtensionFinder;
import org.pf4j.DefaultPluginFactory;
import org.pf4j.DefaultPluginManager;
import org.pf4j.ExtensionFinder;
import org.pf4j.PluginFactory;

class DemoPluginManager extends DefaultPluginManager {

// Use below code if you want to enable ServiceProviderExtensionFinder
/*
@Override
protected ExtensionFinder createExtensionFinder() {
DefaultExtensionFinder extensionFinder = (DefaultExtensionFinder) super.createExtensionFinder();
extensionFinder.addServiceProviderExtensionFinder(); // to activate "HowdyGreeting" extension
return extensionFinder;
}
*/

@Override
protected PluginFactory createPluginFactory() {
return new DemoPluginFactory();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,26 @@
package org.pf4j.demo.welcome;

import org.apache.commons.lang.StringUtils;

import org.pf4j.PluginWrapper;
import org.pf4j.Extension;
import org.pf4j.RuntimeMode;
import org.pf4j.demo.api.DemoPlugin;
import org.pf4j.demo.api.Greeting;
import org.pf4j.Extension;
import org.pf4j.Plugin;
import org.pf4j.demo.api.PluginContext;

/**
* @author Decebal Suiu
*/
public class WelcomePlugin extends Plugin {
public class WelcomePlugin extends DemoPlugin {

public WelcomePlugin(PluginWrapper wrapper) {
super(wrapper);
public WelcomePlugin(PluginContext context) {
super(context);
}

@Override
public void start() {
log.info("WelcomePlugin.start()");
// for testing the development mode
if (RuntimeMode.DEVELOPMENT.equals(wrapper.getRuntimeMode())) {
if (RuntimeMode.DEVELOPMENT.equals(context.getRuntimeMode())) {
log.info(StringUtils.upperCase("WelcomePlugin"));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@
package org.pf4j.demo.hello;

import org.pf4j.Extension;
import org.pf4j.Plugin;
import org.pf4j.PluginWrapper;
import org.pf4j.demo.api.DemoPlugin;
import org.pf4j.demo.api.Greeting;
import org.pf4j.demo.api.PluginContext;

/**
* A very simple plugin.
*
* @author Decebal Suiu
*/
public class HelloPlugin extends Plugin {
public class HelloPlugin extends DemoPlugin {

public HelloPlugin(PluginWrapper wrapper) {
super(wrapper);
public HelloPlugin(PluginContext context) {
super(context);
}

@Override
Expand Down
26 changes: 20 additions & 6 deletions pf4j/src/main/java/org/pf4j/DefaultPluginFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,16 @@

/**
* The default implementation for {@link PluginFactory}.
* It uses {@link Class#newInstance()} method.
* It uses {@link Constructor#newInstance(Object...)} method.
*
* @author Decebal Suiu
*/
public class DefaultPluginFactory implements PluginFactory {

private static final Logger log = LoggerFactory.getLogger(DefaultPluginFactory.class);
protected static final Logger log = LoggerFactory.getLogger(DefaultPluginFactory.class);

/**
* Creates a plugin instance. If an error occurs than that error is logged and the method returns null.
* @param pluginWrapper
* @return
* Creates a plugin instance. If an error occurs than that error is logged and the method returns {@code null}.
*/
@Override
public Plugin create(final PluginWrapper pluginWrapper) {
Expand All @@ -58,10 +56,26 @@ public Plugin create(final PluginWrapper pluginWrapper) {
return null;
}

// create the plugin instance
return createInstance(pluginClass, pluginWrapper);
}

protected Plugin createInstance(Class<?> pluginClass, PluginWrapper pluginWrapper) {
try {
Constructor<?> constructor = pluginClass.getConstructor(PluginWrapper.class);
return (Plugin) constructor.newInstance(pluginWrapper);
} catch (NoSuchMethodException e) {
return createUsingNoParametersConstructor(pluginClass);
} catch (Exception e) {
log.error(e.getMessage(), e);
}

return null;
}

protected Plugin createUsingNoParametersConstructor(Class<?> pluginClass) {
try {
Constructor<?> constructor = pluginClass.getConstructor();
return (Plugin) constructor.newInstance();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
Expand Down
12 changes: 12 additions & 0 deletions pf4j/src/main/java/org/pf4j/Plugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,20 @@ public class Plugin {

/**
* Wrapper of the plugin.
* @deprecated Use application custom {@code PluginContext} instead of {@code PluginWrapper}.
* See demo for more details.
*/
@Deprecated
protected PluginWrapper wrapper;

/**
* Constructor to be used by plugin manager for plugin instantiation.
* Your plugins have to provide constructor with this exact signature to
* be successfully loaded by manager.
* @deprecated Use application custom {@code PluginContext} instead of {@code PluginWrapper}.
* See demo for more details.
*/
@Deprecated
public Plugin(final PluginWrapper wrapper) {
if (wrapper == null) {
throw new IllegalArgumentException("Wrapper cannot be null");
Expand All @@ -49,9 +55,15 @@ public Plugin(final PluginWrapper wrapper) {
this.wrapper = wrapper;
}

public Plugin() {
}

/**
* Retrieves the wrapper of this plug-in.
* @deprecated Use application custom {@code PluginContext} instead of {@code PluginWrapper}.
* See demo for more details.
*/
@Deprecated
public final PluginWrapper getWrapper() {
return wrapper;
}
Expand Down
Loading

0 comments on commit 1f04209

Please sign in to comment.