/*
* JBoss, Home of Professional Open Source.
* Copyright 2010, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.naming.util;
import javax.naming.CannotProceedException;
import javax.naming.Context;
import javax.naming.InvalidNameException;
import javax.naming.Name;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.NotContextException;
import java.util.Collection;
import java.util.Iterator;
/**
* Common utility functions used by the naming implementation.
*
* @author John E. Bailey
*/
public class NamingUtils {
private NamingUtils() {}
/**
* Create a subcontext including any intermediate contexts.
* @param ctx the parent JNDI Context under which value will be bound
* @param name the name relative to ctx of the subcontext.
* @return The new or existing JNDI subcontext
* @throws NamingException on any JNDI failure
*/
private static Context createSubcontext(Context ctx, final Name name) throws NamingException {
Context subctx = ctx;
for (int pos = 0; pos < name.size(); pos++) {
final String ctxName = name.get(pos);
try {
subctx = (Context) ctx.lookup(ctxName);
}
catch (NameNotFoundException e) {
subctx = ctx.createSubcontext(ctxName);
}
// The current subctx will be the ctx for the next name component
ctx = subctx;
}
return subctx;
}
/**
* Get the last component of a name.
*
* @param name the name
* @return the last component
*/
public static String getLastComponent(final Name name) {
if(name.size() > 0)
return name.get(name.size() - 1);
return "";
}
/**
* Determine if a name is empty, or if ot contains only one component which is the empty string.
*
* @param name the name
* @return {@code true} if the name is empty or contains one empty component
*/
public static boolean isEmpty(final Name name) {
return name.isEmpty() || (name.size() == 1 && "".equals(name.get(0)));
}
/**
* Determine whether the last component is empty.
*
* @param name the name to test
* @return {@code true} if the last component is empty, or if the name is empty
*/
public static boolean isLastComponentEmpty(final Name name) {
return name.isEmpty() || getLastComponent(name).equals("");
}
/**
* Create a name-not-found exception.
*
* @param name the name
* @param contextName the context name
* @return the exception
*/
public static NameNotFoundException nameNotFoundException(final String name, final Name contextName) {
return new NameNotFoundException(String.format("Name '%s' not found in context '%s'", name, contextName.toString()));
}
/**
* Create a name-already-bound exception.
*
* @param name the name
* @return the exception
*/
public static NameAlreadyBoundException nameAlreadyBoundException(final Name name) {
return new NameAlreadyBoundException(name.toString());
}
/**
* Create an invalid name exception for an empty name.
*
* @return the exception
*/
public static InvalidNameException emptyNameException() {
return new InvalidNameException("An empty name is not allowed");
}
/**
* Return a not-context exception for a name.
*
* @param name the name
* @return the exception
*/
public static NotContextException notAContextException(Name name) {
return new NotContextException(name.toString());
}
/**
* Return a general naming exception with a root cause.
*
* @param message the message
* @param cause the exception cause, or {@code null} for none
* @return the exception
*/
public static NamingException namingException(final String message, final Throwable cause) {
final NamingException exception = new NamingException(message);
if (cause != null) exception.initCause(cause);
return exception;
}
/**
* Return a general naming exception with a root cause and a remaining name field.
*
* @param message the message
* @param cause the exception cause, or {@code null} for none
* @param remainingName the remaining name
* @return the exception
*/
public static NamingException namingException(final String message, final Throwable cause, final Name remainingName) {
final NamingException exception = namingException(message, cause);
exception.setRemainingName(remainingName);
return exception;
}
/**
* Return a cannot-proceed exception.
*
* @param resolvedObject the resolved object
* @param remainingName the remaining name
* @return the exception
*/
public static CannotProceedException cannotProceedException(final Object resolvedObject, final Name remainingName) {
final CannotProceedException cpe = new CannotProceedException();
cpe.setResolvedObj(resolvedObject);
cpe.setRemainingName(remainingName);
return cpe;
}
/**
* Return a naming enumeration over a collection.
*
* @param collection the collection
* @param <T> the member type
* @return the enumeration
*/
public static <T> NamingEnumeration<T> namingEnumeration(final Collection<T> collection) {
final Iterator<T> iterator = collection.iterator();
return new NamingEnumeration<T>() {
public T next() {
return nextElement();
}
public boolean hasMore() {
return hasMoreElements();
}
public void close() {
}
public boolean hasMoreElements() {
return iterator.hasNext();
}
public T nextElement() {
return iterator.next();
}
};
}
/**
* Rebind val to name in ctx, and make sure that all intermediate contexts exist
*
* @param ctx the parent JNDI Context under which value will be bound
* @param name the name relative to ctx where value will be bound
* @param value the value to bind.
* @throws NamingException for any error
*/
public static void rebind(final Context ctx, final String name, final Object value) throws NamingException {
final Name n = ctx.getNameParser("").parse(name);
rebind(ctx, n, value);
}
/**
* Rebind val to name in ctx, and make sure that all intermediate contexts exist
*
* @param ctx the parent JNDI Context under which value will be bound
* @param name the name relative to ctx where value will be bound
* @param value the value to bind.
* @throws NamingException for any error
*/
public static void rebind(final Context ctx, final Name name, final Object value) throws NamingException {
final int size = name.size();
final String atom = name.get(size - 1);
final Context parentCtx = createSubcontext(ctx, name.getPrefix(size - 1));
parentCtx.rebind(atom, value);
}
/**
* Unbinds a name from ctx, and removes parents if they are empty
*
* @param ctx the parent JNDI Context under which the name will be unbound
* @param name The name to unbind
* @throws NamingException for any error
*/
public static void unbind(Context ctx, String name) throws NamingException {
unbind(ctx, ctx.getNameParser("").parse(name));
}
/**
* Unbinds a name from ctx, and removes parents if they are empty
*
* @param ctx the parent JNDI Context under which the name will be unbound
* @param name The name to unbind
* @throws NamingException for any error
*/
public static void unbind(Context ctx, Name name) throws NamingException {
ctx.unbind(name); //unbind the end node in the name
int sz = name.size();
// walk the tree backwards, stopping at the domain
while (--sz > 0) {
Name pname = name.getPrefix(sz);
try {
ctx.destroySubcontext(pname);
}
catch (NamingException e) {
//log.trace("Unable to remove context " + pname, e);
break;
}
}
}
}