15
15
16
16
import static org .eclipse .jdt .ls .core .internal .JVMConfigurator .configureJVMSettings ;
17
17
18
+ import java .io .ByteArrayInputStream ;
18
19
import java .io .File ;
20
+ import java .io .IOException ;
19
21
import java .net .URI ;
20
22
import java .util .ArrayList ;
21
23
import java .util .Arrays ;
29
31
import java .util .stream .Stream ;
30
32
31
33
import org .apache .commons .lang3 .StringUtils ;
34
+ import org .eclipse .core .internal .preferences .EclipsePreferences ;
32
35
import org .eclipse .core .internal .resources .CharsetManager ;
33
36
import org .eclipse .core .internal .resources .Workspace ;
34
37
import org .eclipse .core .resources .FileInfoMatcherDescription ;
38
+ import org .eclipse .core .resources .IFile ;
35
39
import org .eclipse .core .resources .IFolder ;
36
40
import org .eclipse .core .resources .IMarker ;
37
41
import org .eclipse .core .resources .IProject ;
52
56
import org .eclipse .core .runtime .IProgressMonitor ;
53
57
import org .eclipse .core .runtime .IStatus ;
54
58
import org .eclipse .core .runtime .MultiStatus ;
59
+ import org .eclipse .core .runtime .NullProgressMonitor ;
55
60
import org .eclipse .core .runtime .OperationCanceledException ;
56
61
import org .eclipse .core .runtime .Platform ;
57
62
import org .eclipse .core .runtime .Status ;
@@ -343,6 +348,45 @@ public static IProject createJavaProject(IProject project, IProgressMonitor moni
343
348
return createJavaProject (project , null , "src" , "bin" , monitor );
344
349
}
345
350
351
+ /*
352
+ * ⚠ These value is duplicated in ProjectsManager as both bundles must remain independent,
353
+ * but the same dir should be used for .project or .settings/.classpath.
354
+ * So when updating one, think about updating the other.
355
+ */
356
+ public static final String GENERATES_METADATA_FILES_AT_PROJECT_ROOT = "java.import.generatesMetadataFilesAtProjectRoot" ;
357
+ public static final IPath METADATA_FOLDER_PATH = ResourcesPlugin .getWorkspace ().getRoot ().getLocation ().append (".projects" );
358
+
359
+ /**
360
+ * Check whether the metadata files needs to be generated at project root.
361
+ */
362
+ public static boolean generatesMetadataFilesAtProjectRoot () {
363
+ String property = System .getProperty (GENERATES_METADATA_FILES_AT_PROJECT_ROOT );
364
+ if (property == null ) {
365
+ return true ;
366
+ }
367
+ return Boolean .parseBoolean (property );
368
+ }
369
+
370
+ /**
371
+ * Get the redirected path of the input path. The path will be redirected to
372
+ * the workspace's metadata folder ({@link JLSFsUtils#METADATA_FOLDER_PATH}).
373
+ * @param projectName name of the project.
374
+ * @param path path needs to be redirected.
375
+ * @return the redirected path.
376
+ */
377
+ public static IPath getMetaDataFilePath (String projectName , IPath path ) {
378
+ if (path .segmentCount () == 1 ) {
379
+ return METADATA_FOLDER_PATH .append (projectName ).append (path );
380
+ }
381
+
382
+ String lastSegment = path .lastSegment ();
383
+ if (IProjectDescription .DESCRIPTION_FILE_NAME .equals (lastSegment )) {
384
+ return METADATA_FOLDER_PATH .append (projectName ).append (lastSegment );
385
+ }
386
+
387
+ return null ;
388
+ }
389
+
346
390
public static IProject createJavaProject (IProject project , IPath projectLocation , String src , String bin , IProgressMonitor monitor ) throws CoreException , OperationCanceledException {
347
391
if (project .exists ()) {
348
392
return project ;
@@ -355,6 +399,9 @@ public static IProject createJavaProject(IProject project, IPath projectLocation
355
399
}
356
400
project .create (description , monitor );
357
401
project .open (monitor );
402
+ if (!generatesMetadataFilesAtProjectRoot ()) {
403
+ linkResources (project );
404
+ }
358
405
359
406
//Turn into Java project
360
407
description = project .getDescription ();
@@ -396,6 +443,49 @@ public static IProject createJavaProject(IProject project, IPath projectLocation
396
443
return project ;
397
444
}
398
445
446
+ public static void linkResources (IProject project ) throws CoreException {
447
+ {
448
+ IFolder settingsFolder = project .getFolder (EclipsePreferences .DEFAULT_PREFERENCES_DIRNAME );
449
+ if (!settingsFolder .exists ()) {
450
+ File diskFolder = getMetaDataFilePath (settingsFolder .getProject ().getName (), settingsFolder .getProjectRelativePath ()).toFile ();
451
+ diskFolder .mkdirs ();
452
+ settingsFolder .createLink (diskFolder .toURI (), IResource .NONE , new NullProgressMonitor ());
453
+ }
454
+ }
455
+ {
456
+ IFile classpathFile = project .getFile (IJavaProject .CLASSPATH_FILE_NAME );
457
+ if (!classpathFile .exists ()) {
458
+ File diskFile = getMetaDataFilePath (classpathFile .getProject ().getName (), classpathFile .getProjectRelativePath ()).toFile ();
459
+ if (!diskFile .exists ()) {
460
+ try {
461
+ diskFile .getParentFile ().mkdirs ();
462
+ diskFile .createNewFile ();
463
+ } catch (IOException ex ) {
464
+ throw new CoreException (Status .error (diskFile + " cannot be created" , ex )); //$NON-NLS-1$
465
+ }
466
+ }
467
+ classpathFile .createLink (diskFile .toURI (), IResource .NONE , new NullProgressMonitor ());
468
+ classpathFile .setContents (new ByteArrayInputStream ("<classpath/>" .getBytes ()), 0 , null );
469
+ }
470
+ }
471
+ {
472
+ IFile factorypathFile = project .getFile (".factorypath" );
473
+ if (!factorypathFile .exists ()) {
474
+ File diskFile = getMetaDataFilePath (factorypathFile .getProject ().getName (), factorypathFile .getProjectRelativePath ()).toFile ();
475
+ if (!diskFile .exists ()) {
476
+ try {
477
+ diskFile .getParentFile ().mkdirs ();
478
+ diskFile .createNewFile ();
479
+ } catch (IOException ex ) {
480
+ throw new CoreException (Status .error (diskFile + " cannot be created" , ex )); //$NON-NLS-1$
481
+ }
482
+ }
483
+ factorypathFile .createLink (diskFile .toURI (), IResource .NONE , new NullProgressMonitor ());
484
+ factorypathFile .setContents (new ByteArrayInputStream ("<factorypath/>" .getBytes ()), 0 , null );
485
+ }
486
+ }
487
+ }
488
+
399
489
@ Override
400
490
public Job updateProject (IProject project , boolean force ) {
401
491
if (project == null || ProjectUtils .isInternalBuildSupport (BuildSupportManager .find (project ).orElse (null ))) {
@@ -426,6 +516,7 @@ public IStatus runInWorkspace(IProgressMonitor monitor) {
426
516
updateEncoding (monitor );
427
517
project .deleteMarkers (BUILD_FILE_MARKER_TYPE , false , IResource .DEPTH_ONE );
428
518
long elapsed = System .currentTimeMillis () - start ;
519
+ replaceLinkedMetadataWithLocal (project );
429
520
JavaLanguageServerPlugin .logInfo ("Updated " + projectName + " in " + elapsed + " ms" );
430
521
} catch (Exception e ) {
431
522
String msg = "Error updating " + projectName ;
@@ -625,5 +716,12 @@ public void reportProjectsStatus() {
625
716
JavaLanguageServerPlugin .sendStatus (ServiceStatus .ProjectStatus , "OK" );
626
717
}
627
718
}
719
+
720
+ private void replaceLinkedMetadataWithLocal (IProject p ) throws CoreException {
721
+ if (new File (p .getLocation ().toFile (), IJavaProject .CLASSPATH_FILE_NAME ).exists () &&
722
+ p .getFile (IJavaProject .CLASSPATH_FILE_NAME ).isLinked ()) {
723
+ p .getFile (IJavaProject .CLASSPATH_FILE_NAME ).delete (false , false , null );
724
+ }
725
+ }
628
726
629
727
}
0 commit comments