├── .gitignore ├── model.graffle ├── model.png ├── pom.xml ├── readme.md └── src ├── main ├── java │ └── org │ │ └── neo4j │ │ ├── data │ │ └── file │ │ │ ├── FileHandler.java │ │ │ └── FileSystemVisitor.java │ │ ├── datasource │ │ ├── java │ │ │ ├── JarFileImporter.java │ │ │ ├── analyser │ │ │ │ ├── ClassFileIterator.java │ │ │ │ ├── ClassFileLocator.java │ │ │ │ ├── ClassInspectUtils.java │ │ │ │ ├── ClassInspector.java │ │ │ │ ├── NullClassVisitor.java │ │ │ │ ├── RecordingClassVisitor.java │ │ │ │ ├── RecordingInspector.java │ │ │ │ ├── RecursingClassVisitor.java │ │ │ │ ├── VirtualVisitor.java │ │ │ │ └── stats │ │ │ │ │ ├── DefaultStatistics.java │ │ │ │ │ ├── NullStatistics.java │ │ │ │ │ └── Statistics.java │ │ │ └── declaration │ │ │ │ ├── ClassDeclaration.java │ │ │ │ ├── DeclarationFactory.java │ │ │ │ ├── FieldDeclaration.java │ │ │ │ ├── MethodDeclaration.java │ │ │ │ ├── PackageDeclaration.java │ │ │ │ ├── bean │ │ │ │ ├── BeanDeclarationFactory.java │ │ │ │ ├── ClassDeclarationBean.java │ │ │ │ ├── FieldDeclarationBean.java │ │ │ │ ├── MethodDeclarationBean.java │ │ │ │ └── PackageDeclarationBean.java │ │ │ │ └── neo │ │ │ │ ├── ClassRelations.java │ │ │ │ ├── MapNodeCache.java │ │ │ │ ├── NeoClassDeclaration.java │ │ │ │ ├── NeoDeclarationFactory.java │ │ │ │ ├── NeoFieldDeclaration.java │ │ │ │ ├── NeoMethodDeclaration.java │ │ │ │ ├── NodeCache.java │ │ │ │ └── TypeNodeFinder.java │ │ └── util │ │ │ └── SizeCountingOutputStream.java │ │ └── test │ │ └── NeoTestHelper.java └── resources │ └── streamline.html └── test └── java └── org └── neo4j ├── analyser └── codecity │ ├── Gears.java.save │ ├── HelloWorldDemo.java.save │ ├── JoglFrame.java.save │ ├── JoglTest.java.save │ └── MooseWriter.java ├── api └── core │ └── NeoFileSystemTest.java └── datasource └── java ├── ClassFileFinderTest.java ├── ClassFileLocatorTest.java ├── ClassInspectorTest.java ├── ClassTraversalTest.java ├── RecordingInspectorNeoTest.java ├── RecordingInspectorTest.java └── VirtualInspectorTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | \#* 3 | target 4 | *.swp 5 | .project 6 | .classpath 7 | .settings 8 | .scala_dependencies 9 | .factorypath 10 | *.iws 11 | *.ipr 12 | *.iml 13 | .idea 14 | .DS_Store 15 | .shell_history 16 | cypher/project 17 | cypher/lib_managed 18 | server/neo4j-home/data/ 19 | server/neo4j-home/rrd 20 | server/src/main/resources/webadmin-html/js/neo4j/ 21 | server/src/main/resources/webadmin-html/js/ribcage/ 22 | server/src/main/resources/webadmin-html/js/webadmin.js 23 | artifacts 24 | */pom-with-build-number.xml 25 | -------------------------------------------------------------------------------- /model.graffle: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ActiveLayerIndex 6 | 0 7 | ApplicationVersion 8 | 9 | com.omnigroup.OmniGraffle.MacAppStore 10 | 138.33 11 | 12 | AutoAdjust 13 | 14 | BackgroundGraphic 15 | 16 | Bounds 17 | {{0, 0}, {559, 783}} 18 | Class 19 | SolidGraphic 20 | ID 21 | 2 22 | Style 23 | 24 | shadow 25 | 26 | Draws 27 | NO 28 | 29 | stroke 30 | 31 | Draws 32 | NO 33 | 34 | 35 | 36 | CanvasOrigin 37 | {0, 0} 38 | ColumnAlign 39 | 1 40 | ColumnSpacing 41 | 36 42 | CreationDate 43 | 2012-06-11 00:59:21 +0000 44 | Creator 45 | Michael Hunger 46 | DisplayScale 47 | 1.000 cm = 1.000 cm 48 | GraphDocumentVersion 49 | 8 50 | GraphicsList 51 | 52 | 53 | Bounds 54 | {{119.92012, 424.26245}, {49, 16}} 55 | Class 56 | ShapedGraphic 57 | FitText 58 | YES 59 | Flow 60 | Resize 61 | ID 62 | 70 63 | Shape 64 | Rectangle 65 | Style 66 | 67 | stroke 68 | 69 | Draws 70 | NO 71 | 72 | 73 | Text 74 | 75 | Pad 76 | 2 77 | Text 78 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 79 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 80 | {\colortbl;\red255\green255\blue255;} 81 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 82 | 83 | \f0\fs20 \cf0 THROWS} 84 | VerticalPad 85 | 2 86 | 87 | Wrap 88 | NO 89 | 90 | 91 | Bounds 92 | {{93.787659, 444.63123}, {71, 16}} 93 | Class 94 | ShapedGraphic 95 | FitText 96 | YES 97 | Flow 98 | Resize 99 | ID 100 | 69 101 | Shape 102 | Rectangle 103 | Style 104 | 105 | stroke 106 | 107 | Draws 108 | NO 109 | 110 | 111 | Text 112 | 113 | Pad 114 | 2 115 | Text 116 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 117 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 118 | {\colortbl;\red255\green255\blue255;} 119 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 120 | 121 | \f0\fs20 \cf0 PARAM_TYPE} 122 | VerticalPad 123 | 2 124 | 125 | Wrap 126 | NO 127 | 128 | 129 | Bounds 130 | {{90.287659, 470.81561}, {78, 16}} 131 | Class 132 | ShapedGraphic 133 | FitText 134 | YES 135 | Flow 136 | Resize 137 | ID 138 | 68 139 | Line 140 | 141 | ID 142 | 67 143 | Position 144 | 0.32548815011978149 145 | RotationType 146 | 0 147 | 148 | Shape 149 | Rectangle 150 | Style 151 | 152 | stroke 153 | 154 | Draws 155 | NO 156 | 157 | 158 | Text 159 | 160 | Pad 161 | 2 162 | Text 163 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 164 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 165 | {\colortbl;\red255\green255\blue255;} 166 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 167 | 168 | \f0\fs20 \cf0 RETURN_TYPE} 169 | VerticalPad 170 | 2 171 | 172 | Wrap 173 | NO 174 | 175 | 176 | Class 177 | LineGraphic 178 | Head 179 | 180 | ID 181 | 33 182 | 183 | ID 184 | 67 185 | Points 186 | 187 | {95.020081, 513.52173} 188 | {200.30064, 406.89386} 189 | 190 | Style 191 | 192 | stroke 193 | 194 | HeadArrow 195 | FilledArrow 196 | LineType 197 | 1 198 | TailArrow 199 | 0 200 | 201 | 202 | Tail 203 | 204 | ID 205 | 58 206 | 207 | 208 | 209 | Bounds 210 | {{47.731125, 396.19199}, {67, 16}} 211 | Class 212 | ShapedGraphic 213 | FitText 214 | YES 215 | Flow 216 | Resize 217 | ID 218 | 66 219 | Line 220 | 221 | ID 222 | 65 223 | Position 224 | 0.47107452154159546 225 | RotationType 226 | 0 227 | 228 | Shape 229 | Rectangle 230 | Style 231 | 232 | stroke 233 | 234 | Draws 235 | NO 236 | 237 | 238 | Text 239 | 240 | Pad 241 | 2 242 | Text 243 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 244 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 245 | {\colortbl;\red255\green255\blue255;} 246 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 247 | 248 | \f0\fs20 \cf0 METHOD_OF} 249 | VerticalPad 250 | 2 251 | 252 | Wrap 253 | NO 254 | 255 | 256 | Class 257 | LineGraphic 258 | Head 259 | 260 | ID 261 | 58 262 | 263 | ID 264 | 65 265 | Points 266 | 267 | {188.47989, 394.93719} 268 | {74, 409.5} 269 | {78.020905, 511.50388} 270 | 271 | Style 272 | 273 | stroke 274 | 275 | HeadArrow 276 | FilledArrow 277 | LineType 278 | 1 279 | TailArrow 280 | 0 281 | 282 | 283 | Tail 284 | 285 | ID 286 | 33 287 | 288 | 289 | 290 | Bounds 291 | {{304, 428.79083}, {65, 16}} 292 | Class 293 | ShapedGraphic 294 | FitText 295 | YES 296 | Flow 297 | Resize 298 | ID 299 | 64 300 | Shape 301 | Rectangle 302 | Style 303 | 304 | stroke 305 | 306 | Draws 307 | NO 308 | 309 | 310 | Text 311 | 312 | Pad 313 | 2 314 | Text 315 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 316 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 317 | {\colortbl;\red255\green255\blue255;} 318 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 319 | 320 | \f0\fs20 \cf0 FIELD_TYPE} 321 | VerticalPad 322 | 2 323 | 324 | Wrap 325 | NO 326 | 327 | 328 | Class 329 | LineGraphic 330 | Head 331 | 332 | ID 333 | 33 334 | 335 | ID 336 | 63 337 | Points 338 | 339 | {407.34201, 519.30432} 340 | {336, 442} 341 | {238.82471, 401.27509} 342 | 343 | Style 344 | 345 | stroke 346 | 347 | HeadArrow 348 | FilledArrow 349 | LineType 350 | 1 351 | TailArrow 352 | 0 353 | 354 | 355 | Tail 356 | 357 | ID 358 | 60 359 | 360 | 361 | 362 | Bounds 363 | {{316.45898, 465.39542}, {33, 16}} 364 | Class 365 | ShapedGraphic 366 | FitText 367 | YES 368 | Flow 369 | Resize 370 | ID 371 | 62 372 | Line 373 | 374 | ID 375 | 61 376 | Position 377 | 0.58973211050033569 378 | RotationType 379 | 0 380 | 381 | Shape 382 | Rectangle 383 | Style 384 | 385 | stroke 386 | 387 | Draws 388 | NO 389 | 390 | 391 | Text 392 | 393 | Pad 394 | 2 395 | Text 396 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 397 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 398 | {\colortbl;\red255\green255\blue255;} 399 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 400 | 401 | \f0\fs20 \cf0 FIELD} 402 | VerticalPad 403 | 2 404 | 405 | Wrap 406 | NO 407 | 408 | 409 | Class 410 | LineGraphic 411 | Head 412 | 413 | ID 414 | 60 415 | 416 | ID 417 | 61 418 | Points 419 | 420 | {234.5697, 404.7959} 421 | {401.40695, 521.11908} 422 | 423 | Style 424 | 425 | stroke 426 | 427 | HeadArrow 428 | FilledArrow 429 | LineType 430 | 1 431 | TailArrow 432 | 0 433 | 434 | 435 | Tail 436 | 437 | ID 438 | 33 439 | 440 | 441 | 442 | Bounds 443 | {{387, 518}, {71.5, 36}} 444 | Class 445 | ShapedGraphic 446 | ID 447 | 60 448 | Shape 449 | Circle 450 | Style 451 | 452 | Text 453 | 454 | Text 455 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 456 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 457 | {\colortbl;\red255\green255\blue255;} 458 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 459 | 460 | \f0\b\fs24 \cf0 field} 461 | VerticalPad 462 | 0 463 | 464 | 465 | 466 | Bounds 467 | {{43, 512}, {71.5, 36}} 468 | Class 469 | ShapedGraphic 470 | ID 471 | 58 472 | Shape 473 | Circle 474 | Style 475 | 476 | Text 477 | 478 | Text 479 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 480 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 481 | {\colortbl;\red255\green255\blue255;} 482 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 483 | 484 | \f0\b\fs24 \cf0 method} 485 | VerticalPad 486 | 0 487 | 488 | 489 | 490 | Bounds 491 | {{208.5, 453}, {71, 16}} 492 | Class 493 | ShapedGraphic 494 | FitText 495 | YES 496 | Flow 497 | Resize 498 | ID 499 | 57 500 | Shape 501 | Rectangle 502 | Style 503 | 504 | stroke 505 | 506 | Draws 507 | NO 508 | 509 | 510 | Text 511 | 512 | Pad 513 | 2 514 | Text 515 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 516 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 517 | {\colortbl;\red255\green255\blue255;} 518 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 519 | 520 | \f0\fs20 \cf0 SUPER_TYPE} 521 | VerticalPad 522 | 2 523 | 524 | Wrap 525 | NO 526 | 527 | 528 | Bounds 529 | {{187.50002, 480}, {92, 16}} 530 | Class 531 | ShapedGraphic 532 | FitText 533 | YES 534 | Flow 535 | Resize 536 | ID 537 | 56 538 | Shape 539 | Rectangle 540 | Style 541 | 542 | stroke 543 | 544 | Draws 545 | NO 546 | 547 | 548 | Text 549 | 550 | Pad 551 | 2 552 | Text 553 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 554 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 555 | {\colortbl;\red255\green255\blue255;} 556 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 557 | 558 | \f0\fs20 \cf0 INTERFACE_TYPE} 559 | VerticalPad 560 | 2 561 | 562 | Wrap 563 | NO 564 | 565 | 566 | Bounds 567 | {{261.375, 109}, {84, 16}} 568 | Class 569 | ShapedGraphic 570 | FitText 571 | YES 572 | Flow 573 | Resize 574 | ID 575 | 55 576 | Shape 577 | Rectangle 578 | Style 579 | 580 | stroke 581 | 582 | Draws 583 | NO 584 | 585 | 586 | Text 587 | 588 | Pad 589 | 2 590 | Text 591 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 592 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 593 | {\colortbl;\red255\green255\blue255;} 594 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 595 | 596 | \f0\fs20 \cf0 PACKAGE_TREE} 597 | VerticalPad 598 | 2 599 | 600 | Wrap 601 | NO 602 | 603 | 604 | Bounds 605 | {{118.92012, 150.54126}, {61, 16}} 606 | Class 607 | ShapedGraphic 608 | FitText 609 | YES 610 | Flow 611 | Resize 612 | ID 613 | 54 614 | Shape 615 | Rectangle 616 | Style 617 | 618 | stroke 619 | 620 | Draws 621 | NO 622 | 623 | 624 | Text 625 | 626 | Pad 627 | 2 628 | Text 629 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 630 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 631 | {\colortbl;\red255\green255\blue255;} 632 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 633 | 634 | \f0\fs20 \cf0 ALL_TYPES} 635 | VerticalPad 636 | 2 637 | 638 | Wrap 639 | NO 640 | 641 | 642 | Bounds 643 | {{208, 170.5}, {82, 16}} 644 | Class 645 | ShapedGraphic 646 | FitText 647 | YES 648 | Flow 649 | Resize 650 | ID 651 | 53 652 | Shape 653 | Rectangle 654 | Style 655 | 656 | stroke 657 | 658 | Draws 659 | NO 660 | 661 | 662 | Text 663 | 664 | Pad 665 | 2 666 | Text 667 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 668 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 669 | {\colortbl;\red255\green255\blue255;} 670 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 671 | 672 | \f0\fs20 \cf0 ALL_PACKAGES} 673 | VerticalPad 674 | 2 675 | 676 | Wrap 677 | NO 678 | 679 | 680 | Bounds 681 | {{148.92012, 312.88531}, {31, 16}} 682 | Class 683 | ShapedGraphic 684 | FitText 685 | YES 686 | Flow 687 | Resize 688 | ID 689 | 52 690 | Line 691 | 692 | ID 693 | 34 694 | Position 695 | 0.53521114587783813 696 | RotationType 697 | 0 698 | 699 | Shape 700 | Rectangle 701 | Style 702 | 703 | stroke 704 | 705 | Draws 706 | NO 707 | 708 | 709 | Text 710 | 711 | Pad 712 | 2 713 | Text 714 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 715 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 716 | {\colortbl;\red255\green255\blue255;} 717 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 718 | 719 | \f0\fs20 \cf0 TYPE} 720 | VerticalPad 721 | 2 722 | 723 | Wrap 724 | NO 725 | 726 | 727 | Bounds 728 | {{245.5, 360}, {68, 16}} 729 | Class 730 | ShapedGraphic 731 | FitText 732 | YES 733 | Flow 734 | Resize 735 | ID 736 | 51 737 | Shape 738 | Rectangle 739 | Style 740 | 741 | stroke 742 | 743 | Draws 744 | NO 745 | 746 | 747 | Text 748 | 749 | Pad 750 | 2 751 | Text 752 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 753 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 754 | {\colortbl;\red255\green255\blue255;} 755 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 756 | 757 | \f0\fs20 \cf0 IN_PACKAGE} 758 | VerticalPad 759 | 2 760 | 761 | Wrap 762 | NO 763 | 764 | 765 | Class 766 | LineGraphic 767 | Head 768 | 769 | ID 770 | 42 771 | 772 | ID 773 | 50 774 | Points 775 | 776 | {335.4064, 301.74274} 777 | {308.66214, 321.78131} 778 | 779 | Style 780 | 781 | stroke 782 | 783 | HeadArrow 784 | FilledArrow 785 | LineType 786 | 1 787 | TailArrow 788 | 0 789 | 790 | 791 | Tail 792 | 793 | ID 794 | 47 795 | 796 | 797 | 798 | Class 799 | LineGraphic 800 | Head 801 | 802 | ID 803 | 47 804 | 805 | ID 806 | 49 807 | Points 808 | 809 | {388.79095, 252.55838} 810 | {371.9718, 270.00916} 811 | 812 | Style 813 | 814 | stroke 815 | 816 | HeadArrow 817 | FilledArrow 818 | LineType 819 | 1 820 | TailArrow 821 | 0 822 | 823 | 824 | Tail 825 | 826 | ID 827 | 46 828 | 829 | 830 | 831 | Class 832 | LineGraphic 833 | Head 834 | 835 | ID 836 | 46 837 | 838 | ID 839 | 48 840 | Points 841 | 842 | {404.75, 152.50002} 843 | {404.75, 217.49998} 844 | 845 | Style 846 | 847 | stroke 848 | 849 | HeadArrow 850 | FilledArrow 851 | LineType 852 | 1 853 | TailArrow 854 | 0 855 | 856 | 857 | Tail 858 | 859 | ID 860 | 31 861 | 862 | 863 | 864 | Bounds 865 | {{320, 268.5}, {71.5, 36}} 866 | Class 867 | ShapedGraphic 868 | ID 869 | 47 870 | Shape 871 | Circle 872 | Style 873 | 874 | Text 875 | 876 | Text 877 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 878 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 879 | {\colortbl;\red255\green255\blue255;} 880 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 881 | 882 | \f0\fs24 \cf0 package} 883 | VerticalPad 884 | 0 885 | 886 | 887 | 888 | Bounds 889 | {{369, 218}, {71.5, 36}} 890 | Class 891 | ShapedGraphic 892 | ID 893 | 46 894 | Shape 895 | Circle 896 | Style 897 | 898 | Text 899 | 900 | Text 901 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 902 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 903 | {\colortbl;\red255\green255\blue255;} 904 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 905 | 906 | \f0\fs24 \cf0 package} 907 | VerticalPad 908 | 0 909 | 910 | 911 | 912 | Class 913 | LineGraphic 914 | Head 915 | 916 | ID 917 | 33 918 | 919 | ID 920 | 45 921 | Points 922 | 923 | {267.90408, 352.24194} 924 | {233.84996, 377.7533} 925 | 926 | Style 927 | 928 | stroke 929 | 930 | HeadArrow 931 | FilledArrow 932 | LineType 933 | 1 934 | TailArrow 935 | 0 936 | 937 | 938 | Tail 939 | 940 | ID 941 | 42 942 | 943 | 944 | 945 | Class 946 | LineGraphic 947 | Head 948 | 949 | ID 950 | 42 951 | 952 | ID 953 | 43 954 | Points 955 | 956 | {267.51343, 271.89804} 957 | {282.34476, 318.75739} 958 | 959 | Style 960 | 961 | stroke 962 | 963 | HeadArrow 964 | FilledArrow 965 | LineType 966 | 1 967 | TailArrow 968 | 0 969 | 970 | 971 | Tail 972 | 973 | ID 974 | 30 975 | 976 | 977 | 978 | Bounds 979 | {{252.5, 319}, {71.5, 36}} 980 | Class 981 | ShapedGraphic 982 | ID 983 | 42 984 | Shape 985 | Circle 986 | Style 987 | 988 | Text 989 | 990 | Text 991 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 992 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 993 | {\colortbl;\red255\green255\blue255;} 994 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 995 | 996 | \f0\fs24 \cf0 package} 997 | VerticalPad 998 | 0 999 | 1000 | 1001 | 1002 | Class 1003 | LineGraphic 1004 | Head 1005 | 1006 | ID 1007 | 33 1008 | 1009 | ID 1010 | 38 1011 | Points 1012 | 1013 | {206.1911, 408.89862} 1014 | {179.92012, 458} 1015 | {213, 468} 1016 | {220, 409.5} 1017 | {220.06038, 409.74155} 1018 | 1019 | Style 1020 | 1021 | stroke 1022 | 1023 | HeadArrow 1024 | FilledArrow 1025 | LineType 1026 | 1 1027 | TailArrow 1028 | 0 1029 | 1030 | 1031 | Tail 1032 | 1033 | ID 1034 | 33 1035 | 1036 | 1037 | 1038 | Class 1039 | LineGraphic 1040 | Head 1041 | 1042 | ID 1043 | 31 1044 | 1045 | ID 1046 | 37 1047 | Points 1048 | 1049 | {242.98604, 121.58912} 1050 | {363.76828, 124.17789} 1051 | 1052 | Style 1053 | 1054 | stroke 1055 | 1056 | HeadArrow 1057 | FilledArrow 1058 | LineType 1059 | 1 1060 | TailArrow 1061 | 0 1062 | 1063 | 1064 | Tail 1065 | 1066 | ID 1067 | 28 1068 | 1069 | 1070 | 1071 | Class 1072 | LineGraphic 1073 | Head 1074 | 1075 | ID 1076 | 30 1077 | 1078 | ID 1079 | 36 1080 | Points 1081 | 1082 | {221.78712, 139.00571} 1083 | {249.46001, 218.25804} 1084 | 1085 | Style 1086 | 1087 | stroke 1088 | 1089 | HeadArrow 1090 | FilledArrow 1091 | LineType 1092 | 1 1093 | TailArrow 1094 | 0 1095 | 1096 | 1097 | Tail 1098 | 1099 | ID 1100 | 28 1101 | 1102 | 1103 | 1104 | Class 1105 | LineGraphic 1106 | Head 1107 | 1108 | ID 1109 | 32 1110 | 1111 | ID 1112 | 35 1113 | Points 1114 | 1115 | {200.07478, 136.29132} 1116 | {124.46754, 211.24226} 1117 | 1118 | Style 1119 | 1120 | stroke 1121 | 1122 | HeadArrow 1123 | FilledArrow 1124 | LineType 1125 | 1 1126 | TailArrow 1127 | 0 1128 | 1129 | 1130 | Tail 1131 | 1132 | ID 1133 | 28 1134 | 1135 | 1136 | 1137 | Class 1138 | LineGraphic 1139 | Head 1140 | 1141 | ID 1142 | 33 1143 | 1144 | ID 1145 | 34 1146 | Points 1147 | 1148 | {119.40612, 258.72626} 1149 | {203.51125, 374.86557} 1150 | 1151 | Style 1152 | 1153 | stroke 1154 | 1155 | HeadArrow 1156 | FilledArrow 1157 | LineType 1158 | 1 1159 | TailArrow 1160 | 0 1161 | 1162 | 1163 | Tail 1164 | 1165 | ID 1166 | 32 1167 | 1168 | 1169 | 1170 | Bounds 1171 | {{188.5, 373.5}, {54, 36}} 1172 | Class 1173 | ShapedGraphic 1174 | ID 1175 | 33 1176 | Shape 1177 | Circle 1178 | Style 1179 | 1180 | Text 1181 | 1182 | Text 1183 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 1184 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 1185 | {\colortbl;\red255\green255\blue255;} 1186 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 1187 | 1188 | \f0\b\fs24 \cf0 class} 1189 | VerticalPad 1190 | 0 1191 | 1192 | 1193 | 1194 | Bounds 1195 | {{61, 207}, {81, 54}} 1196 | Class 1197 | ShapedGraphic 1198 | ID 1199 | 32 1200 | Shape 1201 | Circle 1202 | Style 1203 | 1204 | Text 1205 | 1206 | Text 1207 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 1208 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 1209 | {\colortbl;\red255\green255\blue255;} 1210 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 1211 | 1212 | \f0\fs24 \cf0 all types} 1213 | VerticalPad 1214 | 0 1215 | 1216 | 1217 | 1218 | Bounds 1219 | {{364.25, 98}, {81, 54}} 1220 | Class 1221 | ShapedGraphic 1222 | ID 1223 | 31 1224 | Shape 1225 | Circle 1226 | Style 1227 | 1228 | Text 1229 | 1230 | Text 1231 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 1232 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 1233 | {\colortbl;\red255\green255\blue255;} 1234 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 1235 | 1236 | \f0\fs24 \cf0 package tree} 1237 | VerticalPad 1238 | 0 1239 | 1240 | 1241 | 1242 | Bounds 1243 | {{218.5, 218}, {81, 54}} 1244 | Class 1245 | ShapedGraphic 1246 | ID 1247 | 30 1248 | Shape 1249 | Circle 1250 | Style 1251 | 1252 | Text 1253 | 1254 | Text 1255 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 1256 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 1257 | {\colortbl;\red255\green255\blue255;} 1258 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 1259 | 1260 | \f0\fs24 \cf0 all packages} 1261 | VerticalPad 1262 | 0 1263 | 1264 | 1265 | 1266 | Bounds 1267 | {{188.5, 103}, {54, 36}} 1268 | Class 1269 | ShapedGraphic 1270 | ID 1271 | 28 1272 | Shape 1273 | Circle 1274 | Style 1275 | 1276 | Text 1277 | 1278 | Text 1279 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470 1280 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 1281 | {\colortbl;\red255\green255\blue255;} 1282 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 1283 | 1284 | \f0\fs24 \cf0 root} 1285 | VerticalPad 1286 | 0 1287 | 1288 | 1289 | 1290 | GridInfo 1291 | 1292 | GuidesLocked 1293 | NO 1294 | GuidesVisible 1295 | YES 1296 | HPages 1297 | 1 1298 | ImageCounter 1299 | 1 1300 | KeepToScale 1301 | 1302 | Layers 1303 | 1304 | 1305 | Lock 1306 | NO 1307 | Name 1308 | Ebene 1 1309 | Print 1310 | YES 1311 | View 1312 | YES 1313 | 1314 | 1315 | LayoutInfo 1316 | 1317 | Animate 1318 | NO 1319 | circoMinDist 1320 | 18 1321 | circoSeparation 1322 | 0.0 1323 | layoutEngine 1324 | dot 1325 | neatoSeparation 1326 | 0.0 1327 | twopiSeparation 1328 | 0.0 1329 | 1330 | LinksVisible 1331 | NO 1332 | MagnetsVisible 1333 | NO 1334 | MasterSheets 1335 | 1336 | ModificationDate 1337 | 2012-06-11 01:08:37 +0000 1338 | Modifier 1339 | Michael Hunger 1340 | NotesVisible 1341 | NO 1342 | Orientation 1343 | 2 1344 | OriginVisible 1345 | NO 1346 | PageBreaks 1347 | YES 1348 | PrintInfo 1349 | 1350 | NSBottomMargin 1351 | 1352 | float 1353 | 41 1354 | 1355 | NSHorizonalPagination 1356 | 1357 | int 1358 | 0 1359 | 1360 | NSLeftMargin 1361 | 1362 | float 1363 | 18 1364 | 1365 | NSPaperSize 1366 | 1367 | coded 1368 | BAtzdHJlYW10eXBlZIHoA4QBQISEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAx7X05TU2l6ZT1mZn2WgVMCgUoDhg== 1369 | 1370 | NSPrintReverseOrientation 1371 | 1372 | int 1373 | 0 1374 | 1375 | NSRightMargin 1376 | 1377 | float 1378 | 18 1379 | 1380 | NSTopMargin 1381 | 1382 | float 1383 | 18 1384 | 1385 | 1386 | PrintOnePage 1387 | 1388 | ReadOnly 1389 | NO 1390 | RowAlign 1391 | 1 1392 | RowSpacing 1393 | 36 1394 | SheetTitle 1395 | Arbeitsfläche 1 1396 | SmartAlignmentGuidesActive 1397 | YES 1398 | SmartDistanceGuidesActive 1399 | YES 1400 | UniqueID 1401 | 1 1402 | UseEntirePage 1403 | 1404 | VPages 1405 | 1 1406 | WindowInfo 1407 | 1408 | CurrentSheet 1409 | 0 1410 | ExpandedCanvases 1411 | 1412 | Frame 1413 | {{953, 460}, {693, 938}} 1414 | ListView 1415 | 1416 | OutlineWidth 1417 | 142 1418 | RightSidebar 1419 | 1420 | ShowRuler 1421 | 1422 | Sidebar 1423 | 1424 | SidebarWidth 1425 | 120 1426 | VisibleRegion 1427 | {{0, 0}, {558, 783}} 1428 | Zoom 1429 | 1 1430 | ZoomValues 1431 | 1432 | 1433 | Arbeitsfläche 1 1434 | 1 1435 | 1 1436 | 1437 | 1438 | 1439 | saveQuickLookFiles 1440 | YES 1441 | 1442 | 1443 | -------------------------------------------------------------------------------- /model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jexp/class-graph/55a16bf739a98fc0a1d7b68f090a7beb88dd9eb1/model.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | de.jexp 5 | class-graph 6 | jar 7 | 1.0-SNAPSHOT 8 | neotest 9 | http://github.com/jexp/class-graph 10 | 11 | 12 | 13 | 14 | Neo4j releases 15 | http://m2.neo4j.org/milestones 16 | 17 | 18 | 19 | 20 | 21 | org.neo4j 22 | neo4j 23 | 1.8.M03 24 | 25 | 26 | junit 27 | junit 28 | 4.8.1 29 | test 30 | 31 | 32 | asm 33 | asm 34 | 3.3 35 | 36 | 37 | 38 | 39 | 40 | 41 | maven-compiler-plugin 42 | 43 | 1.6 44 | 1.6 45 | UTF-8 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## import class structures from jar-files into Neo4j 2 | 3 | usage: 4 | 5 | java -cp $CLASSPATH org.neo4j.datasource.java.JarFileImporter db-dir package.and.Class 6 | 7 | `package.and.Class` is a class of the jar file which should be imported, must be in the classpath 8 | 9 | e.g. 10 | 11 | java -cp $CLASSPATH org.neo4j.datasource.java.JarFileImporter test-db java.lang.Object 12 | 13 | ## Graph structure 14 | 15 | ROOT-[:ALL_TYPES]->all_types { type: "TYPE" } 16 | -[:TYPE]->class ({name : {slash-name}, access : {access} }) 17 | 18 | ROOT-[:ALL_PACKAGES]->(all_packages { type : "ALL_PACKAGES" }) 19 | -[:{package-name}]->(package { name : {package-name} }) 20 | -[:IN_PACKAGE]->class 21 | 22 | ROOT-[:PACKAGE_TREE]->(p1 {name: {package-name}, part: {part}}) 23 | -[:{part} *]->(p* ...) 24 | -[:{package-name}]->(package {...}) 25 | -[:IN_PACKAGE]->class 26 | 27 | class-[:INTERFACE_TYPE]->interface 28 | class-[:SUPER_TYPE]->superclass 29 | 30 | class-[:FIELD]->field-[:FIELD_TYPE]->field_type 31 | 32 | class-[:METHOD_OF]->method-[:PARAM_TYPE]->param_type 33 | method-[:RETURN_TYPE]->return_type 34 | method-[:THROWS]->exception 35 | 36 | ![graph model](https://raw.github.com/jexp/class-graph/master/model.png) 37 | 38 | ## sample cypher queries 39 | 40 | (might need to increase memory in `neo4j-shell` e.g. `EXTRA_JVM_ARGUMENTS="-Xmx2G -server -d64"`) 41 | 42 | neo4j-community-1.7/bin/neo4j-shell -path test-db/ 43 | 44 | ### Class Count 45 | 46 | start n=node(0) match n-[:ALL_TYPES]->t-[:TYPE]->() return count(*) 47 | +----------+ 48 | | count(*) | 49 | +----------+ 50 | | 19258 | 51 | +----------+ 52 | 53 | 54 | ### Biggest Packages 55 | 56 | start n=node(0) match n-[:ALL_PACKAGES]->()-[]->p-[:IN_PACKAGE]-() return p,count(*) order by count(*) desc limit 10 57 | +--------------------------------------------------------------------------+ 58 | | p | count(*) | 59 | +--------------------------------------------------------------------------+ 60 | | Node[313]{name->"javax.swing"} | 494 | 61 | | Node[303]{name->"com.apple.laf"} | 411 | 62 | | Node[194570]{name->"sun.awt.X11"} | 403 | 63 | | Node[308]{name->"javax.swing.plaf.basic"} | 343 | 64 | +--------------------------------------------------------------------------+ 65 | 66 | ### Biggest Top-Level-Packages 67 | 68 | start n=node(0) match n-[:PACKAGE_TREE]->m-->p-[*0..5]->()-[:IN_PACKAGE]->c return p.name,count(c) order by count(c) desc limit 10 69 | +----------------------+ 70 | | p.name | count(c) | 71 | +----------------------+ 72 | | "sun" | 4292 | 73 | | "javax" | 3455 | 74 | | "java" | 2854 | 75 | | "com" | 1696 | 76 | | "org" | 736 | 77 | | "apple" | 60 | 78 | | "default" | 29 | 79 | | "sunw" | 3 | 80 | +----------------------+ 81 | 82 | 83 | ### Top Used 84 | 85 | start n=node(0) match n-[:ALL_TYPES]->t-[:TYPE]->c<-[:FIELD_TYPE|PARAM_TYPE]-() return c,count(*) order by count(*) desc limit 10 86 | +----------------------------------------------------------+ 87 | | c | count(*) | 88 | +----------------------------------------------------------+ 89 | | Node[17]{name->"int"} | 59920 | 90 | | Node[23]{name->"java/lang/String"} | 41002 | 91 | | Node[10]{name->"java/lang/Object",access->33} | 23268 | 92 | .... 93 | | Node[15]{name->"java/lang/Class"} | 2833 | 94 | .... 95 | +----------------------------------------------------------+ 96 | 97 | ### Top inherited 98 | 99 | start n=node(0) match n-[:ALL_TYPES]->t-[:TYPE]->c<-[:SUPER_TYPE]-() return c,count(*) order by count(*) desc limit 10 100 | +--------------------------------------------------------------------------------------------+ 101 | | c | count(*) | 102 | +--------------------------------------------------------------------------------------------+ 103 | | Node[10]{name->"java/lang/Object",access->33} | 10007 | 104 | | Node[12551]{access->1057,name->"java/util/ListResourceBundle"} | 443 | 105 | | Node[1004]{name->"java/lang/Enum",access->1057} | 208 | 106 | | Node[240976]{access->1057,name->"sun/util/resources/LocaleNamesBundle"} | 184 | 107 | | Node[12367]{name->"java/lang/Exception"} | 124 | 108 | | Node[194573]{access->1056,name->"sun/awt/X11/XWrapperBase"} | 108 | 109 | | Node[3137]{name->"java/lang/RuntimeException"} | 89 | 110 | | Node[4656]{access->1057,name->"javax/swing/AbstractAction"} | 70 | 111 | | Node[36898]{name->"javax/swing/plaf/nimbus/AbstractRegionPainter",access->1057} | 59 | 112 | | Node[1022]{name->"java/io/IOException"} | 56 | 113 | +--------------------------------------------------------------------------------------------+ 114 | 115 | 116 | 117 | ### Collaborative filtering 118 | 119 | Which other classes were used by users of this class (1022 = IOException) 120 | 121 | start c=node(1022) match c<--()-->other return other,count(*) order by count(*) desc limit 20 122 | +--------------------------------------------------------------------------------+ 123 | | other | count(*) | 124 | +--------------------------------------------------------------------------------+ 125 | | Node[12]{name->"void"} | 5010 | 126 | | Node[17]{name->"int"} | 2791 | 127 | | Node[23]{name->"java/lang/String"} | 1687 | 128 | | Node[385]{name->"byte"} | 958 | 129 | | Node[19]{name->"boolean"} | 828 | 130 | | Node[10]{name->"java/lang/Object",access->33} | 619 | 131 | | Node[27]{name->"long"} | 505 | 132 | | Node[176]{name->"java/io/InputStream"} | 457 | 133 | | Node[1344]{name->"java/io/OutputStream"} | 369 | 134 | | Node[1023]{name->"java/lang/ClassNotFoundException"} | 352 | 135 | | Node[1021]{name->"java/io/ObjectInputStream"} | 298 | 136 | | Node[12874]{name->"org/xml/sax/SAXException"} | 280 | 137 | | Node[1318]{name->"java/io/ObjectOutputStream"} | 260 | 138 | | Node[1331]{name->"char"} | 197 | 139 | | Node[41890]{name->"javax/management/ObjectName"} | 196 | 140 | | Node[33623]{access->33,name->"javax/xml/stream/XMLStreamException"} | 194 | 141 | | Node[7283]{name->"java/net/URL"} | 178 | 142 | | Node[230034]{name->"sun/security/krb5/Asn1Exception",access->33} | 167 | 143 | | Node[142477]{name->"java/nio/file/Path"} | 165 | 144 | | Node[2274]{name->"java/io/File"} | 154 | 145 | +--------------------------------------------------------------------------------+ 146 | 147 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/data/file/FileHandler.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.data.file; 2 | 3 | import java.io.File; 4 | 5 | public class FileHandler { 6 | public void downFrom(final File file) { 7 | } 8 | 9 | public void handle(final File file) { 10 | } 11 | 12 | public void upTo(final File file) { 13 | } 14 | 15 | public void finish() { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/data/file/FileSystemVisitor.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.data.file; 2 | 3 | import java.io.FileFilter; 4 | import java.io.File; 5 | 6 | public class FileSystemVisitor implements FileFilter { 7 | int count=0; 8 | private final FileHandler fileHandler; 9 | 10 | public FileSystemVisitor(final FileHandler fileHandler, File startFile) { 11 | this.fileHandler = fileHandler; 12 | startFile.listFiles(this); 13 | } 14 | 15 | public boolean accept(final File file) { 16 | fileHandler.handle(file); 17 | count++; 18 | if (file.isDirectory()) { 19 | fileHandler.downFrom(file); 20 | file.listFiles(this); 21 | fileHandler.upTo(file); 22 | } 23 | return true; 24 | } 25 | 26 | public int getCount() { 27 | return count; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/JarFileImporter.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java; 2 | 3 | import org.neo4j.datasource.java.analyser.ClassFileIterator; 4 | import org.neo4j.datasource.java.analyser.RecordingInspector; 5 | import org.neo4j.datasource.java.declaration.neo.NeoDeclarationFactory; 6 | import org.neo4j.graphdb.GraphDatabaseService; 7 | import org.neo4j.graphdb.Transaction; 8 | import org.neo4j.kernel.EmbeddedGraphDatabase; 9 | import org.neo4j.kernel.impl.util.FileUtils; 10 | 11 | import java.io.File; 12 | import java.io.IOException; 13 | 14 | public class JarFileImporter { 15 | 16 | private final GraphDatabaseService graph; 17 | 18 | public static void main(String[] args) throws ClassNotFoundException { 19 | JarFileImporter importer = new JarFileImporter(args[0], true); 20 | importer.importJarFor(Class.forName(args[1])); 21 | importer.shutDown(); 22 | } 23 | 24 | public JarFileImporter(String databaseLocation, boolean create) { 25 | if (create) { 26 | dropNeoDb(databaseLocation); 27 | } 28 | graph = new EmbeddedGraphDatabase(databaseLocation); 29 | } 30 | 31 | public void shutDown() { 32 | graph.shutdown(); 33 | } 34 | 35 | public void importJarFor(Class type) { 36 | Transaction tx = graph.beginTx(); 37 | final RecordingInspector inspector = new RecordingInspector(); 38 | final NeoDeclarationFactory infoFactory = new NeoDeclarationFactory(graph); 39 | inspector.setDeclarationFactory(infoFactory); 40 | long count = 0; 41 | final ClassFileIterator fileIterator = new ClassFileIterator(); 42 | final String jarFileLocation = fileIterator.getJarLocationByClass(type); 43 | 44 | long time = System.currentTimeMillis(); 45 | for (final String classFileName : fileIterator.getClassFileNames(jarFileLocation)) { 46 | inspector.inspectClass(classFileName); 47 | count++; 48 | if (count % 500 == 0) { 49 | tx.success(); 50 | tx.finish(); 51 | tx = graph.beginTx(); 52 | } 53 | } 54 | tx.success(); 55 | tx.finish(); 56 | long delta = (System.currentTimeMillis() - time); 57 | System.out.println(count + " classes took " + delta + " ms."); 58 | } 59 | 60 | public static void dropNeoDb(final String neoStoreName) { 61 | File file = new File(neoStoreName); 62 | if (!file.exists()) return; 63 | try { 64 | FileUtils.deleteRecursively(file); 65 | } catch (IOException ioe) { 66 | throw new RuntimeException("Error deleting directory ", ioe); 67 | } 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/analyser/ClassFileIterator.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.analyser; 2 | 3 | import org.neo4j.data.file.FileHandler; 4 | import org.neo4j.data.file.FileSystemVisitor; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.net.URLDecoder; 9 | import java.util.Collection; 10 | import java.util.Enumeration; 11 | import java.util.LinkedList; 12 | import java.util.jar.JarEntry; 13 | import java.util.jar.JarFile; 14 | import java.net.URL; 15 | import java.net.MalformedURLException; 16 | 17 | public class ClassFileIterator { 18 | 19 | public static final int CLASS_LENGTH = ".class".length(); 20 | 21 | public void iterateJar(String jarLocation, ClassInspector classInspector) { 22 | if (jarLocation == null) throw new IllegalArgumentException("JarLocation must not be null"); 23 | for (String classFileName : getClassFileNames(jarLocation)) { 24 | classInspector.inspectClass(classFileName); 25 | } 26 | } 27 | 28 | public Iterable getClassFileNames(final String classLocation) { 29 | if (classLocation.endsWith(".jar")) // todo zip 30 | return getClassesFromJarFile(classLocation); 31 | return getClassesFromDirectory(classLocation); 32 | } 33 | 34 | private Iterable getClassesFromDirectory(final String classLocation) { 35 | final File classesDirectory = new File(classLocation); 36 | if (!classesDirectory.isDirectory()) throw new IllegalArgumentException(classLocation + " is no directory"); 37 | final ClassFileCollector classFileCollector = new ClassFileCollector(classesDirectory); 38 | new FileSystemVisitor(classFileCollector, classesDirectory); 39 | return classFileCollector.getClassFiles(); 40 | } 41 | 42 | private Iterable getClassesFromJarFile(final String classLocation) { 43 | try { 44 | final JarFile jarFile = new JarFile(classLocation); 45 | final Enumeration entries = jarFile.entries(); 46 | Collection classNames = new LinkedList(); 47 | while (entries.hasMoreElements()) { 48 | JarEntry jarEntry = entries.nextElement(); 49 | if (!jarEntry.isDirectory()) { 50 | final String classFileName = toClassFileName(jarEntry.getName()); 51 | if (classFileName != null) 52 | classNames.add(classFileName); 53 | } else { 54 | 55 | } 56 | } 57 | return classNames; 58 | } catch (IOException e) { 59 | throw new RuntimeException("Error accessing jar file " + classLocation, e); 60 | } 61 | } 62 | 63 | private String toClassFileName(final String name) { 64 | assert name != null; 65 | final String fileName = new File(name).getPath(); 66 | if (fileName.endsWith(".class")) 67 | return fileName.substring(0, fileName.length() - ".class".length()); 68 | return null; 69 | } 70 | 71 | public String getJarLocationFromClassPath(final String jarName, final String classPath) { 72 | final String[] entries = classPath.split(File.pathSeparator); 73 | for (String entry : entries) { 74 | if (entry.endsWith(jarName)) return entry; 75 | } 76 | return null; 77 | } 78 | 79 | public String getJarLocationFromClassPath(final String jarName) { 80 | return getJarLocationFromClassPath(jarName, System.getProperty("java.class.path")); 81 | } 82 | 83 | public String getJarLocationByClass(final String className) { 84 | final ClassLoader classLoader = ClassLoader.getSystemClassLoader(); 85 | final String classFileName = ClassInspectUtils.toSlashName(className) + ".class"; 86 | final URL url = classLoader.getResource(classFileName); 87 | final String path = getPathFromUrl(url); 88 | if (path.endsWith("/" + classFileName)) { 89 | final int baseLength = path.length() - classFileName.length() - 1; 90 | final String basePath = path.substring(0, baseLength); 91 | if (basePath.endsWith("!")) return basePath.substring(0, basePath.length() - 1); 92 | return basePath; 93 | } 94 | return path; 95 | } 96 | 97 | public String getPathFromUrl(final URL url) { 98 | final String path = url.getPath(); 99 | if (!path.startsWith("file:")) { 100 | return path; 101 | } else { 102 | try { 103 | return URLDecoder.decode(new URL(path).getPath()); 104 | } catch (MalformedURLException e) { 105 | throw new RuntimeException("Error parsing url " + path, e); 106 | } 107 | } 108 | } 109 | 110 | public String getJarLocationByClass(final Class className) { 111 | if (className == null) throw new IllegalArgumentException("ClassName must not be null"); 112 | return getJarLocationByClass(className.getName()); 113 | } 114 | 115 | private static class ClassFileCollector extends FileHandler { 116 | public Collection classFiles = new LinkedList(); 117 | private final String basePath; 118 | 119 | public ClassFileCollector(final File classesDirectory) { 120 | basePath = classesDirectory.getPath(); 121 | } 122 | 123 | @Override public void handle(final File file) { 124 | if (!file.isDirectory() && file.getName().endsWith(".class")) { 125 | String filePath = file.getPath(); 126 | if (filePath.startsWith(basePath)) filePath = filePath.substring(basePath.length()+1); 127 | int length = filePath.length(); 128 | classFiles.add(filePath.substring(0,length - CLASS_LENGTH)); 129 | } 130 | } 131 | 132 | public Collection getClassFiles() { 133 | return classFiles; 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/analyser/ClassFileLocator.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.analyser; 2 | 3 | import java.io.InputStream; 4 | import java.io.BufferedInputStream; 5 | import java.io.IOException; 6 | import java.io.File; 7 | import java.net.URL; 8 | import java.net.URLClassLoader; 9 | import java.net.MalformedURLException; 10 | 11 | public class ClassFileLocator { 12 | ClassLoader cl; 13 | // todo filesystem, jar files, mvn dependencies -> pom 14 | public ClassFileLocator(String path) { 15 | if (path == null) throw new IllegalArgumentException("Path must not be null"); 16 | this.cl = new URLClassLoader(pathToUrls(path), ClassLoader.getSystemClassLoader()); 17 | } 18 | 19 | private URL[] pathToUrls(final String path) { 20 | final String[] files = path.split(File.pathSeparator); 21 | URL[] urls = new URL[files.length]; 22 | for (int i = 0; i < files.length; i++) { 23 | final String file = files[i]; 24 | try { 25 | if (file.matches("^\\w://.+")) 26 | urls[i]=new URL(file); 27 | else 28 | urls[i]=new File(file).toURL(); 29 | } catch (MalformedURLException e) { 30 | throw new RuntimeException("Error creating URL from "+ file,e); 31 | } 32 | } 33 | return urls; 34 | } 35 | 36 | public InputStream getStreamFromURL(final URL url) { 37 | try { 38 | if (url==null) { 39 | return null; 40 | } 41 | return new BufferedInputStream(url.openStream()); 42 | } catch (IOException e) { 43 | throw new RuntimeException("Error reading stream from url "+url,e); 44 | } 45 | } 46 | 47 | public URL resolveClassName(final String slashClassName) { 48 | final String fileClassName = slashClassName.concat(".class"); 49 | return ClassLoader.getSystemResource(fileClassName); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/analyser/ClassInspectUtils.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.analyser; 2 | 3 | import org.neo4j.datasource.java.declaration.ClassDeclaration; 4 | import org.neo4j.datasource.java.declaration.FieldDeclaration; 5 | import org.neo4j.datasource.java.declaration.MethodDeclaration; 6 | 7 | import java.util.Collection; 8 | 9 | public class ClassInspectUtils { 10 | public static String toSlashName(final Class type) { 11 | return toSlashName(type.getName()); 12 | } 13 | 14 | public static String toSlashName(final String typeName) { 15 | return typeName.replace('.','/'); 16 | } 17 | 18 | public static String toClassName(String name) { 19 | return name.replace('/', '.'); 20 | } 21 | 22 | public static String getSignature(final MethodDeclaration methodDeclaration) { 23 | String result = methodDeclaration.getReturnType() + " " + methodDeclaration.getName() + "(" + paramList(methodDeclaration.getParams()) + ")"; 24 | Collection exceptions = methodDeclaration.getExceptions(); 25 | if (!exceptions.isEmpty()) { 26 | return result + " throws "+paramList(exceptions); 27 | } 28 | return result; 29 | } 30 | 31 | private static String paramList(final Collection params) { 32 | if (params == null || params.isEmpty()) return ""; 33 | final StringBuilder sb = new StringBuilder(); 34 | for (String param : params) { 35 | sb.append(", ").append(param); 36 | } 37 | return sb.substring(2); 38 | } 39 | 40 | public static String getSignature(final FieldDeclaration fieldDeclaration) { 41 | return fieldDeclaration.getType()+" "+ fieldDeclaration.getName(); 42 | } 43 | 44 | public static String getSignature(final ClassDeclaration classDeclaration) { 45 | StringBuilder sb = new StringBuilder(classDeclaration.getName()); 46 | final ClassDeclaration superClass = classDeclaration.getSuperClass(); 47 | if (superClass != null && !superClass.isRoot()) sb.append(" extends ").append(superClass); 48 | final Collection anInterfaces = classDeclaration.getAnInterfaces(); 49 | if (!anInterfaces.isEmpty()) 50 | sb.append("implements ").append(anInterfaces); 51 | return sb.toString(); 52 | } 53 | 54 | public static String getClassPath() { 55 | return System.getProperty("java.class.path"); 56 | } 57 | 58 | public static String arrayToClassName(String typeName) { 59 | if (isArrayType(typeName)) typeName=typeName.substring(0,typeName.length()-2); 60 | return typeName; 61 | } 62 | 63 | public static boolean isArrayType(final String typeName) { 64 | return typeName.endsWith("[]"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/analyser/ClassInspector.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.analyser; 2 | 3 | import org.objectweb.asm.ClassReader; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.net.URL; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | public abstract class ClassInspector { 12 | ClassFileLocator classFileLocator; // todo 13 | private final Map classes = new HashMap(500); 14 | 15 | public ClassInspector(final String classPath) { 16 | if (classPath == null) throw new IllegalArgumentException("ClassPath must not be null"); 17 | classFileLocator = new ClassFileLocator(classPath); 18 | } 19 | 20 | public R inspectClass(Class type) { 21 | if (type == null) throw new IllegalArgumentException("Type must not be null"); 22 | return inspectClass(ClassInspectUtils.toSlashName(type)); 23 | } 24 | 25 | public R inspectClass(String slashClassName) { 26 | if (slashClassName == null) throw new IllegalArgumentException("SlashClassName must not be null"); 27 | if (classes.containsKey(slashClassName)) { 28 | return classes.get(slashClassName); 29 | } 30 | ClassReader classReader = createClassReader(slashClassName); 31 | if (classReader==null) return null; 32 | final RecursingClassVisitor classVisitor = createVisitor(); 33 | classReader.accept(classVisitor, 0); 34 | classes.put(slashClassName, classVisitor.get()); 35 | return classVisitor.get(); 36 | } 37 | 38 | protected abstract RecursingClassVisitor createVisitor(); 39 | 40 | private ClassReader createClassReader(final String slashClassName) { 41 | assert slashClassName != null; 42 | URL classResource = classFileLocator.resolveClassName(slashClassName); 43 | try { 44 | InputStream streamFromURL = classFileLocator.getStreamFromURL(classResource); 45 | if (streamFromURL==null) { 46 | System.err.println("File not found for "+slashClassName); 47 | return null; 48 | } 49 | return new ClassReader(streamFromURL); 50 | } catch (IOException e) { 51 | throw new RuntimeException("Error creating ClassReader for class " + slashClassName); 52 | } 53 | } 54 | 55 | public Map getClasses() { 56 | return classes; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/analyser/NullClassVisitor.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.analyser; 2 | 3 | import org.objectweb.asm.ClassAdapter; 4 | import org.objectweb.asm.ClassWriter; 5 | import org.objectweb.asm.FieldVisitor; 6 | import org.objectweb.asm.MethodVisitor; 7 | 8 | public class NullClassVisitor extends ClassAdapter implements RecursingClassVisitor { 9 | private static final ClassWriter NULL_WRITER = new ClassWriter(0); 10 | 11 | public NullClassVisitor() { 12 | super(NULL_WRITER); 13 | } 14 | 15 | @Override 16 | public void visit(int version, int access, String name, String signature, 17 | String superName, String[] interfaces) { 18 | } 19 | 20 | @Override 21 | public MethodVisitor visitMethod(int access, String name, String desc, 22 | String signature, String[] exceptions) { 23 | return null; 24 | } 25 | 26 | @Override public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { 27 | return null; 28 | } 29 | 30 | public Void get() { 31 | return null; 32 | } 33 | } -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/analyser/RecordingClassVisitor.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.analyser; 2 | 3 | import org.neo4j.datasource.java.declaration.ClassDeclaration; 4 | import org.neo4j.datasource.java.declaration.DeclarationFactory; 5 | import org.neo4j.datasource.java.declaration.FieldDeclaration; 6 | import org.neo4j.datasource.java.declaration.MethodDeclaration; 7 | import org.objectweb.asm.*; 8 | 9 | import java.util.Collection; 10 | import java.util.ArrayList; 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | import static java.util.Arrays.asList; 15 | 16 | public class RecordingClassVisitor extends ClassAdapter implements RecursingClassVisitor { 17 | private ClassDeclaration classDeclaration; 18 | private final ClassInspector classInspector; 19 | private final DeclarationFactory declarationFactory; 20 | private static final ClassWriter NULL_WRITER = new ClassWriter(0); 21 | 22 | public RecordingClassVisitor(ClassInspector classInspector, final DeclarationFactory declarationFactory) { 23 | super(NULL_WRITER); 24 | this.classInspector = classInspector; 25 | this.declarationFactory = declarationFactory; 26 | } 27 | 28 | @Override 29 | public void visit(int version, int access, String name, String signature, 30 | String superName, String[] interfaces) { 31 | if (classDeclaration == null) classDeclaration = declarationFactory.createClassInfo(name,access); 32 | if (superName != null) { // todo filter 33 | classDeclaration.setSuperClass(classInspector.inspectClass(superName)); 34 | } 35 | if (interfaces != null) { 36 | for (String interfaceName : interfaces) { 37 | classDeclaration.addInterface(classInspector.inspectClass(interfaceName)); 38 | } 39 | } 40 | } 41 | 42 | @Override 43 | public MethodVisitor visitMethod(int access, String name, String desc, 44 | String signature, String[] exceptions) { 45 | final Collection params = getParamTypes(desc); 46 | final String returnType = getReturnType(desc); 47 | List exceptionList = exceptions == null ? Collections.emptyList() : asList(exceptions); 48 | final MethodDeclaration methodDeclaration = declarationFactory.createMethodInfo(access, name, params, returnType, exceptionList); 49 | classDeclaration.addMethod(methodDeclaration); 50 | return null; 51 | } 52 | 53 | 54 | 55 | @Override public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { 56 | final String typeName = Type.getType(desc).getClassName(); 57 | final FieldDeclaration fieldDeclaration = declarationFactory.createFieldInfo(access, name, typeName); 58 | classDeclaration.addField(fieldDeclaration); 59 | return null; 60 | } 61 | 62 | private Collection getParamTypes(final String desc) { 63 | Collection params=new ArrayList(); 64 | for (Type paramType : Type.getArgumentTypes(desc)) { 65 | params.add(paramType.getClassName()); 66 | } 67 | return params; 68 | } 69 | 70 | private String getReturnType(final String desc) { 71 | final Type returnType = Type.getReturnType(desc); 72 | return returnType.getClassName(); 73 | } 74 | 75 | public ClassDeclaration get() { 76 | return classDeclaration; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/analyser/RecordingInspector.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.analyser; 2 | 3 | import org.neo4j.datasource.java.declaration.ClassDeclaration; 4 | import org.neo4j.datasource.java.declaration.DeclarationFactory; 5 | import org.neo4j.datasource.java.declaration.bean.BeanDeclarationFactory; 6 | 7 | import static org.neo4j.datasource.java.analyser.ClassInspectUtils.getClassPath; 8 | 9 | public class RecordingInspector extends ClassInspector { 10 | private DeclarationFactory declarationFactory; 11 | 12 | public RecordingInspector() { 13 | this(getClassPath()); 14 | } 15 | 16 | public RecordingInspector(final String classPath) { 17 | super(classPath); 18 | declarationFactory = new BeanDeclarationFactory(); 19 | } 20 | 21 | public void setDeclarationFactory(final DeclarationFactory declarationFactory) { 22 | if (declarationFactory == null) throw new IllegalArgumentException("InfoFactory must not be null"); 23 | this.declarationFactory = declarationFactory; 24 | } 25 | 26 | protected RecursingClassVisitor createVisitor() { 27 | return new RecordingClassVisitor(this, declarationFactory); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/analyser/RecursingClassVisitor.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.analyser; 2 | 3 | import org.objectweb.asm.ClassVisitor; 4 | 5 | public interface RecursingClassVisitor extends ClassVisitor { 6 | R get(); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/analyser/VirtualVisitor.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.analyser; 2 | 3 | import org.objectweb.asm.ClassVisitor; 4 | 5 | import java.lang.reflect.InvocationHandler; 6 | import java.lang.reflect.Method; 7 | import java.lang.reflect.Proxy; 8 | import java.util.Arrays; 9 | 10 | public class VirtualVisitor implements InvocationHandler { 11 | private final ClassInspector classInspector; 12 | private final int indent; 13 | 14 | public VirtualVisitor(final ClassInspector classInspector, final int indent) { 15 | this.classInspector = classInspector; 16 | this.indent = indent; 17 | } 18 | 19 | public static T visitor(Class visitorType, ClassInspector classInspector, final int indent) { 20 | return visitorType.cast(Proxy.newProxyInstance(visitorType.getClassLoader(), new Class[]{visitorType}, new VirtualVisitor(classInspector, indent))); 21 | } 22 | 23 | public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { 24 | if (args != null) 25 | System.out.println(indent() + method.getName() + " " + Arrays.deepToString(args)); 26 | if (method.getDeclaringClass().equals(ClassVisitor.class) && method.getName().equals("visit")) { 27 | if (args != null && args.length == 6) { 28 | if (args[4] instanceof String) classInspector.inspectClass(args[4].toString()); 29 | if (args[5] instanceof String[]) { 30 | for (String interfaceName : (String[]) args[5]) { 31 | classInspector.inspectClass(interfaceName); 32 | } 33 | } 34 | } 35 | } 36 | final Class returnType = method.getReturnType(); 37 | if (returnType.isInterface()) { 38 | return visitor(returnType, classInspector, indent + 1); 39 | } 40 | return null; 41 | } 42 | 43 | private String indent() { 44 | if (indent == 0) return ""; 45 | final StringBuilder sb = new StringBuilder(indent * 2); 46 | for (int i = 0; i < indent; i++) { 47 | sb.append(" "); 48 | } 49 | return sb.toString(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/analyser/stats/DefaultStatistics.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.analyser.stats; 2 | 3 | import java.util.EnumMap; 4 | import java.util.Map; 5 | 6 | public class DefaultStatistics> implements Statistics { 7 | private final Map infos; 8 | 9 | public DefaultStatistics(final Class tokenType) { 10 | infos = new EnumMap(tokenType); 11 | for (E token : tokenType.getEnumConstants()) { 12 | infos.put(token, new TimeInfo(token.name())); 13 | } 14 | } 15 | 16 | public void reset(final E token) { 17 | infos.get(token).reset(); 18 | } 19 | 20 | public void addTotal(final E token) { 21 | infos.get(token).addTotal(); 22 | } 23 | 24 | public void inc(final E token) { 25 | infos.get(token).inc(); 26 | } 27 | 28 | public String toString(final E token) { 29 | return infos.get(token).toString(); 30 | } 31 | 32 | public void done(final E token) { 33 | final TimeInfo timeInfo = infos.get(token); 34 | if (timeInfo.addTotal() != -1) { 35 | timeInfo.inc(); 36 | } 37 | } 38 | 39 | static class TimeInfo { 40 | private long start; 41 | private int count; 42 | private long delta; 43 | private long totalInMillis; 44 | 45 | private final String token; 46 | 47 | public TimeInfo(final String token) { 48 | this.token = token; 49 | } 50 | 51 | public void start() { 52 | start = System.currentTimeMillis(); 53 | } 54 | 55 | public void reset() { 56 | start = -1; 57 | } 58 | 59 | public long addTotal() { 60 | delta=-1; 61 | if (start >= 0) { 62 | delta = (System.currentTimeMillis() - start); 63 | totalInMillis += delta; 64 | } 65 | return delta; 66 | } 67 | 68 | public void inc() { 69 | count++; 70 | } 71 | 72 | public String toString() { 73 | return String.format("%s: last %d ms total: %d ms / %d = %.2f ms ", 74 | token, delta, totalInMillis, count, (float) totalInMillis / count); 75 | } 76 | } 77 | 78 | public void start(final E token) { 79 | infos.get(token).start(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/analyser/stats/NullStatistics.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.analyser.stats; 2 | 3 | public class NullStatistics> implements Statistics { 4 | public void reset(final Enum token) { 5 | } 6 | 7 | public void addTotal(final Enum token) { 8 | } 9 | 10 | public void inc(final Enum token) { 11 | } 12 | 13 | public String toString(final Enum token) { 14 | return ""; 15 | } 16 | 17 | public void done(final Enum token) { 18 | } 19 | 20 | public void start(final Enum token) { 21 | } 22 | 23 | @Override public String toString() { 24 | return ""; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/analyser/stats/Statistics.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.analyser.stats; 2 | 3 | public interface Statistics> { 4 | void reset(E token); 5 | 6 | void addTotal(E token); 7 | 8 | void inc(E token); 9 | 10 | String toString(E token); 11 | 12 | void done(E token); 13 | 14 | void start(E token); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/ClassDeclaration.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration; 2 | 3 | import java.util.Map; 4 | import java.util.Collection; 5 | 6 | public interface ClassDeclaration { 7 | int getId(); 8 | 9 | String getName(); 10 | 11 | Map getMethods(); 12 | 13 | void addMethod(MethodDeclaration methodDeclaration); 14 | 15 | void addInterface(ClassDeclaration classDeclaration); 16 | 17 | void setSuperClass(ClassDeclaration classDeclaration); 18 | 19 | ClassDeclaration getSuperClass(); 20 | 21 | Collection getAnInterfaces(); 22 | 23 | void addField(FieldDeclaration fieldDeclaration); 24 | 25 | Map getFields(); 26 | 27 | boolean isRoot(); 28 | 29 | String getPackage(); 30 | String getSimpleName(); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/DeclarationFactory.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration; 2 | 3 | import java.util.Collection; 4 | 5 | public interface DeclarationFactory { 6 | ClassDeclaration createClassInfo(String name, int access); 7 | 8 | MethodDeclaration createMethodInfo(int access, String name, Collection params, String returnType, Collection exceptions); 9 | 10 | FieldDeclaration createFieldInfo(int access, String name, String typeName); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/FieldDeclaration.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration; 2 | 3 | public interface FieldDeclaration { 4 | int getAccess(); 5 | 6 | String getName(); 7 | 8 | String getType(); 9 | 10 | String getSignature(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/MethodDeclaration.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration; 2 | 3 | import java.util.Collection; 4 | 5 | public interface MethodDeclaration { 6 | String getName(); 7 | 8 | String getReturnType(); 9 | 10 | int getAccess(); 11 | 12 | String getSignature(); 13 | 14 | Collection getParams(); 15 | 16 | Collection getExceptions(); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/PackageDeclaration.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration; 2 | 3 | import java.util.Collection; 4 | import java.util.Map; 5 | 6 | public interface PackageDeclaration { 7 | int getId(); 8 | String getName(); 9 | 10 | String getSuperPackage(); 11 | 12 | boolean isRoot(); 13 | } -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/bean/BeanDeclarationFactory.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration.bean; 2 | 3 | import org.neo4j.datasource.java.declaration.*; 4 | import org.neo4j.datasource.java.declaration.DeclarationFactory; 5 | import org.neo4j.datasource.java.declaration.FieldDeclaration; 6 | import org.neo4j.datasource.java.declaration.MethodDeclaration; 7 | 8 | import java.util.Collection; 9 | 10 | public class BeanDeclarationFactory implements DeclarationFactory { 11 | private int id=2; 12 | 13 | public ClassDeclaration createClassInfo(final String name, int access) { 14 | return new ClassDeclarationBean(name,id++); 15 | } 16 | 17 | public MethodDeclaration createMethodInfo(final int access, final String name, final Collection params, final String returnType, Collection exceptions) { 18 | return new MethodDeclarationBean(access, name, returnType, params,exceptions); 19 | } 20 | 21 | public FieldDeclaration createFieldInfo(final int access, final String name, final String typeName) { 22 | return new FieldDeclarationBean(access,name, typeName); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/bean/ClassDeclarationBean.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration.bean; 2 | 3 | import org.neo4j.datasource.java.analyser.ClassInspectUtils; 4 | import org.neo4j.datasource.java.declaration.ClassDeclaration; 5 | import org.neo4j.datasource.java.declaration.FieldDeclaration; 6 | import org.neo4j.datasource.java.declaration.MethodDeclaration; 7 | 8 | import java.io.Serializable; 9 | import java.util.Collection; 10 | import java.util.HashMap; 11 | import java.util.LinkedList; 12 | import java.util.Map; 13 | 14 | public class ClassDeclarationBean implements ClassDeclaration, Serializable { 15 | private final String name; 16 | private final Map methods = new HashMap(20); 17 | private ClassDeclaration superClass; 18 | private final Collection anInterfaces = new LinkedList(); 19 | private Map fieldInfos = new HashMap(15); 20 | private int id; 21 | 22 | public ClassDeclarationBean(final String name) { 23 | if (name == null) throw new IllegalArgumentException("Name must not be null"); 24 | this.name = ClassInspectUtils.toClassName(name); 25 | } 26 | 27 | public ClassDeclarationBean(final String name, int id) { 28 | this(name); 29 | this.id=id; 30 | } 31 | 32 | public int getId() { 33 | return id; 34 | } 35 | 36 | public String getName() { 37 | return name; 38 | } 39 | 40 | public String getSlashName() { 41 | return ClassInspectUtils.toSlashName(name); 42 | } 43 | 44 | public Map getMethods() { 45 | return methods; 46 | } 47 | 48 | public void addMethod(MethodDeclaration methodDeclaration) { 49 | methods.put(methodDeclaration.getSignature(), methodDeclaration); 50 | } 51 | 52 | public void addInterface(final ClassDeclaration classDeclaration) { 53 | anInterfaces.add(classDeclaration); 54 | } 55 | 56 | public void setSuperClass(final ClassDeclaration classDeclaration) { 57 | this.superClass = classDeclaration; 58 | } 59 | 60 | public ClassDeclaration getSuperClass() { 61 | return superClass; 62 | } 63 | 64 | public Collection getAnInterfaces() { 65 | return anInterfaces; 66 | } 67 | 68 | public boolean equals(final Object o) { 69 | if (this == o) return true; 70 | if (o == null || getClass() != o.getClass()) return false; 71 | 72 | final ClassDeclarationBean classInfo = (ClassDeclarationBean) o; 73 | 74 | return name.equals(classInfo.name); 75 | 76 | } 77 | 78 | public int hashCode() { 79 | return name.hashCode(); 80 | } 81 | 82 | public void addField(final FieldDeclaration fieldDeclaration) { 83 | fieldInfos.put(fieldDeclaration.getName(), fieldDeclaration); 84 | } 85 | 86 | public Map getFields() { 87 | return fieldInfos; 88 | } 89 | 90 | @Override public String toString() { 91 | StringBuilder sb = new StringBuilder(name); 92 | if (superClass != null && !superClass.isRoot()) sb.append(" extends ").append(superClass); 93 | if (!anInterfaces.isEmpty()) 94 | sb.append("implements ").append(anInterfaces); 95 | return sb.toString(); 96 | } 97 | 98 | public boolean isRoot() { 99 | return name.equals("java.lang.Object"); 100 | } 101 | 102 | @Override 103 | public String getPackage() { 104 | return name.substring(0,name.lastIndexOf(".")); 105 | } 106 | public String getSimpleName() { 107 | return name.substring(name.lastIndexOf(".")+1); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/bean/FieldDeclarationBean.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration.bean; 2 | 3 | import org.neo4j.datasource.java.analyser.ClassInspectUtils; 4 | import org.neo4j.datasource.java.declaration.FieldDeclaration; 5 | 6 | import java.lang.reflect.Modifier; 7 | import java.io.Serializable; 8 | 9 | public class FieldDeclarationBean implements FieldDeclaration, Serializable { 10 | private final int access; 11 | private final String name; 12 | private final String type; 13 | 14 | public FieldDeclarationBean(final int access, final String name, final String type) { 15 | this.access = access; 16 | this.name = name; 17 | this.type = type; 18 | } 19 | 20 | public int getAccess() { 21 | return access; 22 | } 23 | 24 | public String getName() { 25 | return name; 26 | } 27 | 28 | public String getType() { 29 | return type; 30 | } 31 | 32 | @Override public String toString() { 33 | return Modifier.toString(access)+" "+ getSignature()+"\n"; 34 | } 35 | 36 | public String getSignature() { 37 | return ClassInspectUtils.getSignature(this); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/bean/MethodDeclarationBean.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration.bean; 2 | 3 | import org.neo4j.datasource.java.analyser.ClassInspectUtils; 4 | import org.neo4j.datasource.java.declaration.MethodDeclaration; 5 | 6 | import java.lang.reflect.Modifier; 7 | import java.util.Collection; 8 | import java.io.Serializable; 9 | 10 | public class MethodDeclarationBean implements MethodDeclaration, Serializable { 11 | private final String name; 12 | private final Collection params; 13 | private final Collection exceptions; 14 | private final String returnType; 15 | private final int access; 16 | 17 | public MethodDeclarationBean(int access, String name, String returnType, final Collection params, Collection exceptions) { 18 | this.access = access; 19 | this.returnType = returnType; 20 | this.name = name; 21 | this.params = params; 22 | this.exceptions = exceptions; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public String getReturnType() { 30 | return returnType; 31 | } 32 | 33 | public int getAccess() { 34 | return access; 35 | } 36 | 37 | public Collection getParams() { 38 | return params; 39 | } 40 | 41 | @Override 42 | public Collection getExceptions() { 43 | return exceptions; 44 | } 45 | 46 | @Override public String toString() { 47 | return Modifier.toString(access) + " " + getSignature() + "\n"; 48 | } 49 | 50 | public String getSignature() { 51 | return ClassInspectUtils.getSignature(this); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/bean/PackageDeclarationBean.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration.bean; 2 | 3 | import org.neo4j.datasource.java.declaration.PackageDeclaration; 4 | 5 | /** 6 | * @author Michael Hunger 7 | * @since 07.10.2009 8 | */ 9 | public class PackageDeclarationBean implements PackageDeclaration { 10 | private final int id; 11 | private final String name; 12 | 13 | public PackageDeclarationBean(String name, int id) { 14 | this.name = name; 15 | this.id = id; 16 | } 17 | 18 | @Override 19 | public int getId() { 20 | return id; 21 | } 22 | 23 | @Override 24 | public String getName() { 25 | return name; 26 | } 27 | 28 | @Override 29 | public boolean equals(Object o) { 30 | if (this == o) return true; 31 | if (o == null || getClass() != o.getClass()) return false; 32 | 33 | return name.equals(((PackageDeclarationBean) o).name); 34 | 35 | } 36 | 37 | @Override 38 | public int hashCode() { 39 | return name.hashCode(); 40 | } 41 | 42 | @Override 43 | public String getSuperPackage() { 44 | int idx=name.indexOf('.'); 45 | if (idx==-1) return null; 46 | return name.substring(0,idx); 47 | } 48 | 49 | @Override 50 | public boolean isRoot() { 51 | return name.indexOf('.')==-1; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return name+" "+id; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/neo/ClassRelations.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration.neo; 2 | 3 | import org.neo4j.graphdb.RelationshipType; 4 | 5 | /** 6 | * @author mh14 @ jexp.de 7 | * @since 27.09.2008 16:31:45 (c) 2008 jexp.de 8 | */ 9 | public enum ClassRelations implements RelationshipType { 10 | METHOD_OF, OF_TYPE, RETURN_TYPE, PARAM_TYPE, FIELD_TYPE, FIELD_OF, ALL_TYPES, TYPE, INTERFACE_TYPE, SUPER_TYPE, TYPE_ARRAY, THROWS, ALL_PACKAGES, PACKAGE_TREE, IN_PACKAGE; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/neo/MapNodeCache.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration.neo; 2 | 3 | import org.neo4j.graphdb.Node; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | import java.util.concurrent.ConcurrentHashMap; 8 | 9 | public class MapNodeCache implements NodeCache { 10 | private final Map typeNodes = new HashMap (1000); 11 | private int hits; 12 | 13 | public Node getCachedNode(final String typeName) { 14 | final Node node = typeNodes.get(typeName); 15 | if (node != null) hits++; 16 | return node; 17 | } 18 | 19 | public void cacheNode(final String typeName, final Node newTypeNode) { 20 | typeNodes.put(typeName, newTypeNode); 21 | } 22 | 23 | @Override public String toString() { 24 | return "size " + typeNodes.size() + " hits " + hits; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/neo/NeoClassDeclaration.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration.neo; 2 | 3 | import org.neo4j.datasource.java.analyser.ClassInspectUtils; 4 | import org.neo4j.datasource.java.declaration.ClassDeclaration; 5 | import org.neo4j.datasource.java.declaration.FieldDeclaration; 6 | import org.neo4j.datasource.java.declaration.MethodDeclaration; 7 | import org.neo4j.graphdb.Direction; 8 | import org.neo4j.graphdb.Node; 9 | import org.neo4j.graphdb.Relationship; 10 | 11 | import java.util.*; 12 | 13 | public class NeoClassDeclaration implements ClassDeclaration { 14 | private final Node node; 15 | 16 | public NeoClassDeclaration(final Node node) { 17 | this.node = node; 18 | } 19 | 20 | @Override 21 | public int getId() { 22 | throw new UnsupportedOperationException(); 23 | } 24 | 25 | @Override 26 | public String getPackage() { 27 | throw new UnsupportedOperationException(); 28 | } 29 | 30 | public String getName() { 31 | return (String) node.getProperty("name"); 32 | } 33 | 34 | public Map getMethods() { 35 | final Iterable methods = node.getRelationships(ClassRelations.METHOD_OF, Direction.OUTGOING); 36 | Map methodInfos = new HashMap(); 37 | for (Relationship method : methods) { 38 | final NeoMethodDeclaration methodInfo = new NeoMethodDeclaration(method.getEndNode()); 39 | methodInfos.put(methodInfo.getSignature(), methodInfo); 40 | } 41 | return methodInfos; 42 | } 43 | 44 | public void addMethod(final MethodDeclaration methodDeclaration) { 45 | final Node methodNode = ((NeoMethodDeclaration) methodDeclaration).getNode(); 46 | node.createRelationshipTo(methodNode, ClassRelations.METHOD_OF); 47 | //methodNode.createRelationshipTo(node, ClassRelations.METHOD_OF); 48 | } 49 | 50 | public void addInterface(final ClassDeclaration classDeclaration) { 51 | final Node interfaceNode = ((NeoClassDeclaration) classDeclaration).getNode(); 52 | node.createRelationshipTo(interfaceNode, ClassRelations.INTERFACE_TYPE); 53 | // interfaceNode.createRelationshipTo(node,ClassRelations.INTERFACE_TYPE); 54 | } 55 | 56 | public void setSuperClass(final ClassDeclaration classDeclaration) { 57 | final Node superNode = ((NeoClassDeclaration) classDeclaration).getNode(); 58 | node.createRelationshipTo(superNode, ClassRelations.SUPER_TYPE); 59 | // superNode.createRelationshipTo(node,ClassRelations.SUPER_TYPE); 60 | } 61 | 62 | public ClassDeclaration getSuperClass() { 63 | final Relationship superType = getNode().getSingleRelationship(ClassRelations.SUPER_TYPE, Direction.OUTGOING); 64 | if (superType==null) return null; 65 | return new NeoClassDeclaration(superType.getEndNode()); 66 | } 67 | 68 | public Collection getAnInterfaces() { 69 | final Iterable interfaces = node.getRelationships(ClassRelations.INTERFACE_TYPE, Direction.OUTGOING); 70 | Collection result=new LinkedList(); 71 | for (Relationship interfaceRelationship : interfaces) { 72 | result.add(new NeoClassDeclaration(interfaceRelationship.getEndNode())); 73 | } 74 | return result; 75 | } 76 | 77 | public void addField(final FieldDeclaration fieldDeclaration) { 78 | final Node fieldNode = ((NeoFieldDeclaration) fieldDeclaration).getNode(); 79 | node.createRelationshipTo(fieldNode, ClassRelations.FIELD_OF); 80 | //fieldNode.createRelationshipTo(node, ClassRelations.FIELD); 81 | } 82 | 83 | public Map getFields() { 84 | final Iterable fields = node.getRelationships(ClassRelations.FIELD_OF, Direction.OUTGOING); 85 | Map fieldInfos = new HashMap(); 86 | for (Relationship field : fields) { 87 | final NeoFieldDeclaration fieldInfo = new NeoFieldDeclaration(field.getEndNode()); 88 | fieldInfos.put(fieldInfo.getSignature(), fieldInfo); 89 | } 90 | return fieldInfos; 91 | } 92 | 93 | public boolean isRoot() { 94 | return false; 95 | } 96 | 97 | public Node getNode() { 98 | return node; 99 | } 100 | 101 | @Override public String toString() { 102 | return ClassInspectUtils.getSignature(this); 103 | } 104 | 105 | @Override 106 | public String getSimpleName() { 107 | return null; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/neo/NeoDeclarationFactory.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration.neo; 2 | 3 | 4 | import org.neo4j.datasource.java.analyser.ClassInspectUtils; 5 | import org.neo4j.datasource.java.declaration.ClassDeclaration; 6 | import org.neo4j.datasource.java.declaration.DeclarationFactory; 7 | import org.neo4j.datasource.java.declaration.FieldDeclaration; 8 | import org.neo4j.datasource.java.declaration.MethodDeclaration; 9 | import org.neo4j.graphdb.GraphDatabaseService; 10 | import org.neo4j.graphdb.Node; 11 | 12 | import java.util.Collection; 13 | 14 | public class NeoDeclarationFactory implements DeclarationFactory { 15 | private final GraphDatabaseService graph; 16 | private TypeNodeFinder typeNodeFinder; 17 | 18 | public NeoDeclarationFactory(final GraphDatabaseService graph) { 19 | this.graph = graph; 20 | typeNodeFinder = new TypeNodeFinder(graph); 21 | } 22 | 23 | public ClassDeclaration createClassInfo(final String name, int access) { 24 | final Node typeNode = typeNodeFinder.getOrCreateTypeNode(name,access); 25 | return new NeoClassDeclaration(typeNode); 26 | } 27 | 28 | public MethodDeclaration createMethodInfo(final int access, final String name, final Collection params, final String returnType, Collection exceptions) { 29 | final Node methodNode = graph.createNode(); 30 | methodNode.setProperty("access", access); 31 | methodNode.setProperty("name", name); 32 | //System.out.println("returnType = " + returnType); 33 | final Node returnTypeNode = typeNodeFinder.getOrCreateTypeNode(returnType); 34 | methodNode.createRelationshipTo(returnTypeNode, ClassRelations.RETURN_TYPE); 35 | if (ClassInspectUtils.isArrayType(returnType)) { 36 | methodNode.createRelationshipTo(returnTypeNode, ClassRelations.TYPE_ARRAY); 37 | } 38 | for (String paramName : params) { 39 | final Node paramNode = typeNodeFinder.getOrCreateTypeNode(paramName); 40 | // todo paramNodes, array params 41 | methodNode.createRelationshipTo(paramNode, ClassRelations.PARAM_TYPE); 42 | } 43 | for (String exception : exceptions) { 44 | final Node paramNode = typeNodeFinder.getOrCreateTypeNode(exception); 45 | methodNode.createRelationshipTo(paramNode, ClassRelations.THROWS); 46 | } 47 | final NeoMethodDeclaration methodInfo = new NeoMethodDeclaration(methodNode); 48 | methodInfo.setSignature(returnType + " " + name + "(" + params + ") throws "+exceptions); 49 | return methodInfo; 50 | } 51 | 52 | public FieldDeclaration createFieldInfo(final int access, final String name, final String typeName) { 53 | final Node fieldNode = graph.createNode(); 54 | fieldNode.setProperty("access", access); 55 | fieldNode.setProperty("name", name); 56 | // System.out.println("typeName = " + typeName); 57 | final Node typeNode = typeNodeFinder.getOrCreateTypeNode(typeName); 58 | fieldNode.createRelationshipTo(typeNode, ClassRelations.FIELD_TYPE); 59 | if (ClassInspectUtils.isArrayType(typeName)) 60 | fieldNode.createRelationshipTo(typeNode, ClassRelations.TYPE_ARRAY); 61 | 62 | final NeoFieldDeclaration fieldInfo = new NeoFieldDeclaration(fieldNode); 63 | fieldInfo.setSignature(typeName+" "+name); 64 | return fieldInfo; 65 | } 66 | 67 | @Override public String toString() { 68 | return "NeoInfoFactory: "+typeNodeFinder.toString(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/neo/NeoFieldDeclaration.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration.neo; 2 | 3 | import org.neo4j.datasource.java.analyser.ClassInspectUtils; 4 | import org.neo4j.datasource.java.declaration.FieldDeclaration; 5 | import org.neo4j.graphdb.Direction; 6 | import org.neo4j.graphdb.Node; 7 | import org.neo4j.graphdb.Relationship; 8 | 9 | public class NeoFieldDeclaration implements FieldDeclaration { 10 | Node node; 11 | private transient String signature; 12 | 13 | public NeoFieldDeclaration(Node node) { 14 | this.node = node; 15 | } 16 | 17 | public int getAccess() { 18 | return (Integer)node.getProperty("access"); 19 | } 20 | 21 | public String getName() { 22 | return (String) node.getProperty("name"); 23 | } 24 | 25 | public String getType() { 26 | final Relationship typeRelation = node.getSingleRelationship(ClassRelations.FIELD_TYPE, Direction.OUTGOING); 27 | return new NeoClassDeclaration(typeRelation.getEndNode()).getName(); 28 | } 29 | 30 | public String getSignature() { 31 | if (signature==null) signature= ClassInspectUtils.getSignature(this); 32 | return signature; 33 | } 34 | 35 | public Node getNode() { 36 | return node; 37 | } 38 | 39 | public void setSignature(final String signature) { 40 | this.signature = signature; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/neo/NeoMethodDeclaration.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration.neo; 2 | 3 | import org.neo4j.datasource.java.analyser.ClassInspectUtils; 4 | import org.neo4j.datasource.java.declaration.MethodDeclaration; 5 | import org.neo4j.graphdb.Direction; 6 | import org.neo4j.graphdb.Node; 7 | import org.neo4j.graphdb.Relationship; 8 | 9 | import java.util.Collection; 10 | import java.util.LinkedList; 11 | 12 | public class NeoMethodDeclaration implements MethodDeclaration { 13 | private final Node node; 14 | private transient String signature; 15 | 16 | public NeoMethodDeclaration(final Node node) { 17 | this.node = node; 18 | } 19 | 20 | public String getName() { 21 | return (String) node.getProperty("name"); 22 | } 23 | 24 | public String getReturnType() { 25 | final Relationship returnType = node.getSingleRelationship(ClassRelations.RETURN_TYPE, Direction.OUTGOING); 26 | return new NeoClassDeclaration(returnType.getEndNode()).getName(); 27 | } 28 | 29 | public Collection getParams() { 30 | final Iterable params = node.getRelationships(ClassRelations.PARAM_TYPE, Direction.OUTGOING); 31 | final Collection result=new LinkedList(); 32 | for (final Relationship param : params) { 33 | result.add(new NeoClassDeclaration(param.getEndNode()).getName()); 34 | } 35 | return result; 36 | } 37 | 38 | @Override 39 | public Collection getExceptions() { 40 | final Iterable params = node.getRelationships(ClassRelations.THROWS, Direction.OUTGOING); 41 | final Collection result=new LinkedList(); 42 | for (final Relationship param : params) { 43 | result.add(new NeoClassDeclaration(param.getEndNode()).getName()); 44 | } 45 | return result; 46 | } 47 | 48 | public int getAccess() { 49 | return (Integer)node.getProperty("access"); 50 | } 51 | 52 | public String getSignature() { 53 | if (signature==null) signature= ClassInspectUtils.getSignature(this); 54 | return signature; 55 | } 56 | 57 | public void setSignature(final String signature) { 58 | this.signature = signature; 59 | } 60 | 61 | public Node getNode() { 62 | return node; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/neo/NodeCache.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration.neo; 2 | 3 | import org.neo4j.graphdb.Node; 4 | 5 | public interface NodeCache { 6 | Node getCachedNode(String typeName); 7 | 8 | void cacheNode(String typeName, Node newTypeNode); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/java/declaration/neo/TypeNodeFinder.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java.declaration.neo; 2 | 3 | import org.neo4j.datasource.java.analyser.stats.DefaultStatistics; 4 | import org.neo4j.datasource.java.analyser.stats.Statistics; 5 | import org.neo4j.datasource.java.analyser.ClassInspectUtils; 6 | import org.neo4j.graphdb.*; 7 | import org.neo4j.graphdb.index.Index; 8 | 9 | import java.util.List; 10 | 11 | import static java.util.Arrays.asList; 12 | import static org.neo4j.datasource.java.declaration.neo.TypeNodeFinder.StatTokens.method; 13 | import static org.neo4j.datasource.java.declaration.neo.TypeNodeFinder.StatTokens.create; 14 | 15 | public class TypeNodeFinder { 16 | NodeCache packageCache = new MapNodeCache(); 17 | NodeCache nodeCache = new MapNodeCache(); 18 | private final GraphDatabaseService graph; 19 | private Node typesNode; 20 | private Node packagesNode; 21 | private Node packageTreeNode; 22 | private Index packageIndex; 23 | private Index typeIndex; 24 | 25 | public Node getOrCreateTypeNode(String name) { 26 | return getOrCreateTypeNode(name,-1); 27 | } 28 | 29 | enum StatTokens {method, create} 30 | Statistics statistics= // new NullStatistics(); 31 | new DefaultStatistics(StatTokens.class); 32 | 33 | public TypeNodeFinder(final GraphDatabaseService graph) { 34 | this.graph = graph; 35 | this.typesNode = getTypesNode(); 36 | this.packagesNode = getPackagesNode(); 37 | this.packageTreeNode = getPackageTreeNode(); 38 | this.typeIndex = graph.index().forNodes("types"); 39 | this.packageIndex = graph.index().forNodes("packages"); 40 | } 41 | 42 | public Node getOrCreateTypeNode(String typeName, int access) { 43 | typeName = toStoredTypeName(typeName); 44 | statistics.start(method); 45 | statistics.reset(create); 46 | try { 47 | final Node cachedNode = nodeCache.getCachedNode(typeName); 48 | if (cachedNode != null) { 49 | return cachedNode; 50 | } 51 | statistics.start(create); 52 | final Node newTypeNode = createTypeNode(typeName,access); 53 | nodeCache.cacheNode(typeName, newTypeNode); 54 | return newTypeNode; 55 | } finally { 56 | statistics.done(create); 57 | statistics.done(method); 58 | } 59 | } 60 | 61 | private String toStoredTypeName(String typeName) { 62 | typeName = ClassInspectUtils.toClassName(typeName); 63 | typeName = ClassInspectUtils.arrayToClassName(typeName); 64 | return typeName; 65 | } 66 | 67 | public String toString() { 68 | return statistics.toString(method)+ statistics.toString(create)+ " cache "+nodeCache; 69 | } 70 | 71 | private Node createTypeNode(final String typeName, int access) { 72 | Node packageNode = getPackageForType(typeName); 73 | if (packageNode==null) { 74 | packageNode = createPackageNode(typeName); 75 | } 76 | final Node typeNode = graph.createNode(); 77 | typeNode.setProperty("name", typeName); 78 | typeIndex.add(typeNode,"name",typeName); 79 | if (access!=-1) { 80 | typeNode.setProperty("access",access); 81 | } 82 | packageNode.createRelationshipTo(typeNode, ClassRelations.IN_PACKAGE); 83 | typesNode.createRelationshipTo(typeNode, ClassRelations.TYPE); 84 | return typeNode; 85 | } 86 | 87 | private Node createPackageNode(String typeName) { 88 | Node packageNode = graph.createNode(); 89 | String packageName = toPackageName(typeName); 90 | packageNode.setProperty("name", packageName); 91 | packageIndex.add(packageNode,"name",packageName); 92 | packagesNode.createRelationshipTo(packageNode, DynamicRelationshipType.withName(packageName)); 93 | addPackageTree(packageNode, packageName); 94 | return packageNode; 95 | } 96 | 97 | private void addPackageTree(Node packageNode, String packageName) { 98 | Node node = packageTreeNode; 99 | List parts = asList(packageName.split("\\.")); 100 | String pkg=""; 101 | for (String part : parts.subList(0,parts.size())) { 102 | pkg += part; 103 | DynamicRelationshipType partType = DynamicRelationshipType.withName(part); 104 | Relationship rel = node.getSingleRelationship(partType, Direction.OUTGOING); 105 | if (rel==null) { 106 | Node partNode = graph.createNode(); 107 | partNode.setProperty("name",part); 108 | partNode.setProperty("package",pkg); 109 | node.createRelationshipTo(partNode,partType); 110 | node = partNode; 111 | } else { 112 | node = rel.getEndNode(); 113 | } 114 | pkg += "."; 115 | } 116 | String lastPart=parts.get(parts.size()-1); 117 | node.createRelationshipTo(packageNode,DynamicRelationshipType.withName(lastPart)); 118 | } 119 | 120 | public Node getTypeNode(String typeName) { 121 | typeName = toStoredTypeName(typeName); 122 | final Node cachedNode = nodeCache.getCachedNode(typeName); 123 | if (cachedNode != null) return cachedNode; 124 | 125 | for (Relationship inPackage : getPackageForType(typeName).getRelationships(ClassRelations.TYPE, Direction.OUTGOING)) { 126 | final Node typeNode = inPackage.getEndNode(); 127 | if (typeNode.hasProperty("name") && typeNode.getProperty("name").equals(typeName)) { 128 | return typeNode; 129 | } 130 | } 131 | return null; 132 | } 133 | 134 | private Node getPackageForType(String typeName) { 135 | String packageName = toPackageName(typeName); 136 | Node cachedNode = packageCache.getCachedNode(packageName); 137 | if (cachedNode!=null) { 138 | return cachedNode; 139 | } 140 | Relationship packageRel = packagesNode.getSingleRelationship(DynamicRelationshipType.withName(packageName), Direction.OUTGOING); 141 | if (packageRel==null) return null; 142 | return packageRel.getEndNode(); 143 | } 144 | 145 | private String toPackageName(String typeName) { 146 | int idx = typeName.lastIndexOf("."); 147 | return idx == -1 ? "default" : typeName.substring(0, idx).replace('/', '.'); 148 | } 149 | 150 | public Node getTypesNode() { 151 | return getCategoryNode(ClassRelations.ALL_TYPES); 152 | } 153 | 154 | public Node getPackagesNode() { 155 | return getCategoryNode(ClassRelations.ALL_PACKAGES); 156 | } 157 | 158 | public Node getPackageTreeNode() { 159 | return getCategoryNode(ClassRelations.PACKAGE_TREE); 160 | } 161 | 162 | public Node getCategoryNode(ClassRelations type) { 163 | final Node referenceNode = graph.getReferenceNode(); 164 | final Relationship relationship = referenceNode.getSingleRelationship(type, Direction.OUTGOING); 165 | if (relationship == null) { 166 | final Transaction tx = graph.beginTx(); 167 | try { 168 | final Node categoryNode = graph.createNode(); 169 | categoryNode.setProperty("name", type.name()); 170 | referenceNode.createRelationshipTo(categoryNode, type); 171 | tx.success(); 172 | return categoryNode; 173 | } finally { 174 | tx.finish(); 175 | } 176 | } else { 177 | return relationship.getEndNode(); 178 | } 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/datasource/util/SizeCountingOutputStream.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.util; 2 | 3 | import java.io.OutputStream; 4 | import java.io.IOException; 5 | 6 | public class SizeCountingOutputStream extends OutputStream { 7 | private long count; 8 | 9 | public void write(final int b) throws IOException { 10 | count++; 11 | } 12 | 13 | public long getCount() { 14 | return count; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/neo4j/test/NeoTestHelper.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.test; 2 | 3 | import org.neo4j.kernel.impl.util.FileUtils; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | 8 | public class NeoTestHelper { 9 | public static void dropNeoDb(final String neoStoreName) { 10 | try { 11 | FileUtils.deleteRecursively(new File(neoStoreName)); 12 | } catch (IOException ioe) { 13 | System.err.println(ioe.getMessage()); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/resources/streamline.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | StreamLine Brainstorming Rickard and Michael 4 | 5 | 6 |

