1313 *******************************************************************************/
1414package org .eclipse .pde .internal .core ;
1515
16- import java .io .BufferedOutputStream ;
17- import java .io .File ;
18- import java .io .FileInputStream ;
19- import java .io .FileNotFoundException ;
20- import java .io .FileOutputStream ;
21- import java .io .InputStream ;
2216import java .util .ArrayList ;
2317import java .util .Arrays ;
24- import java .util .Collection ;
2518import java .util .Collections ;
2619import java .util .HashMap ;
2720import java .util .Iterator ;
2821import java .util .LinkedHashMap ;
2922import java .util .List ;
3023import java .util .Map ;
3124import java .util .Map .Entry ;
32- import java .util .Objects ;
33- import java .util .Queue ;
34- import java .util .concurrent .ConcurrentLinkedQueue ;
3525import java .util .regex .Pattern ;
3626import java .util .stream .Collectors ;
3727import java .util .stream .Stream ;
3828
3929import org .eclipse .core .resources .IFile ;
4030import org .eclipse .core .resources .IProject ;
4131import org .eclipse .core .resources .IResource ;
42- import org .eclipse .core .resources .IResourceChangeEvent ;
43- import org .eclipse .core .resources .IResourceChangeListener ;
44- import org .eclipse .core .resources .ResourcesPlugin ;
4532import org .eclipse .core .runtime .CoreException ;
4633import org .eclipse .core .runtime .IPath ;
47- import org .eclipse .core .runtime .IProgressMonitor ;
48- import org .eclipse .core .runtime .IStatus ;
49- import org .eclipse .core .runtime .MultiStatus ;
50- import org .eclipse .core .runtime .Status ;
51- import org .eclipse .core .runtime .SubMonitor ;
52- import org .eclipse .core .runtime .jobs .Job ;
5334import org .eclipse .jdt .core .IClasspathAttribute ;
5435import org .eclipse .jdt .core .IClasspathContainer ;
5536import org .eclipse .jdt .core .IClasspathEntry ;
6950import org .eclipse .pde .core .plugin .IPluginLibrary ;
7051import org .eclipse .pde .core .plugin .IPluginModelBase ;
7152import org .eclipse .pde .internal .core .build .WorkspaceBuildModel ;
72- import org .eclipse .pde .internal .core .natures .PluginProject ;
7353import org .eclipse .pde .internal .core .project .PDEProject ;
7454import org .eclipse .pde .internal .core .util .CoreUtility ;
75- import org .eclipse .pde .internal .core .util .PDEClasspathContainerSaveHelper ;
7655import org .eclipse .team .core .RepositoryProvider ;
7756
7857public class ClasspathComputer {
@@ -87,26 +66,6 @@ private record ClasspathConfiguration(IPluginModelBase model, IJavaProject javaP
8766 private static final int SEVERITY_WARNING = 2 ;
8867 private static final int SEVERITY_IGNORE = 1 ;
8968
90- /**
91- * Job used to update class path containers.
92- */
93- private static final UpdateClasspathsJob fUpdateJob = new UpdateClasspathsJob ();
94-
95- static final IResourceChangeListener CHANGE_LISTENER = new IResourceChangeListener () {
96-
97- @ Override
98- public void resourceChanged (IResourceChangeEvent event ) {
99- IResource resource = event .getResource ();
100- if (resource instanceof IProject project ) {
101- if (PDECore .DEBUG_STATE ) {
102- PDECore .TRACE .trace (PDECore .KEY_DEBUG_STATE ,
103- String .format ("Project %s was deleted." , project .getName ())); //$NON-NLS-1$
104- }
105- getStateFile (project ).delete ();
106- }
107- }
108- };
109-
11069 public static void setClasspath (IProject project , IPluginModelBase model ) throws CoreException {
11170 IClasspathEntry [] entries = getClasspath (project , model , null , false , true );
11271 JavaCore .create (project ).setRawClasspath (entries , null );
@@ -520,225 +479,4 @@ public static IClasspathEntry[] computeClasspathEntries(IPluginModelBase model,
520479 return container .getClasspathEntries ();
521480 }
522481
523- public static void requestClasspathUpdate (IProject project ) {
524- if (project == null ) {
525- return ;
526- }
527- requestClasspathUpdate (List .of (project ));
528- }
529-
530- public static void requestClasspathUpdate (Collection <IProject > updateProjects ) {
531- if (updateProjects == null || updateProjects .isEmpty ()) {
532- return ;
533- }
534- fUpdateJob .addAll (updateProjects );
535- }
536-
537- static void requestClasspathUpdate (IProject project , IClasspathContainer savedState ) {
538- fUpdateJob .add (project , savedState );
539- }
540-
541- /**
542- * Job to update class path containers asynchronously. Avoids blocking the
543- * UI thread. The job is given a workspace lock so other jobs can't run on a
544- * stale classpath.
545- */
546- private static final class UpdateClasspathsJob extends Job {
547-
548- private static final int WORK = 10_000 ;
549- private final Queue <UpdateRequest > workQueue = new ConcurrentLinkedQueue <>();
550-
551- /**
552- * Constructs a new job.
553- */
554- public UpdateClasspathsJob () {
555- super (PDECoreMessages .PluginModelManager_1 );
556- // The job is given a workspace lock so other jobs can't run on a
557- // stale classpath (bug 354993)
558- setRule (ResourcesPlugin .getWorkspace ().getRoot ());
559- }
560-
561- @ Override
562- public boolean belongsTo (Object family ) {
563- return family == PluginModelManager .class || family == ClasspathComputer .class ;
564- }
565-
566- @ Override
567- protected IStatus run (IProgressMonitor jobMonitor ) {
568- SubMonitor monitor = SubMonitor .convert (jobMonitor , PDECoreMessages .PluginModelManager_1 , WORK );
569- PluginModelManager .getInstance ().initialize (monitor .split (10 ));
570- PluginModelManager modelManager = PluginModelManager .getInstance ();
571- Map <IJavaProject , IClasspathContainer > updateProjects = new LinkedHashMap <>();
572- Map <IProject , IStatus > errorsPerProject = new LinkedHashMap <>();
573- UpdateRequest request ;
574- while (!monitor .isCanceled () && (request = workQueue .poll ()) != null ) {
575- monitor .setWorkRemaining (WORK );
576- IProject project = request .project ();
577- if (project .exists () && project .isOpen ()) {
578- IPluginModelBase model = modelManager .findModel (project );
579- if (model != null && PluginProject .isJavaProject (project )) {
580- IJavaProject javaProject = JavaCore .create (project );
581- RequiredPluginsClasspathContainer classpathContainer = new RequiredPluginsClasspathContainer (
582- model , project );
583- try {
584- if (!isUpToDate (project , classpathContainer .computeEntries (), request .container ())) {
585- updateProjects .put (javaProject , classpathContainer );
586- errorsPerProject .remove (project );
587- saveState (project , classpathContainer );
588- }
589- } catch (CoreException e ) {
590- errorsPerProject .put (project , e .getStatus ());
591- }
592- monitor .worked (1 );
593- }
594- }
595- }
596- if (monitor .isCanceled ()) {
597- return Status .CANCEL_STATUS ;
598- }
599- if (!updateProjects .isEmpty ()) {
600- int i = 0 ;
601- int n = updateProjects .size ();
602- IJavaProject [] javaProjects = new IJavaProject [n ];
603- IClasspathContainer [] container = new IClasspathContainer [n ];
604- for (Entry <IJavaProject , IClasspathContainer > entry : updateProjects .entrySet ()) {
605- javaProjects [i ] = entry .getKey ();
606- container [i ] = entry .getValue ();
607- i ++;
608- }
609- try {
610- setProjectContainers (javaProjects , container , monitor );
611- } catch (JavaModelException e ) {
612- return e .getStatus ();
613- }
614- }
615- IStatus [] errors = errorsPerProject .values ().toArray (IStatus []::new );
616- if (errors .length == 0 ) {
617- return Status .OK_STATUS ;
618- }
619- if (errors .length == 1 ) {
620- return errors [0 ];
621- }
622- MultiStatus overallStatus = new MultiStatus (ClasspathComputer .class , 0 ,
623- PDECoreMessages .ClasspathComputer_failed );
624- for (IStatus status : errors ) {
625- overallStatus .add (status );
626- }
627- return overallStatus ;
628- }
629-
630- /**
631- * Queues more projects/containers.
632- */
633- void addAll (Collection <IProject > tocheck ) {
634- for (IProject project : tocheck ) {
635- workQueue .add (new UpdateRequest (project , null ));
636- }
637- schedule ();
638- }
639-
640- void add (IProject project , IClasspathContainer classpathContainer ) {
641- if (project == null ) {
642- return ;
643- }
644- workQueue .add (new UpdateRequest (project , classpathContainer ));
645- schedule ();
646- }
647-
648- }
649-
650- private static boolean isUpToDate (IProject project , IClasspathEntry [] currentEntries ,
651- IClasspathContainer previousClasspathContainer ) {
652- if (previousClasspathContainer == null ) {
653- if (PDECore .DEBUG_STATE ) {
654- PDECore .TRACE .trace (PDECore .KEY_DEBUG_STATE ,
655- String .format ("%s need update because it has no state to compare" , project .getName ())); //$NON-NLS-1$
656- }
657- return false ;
658- }
659- IClasspathEntry [] previousEntries = previousClasspathContainer .getClasspathEntries ();
660- if (previousEntries == null || previousEntries .length != currentEntries .length ) {
661- if (PDECore .DEBUG_STATE ) {
662- PDECore .TRACE .trace (PDECore .KEY_DEBUG_STATE ,
663- String .format ("%s need update because entries do not match in size!" , //$NON-NLS-1$
664- project .getName ()));
665- }
666- return false ;
667- }
668- for (int i = 0 ; i < previousEntries .length ; i ++) {
669- IClasspathEntry previous = previousEntries [i ];
670- IClasspathEntry current = currentEntries [i ];
671- if (!Objects .equals (current , previous )) {
672- if (PDECore .DEBUG_STATE ) {
673- PDECore .TRACE .trace (PDECore .KEY_DEBUG_STATE ,
674- String .format ("%s need update because entry at position %d is different:\n \t %s\n \t %s" , //$NON-NLS-1$
675- project .getName (), i , current , previous ));
676- }
677- return false ;
678- }
679- }
680- return true ;
681- }
682-
683- private static void saveState (IProject project , RequiredPluginsClasspathContainer classpathContainer ) {
684- synchronized (project ) {
685- try {
686- File stateFile = getStateFile (project );
687- stateFile .getParentFile ().mkdirs ();
688- try (BufferedOutputStream stream = new BufferedOutputStream (new FileOutputStream (stateFile ))) {
689- PDEClasspathContainerSaveHelper .writeContainer (classpathContainer , stream );
690- }
691- } catch (Exception e ) {
692- // can't write then...
693- if (PDECore .DEBUG_STATE ) {
694- PDECore .TRACE .trace (PDECore .KEY_DEBUG_STATE ,
695- String .format ("Writing project state for %s failed!" , project .getName ()), //$NON-NLS-1$
696- e );
697- }
698- }
699- }
700- }
701-
702- static IClasspathContainer readState (IProject project ) {
703- synchronized (project ) {
704- try {
705- File stateFile = getStateFile (project );
706- try (InputStream stream = new FileInputStream (stateFile )) {
707- IClasspathContainer container = Objects
708- .requireNonNull (PDEClasspathContainerSaveHelper .readContainer (stream ));
709- if (PDECore .DEBUG_STATE ) {
710- PDECore .TRACE .trace (PDECore .KEY_DEBUG_STATE ,
711- String .format ("%s is restored from previous state." , project .getName ())); //$NON-NLS-1$
712- }
713- return container ;
714- }
715- } catch (Exception e ) {
716- if (PDECore .DEBUG_STATE ) {
717- if (e instanceof FileNotFoundException ) {
718- PDECore .TRACE .trace (PDECore .KEY_DEBUG_STATE ,
719- String .format ("%s has no saved state!" , project .getName ())); //$NON-NLS-1$
720- } else {
721- PDECore .TRACE .trace (PDECore .KEY_DEBUG_STATE ,
722- String .format ("Restoring project state for %s failed!" , project .getName ()), e ); //$NON-NLS-1$
723- }
724- }
725- return PDEClasspathContainerSaveHelper .emptyContainer ();
726- }
727- }
728- }
729-
730- static void setProjectContainers (IJavaProject [] javaProjects , IClasspathContainer [] container ,
731- IProgressMonitor monitor ) throws JavaModelException {
732- JavaCore .setClasspathContainer (PDECore .REQUIRED_PLUGINS_CONTAINER_PATH , javaProjects , container , monitor );
733- }
734-
735- private static File getStateFile (IProject project ) {
736- return PDECore .getDefault ().getStateLocation ().append ("cpc" ).append (project .getName ()) //$NON-NLS-1$
737- .toFile ();
738- }
739-
740- private static record UpdateRequest (IProject project , IClasspathContainer container ) {
741-
742- }
743-
744482}
0 commit comments