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 }