org.xnio.Option Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
/*
* JBoss, Home of Professional Open Source
*
* Copyright 2010 Red Hat, Inc. and/or its affiliates.
*
* 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.xnio;
import java.io.InvalidObjectException;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.xnio._private.Messages.msg;
/**
* A strongly-typed option to configure an aspect of a service or connection. Options are immutable and use identity comparisons
* and hash codes. Options should always be declared as public static final
members in order to support serialization.
*
* @param the option value type
*/
public abstract class Option implements Serializable {
private static final long serialVersionUID = -1564427329140182760L;
private final Class> declClass;
private final String name;
Option(final Class> declClass, final String name) {
if (declClass == null) {
throw msg.nullParameter("declClass");
}
if (name == null) {
throw msg.nullParameter("name");
}
this.declClass = declClass;
this.name = name;
}
/**
* Create an option with a simple type. The class object given must represent some immutable type, otherwise
* unexpected behavior may result.
*
* @param declClass the declaring class of the option
* @param name the (field) name of this option
* @param type the class of the value associated with this option
* @return the option instance
*/
public static Option simple(final Class> declClass, final String name, final Class type) {
return new SingleOption(declClass, name, type);
}
/**
* Create an option with a sequence type. The class object given must represent some immutable type, otherwise
* unexpected behavior may result.
*
* @param declClass the declaring class of the option
* @param name the (field) name of this option
* @param elementType the class of the sequence element value associated with this option
* @return the option instance
*/
public static Option> sequence(final Class> declClass, final String name, final Class elementType) {
return new SequenceOption(declClass, name, elementType);
}
/**
* Create an option with a class type. The class object given may represent any type.
*
* @param declClass the declaring class of the option
* @param name the (field) name of this option
* @param declType the class object for the type of the class object given
* @param the type of the class object given
* @return the option instance
*/
public static Option> type(final Class> declClass, final String name, final Class declType) {
return new TypeOption(declClass, name, declType);
}
/**
* Create an option with a sequence-of-types type. The class object given may represent any type.
*
* @param declClass the declaring class of the option
* @param name the (field) name of this option
* @param elementDeclType the class object for the type of the sequence element class object given
* @param the type of the sequence element class object given
* @return the option instance
*/
public static Option>> typeSequence(final Class> declClass, final String name, final Class elementDeclType) {
return new TypeSequenceOption(declClass, name, elementDeclType);
}
/**
* Get the name of this option.
*
* @return the option name
*/
public String getName() {
return name;
}
/**
* Get a human-readable string representation of this object.
*
* @return the string representation
*/
public String toString() {
return declClass.getName() + "." + name;
}
/**
* Get an option from a string name, using the given classloader. If the classloader is {@code null}, the bootstrap
* classloader will be used.
*
* @param name the option string
* @param classLoader the class loader
* @return the option
* @throws IllegalArgumentException if the given option name is not valid
*/
public static Option> fromString(String name, ClassLoader classLoader) throws IllegalArgumentException {
final int lastDot = name.lastIndexOf('.');
if (lastDot == -1) {
throw msg.invalidOptionName(name);
}
final String fieldName = name.substring(lastDot + 1);
final String className = name.substring(0, lastDot);
final Class> clazz;
try {
clazz = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException e) {
throw msg.optionClassNotFound(className, classLoader);
}
final Field field;
try {
field = clazz.getField(fieldName);
} catch (NoSuchFieldException e) {
throw msg.noField(fieldName, clazz);
}
final int modifiers = field.getModifiers();
if (! Modifier.isPublic(modifiers)) {
throw msg.fieldNotAccessible(fieldName, clazz);
}
if (! Modifier.isStatic(modifiers)) {
throw msg.fieldNotStatic(fieldName, clazz);
}
final Option> option;
try {
option = (Option>) field.get(null);
} catch (IllegalAccessException e) {
throw msg.fieldNotAccessible(fieldName, clazz);
}
if (option == null) {
throw msg.invalidNullOption(name);
}
return option;
}
/**
* Return the given object as the type of this option. If the cast could not be completed, an exception is thrown.
*
* @param o the object to cast
* @return the cast object
* @throws ClassCastException if the object is not of a compatible type
*/
public abstract T cast(Object o) throws ClassCastException;
/**
* Return the given object as the type of this option. If the cast could not be completed, an exception is thrown.
*
* @param o the object to cast
* @param defaultVal the value to return if {@code o} is {@code null}
*
* @return the cast object
*
* @throws ClassCastException if the object is not of a compatible type
*/
public final T cast(Object o, T defaultVal) throws ClassCastException {
return o == null ? defaultVal : cast(o);
}
/**
* Parse a string value for this option.
*
* @param string the string
* @param classLoader the class loader to use to parse the value
* @return the parsed value
* @throws IllegalArgumentException if the argument could not be parsed
*/
public abstract T parseValue(String string, ClassLoader classLoader) throws IllegalArgumentException;
/**
* Resolve this instance for serialization.
*
* @return the resolved object
* @throws java.io.ObjectStreamException if the object could not be resolved
*/
protected final Object readResolve() throws ObjectStreamException {
try {
final Field field = declClass.getField(name);
final int modifiers = field.getModifiers();
if (! Modifier.isPublic(modifiers)) {
throw new InvalidObjectException("Invalid Option instance (the field is not public)");
}
if (! Modifier.isStatic(modifiers)) {
throw new InvalidObjectException("Invalid Option instance (the field is not static)");
}
final Option> option = (Option>) field.get(null);
if (option == null) {
throw new InvalidObjectException("Invalid null Option");
}
return option;
} catch (NoSuchFieldException e) {
throw new InvalidObjectException("Invalid Option instance (no matching field)");
} catch (IllegalAccessException e) {
throw new InvalidObjectException("Invalid Option instance (Illegal access on field get)");
}
}
/**
* Create a builder for an immutable option set.
*
* @return the builder
*/
public static Option.SetBuilder setBuilder() {
return new Option.SetBuilder();
}
/**
* A builder for an immutable option set.
*/
public static class SetBuilder {
private List