001    /*
002     * Copyright (C) 2010 eXo Platform SAS.
003     *
004     * This is free software; you can redistribute it and/or modify it
005     * under the terms of the GNU Lesser General Public License as
006     * published by the Free Software Foundation; either version 2.1 of
007     * the License, or (at your option) any later version.
008     *
009     * This software is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012     * Lesser General Public License for more details.
013     *
014     * You should have received a copy of the GNU Lesser General Public
015     * License along with this software; if not, write to the Free
016     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018     */
019    package org.crsh.jcr;
020    
021    import groovy.lang.GroovySystem;
022    import groovy.lang.MetaClassRegistry;
023    import org.crsh.jcr.groovy.NodeMetaClass;
024    import org.crsh.plugin.CRaSHPlugin;
025    
026    import javax.jcr.Node;
027    import java.beans.IntrospectionException;
028    import java.util.*;
029    import javax.jcr.Repository;
030    
031    /**
032     * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
033     * @version $Revision$
034     */
035    public abstract class JCRPlugin<T extends JCRPlugin> extends CRaSHPlugin<T> {
036    
037      public static Repository findRepository(Map<String, String> properties) throws Exception {
038        for (JCRPlugin plugin : ServiceLoader.load(JCRPlugin.class)) {
039          Repository repository = plugin.getRepository(properties);
040          if (repository != null) {
041            return repository;
042          }
043        }
044        return null;
045      }
046    
047      public static Iterable<JCRPlugin> findRepositories() throws Exception {
048        return ServiceLoader.load(JCRPlugin.class);
049      }
050    
051      /** . */
052      private static final Collection<String> NODES = Arrays.asList(
053          "org.exoplatform.services.jcr.impl.core.NodeImpl",
054          "org.apache.jackrabbit.core.NodeImpl", "org.apache.jackrabbit.rmi.client.ClientNode",
055          "org.apache.jackrabbit.rmi.server.ServerNode");
056    
057      /** . */
058      private static final Object LOCK = new Object();
059    
060      /** . */
061      private static boolean integrated = false;
062    
063      public Collection<String> getNodeClassNames() {
064        return NODES;
065      }
066      
067      public abstract Repository getRepository(Map<String, String> properties) throws Exception;
068    
069      public abstract String getName();
070    
071      public abstract String getDisplayName();
072    
073      public abstract String getUsage();
074    
075      @Override
076      public void init() {
077        // Force integration of node meta class
078        NodeMetaClass.setup();
079        synchronized (LOCK) {
080          if (!integrated) {
081            try {
082              MetaClassRegistry registry = GroovySystem.getMetaClassRegistry();
083              Collection<Class<? extends Node>> nodes = loadAvailablesNodeImplementations(getNodeClassNames());
084              for (Class<? extends Node> nodeClass : nodes) {
085                registerNodeImplementation(registry, nodeClass);
086              }
087            } catch (IntrospectionException e) {
088              throw new RuntimeException(e);
089            }
090          }
091          integrated = true;
092        }
093      }
094    
095      private Collection<Class<? extends Node>> loadAvailablesNodeImplementations(
096          Collection<String> classNames) {
097        List<Class<? extends Node>> classes = new ArrayList<Class<? extends Node>>(classNames.size());
098        for (String className : classNames) {
099          Class<? extends Node> nodeClass = loadNodeImplementation(className);
100          if (nodeClass != null) {
101            classes.add(nodeClass);
102          }
103        }
104        return classes;
105      }
106    
107      private Class<? extends Node> loadNodeImplementation(String className) {
108        try {
109          return (Class<? extends Node>) Thread.currentThread().getContextClassLoader().loadClass(
110              className);
111        } catch (ClassNotFoundException e) {
112          return null;
113        }
114      }
115    
116      private void registerNodeImplementation(MetaClassRegistry registry,
117          Class<? extends Node> nodeClass) throws IntrospectionException {
118        NodeMetaClass mc2 = new NodeMetaClass(registry, nodeClass);
119        mc2.initialize();
120        registry.setMetaClass(nodeClass, mc2);
121      }
122    }