1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
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 }