2424import java .io .IOException ;
2525import java .net .URI ;
2626import java .util .HashMap ;
27+ import java .util .LinkedHashMap ;
2728import java .util .Map ;
29+ import java .util .Map .Entry ;
2830import org .eclipse .core .filesystem .URIUtil ;
31+ import org .eclipse .core .internal .events .BuildCommand ;
2932import org .eclipse .core .internal .localstore .SafeChunkyInputStream ;
3033import org .eclipse .core .internal .localstore .SafeChunkyOutputStream ;
3134import org .eclipse .core .internal .utils .Messages ;
3235import org .eclipse .core .internal .utils .Policy ;
3336import org .eclipse .core .resources .IBuildConfiguration ;
37+ import org .eclipse .core .resources .ICommand ;
3438import org .eclipse .core .resources .IProject ;
3539import org .eclipse .core .resources .IResource ;
3640import org .eclipse .core .resources .IResourceStatus ;
@@ -330,6 +334,8 @@ public ProjectDescription readOldDescription(IProject project) throws CoreExcept
330334 * location should be used. In the case of failure, log the exception and
331335 * return silently, thus reverting to using the default location and no
332336 * dynamic references. The current format of the location file is:
337+ *
338+ * <pre>
333339 * UTF - project location
334340 * int - number of dynamic project references
335341 * UTF - project reference 1
@@ -347,6 +353,19 @@ public ProjectDescription readOldDescription(IProject project) throws CoreExcept
347353 * UTF - configName if hasConfigName
348354 * ... repeat for number of referenced configurations
349355 * ... repeat for number of build configurations with references
356+ * since 3.23:
357+ * bool - private flag if project should only be read from its private project configuration
358+ * int - number of natures
359+ * UTF - nature id
360+ * ... repeated for N natures
361+ * int - number of buildspecs
362+ * byte - type of buildspec
363+ * (type 1) UTF - name of builder
364+ * int - number of arguments
365+ * UTF arg key
366+ * UTF arg value
367+ * UTF - triggers string
368+ * </pre>
350369 */
351370 public void readPrivateDescription (IProject target , ProjectDescription description ) {
352371 IPath locationFile = locationFor (target ).append (F_PROJECT_LOCATION );
@@ -357,6 +376,17 @@ public void readPrivateDescription(IProject target, ProjectDescription descripti
357376 if (!file .exists ())
358377 return ;
359378 }
379+ try {
380+ readFromFile (target , description , file );
381+ } catch (IOException e ) {
382+ //ignore - this is an old location file or an exception occurred
383+ // closing the stream
384+ }
385+ }
386+
387+ @ SuppressWarnings ("deprecation" )
388+ public void readFromFile (IProject target , ProjectDescription description , java .io .File file ) throws IOException {
389+ description .setName (target .getName ());
360390 try (DataInputStream dataIn = new DataInputStream (new SafeChunkyInputStream (file , 500 ))) {
361391 try {
362392 String location = dataIn .readUTF ();
@@ -408,9 +438,34 @@ public void readPrivateDescription(IProject target, ProjectDescription descripti
408438 m .put (configName , refs );
409439 }
410440 description .setBuildConfigReferences (m );
411- } catch (IOException e ) {
412- //ignore - this is an old location file or an exception occurred
413- // closing the stream
441+ // read parts since 3.23
442+ int natures = dataIn .readInt ();
443+ String [] natureIds = new String [natures ];
444+ for (int i = 0 ; i < natures ; i ++) {
445+ natureIds [i ] = dataIn .readUTF ();
446+ }
447+ description .setNatureIds (natureIds );
448+ int buildspecs = dataIn .readInt ();
449+ ICommand [] buildSpecData = new ICommand [buildspecs ];
450+ for (int i = 0 ; i < buildspecs ; i ++) {
451+ BuildCommand command = new BuildCommand ();
452+ buildSpecData [i ] = command ;
453+ int type = dataIn .read ();
454+ if (type == 1 ) {
455+ command .setName (dataIn .readUTF ());
456+ int args = dataIn .readInt ();
457+ Map <String , String > map = new LinkedHashMap <>();
458+ for (int j = 0 ; j < args ; j ++) {
459+ map .put (dataIn .readUTF (), dataIn .readUTF ());
460+ }
461+ command .setArguments (map );
462+ String trigger = dataIn .readUTF ();
463+ if (!trigger .isEmpty ()) {
464+ ProjectDescriptionReader .parseBuildTriggers (command , trigger );
465+ }
466+ }
467+ }
468+ description .setBuildSpec (buildSpecData );
414469 }
415470 }
416471
@@ -426,13 +481,25 @@ public void writePrivateDescription(IProject target) throws CoreException {
426481 Workspace .clear (file );
427482 //don't write anything if there is no interesting private metadata
428483 ProjectDescription desc = ((Project ) target ).internalGetDescription ();
484+ try {
485+ writeToFile (desc , file );
486+ } catch (IOException e ) {
487+ String message = NLS .bind (Messages .resources_exSaveProjectLocation , target .getName ());
488+ throw new ResourceException (IResourceStatus .INTERNAL_ERROR , null , message , e );
489+ }
490+ }
491+
492+ public void writeToFile (ProjectDescription desc , java .io .File file ) throws IOException {
429493 if (desc == null )
430494 return ;
431495 final URI projectLocation = desc .getLocationURI ();
432496 final IProject [] prjRefs = desc .getDynamicReferences (false );
433497 final String [] buildConfigs = desc .configNames ;
434498 final Map <String , IBuildConfiguration []> configRefs = desc .getBuildConfigReferences (false );
435- if (projectLocation == null && prjRefs .length == 0 && buildConfigs .length == 0 && configRefs .isEmpty ())
499+ final String [] natureIds = desc .getNatureIds ();
500+ final ICommand [] buildSpec = desc .getBuildSpec (false );
501+ if (projectLocation == null && prjRefs .length == 0 && buildConfigs .length == 0 && configRefs .isEmpty ()
502+ && natureIds .length == 0 && buildSpec .length == 0 )
436503 return ;
437504 //write the private metadata file
438505 try (SafeChunkyOutputStream output = new SafeChunkyOutputStream (file ); DataOutputStream dataOut = new DataOutputStream (output );) {
@@ -470,10 +537,33 @@ public void writePrivateDescription(IProject target) throws CoreException {
470537 }
471538 }
472539 }
540+ // write parts since 3.23
541+ dataOut .writeInt (natureIds .length );
542+ for (String id : natureIds ) {
543+ dataOut .writeUTF (id );
544+ }
545+ dataOut .writeInt (buildSpec .length );
546+ for (ICommand command : buildSpec ) {
547+ if (command instanceof BuildCommand b ) {
548+ dataOut .write (1 );
549+ dataOut .writeUTF (b .getName ());
550+ Map <String , String > arguments = b .getArguments ();
551+ dataOut .writeInt (arguments .size ());
552+ for (Entry <String , String > entry : arguments .entrySet ()) {
553+ dataOut .writeUTF (entry .getKey ());
554+ dataOut .writeUTF (entry .getValue ());
555+ }
556+ if (ModelObjectWriter .shouldWriteTriggers (b )) {
557+ dataOut .writeUTF (ModelObjectWriter .triggerString (b ));
558+ } else {
559+ dataOut .writeUTF ("" ); //$NON-NLS-1$
560+ }
561+ } else {
562+ dataOut .write (0 );
563+ }
564+ }
565+ dataOut .flush ();
473566 output .succeed ();
474- } catch (IOException e ) {
475- String message = NLS .bind (Messages .resources_exSaveProjectLocation , target .getName ());
476- throw new ResourceException (IResourceStatus .INTERNAL_ERROR , null , message , e );
477567 }
478568 }
479569}
0 commit comments