    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 }