StreamLine Brainstorming Rickard and Michael

7 | 8 |

Basic Building Blocks

9 | 10 |

11 | We use a nodespaces of semistructured data to represent each item contained in the application as a 12 | changelog of Quadruples (4 Dimensions) of Person, Location 13 | , Time and Content. 14 | This Quadruple is called Change. 15 |

16 | 17 |

18 | The number of changes that forms a document or communication is called ChangeLog/Stream/ChangeStream/ChangeTree. 19 | In its simplest form it contains only a single entry. A linear thread of changes forms a stream. Whereas a realistic 20 | representation forms a tree originating at the starting root entry and branching off as parallel versions are 21 | created. If versions are merged again this tree evolves to a graph or network of changes. Each change within a 22 | stream must be additionally identified by a version number.
23 | Each change also has a direct relationship to the node representing the whole stream which also contains the 24 | properties 25 | and relationships that are valid (and immutable) for the whole stream. 26 |

27 | 28 |

29 | The person making the change is perhaps not directly connected to the change but rather as 30 | contributor 31 | containing a link to the person and a second to a role in which the contribution was made. Its also possible that 32 | multiple persons made a change at the same time. The location of these persons then would also be attached rather 33 | to the contributor node than to the change node. 34 |

35 | 36 |

37 | The core of the framework is a very fast store for Changes which maintains a HEAD revision. Filtering, 38 | querying the store for different projections of the stream. 39 |

