org.xnio.Option Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xnio-api Show documentation
Show all versions of xnio-api Show documentation
The API JAR of the XNIO project
/*
* 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