You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2007/04/12 09:12:58 UTC

svn commit: r527797 - in /jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client: BrokenRemoteRepository.java ClientRepositoryFactory.java SafeClientRepository.java

Author: jukka
Date: Thu Apr 12 00:12:57 2007
New Revision: 527797

URL: http://svn.apache.org/viewvc?view=rev&rev=527797
Log:
JCR-622: Added a "safe" client repository adapter that automatically reloads broken remote repository reference.

Added:
    jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/BrokenRemoteRepository.java   (with props)
    jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/SafeClientRepository.java   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/ClientRepositoryFactory.java

Added: jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/BrokenRemoteRepository.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/BrokenRemoteRepository.java?view=auto&rev=527797
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/BrokenRemoteRepository.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/BrokenRemoteRepository.java Thu Apr 12 00:12:57 2007
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE 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.jackrabbit.rmi.client;
+
+import java.rmi.RemoteException;
+
+import javax.jcr.Credentials;
+
+import org.apache.jackrabbit.rmi.remote.RemoteRepository;
+import org.apache.jackrabbit.rmi.remote.RemoteSession;
+
+/**
+ * Dummy remote repository instance that throws a {@link RemoteException}
+ * whenever any method is invoked. Used as a sentinel object by the
+ * {@link SafeClientRepository} class.
+ */
+public class BrokenRemoteRepository implements RemoteRepository {
+
+    /**
+     * The remote exception thrown by methods of this instance.
+     */
+    private final RemoteException exception;
+
+    /**
+     * Creates a remote repository whose methods throw the given
+     * exception.
+     *
+     * @param exception remote exception
+     */
+    public BrokenRemoteRepository(RemoteException exception) {
+        this.exception = exception;
+    }
+
+    /**
+     * Creates a remote repository whose methods trow a remote
+     * exception with the given message.
+     *
+     * @param message exception message
+     */
+    public BrokenRemoteRepository(String message) {
+        this(new RemoteException(message));
+    }
+
+    /**
+     * Creates a remote repository whose methods throw a remote exception.
+     */
+    public BrokenRemoteRepository() {
+        this(new RemoteException());
+    }
+
+    //----------------------------------------------------< RemoteRepository >
+
+    /**
+     * Throws a {@link RemoteException}.
+     *
+     * @param key ignored
+     * @return nothing
+     * @throws RemoteException always thrown
+     */
+    public String getDescriptor(String key) throws RemoteException {
+        throw exception;
+    }
+
+    /**
+     * Throws a {@link RemoteException}.
+     *
+     * @return nothing
+     * @throws RemoteException always thrown
+     */
+    public String[] getDescriptorKeys() throws RemoteException {
+        throw exception;
+    }
+
+    /**
+     * Throws a {@link RemoteException}.
+     *
+     * @return nothing
+     * @throws RemoteException always thrown
+     */
+    public RemoteSession login() throws RemoteException {
+        throw exception;
+    }
+
+    /**
+     * Throws a {@link RemoteException}.
+     *
+     * @param workspace ignored
+     * @return nothing
+     * @throws RemoteException always thrown
+     */
+    public RemoteSession login(String workspace) throws RemoteException {
+        throw exception;
+    }
+
+    /**
+     * Throws a {@link RemoteException}.
+     *
+     * @param credentials ignored
+     * @return nothing
+     * @throws RemoteException always thrown
+     */
+    public RemoteSession login(Credentials credentials) throws RemoteException {
+        throw exception;
+    }
+
+    /**
+     * Throws a {@link RemoteException}.
+     *
+     * @param workspace ignored
+     * @param credentials ignored
+     * @return nothing
+     * @throws RemoteException always thrown
+     */
+    public RemoteSession login(Credentials credentials, String workspace)
+            throws RemoteException {
+        throw exception;
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/BrokenRemoteRepository.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/ClientRepositoryFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/ClientRepositoryFactory.java?view=diff&rev=527797&r1=527796&r2=527797
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/ClientRepositoryFactory.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/ClientRepositoryFactory.java Thu Apr 12 00:12:57 2007
@@ -25,7 +25,6 @@
 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;
@@ -36,7 +35,6 @@
  * 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 {
@@ -70,65 +68,49 @@
 
     /**
      * 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.
+     * repository is looked up from the RMI registry using the given URL by
+     * the returned {@link SafeClientRepository} instance.
      *
      * @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 {
-        RemoteRepository remote = (RemoteRepository) Naming.lookup(url);
-        return factory.getRepository(remote);
-    }
-
-    /**
-     * 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());
-        }
+    public Repository getRepository(final String url) {
+        return new SafeClientRepository(factory) {
+
+            protected RemoteRepository getRemoteRepository()
+                    throws RemoteException {
+                try {
+                    return (RemoteRepository) Naming.lookup(url);
+                } catch (MalformedURLException e) {
+                    throw new RemoteException("Malformed URL: " + url, e);
+                } catch (NotBoundException e) {
+                    throw new RemoteException("No target found: " + url, e);
+                } catch (ClassCastException e) {
+                    throw new RemoteException("Unknown target: " + url, e);
+                }
+            }
+            
+        };
     }
 
     /**
-     * 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.
+     * JNDI factory method for creating JCR-RMI clients. Creates a lazy
+     * client repository instance that uses the reference parameter "url"
+     * as the RMI URL where the remote repository is looked up when accessed.
      *
      * @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 {
+            Object object, Name name, Context context, Hashtable environment) {
         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);
-                }
+            RefAddr url = reference.get(URL_PARAMETER);
+            if (url != null && url.getContent() != null) {
+                return getRepository(url.getContent().toString());
             }
         }
         return null;

Added: jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/SafeClientRepository.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/SafeClientRepository.java?view=auto&rev=527797
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/SafeClientRepository.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/SafeClientRepository.java Thu Apr 12 00:12:57 2007
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE 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.jackrabbit.rmi.client;
+
+import java.rmi.RemoteException;
+
+import javax.jcr.Credentials;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.rmi.remote.RemoteRepository;
+import org.apache.jackrabbit.rmi.remote.RemoteSession;
+
+/**
+ * A "safe" local adapter for the JCR-RMI
+ * {@link org.apache.jackrabbit.rmi.remote.RemoteRepository RemoteRepository}
+ * inteface. This class uses an abstract factory method for loading
+ * (and reloading) the remote repository instance that is made locally
+ * available through the JCR {@link Repository} interface. If the remote
+ * reference breaks (a RemoteException is thrown by a remote call), then
+ * this adapter attempts to reload the remote reference once before failing.
+ *
+ * @see javax.jcr.Repository
+ * @see org.apache.jackrabbit.rmi.remote.RemoteRepository
+ */
+public abstract class SafeClientRepository extends ClientObject
+        implements Repository {
+
+    /** The adapted remote repository. */
+    private RemoteRepository remote;
+
+    /**
+     * Creates a client adapter for the given remote repository.
+     *
+     * @param remote remote repository
+     * @param factory local adapter factory
+     */
+    public SafeClientRepository(LocalAdapterFactory factory) {
+        super(factory);
+        try {
+            remote = getRemoteRepository();
+        } catch (RemoteException e) {
+            remote = new BrokenRemoteRepository(e);
+        }
+    }
+
+    /**
+     * Abstract factory class for getting the remote repository.
+     *
+     * @return remote repository
+     * @throws RemoteException if the remote repository could not be accessed
+     */
+    protected abstract RemoteRepository getRemoteRepository()
+            throws RemoteException;
+
+    /** {@inheritDoc} */
+    public synchronized String getDescriptor(String name) {
+        try {
+            return remote.getDescriptor(name);
+        } catch (RemoteException e1) {
+            try {
+                remote = getRemoteRepository();
+                return remote.getDescriptor(name);
+            } catch (RemoteException e2) {
+                remote = new BrokenRemoteRepository(e2);
+                throw new RemoteRuntimeException(e2);
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    public synchronized String[] getDescriptorKeys() {
+        try {
+            return remote.getDescriptorKeys();
+        } catch (RemoteException e1) {
+            try {
+                remote = getRemoteRepository();
+                return remote.getDescriptorKeys();
+            } catch (RemoteException e2) {
+                remote = new BrokenRemoteRepository(e2);
+                throw new RemoteRuntimeException(e2);
+            }
+        }
+    }
+
+    private synchronized RemoteSession remoteLogin(
+            Credentials credentials, String workspace)
+            throws RepositoryException {
+        try {
+            return remote.login(credentials, workspace);
+        } catch (RemoteException e1) {
+            try {
+                remote = getRemoteRepository();
+                return remote.login(credentials, workspace);
+            } catch (RemoteException e2) {
+                remote = new BrokenRemoteRepository(e2);
+                throw new RemoteRepositoryException(e2);
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    public Session login(Credentials credentials, String workspace)
+            throws RepositoryException {
+        RemoteSession session = remoteLogin(credentials, workspace);
+        return getFactory().getSession(this, session);
+    }
+
+    /** {@inheritDoc} */
+    public Session login(String workspace) throws RepositoryException {
+        return login(null, workspace);
+    }
+
+    /** {@inheritDoc} */
+    public Session login(Credentials credentials) throws RepositoryException {
+        return login(credentials, null);
+    }
+
+    /** {@inheritDoc} */
+    public Session login() throws RepositoryException {
+        return login(null, null);
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-jcr-rmi/src/main/java/org/apache/jackrabbit/rmi/client/SafeClientRepository.java
------------------------------------------------------------------------------
    svn:eol-style = native