// Licensed to the Apache Software Foundation (ASF) under one or more contributor
// license agreements.  See the NOTICE.txt 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.

package org.apache.oodt.commons.object.jndi;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.URI;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Properties;
import javax.naming.CompositeName;
import javax.naming.Context;
import javax.naming.InvalidNameException;
import javax.naming.Name;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NameClassPair;
import javax.naming.NameNotFoundException;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.OperationNotSupportedException;
import org.apache.oodt.commons.util.Utility;

/**
 * Context for binding and looking up distributed objects.
 *
 * @author Kelly
 * @version $Revision: 1.5 $
 */
class ObjectContext implements Context {
	/**
	 * Construct the object context.
	 *
	 * @param environment Its environment, currently unused.
	 */
	ObjectContext(Hashtable environment) {
		this.environment = environment != null? (Hashtable) environment.clone() : new Hashtable();

		// Add the CORBA context, but by name so we don't get a compile-time
		// coupling with the edm-corba component, and only if CORBA's available.
		try {
			Class clazz = Class.forName("org.apache.oodt.commons.object.jndi.CORBAContext");
			Constructor ctor = clazz.getConstructor(new Class[]{Hashtable.class});
			Object corbaContext = ctor.newInstance(new Object[]{this.environment});
			contexts.add(corbaContext);
		} catch (Throwable ex) {}

		String registryList = (String) environment.get("rmiregistries");
		if (registryList != null) for (Iterator i = Utility.parseCommaList(registryList); i.hasNext();) {
			Hashtable rmiEnv = (Hashtable) this.environment.clone();
			URI uri = URI.create((String) i.next());
			rmiEnv.put("host", uri.getHost());
			rmiEnv.put("port", new Integer(uri.getPort()));
			contexts.add(new RMIContext(rmiEnv));
		}

		Hashtable httpEnv = (Hashtable) this.environment.clone();
		contexts.add(new HTTPContext(httpEnv));

		String className = null;
		for (Iterator i = org.apache.oodt.commons.util.Utility.parseCommaList(System.getProperty("org.apache.oodt.commons.object.contexts", ""));
		        i.hasNext();) try {
			className = (String) i.next();
			Class clazz = Class.forName(className);
			contexts.add(clazz.newInstance());
		} catch (ClassNotFoundException ex) {
			System.err.println("Ignoring not-found context class `" + className + "': " + ex.getMessage());
		} catch (InstantiationException ex) {
			System.err.println("Ignoring non-instantiable context class `" + className + "': " + ex.getMessage());
		} catch (IllegalAccessException ex) {
			System.err.println("Ignoring context class `" + className + "' with non-accessible no-args c'tor: "
				+ ex.getMessage());
		}

		installAliases();
		System.err.println("Object context ready; delegating to: " + contexts);
	}

	/**
	 * Creates a new <code>ObjectContext</code> instance.  This constructor takes a
	 * list of delegate contexts instead of building them from a passed-in
	 * environment.  Currently, it's used solely for this class's {@link
	 * ObjectContextTest unit test}.
	 *
	 * @param contexts a <code>List</code> of {@link Context}s.
	 */
	ObjectContext(List contexts) {
		this.contexts = contexts;
		installAliases();
	}

	/**
	 * Returns the object to which the given name is bound.  Because this context
	 * delegates to multiple other contexts, the lookup returns the first successful
	 * match.
	 *
	 * @param name a <code>String</code> value.
	 * @return an <code>Object</code> value.
	 * @throws NamingException if an error occurs.
	 */
	public Object lookup(String name) throws NamingException {
		if (name == null) throw new IllegalArgumentException("Name required");
		if (name.length() == 0) return this;

		// Let alias redirection do its magic
		String alias = aliases.getProperty(name);
		if (alias != null) name = alias;

		for (Iterator i = contexts.iterator(); i.hasNext();) {
			Context c = (Context) i.next();
			try {
				return c.lookup(name);
			} catch (InvalidNameException ignore) {
			} catch (NameNotFoundException ignore) {
			} catch (NamingException ignore){}
		}
		throw new NameNotFoundException(name + " not found in any managed subcontext");
	}

	public Object lookup(Name name) throws NamingException {
		return lookup(name.toString());
	}

	public synchronized void bind(String name, Object obj) throws NamingException {
		if (name == null) throw new IllegalArgumentException("Name required");
		if (name.length() == 0) throw new InvalidNameException("Cannot bind object named after context");

		// If it's an alias name, stop here.
		if (aliases.containsKey(name))
			throw new NameAlreadyBoundException("Name \"" + name + "\" already bound as an aliased name");

		// Make sure it isn't bound anywhere
		for (NamingEnumeration e = list(""); e.hasMore();) {
			NameClassPair nameClassPair = (NameClassPair) e.next();
			if (name.equals(nameClassPair.getName()))
				throw new NameAlreadyBoundException("Name \"" + name + "\" already bound by a managed subcontext");
		}
		doRebind(name, obj);
	}