40 | 41 |

42 | All changes in the system form a cloud in the named four dimensions which can be filtered, queried, projected and 43 | represented according to the requirements of the usecase. The perspectives and views choosen to represent the 44 | projected change are also not restricted. 45 |

46 | 47 |

Using a REST based approach which separates internal models from the 48 | external representations that are made available to the clients allows a multitude of representations without 49 | coupling these to the internal handling of the model. So for instance displaying a document as mindmap, 50 | text-processor document or version history is just a question of the choosen representations. 51 | Representations could also include highly interactive and visual approaches. See Parallax Freebase for massive 52 | interactive querying and the Vimeo Code Swarm Visualization for SVN repository histories. 53 |

54 | 55 |

56 | The basic approach should be considered as similar to a distributed source control management system (like git or 57 | mercurial). For offline work local copies of the repository with all the functionality must be available. 58 | Individuals 59 | have the responsibility and possibility of deciding which of their locally stored change-set are published to 60 | the public stores or other personal stores. Change identification doesn't rely on files and their attributes but 61 | rather on internal representations (kind of hashes) of the documents edited. 62 |

63 | 64 |

65 | Another idea regarding the processing of changes is the application of tree and graph theory also for applying and 66 | merging changes. Transforming content and changes into parsed tree representations (AST) allows a much more easy 67 | merging that with current text only based diff tools. (See refactoring on the AST/PSI in IntelliJ) 68 | But even then generating, applying and merging the changes is the main challenge of this kind of 69 | application. 70 |

