diff options
Diffstat (limited to 'utils/src/main')
5 files changed, 315 insertions, 503 deletions
diff --git a/utils/src/main/java/org/onap/policy/common/utils/network/NetworkUtil.java b/utils/src/main/java/org/onap/policy/common/utils/network/NetworkUtil.java index ae70ba44..3976c7a2 100644 --- a/utils/src/main/java/org/onap/policy/common/utils/network/NetworkUtil.java +++ b/utils/src/main/java/org/onap/policy/common/utils/network/NetworkUtil.java @@ -1,8 +1,8 @@ -/*- +/* * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,9 +23,13 @@ package org.onap.policy.common.utils.network; import java.io.IOException; import java.net.ConnectException; import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; - +import java.security.cert.X509Certificate; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,11 +45,84 @@ public class NetworkUtil { */ public static final String IPv4_WILDCARD_ADDRESS = "0.0.0.0"; + + /** + * A trust manager that always trusts certificates. + */ + // @formatter:off + private static final TrustManager[] ALWAYS_TRUST_MANAGER = new TrustManager[] { + new X509TrustManager() { + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void checkClientTrusted(final java.security.cert.X509Certificate[] certs, + final String authType) { + // always trust + } + + @Override + public void checkServerTrusted(final java.security.cert.X509Certificate[] certs, + final String authType) { + // always trust + } + } + }; + // @formatter:on + private NetworkUtil() { // Empty constructor } /** + * Allocates an available port on which a server may listen. + * + * @return an available port + * @throws IOException if a socket cannot be created + */ + public static int allocPort() throws IOException { + return allocPort((InetSocketAddress) null); + } + + /** + * Allocates an available port on which a server may listen. + * + * @param hostName the server's host name + * @return an available port + * @throws IOException if a socket cannot be created + */ + public static int allocPort(String hostName) throws IOException { + return allocPort(new InetSocketAddress(hostName, 0)); + } + + /** + * Allocates an available port on which a server may listen. + * + * @param hostAddr the server's host address on which to listen + * @return an available port + * @throws IOException if a socket cannot be created + */ + public static int allocPort(InetSocketAddress hostAddr) throws IOException { + try (ServerSocket socket = new ServerSocket()) { + socket.bind(hostAddr); + + return socket.getLocalPort(); + } + } + + /** + * Gets a trust manager that accepts all certificates. + * + * @return a trust manager that accepts all certificates + */ + public static TrustManager[] getAlwaysTrustingManager() { + return ALWAYS_TRUST_MANAGER; + } + + /** * try to connect to $host:$port $retries times while we are getting connection failures. * * @param host host diff --git a/utils/src/main/java/org/onap/policy/common/utils/properties/BeanConfigurator.java b/utils/src/main/java/org/onap/policy/common/utils/properties/BeanConfigurator.java index 9d02819a..2ef91911 100644 --- a/utils/src/main/java/org/onap/policy/common/utils/properties/BeanConfigurator.java +++ b/utils/src/main/java/org/onap/policy/common/utils/properties/BeanConfigurator.java @@ -526,9 +526,8 @@ public class BeanConfigurator { * @param methodName name of the method to return * @return the method to be used to get the field's value * @throws NoSuchMethodException if the method does not exist - * @throws SecurityException if the method cannot be accessed */ - protected Method getGetter(Field field, String methodName) throws NoSuchMethodException, SecurityException { + protected Method getGetter(Field field, String methodName) throws NoSuchMethodException { return field.getDeclaringClass().getMethod(methodName); } diff --git a/utils/src/main/java/org/onap/policy/common/utils/properties/PropertyConfiguration.java b/utils/src/main/java/org/onap/policy/common/utils/properties/PropertyConfiguration.java deleted file mode 100644 index b41f3bc0..00000000 --- a/utils/src/main/java/org/onap/policy/common/utils/properties/PropertyConfiguration.java +++ /dev/null @@ -1,498 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP Policy Engine - Common Modules - * ================================================================================ - * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.common.utils.properties; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Properties; -import org.apache.commons.lang3.StringUtils; -import org.onap.policy.common.utils.properties.exception.PropertyAccessException; -import org.onap.policy.common.utils.properties.exception.PropertyException; -import org.onap.policy.common.utils.properties.exception.PropertyInvalidException; -import org.onap.policy.common.utils.properties.exception.PropertyMissingException; - -/** - * Configuration whose fields are initialized by reading from a set of {@link Properties}, - * as directed by the {@link Property} annotations that appear on fields within the - * subclass. The values of the fields are set via <i>setXxx()</i> methods. As a result, if - * a field is annotated and there is no corresponding <i>setXxx()</i> method, then an - * exception will be thrown. - * - * <p>It is possible that an invalid <i>defaultValue</i> is specified via the - * {@link Property} annotation. This could remain undetected until an optional property is - * left out of the {@link Properties}. Consequently, this class will always validate a - * {@link Property}'s default value, if the <i>defaultValue</i> is not empty or if - * <i>accept</i> includes the "empty" option. - */ -public class PropertyConfiguration { - - /** - * The "empty" option that may appear within the {@link Property}'s <i>accept</i> - * attribute. - */ - public static final String ACCEPT_EMPTY = "empty"; - - /** - * Constructs a configuration, without populating any fields; fields should be - * populated later by invoking {@link #setAllFields(Properties)}. - */ - public PropertyConfiguration() { - super(); - } - - /** - * Initializes each "@Property" field with its value, as found in the properties. - * - * @param props properties from which to extract the values - * @throws PropertyException if an error occurs - */ - public PropertyConfiguration(Properties props) throws PropertyException { - setAllFields(props); - } - - /** - * Walks the class hierarchy of "this" object, populating fields defined in each - * class, using values extracted from the given property set. - * - * @param props properties from which to extract the values - * @throws PropertyException if an error occurs - */ - public void setAllFields(Properties props) throws PropertyException { - Class<?> clazz = getClass(); - - while (clazz != PropertyConfiguration.class) { - for (Field field : clazz.getDeclaredFields()) { - setValue(field, props); - } - - clazz = clazz.getSuperclass(); - } - } - - /** - * Sets a field's value, within an object, based on what's in the properties. - * - * @param field field whose value is to be set - * @param props properties from which to get the value - * @return {@code true} if the property's value was set, {@code false} otherwise - * @throws PropertyException if an error occurs - */ - protected boolean setValue(Field field, Properties props) throws PropertyException { - Property prop = field.getAnnotation(Property.class); - if (prop == null) { - return false; - } - - checkModifiable(field, prop); - - Method setter = getSetter(field, prop); - checkSetter(setter, prop); - - if (setValue(setter, field, props, prop)) { - return true; - } - - throw new PropertyAccessException(prop.name(), field.getName(), "unsupported field type"); - } - - /** - * Sets a field's value from a particular property. - * - * @param setter method to be used to set the field's value - * @param field field whose value is to be set - * @param props properties from which to get the value - * @param prop property of interest - * @return {@code true} if the property's value was set, {@code false} otherwise - * @throws PropertyException if an error occurs - */ - protected boolean setValue(Method setter, Field field, Properties props, Property prop) throws PropertyException { - - try { - Object val = getValue(field, props, prop); - if (val == null) { - return false; - - } else { - setter.invoke(this, val); - return true; - } - - } catch (IllegalArgumentException e) { - throw new PropertyInvalidException(prop.name(), field.getName(), e); - - } catch (IllegalAccessException | InvocationTargetException e) { - throw new PropertyAccessException(prop.name(), setter.getName(), e); - } - } - - /** - * Get the setter. - * - * @param field field whose value is to be set - * @param prop property of interest - * @return the method to be used to set the field's value - * @throws PropertyAccessException if a "set" method cannot be identified - */ - private Method getSetter(Field field, Property prop) throws PropertyAccessException { - String nm = "set" + StringUtils.capitalize(field.getName()); - - try { - return this.getClass().getMethod(nm, field.getType()); - - } catch (NoSuchMethodException | SecurityException e) { - throw new PropertyAccessException(prop.name(), nm, e); - } - } - - /** - * Gets a property value, coercing it to the field's type. - * - * @param field field whose value is to be set - * @param props properties from which to get the value - * @param prop property of interest - * @return the value extracted from the property, or {@code null} if the field type is - * not supported - * @throws PropertyException if an error occurs - */ - protected Object getValue(Field field, Properties props, Property prop) throws PropertyException { - - Class<?> clazz = field.getType(); - String fieldName = field.getName(); - - // can still add support for short, float, double, enum - - if (clazz == String.class) { - return getStringValue(fieldName, props, prop); - - } else if (clazz == Boolean.class || clazz == boolean.class) { - return getBooleanValue(fieldName, props, prop); - - } else if (clazz == Integer.class || clazz == int.class) { - return getIntegerValue(fieldName, props, prop); - - } else if (clazz == Long.class || clazz == long.class) { - return getLongValue(fieldName, props, prop); - - } else { - return null; - } - } - - /** - * Verifies that the field can be modified, i.e., it's neither <i>static</i>, nor - * <i>final</i>. - * - * @param field field whose value is to be set - * @param prop property of interest - * @throws PropertyAccessException if the field is not modifiable - */ - protected void checkModifiable(Field field, Property prop) throws PropertyAccessException { - int mod = field.getModifiers(); - - if (Modifier.isStatic(mod)) { - throw new PropertyAccessException(prop.name(), field.getName(), "'static' variable cannot be modified"); - } - - if (Modifier.isFinal(mod)) { - throw new PropertyAccessException(prop.name(), field.getName(), "'final' variable cannot be modified"); - } - } - - /** - * Verifies that the setter method is not <i>static</i>. - * - * @param setter method to be checked - * @param prop property of interest - * @throws PropertyAccessException if the method is static - */ - private void checkSetter(Method setter, Property prop) throws PropertyAccessException { - int mod = setter.getModifiers(); - - if (Modifier.isStatic(mod)) { - throw new PropertyAccessException(prop.name(), setter.getName(), "method is 'static'"); - } - } - - /** - * Gets a property value, coercing it to a String. - * - * @param fieldName field whose value is to be set - * @param props properties from which to get the value - * @param prop property of interest - * @return the value extracted from the property - * @throws PropertyException if an error occurs - */ - protected String getStringValue(String fieldName, Properties props, Property prop) throws PropertyException { - - /* - * Note: the default value for a String type is always valid, thus no need to - * check it. - */ - - return getPropValue(fieldName, props, prop); - } - - /** - * Gets a property value, coercing it to a Boolean. - * - * @param fieldName field whose value is to be set - * @param props properties from which to get the value - * @param prop property of interest - * @return the value extracted from the property - * @throws PropertyException if an error occurs - */ - protected Boolean getBooleanValue(String fieldName, Properties props, Property prop) throws PropertyException { - // validate the default value - checkDefaultValue(fieldName, prop, xxx -> makeBoolean(fieldName, prop, prop.defaultValue())); - - return makeBoolean(fieldName, prop, getPropValue(fieldName, props, prop)); - } - - /** - * Gets a property value, coercing it to an Integer. - * - * @param fieldName field whose value is to be set - * @param props properties from which to get the value - * @param prop property of interest - * @return the value extracted from the property - * @throws PropertyException if an error occurs - */ - protected Integer getIntegerValue(String fieldName, Properties props, Property prop) throws PropertyException { - // validate the default value - checkDefaultValue(fieldName, prop, xxx -> makeInteger(fieldName, prop, prop.defaultValue())); - - return makeInteger(fieldName, prop, getPropValue(fieldName, props, prop)); - } - - /** - * Gets a property value, coercing it to a Long. - * - * @param fieldName field whose value is to be set - * @param props properties from which to get the value - * @param prop property of interest - * @return the value extracted from the property - * @throws PropertyException if an error occurs - */ - protected Long getLongValue(String fieldName, Properties props, Property prop) throws PropertyException { - // validate the default value - checkDefaultValue(fieldName, prop, xxx -> makeLong(fieldName, prop, prop.defaultValue())); - - return makeLong(fieldName, prop, getPropValue(fieldName, props, prop)); - } - - /** - * Gets a value from the property set. - * - * @param fieldName field whose value is to be set - * @param props properties from which to get the value - * @param prop property of interest - * @return the value extracted from the property, or the <i>defaultValue</i> if the - * value does not exist - * @throws PropertyMissingException if the property does not exist and the - * <i>defaultValue</i> is empty and <i>emptyOk</i> is {@code false} - */ - protected String getPropValue(String fieldName, Properties props, Property prop) throws PropertyMissingException { - String propnm = prop.name(); - - String val = getRawPropertyValue(props, propnm); - if (val != null && isEmptyOk(prop, val)) { - return val; - } - - val = prop.defaultValue(); - if (val != null && isEmptyOk(prop, val)) { - return val; - } - - throw new PropertyMissingException(prop.name(), fieldName); - } - - /** - * Gets the property value, straight from the property set. - * - * @param props properties from which to get the value - * @param propnm name of the property of interest - * @return the raw property value - */ - protected String getRawPropertyValue(Properties props, String propnm) { - return props.getProperty(propnm); - } - - /** - * Coerces a String value into a Boolean. - * - * @param fieldName field whose value is to be set - * @param prop property of interest - * @param value value to be coerced - * @return the Boolean value represented by the String value - * @throws PropertyInvalidException if the value does not represent a valid Boolean - */ - private Boolean makeBoolean(String fieldName, Property prop, String value) throws PropertyInvalidException { - if ("true".equalsIgnoreCase(value)) { - return Boolean.TRUE; - - } else if ("false".equalsIgnoreCase(value)) { - return Boolean.FALSE; - - } else { - throw new PropertyInvalidException(prop.name(), fieldName, "expecting 'true' or 'false'"); - } - } - - /** - * Coerces a String value into an Integer. - * - * @param fieldName field whose value is to be set - * @param prop property of interest - * @param value value to be coerced - * @return the Integer value represented by the String value - * @throws PropertyInvalidException if the value does not represent a valid Integer - */ - private Integer makeInteger(String fieldName, Property prop, String value) throws PropertyInvalidException { - try { - return Integer.valueOf(value); - - } catch (NumberFormatException e) { - throw new PropertyInvalidException(prop.name(), fieldName, e); - } - } - - /** - * Coerces a String value into a Long. - * - * @param fieldName field whose value is to be set - * @param prop property of interest - * @param value value to be coerced - * @return the Long value represented by the String value - * @throws PropertyInvalidException if the value does not represent a valid Long - */ - private Long makeLong(String fieldName, Property prop, String value) throws PropertyInvalidException { - try { - return Long.valueOf(value); - - } catch (NumberFormatException e) { - throw new PropertyInvalidException(prop.name(), fieldName, e); - } - } - - /** - * Applies a function to check a property's default value. If the function throws an - * exception about an invalid property, then it's re-thrown as an exception about an - * invalid <i>defaultValue</i>. - * - * @param fieldName name of the field being checked - * @param prop property of interest - * @param func function to invoke to check the default value - */ - private void checkDefaultValue(String fieldName, Property prop, CheckDefaultValueFunction func) - throws PropertyInvalidException { - - if (isEmptyOk(prop, prop.defaultValue())) { - try { - func.apply(null); - - } catch (PropertyInvalidException ex) { - throw new PropertyInvalidException(ex.getPropertyName(), fieldName, "defaultValue is invalid", ex); - } - } - } - - /** - * Determines if a value is OK, even if it's empty. - * - * @param prop property specifying what's acceptable - * @param value value to be checked - * @return {@code true} if the value is not empty or empty is allowed, {@code false} - * otherwise - */ - protected boolean isEmptyOk(Property prop, String value) { - return !value.isEmpty() || isEmptyOk(prop); - } - - /** - * Determines if a {@link Property}'s <i>accept</i> attribute includes the "empty" - * option. - * - * @param prop property whose <i>accept</i> attribute is to be examined - * @return {@code true} if the <i>accept</i> attribute includes "empty" - */ - protected boolean isEmptyOk(Property prop) { - for (String option : prop.accept().split(",")) { - if (ACCEPT_EMPTY.equals(option)) { - return true; - } - } - - return false; - } - - /** - * Functions to check a default value. - */ - @FunctionalInterface - private static interface CheckDefaultValueFunction { - - /** - * Checks the default value. - * - * @param arg always {@code null} - * @throws PropertyInvalidException if an error occurs - */ - public void apply(Void arg) throws PropertyInvalidException; - } - - /** - * Annotation that declares a variable to be configured via {@link Properties}. - */ - @Target(ElementType.FIELD) - @Retention(RetentionPolicy.RUNTIME) - - protected static @interface Property { - - /** - * Name of the property. - * - * @return the property name - */ - public String name(); - - /** - * Default value, used when the property does not exist. - * - * @return the default value - */ - public String defaultValue() default ""; - - /** - * Comma-separated options identifying what's acceptable. The word, "empty", - * indicates that an empty string, "", is an acceptable value. - * - * @return options identifying what's acceptable - */ - public String accept() default ""; - } -} diff --git a/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManager.java b/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManager.java new file mode 100644 index 00000000..8bf89d56 --- /dev/null +++ b/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManager.java @@ -0,0 +1,190 @@ +/* + * ============LICENSE_START======================================================= + * ONAP PAP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.utils.services; + +import java.util.Deque; +import java.util.Iterator; +import java.util.LinkedList; +import org.onap.policy.common.capabilities.Startable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Manages a series of services. The services are started in order, and stopped in reverse + * order. + */ +public class ServiceManager { + private static final Logger logger = LoggerFactory.getLogger(ServiceManager.class); + + /** + * Services to be started/stopped. + */ + private final Deque<Service> items = new LinkedList<>(); + + /** + * {@code True} if the services are currently running, {@code false} otherwise. + */ + private boolean running; + + /** + * Adds a pair of service actions to the manager. + * + * @param stepName name to be logged when the service is started/stopped + * @param starter function to start the service + * @param stopper function to stop the service + * @return this manager + */ + public synchronized ServiceManager addAction(String stepName, RunnableWithEx starter, RunnableWithEx stopper) { + if (running) { + throw new IllegalStateException("services are already running; cannot add " + stepName); + } + + items.add(new Service(stepName, starter, stopper)); + return this; + } + + /** + * Adds a service to the manager. The manager will invoke the service's + * {@link Startable#start()} and {@link Startable#stop()} methods. + * + * @param stepName name to be logged when the service is started/stopped + * @param service object to be started/stopped + * @return this manager + */ + public synchronized ServiceManager addService(String stepName, Startable service) { + if (running) { + throw new IllegalStateException("services are already running; cannot add " + stepName); + } + + items.add(new Service(stepName, () -> service.start(), () -> service.stop())); + return this; + } + + /** + * Starts each service, in order. If a service throws an exception, then the + * previously started services are stopped, in reverse order. + * + * @throws ServiceManagerException if a service fails to start + */ + public synchronized void start() throws ServiceManagerException { + if (running) { + throw new IllegalStateException("services are already running"); + } + + // tracks the services that have been started so far + Deque<Service> started = new LinkedList<>(); + Exception ex = null; + + for (Service item : items) { + try { + logger.info("starting {}", item.stepName); + item.starter.run(); + started.add(item); + + } catch (Exception e) { + logger.error("failed to start {}; rewinding steps", item.stepName); + ex = e; + break; + } + } + + if (ex == null) { + running = true; + return; + } + + // one of the services failed to start - rewind those we've previously started + try { + rewind(started); + + } catch (ServiceManagerException e) { + logger.error("rewind failed", e); + } + + throw new ServiceManagerException(ex); + } + + /** + * Stops the services, in reverse order from which they were started. Stops all of the + * services, even if one of the "stop" functions throws an exception. Assumes that + * {@link #start()} has completed successfully. + * + * @throws ServiceManagerException if a service fails to stop + */ + public synchronized void stop() throws ServiceManagerException { + if (!running) { + throw new IllegalStateException("services are not running"); + } + + running = false; + rewind(items); + } + + /** + * Rewinds a list of services, stopping them in reverse order. Stops all of the + * services, even if one of the "stop" functions throws an exception. + * + * @param running services that are running, in the order they were started + * @throws ServiceManagerException if a service fails to stop + */ + private void rewind(Deque<Service> running) throws ServiceManagerException { + Exception ex = null; + + // stop everything, in reverse order + Iterator<Service> it = running.descendingIterator(); + while (it.hasNext()) { + Service item = it.next(); + try { + logger.info("stopping {}", item.stepName); + item.stopper.run(); + } catch (Exception e) { + logger.error("failed to stop {}", item.stepName); + ex = e; + + // do NOT break or re-throw, as we must stop ALL remaining items + } + } + + if (ex != null) { + throw new ServiceManagerException(ex); + } + } + + /** + * Service information. + */ + private static class Service { + private String stepName; + private RunnableWithEx starter; + private RunnableWithEx stopper; + + public Service(String stepName, RunnableWithEx starter, RunnableWithEx stopper) { + this.stepName = stepName; + this.starter = starter; + this.stopper = stopper; + } + } + + @FunctionalInterface + public static interface RunnableWithEx { + public void run() throws Exception; + } +} diff --git a/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManagerException.java b/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManagerException.java new file mode 100644 index 00000000..3daa441a --- /dev/null +++ b/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManagerException.java @@ -0,0 +1,44 @@ +/* + * ============LICENSE_START======================================================= + * ONAP PAP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.utils.services; + +/** + * Exceptions thrown by the ServiceManager. + */ +public class ServiceManagerException extends Exception { + private static final long serialVersionUID = 1L; + + public ServiceManagerException() { + super(); + } + + public ServiceManagerException(String message) { + super(message); + } + + public ServiceManagerException(Throwable cause) { + super(cause); + } + + public ServiceManagerException(String message, Throwable cause) { + super(message, cause); + } +} |