	public void bind(Name name, Object obj) throws NamingException {
		bind(name.toString(), obj);
	}

	/** {@inheritDoc} */
	public synchronized void rebind(String name, Object obj) throws NamingException {
		if (name == null) throw new IllegalArgumentException("Name required");
		if (name.length() == 0) throw new InvalidNameException("Cannot rebind object named after context");

		// If it's an alias name, remove the alias
		if (aliases.containsKey(name))
			aliases.remove(name);

		doRebind(name, obj);
	}

	/**
	 * Rebind the given name to the given object.
	 *
	 * @param name Name to rebind
	 * @param obj Object to which it's bound
	 * @throws NamingException if an error occurs.
	 */
	private void doRebind(String name, Object obj) throws NamingException {
		boolean bound = false;
		for (Iterator i = contexts.iterator(); i.hasNext();) {
			Context c = (Context) i.next();
			try {
				c.rebind(name, obj);
				bound = true;
			} catch (NamingException ex) {}
		}
		if (!bound) throw new InvalidNameException("Name \"" + name + "\" not compatible with any managed subcontext");
	}

	public void rebind(Name name, Object obj) throws NamingException {
		rebind(name.toString(), obj);
	}

	public void unbind(String name) throws NamingException {
		if (name == null) throw new IllegalArgumentException("Name required");
		if (name.length() == 0) throw new InvalidNameException("Cannot unbind object named after context");

		// See if it's an aliased name
		if (aliases.containsKey(name)) {
			aliases.remove(name);
			return;
		}

		boolean unbound = false;
		for (Iterator i = contexts.iterator(); i.hasNext();) {
			Context c = (Context) i.next();
			try {
				c.unbind(name);
				unbound = true;
			} catch (NamingException ignore) {}
		}
		if (!unbound) throw new InvalidNameException("Name \"" + name + "\" not compatible with any managed subcontext");
	}

	public void unbind(Name name) throws NamingException {
		unbind(name.toString());
	}

	public void rename(String oldName, String newName) throws NamingException {
		if (oldName == null || newName == null)
			throw new IllegalArgumentException("Name required");
		if (oldName.length() == 0 || newName.length() == 0)
			throw new InvalidNameException("Cannot rename object named after context");

		// See if it's an aliased name
		String oldValue = (String) aliases.remove(oldName);
		if (oldValue != null) {
			aliases.setProperty(newName, oldName);
			return;
		}

		boolean renamed = false;
		for (Iterator i = contexts.iterator(); i.hasNext();) {
			Context c = (Context) i.next();
			try {
				c.rename(oldName, newName);
				renamed = true;
			} catch (NamingException ignore) {}
		}
		if (!renamed) throw new InvalidNameException("Names not compatible with any managed subcontext");
	}

	public void rename(Name oldName, Name newName) throws NamingException {
		rename(oldName.toString(), newName.toString());
	}

	public NamingEnumeration list(final String name) throws NamingException {
		final Iterator eachContext = contexts.iterator();
		return new NamingEnumeration() {
			private NamingEnumeration enumeration
				= eachContext.hasNext()? ((Context) eachContext.next()).list(name) : null;
			private boolean open = true;
			public Object next() throws NamingException {
				if (!open) throw new NamingException("closed");
				if (enumeration != null && enumeration.hasMore())
					return enumeration.next();
				else if (eachContext.hasNext()) {
					enumeration = ((Context) eachContext.next()).list(name);
					if (enumeration.hasMore())
						return enumeration.next();
				}
				throw new NoSuchElementException("No more objects in context");
			}
			public Object nextElement() {
				Object rc = null;
				try {
					rc = next();
				} catch (NamingException ignore) {}
				return rc;
			}
			public boolean hasMore() throws NamingException {
				if (!open) return false;
				if (enumeration == null)
					return false;
				else if (enumeration.hasMore())
					return true;
				else if (eachContext.hasNext()) {
					enumeration = ((Context) eachContext.next()).list(name);
					return hasMore();
				}
				return false;
			}
			public boolean hasMoreElements() {
				boolean h = false;
				try {
					h = hasMore();
				} catch (NamingException ignore) {}
				return h;
			}
			public void close() throws NamingException {
				open = false;
				if (enumeration != null)
					enumeration.close();
			}
		};
	}
		
