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.rest.web;
21  
22  import org.neo4j.graphdb.GraphDatabaseService;
23  import org.neo4j.graphdb.Node;
24  import org.neo4j.graphdb.NotFoundException;
25  import org.neo4j.graphdb.Relationship;
26  import org.neo4j.kernel.AbstractGraphDatabase;
27  import org.neo4j.server.database.Database;
28  import org.neo4j.server.plugins.BadPluginInvocationException;
29  import org.neo4j.server.plugins.ParameterList;
30  import org.neo4j.server.plugins.PluginInvocationFailureException;
31  import org.neo4j.server.plugins.PluginInvocator;
32  import org.neo4j.server.plugins.PluginLookupException;
33  import org.neo4j.server.rest.repr.BadInputException;
34  import org.neo4j.server.rest.repr.InputFormat;
35  import org.neo4j.server.rest.repr.MappingRepresentation;
36  import org.neo4j.server.rest.repr.MappingSerializer;
37  import org.neo4j.server.rest.repr.OutputFormat;
38  import org.neo4j.server.rest.repr.Representation;
39  import org.neo4j.server.rest.repr.ServerExtensionRepresentation;
40  
41  import javax.ws.rs.GET;
42  import javax.ws.rs.POST;
43  import javax.ws.rs.Path;
44  import javax.ws.rs.PathParam;
45  import javax.ws.rs.core.Context;
46  import javax.ws.rs.core.Response;
47  
48  @Path( "ext" )
49  public class ExtensionService
50  {
51      private static final String PATH_EXTENSION = "/{name}";
52      private static final String PATH_GRAPHDB_EXTENSION_METHOD = PATH_EXTENSION
53                                                                  + "/graphdb/{method}";
54      private static final String PATH_NODE_EXTENSION_METHOD = PATH_EXTENSION + "/node/{nodeId}/{method}";
55      private static final String PATH_RELATIONSHIP_EXTENSION_METHOD = PATH_EXTENSION
56                                                                       + "/relationship/{relationshipId}/{method}";
57      private final InputFormat input;
58      private final OutputFormat output;
59      private final PluginInvocator extensions;
60      private final AbstractGraphDatabase graphDb;
61  
62      public ExtensionService( @Context InputFormat input, @Context OutputFormat output,
63              @Context PluginInvocator extensions, @Context Database database )
64      {
65          this.input = input;
66          this.output = output;
67          this.extensions = extensions;
68          this.graphDb = database.graph;
69      }
70  
71      private Node node( long id ) throws NodeNotFoundException
72      {
73          try
74          {
75              return graphDb.getNodeById( id );
76          }
77          catch ( NotFoundException e )
78          {
79              throw new NodeNotFoundException();
80          }
81      }
82  
83      private Relationship relationship( long id ) throws RelationshipNotFoundException
84      {
85          try
86          {
87              return graphDb.getRelationshipById( id );
88          }
89          catch ( NotFoundException e )
90          {
91              throw new RelationshipNotFoundException();
92          }
93      }
94  
95      @GET
96      public Response getExtensionsList()
97      {
98          return output.ok( this.extensionsList() );
99      }
100 
101     @GET
102     @Path( PATH_EXTENSION )
103     public Response getExtensionList( @PathParam( "name" ) String name )
104     {
105         try
106         {
107             return output.ok( this.extensionList( name ) );
108         }
109         catch ( PluginLookupException e )
110         {
111             return output.notFound( e );
112         }
113     }
114 
115     @POST
116     @Path( PATH_GRAPHDB_EXTENSION_METHOD )
117     public Response invokeGraphDatabaseExtension( @PathParam( "name" ) String name,
118             @PathParam( "method" ) String method, String data )
119     {
120         try
121         {
122             return output.ok( this.invokeGraphDatabaseExtension( name, method,
123                     input.readParameterList( data ) ) );
124         }
125         catch ( BadInputException e )
126         {
127             return output.badRequest( e );
128         }
129         catch ( PluginLookupException e )
130         {
131             return output.notFound( e );
132         }
133         catch ( BadPluginInvocationException e )
134         {
135             return output.badRequest( e.getCause() );
136         }
137         catch ( PluginInvocationFailureException e )
138         {
139             return output.serverError( e.getCause() );
140         }
141     }
142 
143     @GET
144     @Path( PATH_GRAPHDB_EXTENSION_METHOD )
145     public Response getGraphDatabaseExtensionDescription( @PathParam( "name" ) String name,
146             @PathParam( "method" ) String method )
147     {
148         try
149         {
150             return output.ok( this.describeGraphDatabaseExtension( name, method ) );
151         }
152         catch ( PluginLookupException e )
153         {
154             return output.notFound( e );
155         }
156     }
157 
158     @POST
159     @Path( PATH_NODE_EXTENSION_METHOD )
160     public Response invokeNodeExtension( @PathParam( "name" ) String name,
161             @PathParam( "method" ) String method, @PathParam( "nodeId" ) long nodeId, String data )
162     {
163         try
164         {
165             return output.ok( this.invokeNodeExtension( nodeId, name, method,
166                     input.readParameterList( data ) ) );
167         }
168         catch ( NodeNotFoundException e )
169         {
170             return output.notFound( e );
171         }
172         catch ( BadInputException e )
173         {
174             return output.badRequest( e );
175         }
176         catch ( PluginLookupException e )
177         {
178             return output.notFound( e );
179         }
180         catch ( BadPluginInvocationException e )
181         {
182             return output.badRequest( e.getCause() );
183         }
184         catch ( PluginInvocationFailureException e )
185         {
186             return output.serverError( e.getCause() );
187         }
188     }
189 
190     @GET
191     @Path( PATH_NODE_EXTENSION_METHOD )
192     public Response getNodeExtensionDescription( @PathParam( "name" ) String name,
193             @PathParam( "method" ) String method, @PathParam( "nodeId" ) long nodeId )
194     {
195         try
196         {
197             return output.ok( this.describeNodeExtension( name, method ) );
198         }
199         catch ( PluginLookupException e )
200         {
201             return output.notFound( e );
202         }
203     }
204 
205     @POST
206     @Path( PATH_RELATIONSHIP_EXTENSION_METHOD )
207     public Response invokeRelationshipExtension( @PathParam( "name" ) String name,
208             @PathParam( "method" ) String method,
209             @PathParam( "relationshipId" ) long relationshipId, String data )
210     {
211         try
212         {
213             return output.ok( this.invokeRelationshipExtension( relationshipId, name, method,
214                     input.readParameterList( data ) ) );
215         }
216         catch ( RelationshipNotFoundException e )
217         {
218             return output.notFound( e );
219         }
220         catch ( BadInputException e )
221         {
222             return output.badRequest( e );
223         }
224         catch ( PluginLookupException e )
225         {
226             return output.notFound( e );
227         }
228         catch ( BadPluginInvocationException e )
229         {
230             return output.badRequest( e.getCause() );
231         }
232         catch ( PluginInvocationFailureException e )
233         {
234             return output.serverError( e.getCause() );
235         }
236     }
237 
238     @GET
239     @Path( PATH_RELATIONSHIP_EXTENSION_METHOD )
240     public Response getRelationshipExtensionDescription( @PathParam( "name" ) String name,
241             @PathParam( "method" ) String method, @PathParam( "relationshipId" ) long relationshipId )
242     {
243         try
244         {
245             return output.ok( this.describeRelationshipExtension( name, method ) );
246         }
247         catch ( PluginLookupException e )
248         {
249             return output.notFound( e );
250         }
251     }
252 
253     // Extensions
254 
255     protected Representation extensionsList()
256     {
257         return new MappingRepresentation( "extensions" )
258         {
259             @Override
260             protected void serialize( MappingSerializer serializer )
261             {
262                 for ( String extension : extensions.extensionNames() )
263                 {
264                     serializer.putUri( extension, "ext/" + extension );
265                 }
266             }
267         };
268     }
269 
270     protected Representation extensionList( String extensionName ) throws PluginLookupException
271     {
272         return new ServerExtensionRepresentation( extensionName,
273                 extensions.describeAll( extensionName ) );
274     }
275 
276     protected Representation invokeGraphDatabaseExtension( String extensionName, String method,
277             ParameterList data ) throws PluginLookupException, BadInputException,
278             PluginInvocationFailureException, BadPluginInvocationException
279     {
280         return extensions.invoke( graphDb, extensionName, GraphDatabaseService.class, method,
281                 graphDb, data );
282     }
283 
284     protected Representation describeGraphDatabaseExtension( String extensionName, String method )
285             throws PluginLookupException
286     {
287         return extensions.describe( extensionName, GraphDatabaseService.class, method );
288     }
289 
290     protected Representation invokeNodeExtension( long nodeId, String extensionName, String method,
291             ParameterList data ) throws NodeNotFoundException, PluginLookupException,
292             BadInputException, PluginInvocationFailureException, BadPluginInvocationException
293     {
294         return extensions.invoke( graphDb, extensionName, Node.class, method, node( nodeId ), data );
295     }
296 
297     protected Representation describeNodeExtension( String extensionName, String method )
298             throws PluginLookupException
299     {
300         return extensions.describe( extensionName, Node.class, method );
301     }
302 
303     protected Representation invokeRelationshipExtension( long relationshipId,
304             String extensionName, String method, ParameterList data )
305             throws RelationshipNotFoundException, PluginLookupException, BadInputException,
306             PluginInvocationFailureException, BadPluginInvocationException
307     {
308         return extensions.invoke( graphDb, extensionName, Relationship.class, method,
309                 relationship( relationshipId ), data );
310     }
311 
312     protected Representation describeRelationshipExtension( String extensionName, String method )
313             throws PluginLookupException
314     {
315         return extensions.describe( extensionName, Relationship.class, method );
316     }
317 }