71 | 72 |

73 | Graph based approaches allow us to store semi-structured data. Therefore no two data sets stored in the node 74 | space must be of equal structure. For keeping type information and other aggregating structures we can use 75 | specialized 76 | type nodes which hold connections to all nodes of a certain type. With the relationship based approach to typing 77 | multiple typing is very easy and attaching additional information on the type itself is also provided. 78 | Concrete nodes and their types form spheres of interest which can be easily accessed by traversing the nodespace 79 | either 80 | inside out from the change or outside in from the type nodes.
81 |
82 | Graph databases allow us fast retrieval and traversal of large structures. Supporting functionality for searching 83 | and filtering comes from full text retrieval systems /indexers like lucene.
84 | All access to the graph database is fully transactional so that multithreaded access poses no problem.
85 | As our data structures will be so simple a tuple space based solution for scaling is also possible (e.g. GigaSpaces, 86 | Coherence). 87 |

88 | 89 |

90 | The change will rely on an universal id at the center. All other data is added in addional layers. First core state 91 | and types and then the data, types and behaviour that come with the patterns/principles (implemented by 92 | concerns and sideeffects of the application domain). 93 |

94 | 95 |

Basic associated Node Types of a Change

96 | 97 | 98 |

Person

99 |

Attributes

100 |
    101 |
  • Name
  • 102 |
  • Portrait
  • 103 |
  • openId
  • 104 |
  • public key
  • 105 |
