1   /**
2    * Licensed to Neo Technology under one or more contributor
3    * license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright
5    * ownership. Neo Technology licenses this file to you under
6    * the Apache License, Version 2.0 (the "License"); you may
7    * not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.neo4j.examples;
20  
21  import org.neo4j.graphdb.*;
22  import org.neo4j.helpers.collection.MapUtil;
23  import org.neo4j.kernel.EmbeddedGraphDatabase;
24  import org.neo4j.shell.ShellServer;
25  import org.neo4j.shell.impl.SameJvmClient;
26  import org.neo4j.shell.kernel.GraphDatabaseShellServer;
27  
28  import java.io.BufferedReader;
29  import java.io.InputStreamReader;
30  import java.util.*;
31  
32  public class Neo4jShell
33  {
34      private static final String DB_PATH = "neo4j-store";
35      private static final String USERNAME_KEY = "username";
36      private static GraphDatabaseService graphDb;
37  
38      private static enum RelTypes implements RelationshipType
39      {
40          USERS_REFERENCE, USER, KNOWS,
41      }
42  
43      public static void main( final String[] args ) throws Exception
44      {
45          registerShutdownHookForNeo();
46          boolean trueForLocal = waitForUserInput(
47              "Would you like to start a "
48                  + "local shell instance or enable neo4j to accept remote "
49                  + "connections [l/r]? " ).equalsIgnoreCase( "l" );
50          if ( trueForLocal )
51          {
52              startLocalShell();
53          }
54          else
55          {
56              startRemoteShellAndWait();
57          }
58          shutdown();
59      }
60  
61      private static void startGraphDb()
62      {
63          graphDb = new EmbeddedGraphDatabase( DB_PATH );
64      }
65  
66      private static void startGraphDb( Map<String, String> settings )
67      {
68          graphDb = new EmbeddedGraphDatabase( DB_PATH, settings );
69      }
70  
71      private static void startLocalShell() throws Exception
72      {
73          startGraphDb();
74          createExampleNodeSpace();
75          ShellServer shellServer = new GraphDatabaseShellServer( graphDb );
76          new SameJvmClient( shellServer ).grabPrompt();
77          shellServer.shutdown();
78      }
79  
80      private static void startRemoteShellAndWait() throws Exception
81      {
82          startGraphDb( MapUtil.stringMap( "enable_remote_shell", "true" ) );
83          createExampleNodeSpace();
84          waitForUserInput( "Remote shell enabled, connect to it by executing\n"
85                            + "the shell-client script in a separate terminal."
86                            + "The script is located in the bin directory.\n"
87                            + "\nWhen you're done playing around, just press [Enter] "
88                            + "in this terminal " );
89      }
90  
91      private static String waitForUserInput( final String textToSystemOut )
92          throws Exception
93      {
94          System.out.print( textToSystemOut );
95          return new BufferedReader( new InputStreamReader( System.in ) )
96              .readLine();
97      }
98  
99      private static void createExampleNodeSpace()
100     {
101         Transaction tx = graphDb.beginTx();
102         try
103         {
104             // Create users sub reference node (see design guide lines on
105             // http://wiki.neo4j.org)
106             System.out.println( "Creating example node space ..." );
107             Random random = new Random();
108             Node usersReferenceNode = graphDb.createNode();
109             graphDb.getReferenceNode().createRelationshipTo(
110                 usersReferenceNode, RelTypes.USERS_REFERENCE );
111             // Create some users and index their names with the IndexService
112             List<Node> users = new ArrayList<Node>();
113             for ( int id = 0; id < 100; id++ )
114             {
115                 Node userNode = createUser( formUserName( id ) );
116                 usersReferenceNode.createRelationshipTo( userNode,
117                     RelTypes.USER );
118                 if ( id > 10 )
119                 {
120                     int numberOfFriends = random.nextInt( 5 );
121                     Set<Node> knows = new HashSet<Node>();
122                     for ( int i = 0; i < numberOfFriends; i++ )
123                     {
124                         Node friend = users
125                             .get( random.nextInt( users.size() ) );
126                         if ( knows.add( friend ) )
127                         {
128                             userNode.createRelationshipTo( friend,
129                                 RelTypes.KNOWS );
130                         }
131                     }
132                 }
133                 users.add( userNode );
134             }
135             tx.success();
136         }
137         finally
138         {
139             tx.finish();
140         }
141     }
142 
143     private static void deleteExampleNodeSpace()
144     {
145         Transaction tx = graphDb.beginTx();
146         try
147         {
148             // Delete the persons and remove them from the index
149             System.out.println( "Deleting example node space ..." );
150             Node usersReferenceNode = graphDb.getReferenceNode()
151                 .getSingleRelationship( RelTypes.USERS_REFERENCE,
152                     Direction.OUTGOING ).getEndNode();
153             for ( Relationship relationship : usersReferenceNode
154                 .getRelationships( RelTypes.USER, Direction.OUTGOING ) )
155             {
156                 Node user = relationship.getEndNode();
157                 for ( Relationship knowsRelationship : user
158                     .getRelationships( RelTypes.KNOWS ) )
159                 {
160                     knowsRelationship.delete();
161                 }
162                 user.delete();
163                 relationship.delete();
164             }
165             usersReferenceNode.getSingleRelationship( RelTypes.USERS_REFERENCE,
166                 Direction.INCOMING ).delete();
167             usersReferenceNode.delete();
168             tx.success();
169         }
170         finally
171         {
172             tx.finish();
173         }
174     }
175 
176     private static void shutdownGraphDb()
177     {
178         System.out.println( "Shutting down database ..." );
179         graphDb.shutdown();
180         graphDb = null;
181     }
182 
183     private static void shutdown()
184     {
185         if ( graphDb != null )
186         {
187             deleteExampleNodeSpace();
188             shutdownGraphDb();
189         }
190     }
191 
192     private static void registerShutdownHookForNeo()
193     {
194         // Registers a shutdown hook for the Neo4j instance so that it
195         // shuts down nicely when the VM exits (even if you "Ctrl-C" the
196         // running example before it's completed)
197         Runtime.getRuntime().addShutdownHook( new Thread()
198         {
199             @Override
200             public void run()
201             {
202                 shutdown();
203             }
204         } );
205     }
206 
207     private static String formUserName( final int id )
208     {
209         return "user" + id + "@neo4j.org";
210     }
211 
212     private static Node createUser( final String username )
213     {
214         Node node = graphDb.createNode();
215         node.setProperty( USERNAME_KEY, username );
216         return node;
217     }
218 }