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.plugin.CRaSHPlugin;
024    
025    import javax.jcr.Node;
026    import java.beans.IntrospectionException;
027    import java.util.ArrayList;
028    import java.util.Arrays;
029    import java.util.Collection;
030    import java.util.List;
031    import java.util.Map;
032    import javax.jcr.Repository;
033    
034    /**
035     * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
036     * @version $Revision$
037     */
038    public abstract class JCRPlugin<T extends JCRPlugin> extends CRaSHPlugin<T> {
039    
040      /** . */
041      private static final Collection<String> NODES = Arrays.asList(
042          "org.exoplatform.services.jcr.impl.core.NodeImpl",
043          "org.apache.jackrabbit.core.NodeImpl", "org.apache.jackrabbit.rmi.client.ClientNode",
044          "org.apache.jackrabbit.rmi.server.ServerNode");
045    
046      /** . */
047      private static final Object LOCK = new Object();
048    
049      /** . */
050      private static boolean integrated = false;
051      
052      public Collection<String> getNodeClassNames() {
053        return NODES;
054      }
055      
056      public abstract Repository getRepository(Map<String, String> properties) throws Exception;
057    
058      @Override
059      public void init() {
060        // Force integration of node meta class
061        NodeMetaClass.setup();
062        synchronized (LOCK) {
063          if (!integrated) {
064            try {
065              MetaClassRegistry registry = GroovySystem.getMetaClassRegistry();
066              Collection<Class<? extends Node>> nodes = loadAvailablesNodeImplementations(getNodeClassNames());
067              for (Class<? extends Node> nodeClass : nodes) {
068                registerNodeImplementation(registry, nodeClass);
069              }
070            } catch (IntrospectionException e) {
071              throw new RuntimeException(e);
072            }
073          }
074          integrated = true;
075        }
076      }
077    
078      private Collection<Class<? extends Node>> loadAvailablesNodeImplementations(
079          Collection<String> classNames) {
080        List<Class<? extends Node>> classes = new ArrayList<Class<? extends Node>>(classNames.size());
081        for (String className : classNames) {
082          Class<? extends Node> nodeClass = loadNodeImplementation(className);
083          if (nodeClass != null) {
084            classes.add(nodeClass);
085          }
086        }
087        return classes;
088      }
089    
090      private Class<? extends Node> loadNodeImplementation(String className) {
091        try {
092          return (Class<? extends Node>) Thread.currentThread().getContextClassLoader().loadClass(
093              className);
094        } catch (ClassNotFoundException e) {
095          return null;
096        }
097      }
098    
099      private void registerNodeImplementation(MetaClassRegistry registry,
100          Class<? extends Node> nodeClass) throws IntrospectionException {
101        NodeMetaClass mc2 = new NodeMetaClass(registry, nodeClass);
102        mc2.initialize();
103        registry.setMetaClass(nodeClass, mc2);
104      }
105    }