This is an automated email from the ASF dual-hosted git repository. tv pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/turbine-core.git
commit 839d61109580658a1ca99c0390e8a19f9a03fb33 Author: Thomas Vandahl <[email protected]> AuthorDate: Sun Dec 14 20:44:54 2025 +0100 Remove InitableBroker and use default interface methods where possible --- .../org/apache/turbine/services/BaseInitable.java | 75 +----- .../turbine/services/BaseInitableBroker.java | 276 --------------------- .../org/apache/turbine/services/BaseService.java | 6 +- .../apache/turbine/services/BaseServiceBroker.java | 127 +++++----- .../turbine/services/BaseUnicastRemoteService.java | 23 +- src/java/org/apache/turbine/services/Initable.java | 36 +-- .../apache/turbine/services/InitableBroker.java | 98 -------- .../turbine/services/TurbineBaseService.java | 2 +- 8 files changed, 85 insertions(+), 558 deletions(-) diff --git a/src/java/org/apache/turbine/services/BaseInitable.java b/src/java/org/apache/turbine/services/BaseInitable.java index 97b910dc..4ddabc11 100644 --- a/src/java/org/apache/turbine/services/BaseInitable.java +++ b/src/java/org/apache/turbine/services/BaseInitable.java @@ -1,6 +1,5 @@ package org.apache.turbine.services; - /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -34,11 +33,8 @@ package org.apache.turbine.services; public class BaseInitable implements Initable { - /** InitableBroker that instantiatd this class. */ - protected InitableBroker initableBroker; - /** Initialization status of this class. */ - protected boolean isInitialized = false; + private boolean isInitialized = false; /** * Default constructor of BaseInitable. @@ -52,72 +48,6 @@ public class BaseInitable // empty } - /** - * Saves InitableBroker reference for later use. - * - * @param broker The InitableBroker that instantiated this object. - */ - @Override - public void setInitableBroker(InitableBroker broker) - { - this.initableBroker = broker; - } - - /** - * Returns an InitableBroker reference. - * - * @return The InitableBroker that instantiated this object. - */ - public InitableBroker getInitableBroker() - { - return initableBroker; - } - - /** - * Performs early initialization. Used in a manner similar to a ctor. - * - * BaseInitable doesn't need early initialization, therefore it - * ignores all objects passed to it and performs no initialization - * activities. - * - * @param data An Object to use for initialization activities. - * @throws InitializationException Initialization of this - * class was not successful. - */ - @Override - public void init(Object data) throws InitializationException - { - // empty - } - - /** - * Performs late initialization. Called when the Service is requested - * for the first time (if not already completely initialized by the - * early initializer). - * - * Late initialization of a BaseInitable is always successful. - * - * @throws InitializationException Initialization of this - * class was not successful. - */ - @Override - public void init() throws InitializationException - { - // empty - } - - /** - * Returns an Initable to uninitialized state. - * - * Calls setInit(false) to mark that we are no longer in initialized - * state. - */ - @Override - public void shutdown() - { - setInit(false); - } - /** * Returns initialization status. * @@ -134,7 +64,8 @@ public class BaseInitable * * @param value The new initialization status. */ - protected void setInit(boolean value) + @Override + public void setInit(boolean value) { this.isInitialized = value; } diff --git a/src/java/org/apache/turbine/services/BaseInitableBroker.java b/src/java/org/apache/turbine/services/BaseInitableBroker.java deleted file mode 100644 index 96aa8d46..00000000 --- a/src/java/org/apache/turbine/services/BaseInitableBroker.java +++ /dev/null @@ -1,276 +0,0 @@ -package org.apache.turbine.services; - - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - - -import java.util.Hashtable; -import java.util.Stack; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -/** - * A generic implementation of <code>InitableBroker</code>. - * Functionality provided by the broker includes: - * - * <ul> - * - * <li>Maintaining single instance of each <code>Initable</code> in - * the system.</li> - * - * <li>Early initialization of <code>Initables</code> during system - * startup.</li> - * - * <li>Late initialization of <code>Initables</code> before they are - * used.</li> - * - * <li>Providing instances of <code>Initables</code> to requesting - * parties.</li> - * - * <li>Maintaining dependencies between <code>Initables</code> during - * early initialization phases, including circular dependencies - * detection.</li> - * - * </ul> - * - * @author <a href="mailto:[email protected]">Kevin Burton</a> - * @author <a href="mailto:[email protected]">Rafal Krzewski</a> - * @author <a href="mailto:[email protected]">Henning P. Schmiedehausen</a> - * @version $Id$ - */ -public abstract class BaseInitableBroker - implements InitableBroker -{ - /** A repository of Initable instances. */ - protected Hashtable<String, Initable> initables = new Hashtable<>(); - - /** - * Names of classes being early-initialized are pushed onto this - * stack. A name appearing twice indicates a circular dependency - * chain. - */ - protected Stack<String> stack = new Stack<>(); - - /** Logging */ - private final Logger log = LogManager.getLogger(this.getClass()); - - /** - * Default constructor of InitableBroker. - * <p> - * This constructor does nothing. Your brokers should be - * singletons, therefore their constructors should be - * private. They should also have public YourBroker getInstance() - * methods. - * </p> - */ - protected BaseInitableBroker() - { - // empty - } - - @Override - public void initClass(String className, Object data) throws InitializationException { - synchronized (stack) { - int pos = stack.search(className); - if (pos != -1) { - throw new InitializationException(buildCircularDependencyMessage(className, pos)); - } - try { - stack.push(className); - Initable instance = getInitableInstance(className); - boolean instanceInitialized = instance.getInit(); - - if (!instanceInitialized) { - instance.init(data); - } - } finally { - stack.pop(); // Ensure class is removed from stack even if an exception occurs. - } - } - } - - /** - * Builds a message for a circular dependency exception. - * - * @param className - * @param dependencyPosition - * @return - */ - private String buildCircularDependencyMessage(String className, int dependencyPosition) { - StringBuilder msg = new StringBuilder() - .append(className) - .append(" couldn't be initialized because of circular dependency chain:") - .append(System.lineSeparator()); - - for (int i = dependencyPosition; i > 0; i--) { - msg.append(stack.elementAt(stack.size() - i - 1)) - .append("->"); - } - msg.append(className).append(System.lineSeparator()); - return msg.toString(); - } - - /** - * Shuts down an <code>Initable</code>. - * - * This method is used to release resources allocated by an - * <code>Initable</code>, and return it to its initial (uninitialized) - * state. - * - * @param className The name of the class to be uninitialized. - */ - @Override - public void shutdownClass(String className) - { - try - { - Initable initable = getInitableInstance(className); - if (initable.getInit()) - { - initable.shutdown(); - ((BaseInitable) initable).setInit(false); - } - } - catch (InstantiationException e) - { - // Shutdown of a nonexistent class was requested. - // This does not hurt anything, so we log the error and continue. - log.error("Shutdown of a nonexistent class {} was requested", className, e); - } - } - - /** - * Provides an instance of Initable class ready to work. - * <p> - * If the requested class couldn't be instantiated or initialized, - * an InstantiationException will be thrown. You needn't handle - * this exception in your code, since it indicates fatal - * misconfiguration of the system. - * </p> - * @param className The name of the Initable requested. - * @return An instance of the requested Initable. - * @throws InstantiationException if there was a problem - * during instantiation or initialization of the Initable. - */ - @Override - public Initable getInitable(String className) - throws InstantiationException - { - Initable initable; - try - { - initable = getInitableInstance(className); - if (!initable.getInit()) - { - synchronized (initable.getClass()) - { - if (!initable.getInit()) - { - initable.init(); - } - if (!initable.getInit()) - { - // this exception will be caught & rethrown by this - // very method. getInit() returning false indicates - // some initialization issue, which in turn prevents - // the InitableBroker from passing a working - // instance of the initable to the client. - throw new InitializationException( - "init() failed to initialize class " - + className); - } - } - } - return initable; - } - catch (InitializationException e) - { - throw new InstantiationException("Class " + className + - " failed to initialize", e); - } - } - - /** - * Retrieves an instance of an Initable from the repository. - * <p> - * If the requested class is not present in the repository, it is - * instantiated and passed a reference to the broker, saved and - * then returned. - * </p> - * @param className The name of the class to be instantiated. - * - * @return an instance of the requested class - * - * @throws InstantiationException if the requested class can't - * be instantiated. - */ - protected Initable getInitableInstance(String className) - throws InstantiationException - { - Initable initable = initables.get(className); - - if (initable == null) - { - try - { - initable = (Initable) Class.forName(className).getDeclaredConstructor().newInstance(); - } - // those two errors must be passed to the VM - catch (ThreadDeath | OutOfMemoryError t) - { - throw t; - } - catch (Throwable t) - { - // Used to indicate error condition. - String msg = null; - - if (t instanceof NoClassDefFoundError) - { - msg = "A class referenced by " + className + - " is unavailable. Check your jars and classes."; - } - else if (t instanceof ClassNotFoundException) - { - msg = "Class " + className + - " is unavailable. Check your jars and classes."; - } - else if (t instanceof ClassCastException) - { - msg = "Class " + className + - " doesn't implement Initable."; - } - else - { - msg = "Failed to instantiate " + className; - } - - throw new InstantiationException(msg, t); - } - - initable.setInitableBroker(this); - initables.put(className, initable); - } - - return initable; - } - -} diff --git a/src/java/org/apache/turbine/services/BaseService.java b/src/java/org/apache/turbine/services/BaseService.java index 88275a90..8ba84d7a 100644 --- a/src/java/org/apache/turbine/services/BaseService.java +++ b/src/java/org/apache/turbine/services/BaseService.java @@ -39,13 +39,13 @@ public class BaseService implements Service { /** A reference to the ServiceBroker that instantiated this object. */ - protected ServiceBroker serviceBroker; + private ServiceBroker serviceBroker; /** The configuration for this service */ - protected Configuration configuration; + private Configuration configuration; /** The name of this Service. */ - protected String name; + private String name; /** * Saves a reference to the ServiceBroker that instantiated this diff --git a/src/java/org/apache/turbine/services/BaseServiceBroker.java b/src/java/org/apache/turbine/services/BaseServiceBroker.java index 1cf50531..d4afc6a3 100644 --- a/src/java/org/apache/turbine/services/BaseServiceBroker.java +++ b/src/java/org/apache/turbine/services/BaseServiceBroker.java @@ -24,11 +24,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.Map; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Collectors; import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; @@ -54,7 +53,6 @@ import org.apache.logging.log4j.Logger; * @author <a href="mailto:[email protected]">Jason van Zyl</a> * @author <a href="mailto:[email protected]">Martin Poeschl</a> * @author <a href="mailto:[email protected]">Henning P. Schmiedehausen</a> - * @version $Id$ */ public abstract class BaseServiceBroker implements ServiceBroker { @@ -282,11 +280,7 @@ public abstract class BaseServiceBroker implements ServiceBroker } } // those two errors must be passed to the VM - catch (ThreadDeath t) - { - throw t; - } - catch (OutOfMemoryError t) + catch (ThreadDeath | OutOfMemoryError t) { throw t; } @@ -337,11 +331,10 @@ public abstract class BaseServiceBroker implements ServiceBroker */ public Iterator<String> getServiceNames(String prefix) { - Set<String> keys = new LinkedHashSet<>(mapping.keySet()); - - keys.removeIf(key -> !key.startsWith(prefix)); - - return Collections.unmodifiableSet(keys).iterator(); + return mapping.keySet().stream() + .filter(key -> !key.startsWith(prefix)) + .collect(Collectors.toUnmodifiableSet()) + .iterator(); } /** @@ -361,16 +354,18 @@ public abstract class BaseServiceBroker implements ServiceBroker // implementation has its name and broker reference set before // initialization. Service instance = getServiceInstance(name); - + serviceLock.lock(); - try { + try + { if (!instance.getInit()) { // this call might result in an indirect recursion instance.init(); } - - } finally { + } + finally + { serviceLock.unlock(); } } @@ -469,7 +464,7 @@ public abstract class BaseServiceBroker implements ServiceBroker serviceLock.lock(); try { service.shutdown(); - + if (service.getInit() && service instanceof BaseService) { // BaseService::shutdown() does this by default, @@ -544,14 +539,17 @@ public abstract class BaseServiceBroker implements ServiceBroker if (!service.getInit()) { serviceLock.lock(); // was synchronized (service.getClass(), but should be equivalent - try { + try + { if (!service.getInit()) { log.info("Start Initializing service (late): {}", name); service.init(); log.info("Finish Initializing service (late): {}", name); } - } finally { + } + finally + { serviceLock.unlock(); } } @@ -597,89 +595,78 @@ public abstract class BaseServiceBroker implements ServiceBroker * called. This calls for two - level accessing the Services * instances. * - * @param name The name of the service requested. + * @param serviceName The name of the service requested. * * @return the Service instance * * @throws InstantiationException The service is unknown or * can't be initialized. */ - protected Service getServiceInstance(String name) + protected Service getServiceInstance(String serviceName) throws InstantiationException { - Service service = services.get(name); - - if (service == null) + Service service = services.computeIfAbsent(serviceName, name -> { serviceLock.lock(); - try { - // Double check - service = services.get(name); + if (!this.isLocalService(name)) + { + throw new InstantiationException( + "ServiceBroker: unknown service " + name + + " requested"); + } - if (service == null) + Service newService; + + try { - if (!this.isLocalService(name)) - { - throw new InstantiationException( - "ServiceBroker: unknown service " + name - + " requested"); - } + Class<?> clazz = mapping.get(name); try { - Class<?> clazz = mapping.get(name); + newService = (Service) clazz.getDeclaredConstructor().newInstance(); - try + // check if the newly created service is also a + // service provider - if so then remember it + if (newService instanceof TurbineServiceProvider) { - service = (Service) clazz.getDeclaredConstructor().newInstance(); - - // check if the newly created service is also a - // service provider - if so then remember it - if (service instanceof TurbineServiceProvider) + Service _service = this.serviceProviderInstanceMap.putIfAbsent(name, newService); + if (_service != null) { - Service _service = this.serviceProviderInstanceMap.putIfAbsent(name,service); - if (_service != null) - { - service = _service; - } + newService = _service; } } - // those two errors must be passed to the VM - catch (ClassCastException e) - { - throw new InstantiationException("Class " + clazz + - " doesn't implement the Service interface", e); - } - catch (ThreadDeath | OutOfMemoryError t) - { - throw t; - } - catch (Throwable t) - { - throw new InstantiationException("Failed to instantiate " + clazz, t); - } } - catch (InstantiationException e) + // those two errors must be passed to the VM + catch (ClassCastException e) + { + throw new InstantiationException("Class " + clazz + + " doesn't implement the Service interface", e); + } + catch (ThreadDeath | OutOfMemoryError t) { - throw new InstantiationException( - "Failed to instantiate service " + name, e); + throw t; } - service.setServiceBroker(this); - service.setName(name); - Service _service = services.putIfAbsent(name, service); - if (_service != null) // Unlikely + catch (Throwable t) { - service = _service; + throw new InstantiationException("Failed to instantiate " + clazz, t); } } + catch (InstantiationException e) + { + throw new InstantiationException( + "Failed to instantiate service " + name, e); + } + newService.setServiceBroker(this); + newService.setName(name); + return newService; } finally { serviceLock.unlock(); } - } + }); return service; } diff --git a/src/java/org/apache/turbine/services/BaseUnicastRemoteService.java b/src/java/org/apache/turbine/services/BaseUnicastRemoteService.java index 8033896b..e310837b 100644 --- a/src/java/org/apache/turbine/services/BaseUnicastRemoteService.java +++ b/src/java/org/apache/turbine/services/BaseUnicastRemoteService.java @@ -42,9 +42,8 @@ public class BaseUnicastRemoteService extends UnicastRemoteObject */ private static final long serialVersionUID = -7775459623190960297L; - protected Configuration configuration; + private Configuration configuration; private boolean isInitialized; - private InitableBroker initableBroker; private String name; private ServiceBroker serviceBroker; @@ -56,9 +55,6 @@ public class BaseUnicastRemoteService extends UnicastRemoteObject throws RemoteException { isInitialized = false; - initableBroker = null; - name = null; - serviceBroker = null; } /** @@ -83,21 +79,6 @@ public class BaseUnicastRemoteService extends UnicastRemoteObject } } - @Override - public void setInitableBroker(InitableBroker broker) - { - this.initableBroker = broker; - } - - /** - * Get the {@link InitableBroker} instance - * @return the broker instance - */ - public InitableBroker getInitableBroker() - { - return initableBroker; - } - @Override public void init(Object data) throws InitializationException @@ -111,7 +92,7 @@ public class BaseUnicastRemoteService extends UnicastRemoteObject setInit(true); } - protected void setInit(boolean value) + public void setInit(boolean value) { isInitialized = value; } diff --git a/src/java/org/apache/turbine/services/Initable.java b/src/java/org/apache/turbine/services/Initable.java index 7c624d91..d30f1600 100644 --- a/src/java/org/apache/turbine/services/Initable.java +++ b/src/java/org/apache/turbine/services/Initable.java @@ -25,25 +25,12 @@ package org.apache.turbine.services; * Classes that implement this interface need initialization before * they can work. * - * These classes rely also on an <code>InitableBroker</code> that - * ensures that there is only one instance of the class in the system, - * and handles dependencies between <code>Initables</code>. - * * @author <a href="mailto:[email protected]">Kevin Burton</a> * @author <a href="mailto:[email protected]">Rafal Krzewski</a> * @version $Id$ */ public interface Initable { - /** - * Provides an Initable with a reference to the InitableBroker - * that instantiated this object, so that it can access other - * Initables. - * - * @param broker The InitableBroker that instantiated this object. - */ - void setInitableBroker(InitableBroker broker); - /** * Performs early initialization of an Initable * @@ -59,23 +46,27 @@ public interface Initable * expects was not received, you can use late initialization to * throw an exception and complain. * + * Default: do nothing + * * @param data An Object to use for initialization activities. * @throws InitializationException if initialization of this * class was not successful. */ - void init(Object data) throws InitializationException; + default void init(Object data) throws InitializationException {} /** * Performs late initialization of an Initable. - * + * * When your class is being requested from an InitableBroker, it * will call getInit(), and if it returns false, this method will * be invoked. * + * Default: do nothing + * * @throws InitializationException if initialization of this * class was not successful. */ - void init() throws InitializationException; + default void init() throws InitializationException {} /** * Returns an <code>Initable</code> to an uninitialized state. @@ -85,8 +76,12 @@ public interface Initable * You may chose to implement this operation or not. If you support * this operation, getInit() should return false after successful * shutdown of the service. + * + * Default: setInit(false) */ - void shutdown(); + default void shutdown() { + setInit(false); + } /** * Returns initialization status of an Initable. @@ -94,4 +89,11 @@ public interface Initable * @return Initialization status of an Initable. */ boolean getInit(); + + /** + * Sets initialization status. + * + * @param value The new initialization status. + */ + void setInit(boolean value); } diff --git a/src/java/org/apache/turbine/services/InitableBroker.java b/src/java/org/apache/turbine/services/InitableBroker.java deleted file mode 100644 index 0881af7c..00000000 --- a/src/java/org/apache/turbine/services/InitableBroker.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.apache.turbine.services; - - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - - -/** - * Classes that implement this interface can act as a broker for - * <code>Initable</code> classes. - * - * Functionality provided by the broker includes: - * - * <ul> - * - * <li>Maintaining a single instance of each <code>Initable</code> in - * the system.</li> - * - * <li>Early initialization of <code>Initables</code> during system - * startup.</li> - * - * <li>Late initialization of <code>Initables</code> before they are - * used.</li> - * - * <li>Providing instances of <code>Initables</code> to requesting - * parties.</li> - * - * <li>Maintaining dependencies between <code>Initables</code> during - * early initialization phases, including circular dependencies - * detection.</li> - * - * </ul> - * - * @author <a href="mailto:[email protected]">Kevin Burton</a> - * @author <a href="mailto:[email protected]">Rafal Krzewski</a> - * @version $Id$ - */ -public interface InitableBroker -{ - /** - * Performs early initialization of an Initable class. - * - * If your class depends on another Initable being initialized to - * perform early initialization, you should always ask your broker - * to initialize the other class with the objects that are passed - * to you, before you try to retrieve that Initable's instance with - * getInitable(). - * - * @param className The name of the class to be initialized. - * @param data An object to be used for initialization activities. - * @throws InitializationException if initialization of this - * class was not successful. - */ - void initClass(String className, Object data) - throws InitializationException; - - /** - * Shutdowns an Initable class. - * - * This method is used to release resources allocated by an - * Initable class, and return it to initial (uninitialized) - * state. - * - * @param className The name of the class to be uninitialized. - */ - void shutdownClass(String className); - - /** - * Provides an instance of Initable class ready to work. - * - * If the requested class couldn't be instatiated or initialized, - * InstantiationException will be thrown. You needn't handle this - * exception in your code, since it indicates fatal - * misconfigurtion of the system. - * - * @param className The name of the Initable requested. - * @return An instance of requested Initable. - * @throws InstantiationException if there was a problem - * during instantiation or initialization of the Initable. - */ - Initable getInitable(String className) throws InstantiationException; -} diff --git a/src/java/org/apache/turbine/services/TurbineBaseService.java b/src/java/org/apache/turbine/services/TurbineBaseService.java index 4e6bbd8e..9f008638 100644 --- a/src/java/org/apache/turbine/services/TurbineBaseService.java +++ b/src/java/org/apache/turbine/services/TurbineBaseService.java @@ -42,7 +42,7 @@ import org.apache.turbine.util.RunData; * it:</p> * * <pre> - * getServiceBroker().initClass("OtherService",data); + * getServiceBroker().initService("OtherService"); * OtherService service = * (OtherService)getServiceBroker().getService("OtherService"); * </pre>
