View Javadoc

    1   /**
    2    * Copyright (c) 2002-2011 "Neo Technology,"
    3    * Network Engine for Objects in Lund AB [http://neotechnology.com]
    4    *
    5    * This file is part of Neo4j.
    6    *
    7    * Neo4j is free software: you can redistribute it and/or modify
    8    * it under the terms of the GNU General Public License as published by
    9    * the Free Software Foundation, either version 3 of the License, or
    10   * (at your option) any later version.
    11   *
    12   * This program is distributed in the hope that it will be useful,
    13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15   * GNU General Public License for more details.
    16   *
    17   * You should have received a copy of the GNU General Public License
    18   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    19   */
    20  package org.neo4j.server.plugins;
    21
    22  import org.apache.commons.configuration.Configuration;
    23  import org.apache.log4j.Logger;
    24  import org.neo4j.helpers.Pair;
    25  import org.neo4j.kernel.AbstractGraphDatabase;
    26  import org.neo4j.server.rest.repr.BadInputException;
    27  import org.neo4j.server.rest.repr.ExtensionInjector;
    28  import org.neo4j.server.rest.repr.ExtensionPointRepresentation;
    29  import org.neo4j.server.rest.repr.Representation;
    30
    31  import java.util.ArrayList;
    32  import java.util.Collections;
    33  import java.util.HashMap;
    34  import java.util.List;
    35  import java.util.Map;
    36  import java.util.Set;
    37
    38  public final class PluginManager implements ExtensionInjector, PluginInvocator
    39  {
    40      private static final Logger log = Logger.getLogger( PluginManager.class );
    41      private final Map<String/*name*/, ServerExtender> extensions = new HashMap<String, ServerExtender>();
    42
    43      public PluginManager( Configuration serverConfig )
    44      {
    45          this( serverConfig, ServerPlugin.load() );
    46      }
    47
    48      PluginManager( Configuration serverConfig, Iterable<ServerPlugin> plugins )
    49      {
    50          Map<String, Pair<ServerPlugin, ServerExtender>> extensions = new HashMap<String, Pair<ServerPlugin, ServerExtender>>();
    51          for ( ServerPlugin plugin : plugins )
    52          {
    53              PluginPointFactory factory = new PluginPointFactoryImpl();
    54              final ServerExtender extender = new ServerExtender( factory );
    55              try
    56              {
    57                  plugin.loadServerExtender( extender );
    58              } catch ( Exception ex )
    59              {
    60                  log.warn( "Failed to load plugin: " + plugin, ex );
    61                  continue;
    62              } catch ( LinkageError err )
    63              {
    64                  log.warn( "Failed to load plugin: " + plugin, err );
    65                  continue;
    66              }
    67              Pair<ServerPlugin, ServerExtender> old = extensions.put( plugin.name, Pair.of(
    68                      plugin, extender ) );
    69              if ( old != null )
    70              {
    71                  log.warn( String.format(
    72                          "Extension naming conflict \"%s\" between \"%s\" and \"%s\"",
    73                          plugin.name, old.first().getClass(), plugin.getClass() ) );
    74              }
    75          }
    76          for ( Pair<ServerPlugin, ServerExtender> extension : extensions.values() )
    77          {
    78              log.info( String.format( "Loaded server plugin \"%s\"", extension.first().name ));
    79              this.extensions.put( extension.first().name, extension.other() );
    80          }
    81      }
    82
    83      @Override
    84      public Map<String, List<String>> getExensionsFor( Class<?> type )
    85      {
    86          Map<String, List<String>> result = new HashMap<String, List<String>>();
    87          for ( Map.Entry<String, ServerExtender> extension : extensions.entrySet() )
    88          {
    89              List<String> methods = new ArrayList<String>();
    90              for ( PluginPoint method : extension.getValue().getExtensionsFor( type ) )
    91              {
    92                  methods.add( method.name() );
    93              }
    94              if ( !methods.isEmpty() )
    95              {
    96                  result.put( extension.getKey(), methods );
    97              }
    98          }
    99          return result;
    100     }
    101
    102     private PluginPoint extension( String name, Class<?> type, String method )
    103             throws PluginLookupException
    104     {
    105         ServerExtender extender = extensions.get( name );
    106         if ( extender == null )
    107         {
    108             throw new PluginLookupException( "No such ServerPlugin: \"" + name + "\"" );
    109         }
    110         return extender.getExtensionPoint( type, method );
    111     }
    112
    113     @Override
    114     public ExtensionPointRepresentation describe( String name, Class<?> type, String method )
    115             throws PluginLookupException
    116     {
    117         return describe( extension( name, type, method ) );
    118     }
    119
    120     private ExtensionPointRepresentation describe( PluginPoint extension )
    121     {
    122         ExtensionPointRepresentation representation = new ExtensionPointRepresentation( extension.name(), extension.forType(), extension.getDescription() );
    123         extension.describeParameters( representation );
    124         return representation;
    125     }
    126
    127     @Override
    128     public List<ExtensionPointRepresentation> describeAll( String name )
    129             throws PluginLookupException
    130     {
    131         ServerExtender extender = extensions.get( name );
    132         if ( extender == null )
    133         {
    134             throw new PluginLookupException( "No such ServerPlugin: \"" + name + "\"" );
    135         }
    136         List<ExtensionPointRepresentation> result = new ArrayList<ExtensionPointRepresentation>();
    137         for ( PluginPoint plugin : extender.all() )
    138         {
    139             result.add( describe( plugin ) );
    140         }
    141         return result;
    142     }
    143
    144     @Override
    145     public <T> Representation invoke( AbstractGraphDatabase graphDb, String name, Class<T> type,
    146                                       String method, T context, ParameterList params ) throws PluginLookupException,
    147             BadInputException, PluginInvocationFailureException, BadPluginInvocationException
    148     {
    149         PluginPoint plugin = extension( name, type, method );
    150         try
    151         {
    152             return plugin.invoke( graphDb, context, params );
    153         } catch ( BadInputException e )
    154         {
    155             throw e;
    156         } catch ( BadPluginInvocationException e )
    157         {
    158             throw e;
    159         } catch ( PluginInvocationFailureException e )
    160         {
    161             throw e;
    162         } catch ( Exception e )
    163         {
    164             throw new PluginInvocationFailureException( e );
    165         }
    166     }
    167
    168     @Override
    169     public Set<String> extensionNames()
    170     {
    171         return Collections.unmodifiableSet( extensions.keySet() );
    172     }
    173 }