106 |

Relationships

107 |
    108 |
  • 109 | 110 |
  • 111 |
112 |
113 | 114 |

Location

115 | 116 |

117 | Location is the place where the change was made. Can be derived using GPS, IP-Lookup, WLAN-Lookup, Mobile-Tracing 118 | whatever. 119 |

120 | 121 |

Attributes

122 |
    123 |
  • gps coordinates
  • 124 |
  • address - perhaps rather node than attribute
  • 125 |
126 |

Relationships

127 |
    128 |
  • other nodes regarding locality: city, country, addresses
  • 129 |
130 |
131 | 132 |

Time

133 | 134 |

135 | Time is represented as (second) nodes in the nodespace. Only the time nodes that are actually needed by the changes 136 | are created.
137 |

138 |

Time nodes form a node hierarchy.

139 |
    140 |
  1. Second
  2. 141 |
  3. Minute
  4. 142 |
  5. Hour
  6. 143 |
  7. day of month
  8. 144 |
  9. month
  10. 145 |
  11. year
  12. 146 |
  13. epoch
  14. 147 |
148 |

Attributes

149 |
    150 |
  • actual timestamp in gmt
  • 151 |
152 |

Relationships

153 |
    154 |
  • parent time hierarchy nodes
  • 155 |
  • incoming: nodes that occur at this timestamp
  • 156 |
