/*
 * Copyright 2004-2005 The Apache Software Foundation or its licensors,
 *                     as applicable.
 *
 * 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.apache.jackrabbit.rmi.client;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import javax.jcr.Repository;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;

import org.apache.jackrabbit.rmi.remote.RemoteRepository;

/**
 * Object factory for JCR-RMI clients. This factory can be used either
 * directly or as a JNDI object factory.
 *
 * @author Jukka Zitting
 * @see ClientRepository
 */
public class ClientRepositoryFactory implements ObjectFactory {

    /**
     * The JNDI parameter name for configuring the RMI URL of
     * a remote repository.
     */
    public static final String URL_PARAMETER = "url";

    /**
     * Cache for repository references.
     */
    private Map repositories;

    /**
     * Local adapter factory.
     */
    private LocalAdapterFactory factory;

    /**
     * Creates a JCR-RMI client factory with the default adapter factory.
     */
    public ClientRepositoryFactory() {
        this(new ClientAdapterFactory());
    }

    /**
     * Creates a JCR-RMI client factory with the given adapter factory.
     *
     * @param factory local adapter factory
     */
    public ClientRepositoryFactory(LocalAdapterFactory factory) {
        this.repositories = new HashMap();
        this.factory = factory;
    }

    /**
     * Returns a client wrapper for a remote content repository. The remote
     * repository is looked up from the RMI registry using the given URL and
     * wrapped into a {@link ClientRepository ClientRepository} adapter.
     * <p>
     * The repository references are cached so that only one client instance
     * (per factory) exists for each remote repository.
     *
     * @param url the RMI URL of the remote repository
     * @return repository client
     * @throws ClassCastException    if the URL points to an unknown object
     * @throws MalformedURLException if the URL is malformed
     * @throws NotBoundException     if the URL points to nowhere
     * @throws RemoteException       on RMI errors
     */
    public synchronized Repository getRepository(String url) throws
            ClassCastException, MalformedURLException,
            NotBoundException, RemoteException {
        Repository repository = (Repository) repositories.get(url);
        if (repository == null) {
            RemoteRepository remote = (RemoteRepository) Naming.lookup(url);
            repository = factory.getRepository(remote);
            repositories.put(url, repository);
        }
        return repository;
    }

    /**
     * Utility method for looking up the URL within the given RefAddr object.
     * Feeds the content of the RefAddr object to
     * {@link #getRepository(String) getRepository(String)} and wraps all
     * errors to {@link NamingException NamingExceptions}.
     * <p>
     * Used by {@link #getObjectInstance(Object, Name, Context, Hashtable) getObjectInstance()}.
     *
     * @param url the URL reference
     * @return repository client
     * @throws NamingException on all errors
     */
    private Repository getRepository(RefAddr url) throws NamingException {
        try {
            return getRepository((String) url.getContent());
        } catch (Exception ex) {
            throw new NamingException(ex.getMessage());
        }
    }

    /**
     * JNDI factory method for creating JCR-RMI clients. Looks up a
     * remote repository using the reference parameter "url" as the RMI URL
     * and returns a client wrapper for the remote repository.
     *
     * @param object      reference parameters
     * @param name        unused
     * @param context     unused
     * @param environment unused
     * @return repository client
     * @throws NamingException on all errors
     */
    public Object getObjectInstance(
            Object object, Name name, Context context, Hashtable environment)
            throws NamingException {
        if (object instanceof Reference) {
            Reference reference = (Reference) object;
            if (Repository.class.getName().equals(reference.getClassName())) {
                RefAddr url = reference.get(URL_PARAMETER);
                if (url != null) {
                    return getRepository(url);
                }
            }
        }
        return null;
    }

}

@@ -1603,95 +1603,8 @@
 %22;%0A%0A
-    /**%0A     * Cache for repository references.%0A     */%0A    private Map repositories;%0A%0A
     
@@ -1629,32 +1629,32 @@
 dapter factory.%0A
+
      */%0A    priv
@@ -2074,51 +2074,8 @@
 ) %7B%0A
-        this.repositories = new HashMap();%0A
     
@@ -2347,152 +2347,8 @@
 er.%0A
-     * %3Cp%3E%0A     * The repository references are cached so that only one client instance%0A     * (per factory) exists for each remote repository.%0A
     
@@ -2876,114 +2876,8 @@
 n %7B%0A
-        Repository repository = (Repository) repositories.get(url);%0A        if (repository == null) %7B%0A    
     
@@ -2957,24 +2957,14 @@
     
-    repository =
+return
  fac
@@ -2995,92 +2995,8 @@
 e);%0A
-            repositories.put(url, repository);%0A        %7D%0A        return repository;%0A
     

Remove connection caching in ClientRepositoryFactory.