	public NamingEnumeration list(Name name) throws NamingException {
		return list(name.toString());
	}

	public NamingEnumeration listBindings(final String name) throws NamingException {
		final Iterator eachContext = contexts.iterator();
		return new NamingEnumeration() {
			private NamingEnumeration enumeration
				= eachContext.hasNext()? ((Context) eachContext.next()).listBindings(name) : null;
			private boolean open = true;
			public Object next() throws NamingException {
				if (!open) throw new NamingException("closed");
				if (enumeration != null && enumeration.hasMore())
					return enumeration.next();
				else if (eachContext.hasNext()) {
					enumeration = ((Context) eachContext.next()).listBindings(name);
					if (enumeration.hasMore())
						return enumeration.next();
				}
				throw new NoSuchElementException("No more objects in context");
			}
			public Object nextElement() {
				Object rc = null;
				try {
					rc = next();
				} catch (NamingException ignore) {}
				return rc;
			}
			public boolean hasMore() throws NamingException {
				if (!open) return false;
				if (enumeration == null)
					return false;
				else if (enumeration.hasMore())
					return true;
				else if (eachContext.hasNext()) {
					enumeration = ((Context) eachContext.next()).listBindings(name);
					return hasMore();
				}
				return false;
			}
			public boolean hasMoreElements() {
				boolean h = false;
				try {
					h = hasMore();
				} catch (NamingException ignore) {}
				return h;
			}
			public void close() throws NamingException {
				open = false;
				if (enumeration != null)
					enumeration.close();
			}
		};
	}

	public NamingEnumeration listBindings(Name name) throws NamingException {
		return listBindings(name.toString());
	}

	public void destroySubcontext(String name) throws NamingException {
		throw new OperationNotSupportedException("Subcontexts not supported by ObjectContext");
	}

	public void destroySubcontext(Name name) throws NamingException {
		destroySubcontext(name.toString());
	}

	public Context createSubcontext(String name) throws NamingException {
		throw new OperationNotSupportedException("Subcontexts not supported by ObjectContext");
	}

	public Context createSubcontext(Name name) throws NamingException {
		return createSubcontext(name.toString());
	}

	public Object lookupLink(String name) throws NamingException {
		return lookup(name);
	}

	public Object lookupLink(Name name) throws NamingException {
		return lookupLink(name.toString());
	}

	public NameParser getNameParser(String name) throws NamingException {
		return nameParser;
	}

	public NameParser getNameParser(Name name) throws NamingException {
		return getNameParser(name.toString());
	}

	public String composeName(String name, String prefix) throws NamingException {
		Name result = composeName(new CompositeName(name), new CompositeName(prefix));
		return result.toString();
	}

	public Name composeName(Name name, Name prefix) throws NamingException {
		Name result = (Name) prefix.clone();
		result.addAll(name);
		return result;
	}

	public Object addToEnvironment(String propName, Object propVal) throws NamingException {
		if (environment == null) environment = new Hashtable();
		return environment.put(propName, propVal);
	}

	public Object removeFromEnvironment(String propName) throws NamingException {
		if (environment == null) return null;
		return environment.remove(propName);
	}

	public Hashtable getEnvironment() throws NamingException {
		if (environment == null) return new Hashtable();
		return (Hashtable) environment.clone();
	}

	public String getNameInNamespace() throws NamingException {
		return "";
	}

	public void close() throws NamingException {
		environment = null;
	}

	/**
	 * Install aliases specified in the properties file.  The properties file simply
	 * maps a string object name to a new object name.  Use the system property
	 * <code>org.apache.oodt.commons.object.jndi.aliases</code> (preferred) or simply
	 * <code>aliases</code> to tell the location of the properties file.
	 */
	private void installAliases() {
		String aliasFileName = System.getProperty("org.apache.oodt.commons.object.jndi.aliases", System.getProperty("aliases"));
		if (aliasFileName != null && aliasFileName.length() > 0) {
			FileInputStream in = null;
			try {
				in = new FileInputStream(aliasFileName);
				aliases.load(in);
			} catch (IOException ex) {
				throw new IllegalStateException("Cannot handle I/O exception reading alias file " + aliasFileName
					+ ": " + ex.getMessage());
			} finally {
				if (in != null) try {
					in.close();
				} catch (IOException ignore) {}
			}
		}
	}

	/** Context's environment; currently unused. */
	private Hashtable environment;

	/** Parser for object names. */
	private static final NameParser nameParser = new ObjectNameParser();

	/** List of {@link Context}s to which we "multiplex". */
	private List contexts = new ArrayList();

	/** Aliased names. */
	private Properties aliases = new Properties();
}