157 | 158 |
159 | 160 |

Content

161 | 162 |

163 | Content is the data that was produced at this timestamp by this person at this location. It is normally 164 | a part of a larger stream of content (diffs) that form documents or communication. 165 | The content is stored as a log and at the same time a HEAD revision is maintainted as the current representation 166 | of the accumulated changes. 167 |

168 |

Immutability and Security

169 | 170 |

171 | Content is immutable and may be digitally signed (using the public key of the associated person and can be encrypted 172 | if needed. 173 |

174 |

Attributes

175 |
    176 |
  • metadata
  • 177 |
  • size
  • 178 |
  • mime type
  • 179 |
180 |

Relationships

181 |
    182 |
  • time
  • 183 |
  • person
  • 184 |
  • location
  • 185 |
  • tag
  • 186 |
  • document/communication/
  • 187 |
188 | 189 |

Values, Principles and Patterns/Practices

190 | 191 |

192 | A system of values is the basis for every domain. Derived from that are principles 193 | that are the general rules of effective work in this domain. The concrete, applicable practices and 194 | patterns are developed based on these principles in a certain context with individual forces that must be 195 | balanced to achieve the desired outcome.
196 | (Design-)Patterns describe roles and relationships. The same goes for concerns of an application domain (e.g. 197 | workflow).
198 | So what we want to do ist to explore the value system of the targeted application domain and look for existing 199 | principles and patterns and apply them as concerns and sideeffects to our existing basic framework. Each concern 200 | might bring along further behaviour and/or data that is added to the basic entities. 201 | When concerns change, the data does not go away but rather stays available 202 | - Model Change does not require instance change 203 |

204 |

Literature

205 |
    206 |
  • Christopher Alexander - A Timeless Way of Building
  • 207 |
  • Kevlin Henney et al - Patterns of Software Architecture 5
  • 208 |
  • Kent Beck - eXtreme Programming - Explained
  • 209 |
210 | 211 |

Applications on top

212 | 213 |

Potential Applications

214 | 215 |

Workflow Management - StreamFlow

216 | 217 |

Workflow Management is a important issue in governental institutions and companies. Existing 218 | solutions are not sufficient and much to complex. A simpler and more flexible approach is needed that is able to 219 | include 220 |

221 |

Intented Features

222 |
    223 |
  • Immutable Change Log at the core
  • 224 |
  • Multitude of representations
  • 225 |
  • Fast retrieval and querying
  • 226 |
  • Fast handling of merges, projections
  • 227 |
  • Easy extension with concerns and sideeffects derived from the best working practices of the domain 228 |
      for instance 229 |
    • Signing, Encryption with PKI
    • 230 |
    • Roles and role based ACLs
    • 231 |
    232 |
  • 233 |
234 |

Previous thingking about workflow (partially outdated)

235 |
what belongs to a task
236 |
    237 |
  • Content and its Content-Types
  • 238 |
  • Task as basic data
  • 239 |
  • People
  • 240 |
  • Communication
  • 241 |
  • Type
  • 242 |
  • Metadata
  • 243 |
  • Attributes
  • 244 |
  • Relationships
  • 245 |
246 | 247 |

Software Development - StreamSource

248 | 249 |

We want to use the software as dogfood / bootstrapping application for its own distributed 250 | development. So that we get annoyed by incomplete, inconsitent, unusable features and will fix them. 251 |

252 |
    253 |
  • Source Code Management
  • 254 |
  • Agile Methodologies 255 |
      256 |
    • Backlog
    • 257 |
    • Communication
    • 258 |
    • Estimation
    • 259 |
    • Planning
    • 260 |
    • ...
    • 261 |
    262 |
  • 263 |
  • Task / Issue Management
  • 264 |
  • Analysis
  • 265 |
266 | 267 | -------------------------------------------------------------------------------- /src/test/java/org/neo4j/analyser/codecity/Gears.java.save: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java; 2 | 3 | 4 | import com.sun.opengl.util.Animator; 5 | 6 | import javax.media.opengl.*; 7 | import java.awt.*; 8 | import java.awt.event.*; 9 | 10 | /** 11 | * Gears.java
12 | * author: Brian Paul (converted to Java by Ron Cemer and Sven Goethel)

13 | *

14 | * This version is equal to Brian Paul's version 1.2 1999/10/21 15 | */ 16 | 17 | public class Gears implements GLEventListener, MouseListener, MouseMotionListener { 18 | public static void main(String[] args) { 19 | Frame frame = new Frame("Gear Demo"); 20 | GLCanvas canvas = new GLCanvas(); 21 | 22 | canvas.addGLEventListener(new Gears()); 23 | frame.add(canvas); 24 | frame.setSize(300, 300); 25 | final Animator animator = new Animator(canvas); 26 | frame.addWindowListener(new WindowAdapter() { 27 | public void windowClosing(WindowEvent e) { 28 | // Run this on another thread than the AWT event queue to 29 | // make sure the call to Animator.stop() completes before 30 | // exiting 31 | new Thread(new Runnable() { 32 | public void run() { 33 | animator.stop(); 34 | System.exit(0); 35 | } 36 | }).start(); 37 | } 38 | }); 39 | frame.show(); 40 | animator.start(); 41 | } 42 | 43 | private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f; 44 | private int gear1, gear2, gear3; 45 | private float angle = 0.0f; 46 | 47 | private int prevMouseX, prevMouseY; 48 | private boolean mouseRButtonDown = false; 49 | 50 | public void init(GLAutoDrawable drawable) { 51 | // Use debug pipeline 52 | // drawable.setGL(new DebugGL(drawable.getGL())); 53 | 54 | GL gl = drawable.getGL(); 55 | 56 | System.err.println("INIT GL IS: " + gl.getClass().getName()); 57 | 58 | System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities()); 59 | 60 | gl.setSwapInterval(1); 61 | 62 | float pos[] = {5.0f, 5.0f, 10.0f, 0.0f}; 63 | float red[] = {0.8f, 0.1f, 0.0f, 1.0f}; 64 | float green[] = {0.0f, 0.8f, 0.2f, 1.0f}; 65 | float blue[] = {0.2f, 0.2f, 1.0f, 1.0f}; 66 | 67 | gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, pos, 0); 68 | gl.glEnable(GL.GL_CULL_FACE); 69 | gl.glEnable(GL.GL_LIGHTING); 70 | gl.glEnable(GL.GL_LIGHT0); 71 | gl.glEnable(GL.GL_DEPTH_TEST); 72 | 73 | /* make the gears */ 74 | gear1 = gl.glGenLists(1); 75 | gl.glNewList(gear1, GL.GL_COMPILE); 76 | gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, red, 0); 77 | gear(gl, 1.0f, 4.0f, 1.0f, 20, 0.7f); 78 | gl.glEndList(); 79 | 80 | gear2 = gl.glGenLists(1); 81 | gl.glNewList(gear2, GL.GL_COMPILE); 82 | gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, green, 0); 83 | gear(gl, 0.5f, 2.0f, 2.0f, 10, 0.7f); 84 | gl.glEndList(); 85 | 86 | gear3 = gl.glGenLists(1); 87 | gl.glNewList(gear3, GL.GL_COMPILE); 88 | gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, blue, 0); 89 | gear(gl, 1.3f, 2.0f, 0.5f, 10, 0.7f); 90 | gl.glEndList(); 91 | 92 | gl.glEnable(GL.GL_NORMALIZE); 93 | 94 | drawable.addMouseListener(this); 95 | drawable.addMouseMotionListener(this); 96 | } 97 | 98 | public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { 99 | GL gl = drawable.getGL(); 100 | 101 | float h = (float) height / (float) width; 102 | 103 | gl.glMatrixMode(GL.GL_PROJECTION); 104 | 105 | System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); 106 | System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); 107 | System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); 108 | gl.glLoadIdentity(); 109 | gl.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f); 110 | gl.glMatrixMode(GL.GL_MODELVIEW); 111 | gl.glLoadIdentity(); 112 | gl.glTranslatef(0.0f, 0.0f, -40.0f); 113 | } 114 | 115 | public void display(GLAutoDrawable drawable) { 116 | // Turn the gears' teeth 117 | angle += 2.0f; 118 | 119 | // Get the GL corresponding to the drawable we are animating 120 | GL gl = drawable.getGL(); 121 | 122 | // Special handling for the case where the GLJPanel is translucent 123 | // and wants to be composited with other Java 2D content 124 | if ((drawable instanceof GLJPanel) && 125 | !((GLJPanel) drawable).isOpaque() && 126 | ((GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) { 127 | gl.glClear(GL.GL_DEPTH_BUFFER_BIT); 128 | } else { 129 | gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); 130 | } 131 | 132 | // Rotate the entire assembly of gears based on how the user 133 | // dragged the mouse around 134 | gl.glPushMatrix(); 135 | gl.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f); 136 | gl.glRotatef(view_roty, 0.0f, 1.0f, 0.0f); 137 | gl.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f); 138 | 139 | // Place the first gear and call its display list 140 | gl.glPushMatrix(); 141 | gl.glTranslatef(-3.0f, -2.0f, 0.0f); 142 | gl.glRotatef(angle, 0.0f, 0.0f, 1.0f); 143 | gl.glCallList(gear1); 144 | gl.glPopMatrix(); 145 | 146 | // Place the second gear and call its display list 147 | gl.glPushMatrix(); 148 | gl.glTranslatef(3.1f, -2.0f, 0.0f); 149 | gl.glRotatef(-2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f); 150 | gl.glCallList(gear2); 151 | gl.glPopMatrix(); 152 | 153 | // Place the third gear and call its display list 154 | gl.glPushMatrix(); 155 | gl.glTranslatef(-3.1f, 4.2f, 0.0f); 156 | gl.glRotatef(-2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f); 157 | gl.glCallList(gear3); 158 | gl.glPopMatrix(); 159 | 160 | // Remember that every push needs a pop; this one is paired with 161 | // rotating the entire gear assembly 162 | gl.glPopMatrix(); 163 | } 164 | 165 | public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { 166 | } 167 | 168 | public static void gear(GL gl, 169 | float inner_radius, 170 | float outer_radius, 171 | float width, 172 | int teeth, 173 | float tooth_depth) { 174 | int i; 175 | float r0, r1, r2; 176 | float angle, da; 177 | float u, v, len; 178 | 179 | r0 = inner_radius; 180 | r1 = outer_radius - tooth_depth / 2.0f; 181 | r2 = outer_radius + tooth_depth / 2.0f; 182 | 183 | da = 2.0f * (float) Math.PI / teeth / 4.0f; 184 | 185 | gl.glShadeModel(GL.GL_FLAT); 186 | 187 | gl.glNormal3f(0.0f, 0.0f, 1.0f); 188 | 189 | /* draw front face */ 190 | gl.glBegin(GL.GL_QUAD_STRIP); 191 | for (i = 0; i <= teeth; i++) { 192 | angle = i * 2.0f * (float) Math.PI / teeth; 193 | gl.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f); 194 | gl.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f); 195 | if (i < teeth) { 196 | gl.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f); 197 | gl.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da), width * 0.5f); 198 | } 199 | } 200 | gl.glEnd(); 201 | 202 | /* draw front sides of teeth */ 203 | gl.glBegin(GL.GL_QUADS); 204 | for (i = 0; i < teeth; i++) { 205 | angle = i * 2.0f * (float) Math.PI / teeth; 206 | gl.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f); 207 | gl.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f); 208 | gl.glVertex3f(r2 * (float) Math.cos(angle + 2.0f * da), r2 * (float) Math.sin(angle + 2.0f * da), width * 0.5f); 209 | gl.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da), width * 0.5f); 210 | } 211 | gl.glEnd(); 212 | 213 | /* draw back face */ 214 | gl.glBegin(GL.GL_QUAD_STRIP); 215 | for (i = 0; i <= teeth; i++) { 216 | angle = i * 2.0f * (float) Math.PI / teeth; 217 | gl.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f); 218 | gl.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f); 219 | gl.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f); 220 | gl.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f); 221 | } 222 | gl.glEnd(); 223 | 224 | /* draw back sides of teeth */ 225 | gl.glBegin(GL.GL_QUADS); 226 | for (i = 0; i < teeth; i++) { 227 | angle = i * 2.0f * (float) Math.PI / teeth; 228 | gl.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f); 229 | gl.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f); 230 | gl.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f); 231 | gl.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f); 232 | } 233 | gl.glEnd(); 234 | 235 | /* draw outward faces of teeth */ 236 | gl.glBegin(GL.GL_QUAD_STRIP); 237 | for (i = 0; i < teeth; i++) { 238 | angle = i * 2.0f * (float) Math.PI / teeth; 239 | gl.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f); 240 | gl.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f); 241 | u = r2 * (float) Math.cos(angle + da) - r1 * (float) Math.cos(angle); 242 | v = r2 * (float) Math.sin(angle + da) - r1 * (float) Math.sin(angle); 243 | len = (float) Math.sqrt(u * u + v * v); 244 | u /= len; 245 | v /= len; 246 | gl.glNormal3f(v, -u, 0.0f); 247 | gl.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f); 248 | gl.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f); 249 | gl.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f); 250 | gl.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), width * 0.5f); 251 | gl.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f); 252 | u = r1 * (float) Math.cos(angle + 3 * da) - r2 * (float) Math.cos(angle + 2 * da); 253 | v = r1 * (float) Math.sin(angle + 3 * da) - r2 * (float) Math.sin(angle + 2 * da); 254 | gl.glNormal3f(v, -u, 0.0f); 255 | gl.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), width * 0.5f); 256 | gl.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f); 257 | gl.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f); 258 | } 259 | gl.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), width * 0.5f); 260 | gl.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), -width * 0.5f); 261 | gl.glEnd(); 262 | 263 | gl.glShadeModel(GL.GL_SMOOTH); 264 | 265 | /* draw inside radius cylinder */ 266 | gl.glBegin(GL.GL_QUAD_STRIP); 267 | for (i = 0; i <= teeth; i++) { 268 | angle = i * 2.0f * (float) Math.PI / teeth; 269 | gl.glNormal3f(-(float) Math.cos(angle), -(float) Math.sin(angle), 0.0f); 270 | gl.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f); 271 | gl.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f); 272 | } 273 | gl.glEnd(); 274 | } 275 | 276 | // Methods required for the implementation of MouseListener 277 | public void mouseEntered(MouseEvent e) { 278 | } 279 | 280 | public void mouseExited(MouseEvent e) { 281 | } 282 | 283 | public void mousePressed(MouseEvent e) { 284 | prevMouseX = e.getX(); 285 | prevMouseY = e.getY(); 286 | if ((e.getModifiers() & e.BUTTON3_MASK) != 0) { 287 | mouseRButtonDown = true; 288 | } 289 | } 290 | 291 | public void mouseReleased(MouseEvent e) { 292 | if ((e.getModifiers() & e.BUTTON3_MASK) != 0) { 293 | mouseRButtonDown = false; 294 | } 295 | } 296 | 297 | public void mouseClicked(MouseEvent e) { 298 | } 299 | 300 | // Methods required for the implementation of MouseMotionListener 301 | public void mouseDragged(MouseEvent e) { 302 | int x = e.getX(); 303 | int y = e.getY(); 304 | Dimension size = e.getComponent().getSize(); 305 | 306 | float thetaY = 360.0f * ((float) (x - prevMouseX) / (float) size.width); 307 | float thetaX = 360.0f * ((float) (prevMouseY - y) / (float) size.height); 308 | 309 | prevMouseX = x; 310 | prevMouseY = y; 311 | 312 | view_rotx += thetaX; 313 | view_roty += thetaY; 314 | } 315 | 316 | public void mouseMoved(MouseEvent e) { 317 | } 318 | } 319 | 320 | -------------------------------------------------------------------------------- /src/test/java/org/neo4j/analyser/codecity/HelloWorldDemo.java.save: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java; 2 | 3 | // External imports 4 | 5 | import javax.media.opengl.*; 6 | import java.awt.*; 7 | 8 | // Local imports 9 | // None 10 | 11 | /** 12 | * Example application that demonstrates how to put together a single-threaded 13 | * rendering system. 14 | * 15 | * @author Justin Couch 16 | * @version $Revision: 1.5 $ 17 | */ 18 | public class HelloWorldDemo extends Frame 19 | implements GLEventListener { 20 | public HelloWorldDemo() { 21 | super("Basic JOGL Demo"); 22 | 23 | setLayout(new BorderLayout()); 24 | 25 | setSize(400, 400); 26 | setLocation(40, 40); 27 | 28 | // Need to set visible first before starting the rendering thread due 29 | // to a bug in JOGL. See JOGL Issue #54 for more information on this. 30 | // http://jogl.dev.java.net 31 | setVisible(true); 32 | 33 | setupJOGL(); 34 | } 35 | 36 | //--------------------------------------------------------------- 37 | // Methods defined by GLEventListener 38 | //--------------------------------------------------------------- 39 | 40 | /** 41 | * Called by the drawable immediately after the OpenGL context is 42 | * initialized; the GLContext has already been made current when 43 | * this method is called. 44 | * 45 | * @param drawable The display context to render to 46 | */ 47 | public void init(GLAutoDrawable drawable) { 48 | GL gl = drawable.getGL(); 49 | 50 | gl.glClearColor(0, 0, 0, 0); 51 | gl.glMatrixMode(GL.GL_PROJECTION); 52 | 53 | gl.glLoadIdentity(); 54 | gl.glFrustum(-20.0f, 20.0f, -20f, 20, 0f, 30.0f); 55 | 56 | gl.glRotatef(20f, 1.0f, 0.0f, 0.0f); 57 | gl.glRotatef(180f, 0.0f, 1.0f, 0.0f); 58 | gl.glRotatef(20f, 0.0f, 0.0f, 1.0f); 59 | 60 | // gl.glOrtho(-1, 1, -1, 1, -1, 1); 61 | } 62 | 63 | /** 64 | * Called by the drawable when the surface resizes itself. Used to 65 | * reset the viewport dimensions. 66 | * 67 | * @param drawable The display context to render to 68 | */ 69 | public void reshape(GLAutoDrawable drawable, 70 | int x, 71 | int y, 72 | int width, 73 | int height) { 74 | } 75 | 76 | /** 77 | * Called by the drawable when the display mode or the display device 78 | * associated with the GLDrawable has changed 79 | */ 80 | public void displayChanged(GLAutoDrawable drawable, 81 | boolean modeChanged, 82 | boolean deviceChanged) { 83 | } 84 | 85 | /** 86 | * Called by the drawable to perform rendering by the client. 87 | * 88 | * @param drawable The display context to render to 89 | */ 90 | public void display(GLAutoDrawable drawable) { 91 | GL gl = drawable.getGL(); 92 | 93 | gl.glClear(GL.GL_COLOR_BUFFER_BIT); 94 | drawTriangle(gl); 95 | 96 | gl.glColor3f(1, 0, 0); 97 | drawCube(gl,0,0,0, .2f, .2f); 98 | 99 | gl.glColor3f(0, 1, 0); 100 | drawCube(gl,0,1,0, .5f, .01f); 101 | 102 | gl.glColor3f(0, 0, 1); 103 | drawCube(gl,0,-1,0, .1f, .5f); 104 | 105 | gl.glColor3f(0, 1, 1); 106 | drawCube(gl,0.5f,-0.5f,0, .2f, .2f); 107 | 108 | gl.glFlush(); 109 | } 110 | 111 | private void drawTriangle(final GL gl) { 112 | gl.glBegin(GL.GL_TRIANGLES); 113 | 114 | gl.glColor3f(1, 0, 0); 115 | gl.glVertex3f(0.25f, 0.25f, 0); 116 | 117 | gl.glColor3f(0, 1, 0); 118 | gl.glVertex3f(0.5f, 0.25f, 0); 119 | 120 | gl.glColor3f(0, 0, 1); 121 | gl.glVertex3f(0.25f, 0.5f, 0); 122 | 123 | gl.glEnd(); 124 | } 125 | 126 | private void drawCube(GL gl, float x, float y, float z, float width,float height) { 127 | gl.glBegin(GL.GL_QUADS); 128 | final float x1 = x - width; 129 | final float y2 = y + width; 130 | final float y1 = y - width; 131 | final float x2 = x + width; 132 | drawCube(gl, x1, y1, z, x2, y2, z+height); 133 | gl.glEnd(); 134 | } 135 | 136 | 137 | private void drawCube(final GL gl, final float x1, final float y1, final float z1, final float x2, final float y2, final float z2) { 138 | gl.glVertex3d(x1, y1, z1); 139 | gl.glVertex3d(x2, y1, z1); 140 | gl.glVertex3d(x2, y2, z1); 141 | gl.glVertex3d(x1, y2, z1); 142 | 143 | gl.glVertex3d(x1, y1, z2); 144 | gl.glVertex3d(x2, y1, z2); 145 | gl.glVertex3d(x2, y2, z2); 146 | gl.glVertex3d(x1, y2, z2); 147 | 148 | gl.glVertex3d(x1, y1, z1); 149 | gl.glVertex3d(x2, y1, z1); 150 | gl.glVertex3d(x2, y1, z2); 151 | gl.glVertex3d(x1, y1, z2); 152 | 153 | gl.glVertex3d(x1, y2, z1); 154 | gl.glVertex3d(x2, y2, z1); 155 | gl.glVertex3d(x2, y2, z2); 156 | gl.glVertex3d(x1, y2, z2); 157 | 158 | gl.glVertex3d(x1, y1, z1); 159 | gl.glVertex3d(x1, y2, z1); 160 | gl.glVertex3d(x1, y2, z2); 161 | gl.glVertex3d(x1, y1, z2); 162 | 163 | gl.glVertex3d(x2, y1, z1); 164 | gl.glVertex3d(x2, y2, z1); 165 | gl.glVertex3d(x2, y2, z2); 166 | gl.glVertex3d(x2, y1, z2); 167 | } 168 | //--------------------------------------------------------------- 169 | // Local methods 170 | //--------------------------------------------------------------- 171 | 172 | /** 173 | * Create the basics of the JOGL screen details. 174 | */ 175 | private void setupJOGL() { 176 | GLCapabilities caps = new GLCapabilities(); 177 | caps.setDoubleBuffered(true); 178 | caps.setHardwareAccelerated(true); 179 | 180 | GLCanvas canvas = new GLCanvas(caps); 181 | canvas.addGLEventListener(this); 182 | 183 | add(canvas, BorderLayout.CENTER); 184 | 185 | // Animator anim = new Animator(canvas); 186 | // anim.start(); 187 | } 188 | 189 | public static void main(String[] args) { 190 | HelloWorldDemo demo = new HelloWorldDemo(); 191 | demo.setVisible(true); 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /src/test/java/org/neo4j/analyser/codecity/JoglFrame.java.save: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java; 2 | 3 | import javax.media.opengl.GLCapabilities; 4 | import javax.media.opengl.GLJPanel; 5 | 6 | public class JoglFrame extends GLJPanel { 7 | 8 | public JoglFrame() { 9 | super(createCaps()); 10 | } 11 | 12 | private static GLCapabilities createCaps() { 13 | GLCapabilities caps = new GLCapabilities(); 14 | caps.setAlphaBits(8); 15 | return caps; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/org/neo4j/analyser/codecity/JoglTest.java.save: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java; 2 | 3 | import org.junit.Test; 4 | 5 | public class JoglTest { 6 | @Test 7 | public void testJogl() { 8 | new JoglFrame().show(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/test/java/org/neo4j/analyser/codecity/MooseWriter.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.analyser.codecity; 2 | 3 | import org.neo4j.datasource.java.analyser.ClassFileIterator; 4 | import org.neo4j.datasource.java.analyser.RecordingInspector; 5 | import org.neo4j.datasource.java.declaration.ClassDeclaration; 6 | import org.neo4j.datasource.java.declaration.PackageDeclaration; 7 | import org.neo4j.datasource.java.declaration.bean.PackageDeclarationBean; 8 | 9 | import java.io.*; 10 | import static java.lang.System.currentTimeMillis; 11 | import java.util.*; 12 | 13 | /** 14 | * @author Michael Hunger 15 | * @since 07.10.2009 16 | */ 17 | public class MooseWriter { 18 | private final Map classes; 19 | private Set namespaces; 20 | private Collection aPackages; 21 | private int index; 22 | 23 | public MooseWriter(final Map classes) { 24 | this.classes = classes; 25 | index = classes.size() + 2; 26 | System.out.println("max.class.idx = " + index); 27 | this.namespaces = extractNamespaces(classes, index); 28 | index += namespaces.size()+1; 29 | System.out.println("max.ns.idx = " + index); 30 | this.aPackages = extractPackages(namespaces, index); 31 | index += aPackages.size()+1; 32 | System.out.println("max.pkg.idx = " + index); 33 | } 34 | 35 | private Collection extractPackages(Collection namespaces, int startIdx) { 36 | Collection result=new HashSet(namespaces.size()); 37 | for (PackageDeclaration namespace : namespaces) { 38 | PackageDeclaration packageDeclaration = new PackageDeclarationBean(namespace.getName(), startIdx++); 39 | result.add(packageDeclaration); 40 | while (!packageDeclaration.isRoot()) { 41 | final PackageDeclaration superPackage = new PackageDeclarationBean(packageDeclaration.getSuperPackage(), startIdx); 42 | if (!result.contains(superPackage)) { 43 | result.add(superPackage); 44 | startIdx++; 45 | } 46 | packageDeclaration =superPackage; 47 | } 48 | } 49 | return result; 50 | } 51 | 52 | private Set extractNamespaces(final Map classes, int startIdx) { 53 | final Set result = new HashSet(); 54 | for (final ClassDeclaration declaration : classes.values()) { 55 | final PackageDeclarationBean packageInfo = new PackageDeclarationBean(declaration.getPackage(), startIdx); 56 | if (!result.contains(packageInfo)) { 57 | result.add(packageInfo); 58 | startIdx++; 59 | } 60 | } 61 | return result; 62 | } 63 | 64 | public static void main(final String[] args) throws Exception { 65 | final String file = args[0]; 66 | final Class type = args.length > 1 ? Class.forName(args[1]) : Object.class; 67 | long time= currentTimeMillis(); 68 | final Map classes = new ClassParser().loadClasses(type); 69 | time= currentTimeMillis()-time; 70 | System.out.println("reading took " + time+" ms"); 71 | time= currentTimeMillis(); 72 | new MooseWriter(classes).writeFile(file); 73 | time= currentTimeMillis()-time; 74 | System.out.println("\nwriting took " + time+" ms"); 75 | } 76 | 77 | private void writeFile(final String file) { 78 | try { 79 | final Writer os = new BufferedWriter(new FileWriter(file)); 80 | writeHeader(os); 81 | writePackages(os); 82 | writeClasses(os,index); 83 | writeFooter(os); 84 | os.close(); 85 | } catch (IOException ioe) { 86 | throw new RuntimeException(ioe); 87 | } 88 | } 89 | 90 | private void writeClasses(Writer os, int index) throws IOException { 91 | System.out.println("\nWriting classes"); 92 | for (ClassDeclaration declaration : classes.values()) { 93 | os.write("\t\t(FAMIX.Class (id: "+ declaration.getId()+")\n" + 94 | "\t\t\t(name '"+ declaration.getSimpleName()+"')\n" + 95 | "\t\t\t(belongsTo (idref: "+getPackageId(namespaces, declaration.getPackage())+"))\n" + 96 | "\t\t\t(isAbstract false)\n" + 97 | "\t\t\t(isInterface false)\n" + 98 | "\t\t\t(packagedIn (idref: "+getPackageId(aPackages, declaration.getPackage())+")))\n"); 99 | if (!declaration.isRoot()) { 100 | os.write("\t\t(FAMIX.InheritanceDefinition (id: "+(index++)+")\n" + 101 | "\t\t\t(subclass (idref: "+ declaration.getId()+"))\n" + 102 | "\t\t\t(superclass (idref: "+ declaration.getSuperClass().getId() +")))\n"); 103 | } 104 | } 105 | } 106 | 107 | private int getPackageId(Collection aPackages, String pkgName) { 108 | for (PackageDeclaration namespace : aPackages) { 109 | if (namespace.getName().equals(pkgName)) return namespace.getId(); 110 | } 111 | throw new IllegalArgumentException("Unknown package "+pkgName); 112 | } 113 | 114 | private void writePackages(Writer os) throws IOException { 115 | System.out.println("\nWriting namespaces"); 116 | for (PackageDeclaration declaration : namespaces) { 117 | os.write("\t\t(FAMIX.Namespace (id: "+ declaration.getId()+")\n" + 118 | "\t\t\t(name '"+toMoose(declaration.getName())+"'))\n"); 119 | } 120 | System.out.println("\nWriting packages"); 121 | for (PackageDeclaration aPackage : aPackages) { 122 | os.write("\t\t(FAMIX.Package (id: "+aPackage.getId()+")\n" + 123 | "\t\t\t(name '"+toMoose(aPackage.getName())+"')\n" + 124 | "\t\t\t(DIH "+dih(aPackage)+")\n" + 125 | (aPackage.isRoot() ? "" : "\t\t\t(packagedIn (idref: "+getPackageId(aPackages,aPackage.getSuperPackage())+"))") 126 | +")\n"); 127 | } 128 | } 129 | 130 | private int dih(PackageDeclaration aPackage) { 131 | return aPackage.getName().split("\\.").length; 132 | } 133 | 134 | private String toMoose(String pkg) { 135 | return pkg.replaceAll("/","::"); 136 | } 137 | 138 | private void writeFooter(Writer os) throws IOException { 139 | os.write(")\n" + 140 | "\t(LOC 1000)\n" + 141 | "\t(NOC "+classes.size()+")\n" + 142 | "\t(NOP "+ namespaces.size()+")\n" + 143 | "\t(sourceLanguage 'Java'))\n"); 144 | } 145 | 146 | private void writeHeader(Writer os) throws IOException { 147 | os.write("(Moose.Model (id: 1)\n" + 148 | "\t(name 'test')\n" + 149 | "\t(entity"); 150 | } 151 | 152 | static class ClassParser { 153 | public Map loadClasses(final Class type) { 154 | final RecordingInspector inspector = new RecordingInspector(); 155 | final ClassFileIterator fileIterator = new ClassFileIterator(); 156 | final String jarFileLocation = fileIterator.getJarLocationByClass(type); 157 | for (final String classFileName : fileIterator.getClassFileNames(jarFileLocation)) { 158 | inspector.inspectClass(classFileName); 159 | } 160 | return inspector.getClasses(); 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/test/java/org/neo4j/api/core/NeoFileSystemTest.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.api.core; 2 | 3 | import org.junit.After; 4 | import org.junit.Before; 5 | import org.junit.Ignore; 6 | import org.junit.Test; 7 | import org.neo4j.data.file.FileHandler; 8 | import org.neo4j.data.file.FileSystemVisitor; 9 | import org.neo4j.graphdb.*; 10 | import org.neo4j.kernel.EmbeddedGraphDatabase; 11 | 12 | import java.io.File; 13 | import java.util.Collection; 14 | import java.util.Stack; 15 | 16 | import static org.junit.Assert.assertEquals; 17 | import static org.neo4j.test.NeoTestHelper.dropNeoDb; 18 | 19 | public class NeoFileSystemTest { 20 | private GraphDatabaseService neo; 21 | private static final String BASE_DIR = "src"; 22 | private static final File START_FILE = new File(BASE_DIR); 23 | private static final String NEODB = "neodb"; 24 | private static final String SIZE = "size"; 25 | private static final String NAME = "name"; 26 | 27 | @Before 28 | public void setUp() { 29 | dropNeoDb(NEODB); 30 | } 31 | 32 | @Test 33 | public void testNoopFileSystem() { 34 | final File startDir = new File(BASE_DIR); 35 | long time = System.currentTimeMillis(); 36 | final FileSystemVisitor fileSystemVisitor = new FileSystemVisitor(new FileHandler() { 37 | public void handle(final File file) { 38 | final String name = file.getName(); 39 | final long length = file.length(); 40 | } 41 | 42 | public void upTo(final File file) { 43 | } 44 | }, startDir); 45 | time = System.currentTimeMillis() - time; 46 | System.out.println("time = " + time + " ms."); 47 | System.out.println("fileSystemVisitor = " + fileSystemVisitor.getCount()); 48 | } 49 | 50 | 51 | @Test 52 | public void testFileSystem() { 53 | neo = new EmbeddedGraphDatabase(NEODB); 54 | long time = System.currentTimeMillis(); 55 | final FileSystemVisitor fileSystemVisitor = readFileSystem(START_FILE, neo); 56 | time = System.currentTimeMillis() - time; 57 | System.out.println("time = " + time + " ms."); 58 | System.out.println("fileSystemVisitor = " + fileSystemVisitor.getCount()); 59 | } 60 | 61 | @Test 62 | @Ignore 63 | public void testTimeFileSystem() { 64 | neo = new EmbeddedGraphDatabase(NEODB); 65 | long time = System.currentTimeMillis(); 66 | final FileHandler fileHandler = new FileNodeCreator2(neo); 67 | final FileSystemVisitor fileSystemVisitor = new FileSystemVisitor(fileHandler, new File("/Users/mh/java/neo")); 68 | fileHandler.finish(); 69 | time = System.currentTimeMillis() - time; 70 | System.out.println("time = " + time + " ms."); 71 | System.out.println("fileSystemVisitor = " + fileSystemVisitor.getCount()); 72 | } 73 | 74 | private FileSystemVisitor readFileSystem(File startDir, final GraphDatabaseService db) { 75 | final FileNodeCreator fileHandler = new FileNodeCreator(db); 76 | final FileSystemVisitor fileSystemVisitor = new FileSystemVisitor(fileHandler, startDir); 77 | fileHandler.finish(); 78 | return fileSystemVisitor; 79 | } 80 | 81 | @After 82 | public void tearDown() { 83 | if (neo != null) { 84 | neo.shutdown(); 85 | } 86 | } 87 | 88 | @Test 89 | public void queryFileSystemNodes() { 90 | neo = new EmbeddedGraphDatabase(NEODB); 91 | final FileSystemVisitor fileSystemVisitor = readFileSystem(START_FILE, neo); 92 | System.out.println(fileSystemVisitor.getCount()); 93 | final Node node = neo.getReferenceNode(); 94 | final Traverser fileSizeTraverser = node.traverse(Traverser.Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, new ReturnableEvaluator() { 95 | public boolean isReturnableNode(final TraversalPosition traversalPosition) { 96 | final Node node = traversalPosition.currentNode(); 97 | final Long size = (Long) node.getProperty(SIZE, 0L); 98 | return size > 1000; 99 | } 100 | }, Relation.CHILD, Direction.OUTGOING); 101 | 102 | System.out.println("node = " + node); 103 | final Collection allNodes = fileSizeTraverser.getAllNodes(); 104 | assertEquals("27 big files", 27, allNodes.size()); 105 | } 106 | 107 | enum Relation implements RelationshipType { 108 | CHILD 109 | } 110 | 111 | private static class FileNodeCreator extends FileHandler { 112 | private final Stack nodes = new Stack(); 113 | private final GraphDatabaseService graph; 114 | int count = 0; 115 | private Transaction tx; 116 | 117 | public FileNodeCreator(final GraphDatabaseService graph) { 118 | this.graph = graph; 119 | tx = graph.beginTx(); 120 | final Node rootNode = graph.getReferenceNode(); 121 | rootNode.setProperty(NAME, BASE_DIR); 122 | rootNode.setProperty(SIZE, 0L); 123 | this.nodes.push(rootNode); 124 | } 125 | 126 | public void handle(final File file) { 127 | final Node node = graph.createNode(); 128 | node.setProperty(NAME, file.getName()); 129 | node.setProperty(SIZE, file.length()); 130 | nodes.peek().createRelationshipTo(node, Relation.CHILD); 131 | if (file.isDirectory()) nodes.push(node); 132 | count++; 133 | if (count % 5000 == 0) { 134 | tx.success(); 135 | tx.finish(); 136 | tx = graph.beginTx(); 137 | System.out.println("commit " + count); 138 | } 139 | } 140 | 141 | public void upTo(final File file) { 142 | nodes.pop(); 143 | } 144 | 145 | public void finish() { 146 | tx.success(); 147 | tx.finish(); 148 | } 149 | } 150 | 151 | private static class FileNodeCreator2 extends FileHandler { 152 | private final Stack nodes = new Stack(); 153 | private final GraphDatabaseService graph; 154 | int count = 0; 155 | private Transaction tx; 156 | 157 | public FileNodeCreator2(final GraphDatabaseService graph) { 158 | this.graph = graph; 159 | tx = graph.beginTx(); 160 | final Node rootNode = graph.getReferenceNode(); 161 | rootNode.setProperty(NAME, BASE_DIR); 162 | this.nodes.push(rootNode); 163 | } 164 | 165 | public void handle(final File file) { 166 | final Node node = graph.createNode(); 167 | node.setProperty(NAME, file.getName()); 168 | nodes.peek().createRelationshipTo(node, Relation.CHILD); 169 | if (file.isDirectory()) nodes.push(node); 170 | count++; 171 | } 172 | 173 | public void upTo(final File file) { 174 | nodes.pop(); 175 | } 176 | 177 | public void finish() { 178 | tx.success(); 179 | tx.finish(); 180 | } 181 | } 182 | } -------------------------------------------------------------------------------- /src/test/java/org/neo4j/datasource/java/ClassFileFinderTest.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | import org.neo4j.datasource.java.analyser.ClassFileIterator; 6 | import org.neo4j.datasource.java.analyser.ClassInspectUtils; 7 | 8 | public class ClassFileFinderTest extends TestCase { 9 | private ClassFileIterator classFileIterator; 10 | 11 | @Test 12 | public void testCreateNames() { 13 | checkFindInJar(classFileIterator.getJarLocationFromClassPath("dt.jar"), "javax/swing/text/JTextComponentBeanInfo"); 14 | } 15 | @Test 16 | public void testFindObject() { 17 | final String objectClassFile = "java/lang/Object"; 18 | checkFindInJar(classFileIterator.getJarLocationByClass(objectClassFile), objectClassFile); 19 | } 20 | @Test 21 | public void testFindJFrame() { 22 | final String objectClassFile = "javax/swing/JFrame"; 23 | checkFindInJar(classFileIterator.getJarLocationByClass(objectClassFile), objectClassFile); 24 | } 25 | 26 | @Test 27 | public void testFindTestCase() { 28 | final String objectClassFile = ClassInspectUtils.toSlashName(getClass()); 29 | checkFindInJar(classFileIterator.getJarLocationByClass(objectClassFile), objectClassFile); 30 | } 31 | 32 | private void checkFindInJar(final String jarPath, final String classFile) { 33 | System.out.printf("looking for %s in %s",classFile,jarPath); 34 | boolean classFound = false; 35 | for (String className : classFileIterator.getClassFileNames(jarPath)) { 36 | //System.out.println("classNames = " + className); 37 | if (className.equals(classFile)) classFound = true; 38 | } 39 | assertTrue(classFile + " found in " + jarPath, classFound); 40 | } 41 | 42 | @Test 43 | public void testGetJarLocationByClass() { 44 | assertTrue("found in dt.jar", classFileIterator.getJarLocationByClass("javax/swing/text/JTextComponentBeanInfo").startsWith("/Library/Java/JavaVirtualMachines")); 45 | } 46 | 47 | protected void setUp() throws Exception { 48 | super.setUp(); 49 | classFileIterator = new ClassFileIterator(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/org/neo4j/datasource/java/ClassFileLocatorTest.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java; 2 | 3 | import static org.junit.Assert.*; 4 | import org.junit.Test; 5 | import org.neo4j.datasource.java.analyser.ClassFileLocator; 6 | import org.neo4j.datasource.java.analyser.ClassInspectUtils; 7 | 8 | public class ClassFileLocatorTest { 9 | @Test 10 | public void testPath() { 11 | final ClassFileLocator locator = new ClassFileLocator(System.getProperty("java.class.path")); 12 | assertNotNull("found class " + getClass(), locator.resolveClassName(ClassInspectUtils.toSlashName(getClass()))); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/org/neo4j/datasource/java/ClassInspectorTest.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | import org.neo4j.datasource.java.analyser.RecordingInspector; 6 | import org.neo4j.datasource.java.declaration.ClassDeclaration; 7 | 8 | public class ClassInspectorTest extends TestCase { 9 | @Test 10 | public void testInspectObject() { 11 | final ClassDeclaration classDeclaration = new RecordingInspector().inspectClass(String.class); 12 | assertEquals("isObject","java.lang.String", classDeclaration.getName()); 13 | System.out.println("classInfo.getMethods() = " + classDeclaration.getMethods().values()); 14 | System.out.println("classInfo.getFields() = " + classDeclaration.getFields().values()); 15 | assertTrue("concat", classDeclaration.getMethods().containsKey("java.lang.String concat(java.lang.String)")); 16 | assertEquals("java.lang.Object", classDeclaration.getSuperClass().getName()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/org/neo4j/datasource/java/ClassTraversalTest.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java; 2 | 3 | import org.junit.After; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | import org.neo4j.datasource.java.analyser.ClassInspectUtils; 7 | import org.neo4j.datasource.java.declaration.neo.ClassRelations; 8 | import org.neo4j.datasource.java.declaration.neo.NeoClassDeclaration; 9 | import org.neo4j.datasource.java.declaration.neo.TypeNodeFinder; 10 | import org.neo4j.graphdb.Direction; 11 | import org.neo4j.graphdb.GraphDatabaseService; 12 | import org.neo4j.graphdb.Node; 13 | import org.neo4j.graphdb.Relationship; 14 | import org.neo4j.graphdb.traversal.TraversalDescription; 15 | import org.neo4j.kernel.EmbeddedGraphDatabase; 16 | import org.neo4j.kernel.Traversal; 17 | 18 | import java.io.Serializable; 19 | import java.util.List; 20 | import java.util.Set; 21 | 22 | import static org.junit.Assert.assertEquals; 23 | import static org.junit.Assert.assertTrue; 24 | 25 | public class ClassTraversalTest { 26 | private static final String SERIALIZABLE = Serializable.class.getName(); 27 | private static final String OBJECT = Object.class.getName(); 28 | private GraphDatabaseService graph; 29 | 30 | @Test 31 | public void testFindAllSerializableSubclasses() { 32 | final Node serializable = getType(graph, SERIALIZABLE); 33 | final TraversalDescription traversal = Traversal.description().relationships(ClassRelations.INTERFACE_TYPE, Direction.INCOMING); 34 | int count=0; 35 | for (Node node : traversal.traverse(serializable).nodes()) { 36 | count++; 37 | } 38 | assertEquals("subnodes of serializable found", 500, count); 39 | } 40 | 41 | @Test 42 | public void testGetObjectMethods() { 43 | final Node ob = getType(graph, OBJECT); 44 | final Iterable methods = ob.getRelationships(ClassRelations.METHOD_OF, Direction.BOTH); 45 | final Set methodNames = new NeoClassDeclaration(ob).getMethods().keySet(); 46 | assertTrue("hashCode", methodNames.contains("int hashCode()")); 47 | } 48 | 49 | private Node getType(final GraphDatabaseService graph, String name) { 50 | name = ClassInspectUtils.toClassName(name); 51 | final TypeNodeFinder nodeFinder = new TypeNodeFinder(graph); 52 | final Node serializable = nodeFinder.getTypeNode(name); 53 | assertEquals(name, serializable.getProperty("name")); 54 | return serializable; 55 | } 56 | 57 | @Before 58 | public void setUp() { 59 | graph = new EmbeddedGraphDatabase("classes.jar.neo.save"); 60 | } 61 | 62 | @After 63 | public void tearDown() { 64 | if (graph != null) 65 | graph.shutdown(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/test/java/org/neo4j/datasource/java/RecordingInspectorNeoTest.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java; 2 | 3 | import org.junit.After; 4 | import org.junit.Test; 5 | import org.neo4j.datasource.java.analyser.ClassFileIterator; 6 | import org.neo4j.datasource.java.analyser.RecordingInspector; 7 | import org.neo4j.datasource.java.declaration.ClassDeclaration; 8 | import org.neo4j.datasource.java.declaration.neo.NeoDeclarationFactory; 9 | import org.neo4j.graphdb.GraphDatabaseService; 10 | import org.neo4j.graphdb.Transaction; 11 | import org.neo4j.kernel.EmbeddedGraphDatabase; 12 | 13 | import javax.swing.text.JTextComponentBeanInfo; 14 | import java.io.IOException; 15 | 16 | import static org.junit.Assert.assertEquals; 17 | import static org.junit.Assert.assertTrue; 18 | import static org.neo4j.test.NeoTestHelper.dropNeoDb; 19 | 20 | public class RecordingInspectorNeoTest { 21 | private GraphDatabaseService graph; 22 | 23 | @Test 24 | public void testIterateDtJar() { 25 | final String neoStoreName = "dt.jar.neo"; 26 | dropNeoDb(neoStoreName); 27 | graph = new EmbeddedGraphDatabase(neoStoreName); 28 | final Transaction tx = graph.beginTx(); 29 | final ClassFileIterator fileIterator = new ClassFileIterator(); 30 | final String jarFileLocation = fileIterator.getJarLocationByClass(JTextComponentBeanInfo.class); 31 | final RecordingInspector inspector = new RecordingInspector(); 32 | inspector.setDeclarationFactory(new NeoDeclarationFactory(graph)); 33 | long count = 0; 34 | for (final String classFileName : fileIterator.getClassFileNames(jarFileLocation)) { 35 | inspector.inspectClass(classFileName); 36 | count++; 37 | } 38 | tx.success(); 39 | tx.finish(); 40 | assertTrue("Files in dt.jar", count > 40); 41 | } 42 | 43 | @Test 44 | public void testIterateClassesJar() throws IOException { 45 | // /Volumes/ramdisk/ 46 | final String neoStoreName = "classes.jar.neo"; 47 | Class type = Object.class; 48 | dropNeoDb(neoStoreName); 49 | graph = new EmbeddedGraphDatabase(neoStoreName); 50 | Transaction tx = graph.beginTx(); 51 | final RecordingInspector inspector = new RecordingInspector(); 52 | final NeoDeclarationFactory infoFactory = new NeoDeclarationFactory(graph); 53 | inspector.setDeclarationFactory(infoFactory); 54 | long count = 0; 55 | final ClassFileIterator fileIterator = new ClassFileIterator(); 56 | final String jarFileLocation = fileIterator.getJarLocationByClass(type); 57 | 58 | long time = System.currentTimeMillis(); 59 | for (final String classFileName : fileIterator.getClassFileNames(jarFileLocation)) { 60 | final ClassDeclaration classDeclaration = inspector.inspectClass(classFileName); 61 | // System.out.println(classFileName+" -> "+classInfo); 62 | count++; 63 | if (count % 500 == 0) { 64 | tx.success(); 65 | tx.finish(); 66 | tx = graph.beginTx(); 67 | 68 | long delta = (System.currentTimeMillis() - time); 69 | System.out.println("count = " + count + " took " + delta + " ms."); 70 | System.out.println("infoFactory status: " + infoFactory.toString()); 71 | time = System.currentTimeMillis(); 72 | } 73 | } 74 | tx.success(); 75 | tx.finish(); 76 | assertTrue("Files in classes.jar", count>1900); 77 | } 78 | 79 | /* 80 | without signature caching and with field/method relationships in both directions 81 | classFileName = java/lang/Object.class 82 | count = 500 took 8397 ms. 83 | count = 1000 took 8039 ms. 84 | count = 1500 took 14713 ms. 85 | count = 2000 took 19289 ms. 86 | count = 2500 took 22172 ms. 87 | count = 3000 took 26939 ms. 88 | count = 3500 took 27085 ms. 89 | count = 4000 took 39363 ms. 90 | count = 4500 took 24075 ms. 91 | count = 5000 took 28837 ms. 92 | count = 5500 took 49173 ms. 93 | count = 6000 took 44835 ms. 94 | count = 6500 took 52506 ms. 95 | count = 7000 took 52505 ms. 96 | count = 7500 took 53512 ms. 97 | count = 8000 took 54138 ms. 98 | count = 8500 took 60008 ms. 99 | */ 100 | @After 101 | public void tearDown() { 102 | if (graph != null) 103 | graph.shutdown(); 104 | } 105 | } -------------------------------------------------------------------------------- /src/test/java/org/neo4j/datasource/java/RecordingInspectorTest.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java; 2 | 3 | import static org.junit.Assert.*; 4 | import org.junit.Test; 5 | import org.neo4j.datasource.java.analyser.*; 6 | import org.neo4j.datasource.java.declaration.ClassDeclaration; 7 | import org.neo4j.datasource.util.SizeCountingOutputStream; 8 | 9 | import javax.swing.text.JTextComponentBeanInfo; 10 | import java.io.IOException; 11 | import java.io.ObjectOutputStream; 12 | import java.util.Map; 13 | 14 | public class RecordingInspectorTest { 15 | @Test 16 | public void testIterateDtJar() { 17 | final ClassFileIterator fileIterator = new ClassFileIterator(); 18 | final RecordingInspector inspector = new RecordingInspector(); 19 | long count = 0; 20 | for (final String classFileName : fileIterator.getClassFileNames(fileIterator.getJarLocationByClass(JTextComponentBeanInfo.class))) { 21 | inspector.inspectClass(classFileName); 22 | count++; 23 | } 24 | assertEquals("Files in dt.jar", 47, count); 25 | } 26 | 27 | @Test 28 | public void testIterateClassesJar() throws IOException { 29 | final RecordingInspector inspector = new RecordingInspector(); 30 | checkAndRunClassesJar(inspector); 31 | final Map classes = inspector.getClasses(); 32 | final SizeCountingOutputStream countingStream = new SizeCountingOutputStream(); 33 | new ObjectOutputStream(countingStream).writeObject(classes); 34 | System.out.println("countingStream = " + countingStream.getCount()); 35 | assertTrue("20 MB of data", countingStream.getCount() > 20 * 1024 * 1024); 36 | } 37 | 38 | @Test 39 | public void testTimeClassesJar() throws IOException { 40 | final ClassInspector inspector = new ClassInspector(ClassInspectUtils.getClassPath()) { 41 | protected RecursingClassVisitor createVisitor() { 42 | return new NullClassVisitor(); 43 | } 44 | }; 45 | checkAndRunClassesJar(inspector); 46 | } 47 | 48 | private void checkAndRunClassesJar(final ClassInspector inspector) { 49 | final ClassFileIterator fileIterator = new ClassFileIterator(); 50 | final String jarFileLocation = fileIterator.getJarLocationByClass(Object.class); 51 | long count = 0; 52 | long time = System.currentTimeMillis(); 53 | for (final String classFileName : fileIterator.getClassFileNames(jarFileLocation)) { 54 | final T result = inspector.inspectClass(classFileName); 55 | count++; 56 | if (count % 500 == 0) { 57 | long delta = (System.currentTimeMillis() - time); 58 | System.out.println("count = " + count + " took " + delta + " ms."); 59 | time = System.currentTimeMillis(); 60 | } 61 | } 62 | assertEquals("Files in classes.jar", 19196, count); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/org/neo4j/datasource/java/VirtualInspectorTest.java: -------------------------------------------------------------------------------- 1 | package org.neo4j.datasource.java; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | import org.neo4j.datasource.java.analyser.ClassInspector; 6 | import org.neo4j.datasource.java.analyser.RecursingClassVisitor; 7 | import org.neo4j.datasource.java.analyser.VirtualVisitor; 8 | 9 | public class VirtualInspectorTest extends TestCase { 10 | @Test 11 | public void testInspectObject() { 12 | new ClassInspector(System.getProperty("java.class.path")) { 13 | protected RecursingClassVisitor createVisitor() { 14 | return VirtualVisitor.visitor(RecursingClassVisitor.class, this, 0); 15 | } 16 | }.inspectClass(Object.class); 17 | } 18 | 19 | @Test 20 | public void testInspectTest() { 21 | new ClassInspector(System.getProperty("java.class.path")) { 22 | protected RecursingClassVisitor createVisitor() { 23 | return VirtualVisitor.visitor(RecursingClassVisitor.class, this, 0); 24 | } 25 | }.inspectClass(getClass()); 26 | } 27 | } --------------------------------------------------------------------------------