This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 42306
Collapse All | Expand All

(-)ant/project/src/org/netbeans/spi/project/support/ant/AntProjectHelper.java (-128 / +126 lines)
Lines 140-159 Link Here
140
    private final Set/*<String>*/ modifiedMetadataPaths = new HashSet();
140
    private final Set/*<String>*/ modifiedMetadataPaths = new HashSet();
141
    
141
    
142
    /**
142
    /**
143
     * Properties loaded from metadata files on disk.
144
     * Keys are project-relative paths such as {@link #PROJECT_PROPERTIES_PATH}.
145
     * Values are loaded properties objects, or null if the file did not exist.
146
     * If the key does not exist then it needs to be checked on disk.
147
     */
148
    private final Map/*<String,EditableProperties|null>*/ properties = new HashMap();
149
    
150
    /**
151
     * Registered listeners.
143
     * Registered listeners.
152
     * Access must be directly synchronized.
144
     * Access must be directly synchronized.
153
     */
145
     */
154
    private final List/*<AntProjectListener>*/ listeners = new ArrayList();
146
    private final List/*<AntProjectListener>*/ listeners = new ArrayList();
155
    
147
    
156
    // XXX lock any loaded files while the project is modified, to prevent manual editing,
148
    /**
149
     * List of loaded properties.
150
     */
151
    private final ProjectProperties properties;
152
    
153
    // XXX lock any loaded XML files while the project is modified, to prevent manual editing,
157
    // and reload any modified files if the project is unmodified
154
    // and reload any modified files if the project is unmodified
158
    
155
    
159
    private AntProjectHelper(FileObject dir, Document projectXml, ProjectState state, AntBasedProjectType type) {
156
    private AntProjectHelper(FileObject dir, Document projectXml, ProjectState state, AntBasedProjectType type) {
Lines 165-170 Link Here
165
        assert type != null;
162
        assert type != null;
166
        this.projectXml = projectXml;
163
        this.projectXml = projectXml;
167
        assert projectXml != null;
164
        assert projectXml != null;
165
        properties = new ProjectProperties(dir);
168
    }
166
    }
169
    
167
    
170
    /**
168
    /**
Lines 463-493 Link Here
463
                saveXml(privateXml, path);
461
                saveXml(privateXml, path);
464
            } else {
462
            } else {
465
                // All else is assumed to be a properties file.
463
                // All else is assumed to be a properties file.
466
                FileObject f = dir.getFileObject(path);
464
                properties.write(path);
467
                assert properties.containsKey(path);
468
                EditableProperties p = (EditableProperties)properties.get(path);
469
                if (p != null) {
470
                    // Supposed to create/modify the file.
471
                    if (f == null) {
472
                        f = FileUtil.createData(dir, path);
473
                    }
474
                    FileLock lock = f.lock();
475
                    try {
476
                        OutputStream os = f.getOutputStream(lock);
477
                        try {
478
                            p.store(os);
479
                        } finally {
480
                            os.close();
481
                        }
482
                    } finally {
483
                        lock.releaseLock();
484
                    }
485
                } else {
486
                    // We are supposed to remove any existing file.
487
                    if (f != null) {
488
                        f.delete();
489
                    }
490
                }
491
            }
465
            }
492
            // As metadata files are saved, take them off the modified list.
466
            // As metadata files are saved, take them off the modified list.
493
            it.remove();
467
            it.remove();
Lines 508-558 Link Here
508
     * @return a set of properties
482
     * @return a set of properties
509
     */
483
     */
510
    public EditableProperties getProperties(String path) {
484
    public EditableProperties getProperties(String path) {
511
        EditableProperties p = getPropertiesOrNull(path);
485
        if (path.equals(AntProjectHelper.PROJECT_XML_PATH) || path.equals(AntProjectHelper.PRIVATE_XML_PATH)) {
512
        if (p != null) {
486
            throw new IllegalArgumentException("Attempt to load properties from a project XML file"); // NOI18N
513
            return p;
514
        } else {
515
            return new EditableProperties(true);
516
        }
487
        }
517
    }
488
        return properties.getProperties(path);
518
    
519
    /**
520
     * Like {@link #getProperties} but a missing or broken file results
521
     * in a null return rather than an empty properties object.
522
     */
523
    private EditableProperties getPropertiesOrNull(String path) {
524
        if (path.equals(PROJECT_XML_PATH) || path.equals(PRIVATE_XML_PATH)) {
525
            throw new IllegalArgumentException("Attempt to load/store properties from a project XML file"); // NOI18N
526
        }
527
        if (properties.containsKey(path)) {
528
            // In cache.
529
            EditableProperties p = (EditableProperties)properties.get(path);
530
            if (p == null) {
531
                return null;
532
            } else {
533
                return p.cloneProperties();
534
            }
535
        }
536
        // Not in cache.
537
        FileObject fo = dir.getFileObject(path);
538
        if (fo != null) {
539
            try {
540
                InputStream is = fo.getInputStream();
541
                try {
542
                    EditableProperties p = new EditableProperties(true);
543
                    p.load(is);
544
                    properties.put(path, p);
545
                    return p.cloneProperties();
546
                } finally {
547
                    is.close();
548
                }
549
            } catch (IOException e) {
550
                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
551
            }
552
        }
553
        // Broken or missing.
554
        properties.put(path, null);
555
        return null;
556
    }
489
    }
557
    
490
    
558
    /**
491
    /**
Lines 569-580 Link Here
569
     * @param props a set of properties to store, or null to delete any existing properties file there
502
     * @param props a set of properties to store, or null to delete any existing properties file there
570
     */
503
     */
571
    public void putProperties(String path, EditableProperties props) {
504
    public void putProperties(String path, EditableProperties props) {
572
        if (Utilities.compareObjects(props, getPropertiesOrNull(path))) {
505
        if (path.equals(AntProjectHelper.PROJECT_XML_PATH) || path.equals(AntProjectHelper.PRIVATE_XML_PATH)) {
573
            // No change.
506
            throw new IllegalArgumentException("Attempt to store properties from a project XML file"); // NOI18N
574
            return;
507
        }
508
        if (properties.putProperties(path, props)) {
509
            modifying(path);
575
        }
510
        }
576
        properties.put(path, props.cloneProperties());
511
    }
577
        modifying(path);
512
    
513
    /**
514
     * Get a property provider that works with loadable project properties.
515
     * Its current values should match {@link #getProperties}, and calls to
516
     * {@link #putProperties} should cause it to fire changes.
517
     * @param path a relative URI in the project directory, e.g.
518
     *             {@link #PROJECT_PROPERTIES_PATH} or {@link #PRIVATE_PROPERTIES_PATH}
519
     * @return a property provider implementation
520
     */
521
    public PropertyProvider getPropertyProvider(String path) {
522
        if (path.equals(AntProjectHelper.PROJECT_XML_PATH) || path.equals(AntProjectHelper.PRIVATE_XML_PATH)) {
523
            throw new IllegalArgumentException("Attempt to store properties from a project XML file"); // NOI18N
524
        }
525
        return properties.getPropertyProvider(path);
578
    }
526
    }
579
    
527
    
580
    /**
528
    /**
Lines 717-722 Link Here
717
        return new ExtensibleMetadataProviderImpl(this);
665
        return new ExtensibleMetadataProviderImpl(this);
718
    }
666
    }
719
    
667
    
668
    /** @deprecated Use the variant that accepts a property evaluator instead. */
669
    public FileBuiltQueryImplementation createGlobFileBuiltQuery(String[] from, String[] to) throws IllegalArgumentException {
670
        return createGlobFileBuiltQuery(getStandardPropertyEvaluator(), from, to);
671
    }
672
    
720
    /**
673
    /**
721
     * Create an implementation of {@link FileBuiltQuery} that works with files
674
     * Create an implementation of {@link FileBuiltQuery} that works with files
722
     * within the project based on simple glob pattern mappings.
675
     * within the project based on simple glob pattern mappings.
Lines 728-734 Link Here
728
     * glob pattern - this must include exactly one asterisk (<code>*</code>)
681
     * glob pattern - this must include exactly one asterisk (<code>*</code>)
729
     * representing a variable portion of a source file path (always slash-separated
682
     * representing a variable portion of a source file path (always slash-separated
730
     * and relative to the project directory) and may include some Ant property
683
     * and relative to the project directory) and may include some Ant property
731
     * references which will be resolved as per {@link AntProjectHelper#evaluateString}.
684
     * references which will be resolved as per the property evaluator.
732
     * A file is considered out of date if there is no file represented by the
685
     * A file is considered out of date if there is no file represented by the
733
     * matching target pattern (which has the same format), or the target file is older
686
     * matching target pattern (which has the same format), or the target file is older
734
     * than the source file, or the source file is modified as per
687
     * than the source file, or the source file is modified as per
Lines 753-758 Link Here
753
     * <li><samp>${test.build.classes.dir}/*.class</samp>
706
     * <li><samp>${test.build.classes.dir}/*.class</samp>
754
     * </ol>
707
     * </ol>
755
     * </div>
708
     * </div>
709
     * @param a property evaluator to interpret the patterns with
756
     * @param from a list of glob patterns for source files
710
     * @param from a list of glob patterns for source files
757
     * @param to a matching list of glob patterns for built files
711
     * @param to a matching list of glob patterns for built files
758
     * @return a query implementation
712
     * @return a query implementation
Lines 760-767 Link Here
760
     *                                  have zero or multiple asterisks,
714
     *                                  have zero or multiple asterisks,
761
     *                                  or the arrays are not of equal lengths
715
     *                                  or the arrays are not of equal lengths
762
     */
716
     */
763
    public FileBuiltQueryImplementation createGlobFileBuiltQuery(String[] from, String[] to) throws IllegalArgumentException {
717
    public FileBuiltQueryImplementation createGlobFileBuiltQuery(PropertyEvaluator eval, String[] from, String[] to) throws IllegalArgumentException {
764
        return new GlobFileBuiltQuery(this, from, to);
718
        return new GlobFileBuiltQuery(this, eval, from, to);
719
    }
720
721
    /** @deprecated Use the variant that accepts a PropertyEvaluator instead. */
722
    public AntArtifact createSimpleAntArtifact(String type, String locationProperty, String targetName, String cleanTargetName) {
723
        return createSimpleAntArtifact(type, locationProperty, getStandardPropertyEvaluator(), targetName, cleanTargetName);
765
    }
724
    }
766
    
725
    
767
    /**
726
    /**
Lines 770-783 Link Here
770
     * @param type the type of artifact, e.g. {@link AntArtifact#TYPE_JAR}
729
     * @param type the type of artifact, e.g. {@link AntArtifact#TYPE_JAR}
771
     * @param locationProperty an Ant property name giving the project-relative
730
     * @param locationProperty an Ant property name giving the project-relative
772
     *                         location of the artifact, e.g. <samp>dist.jar</samp>
731
     *                         location of the artifact, e.g. <samp>dist.jar</samp>
732
     * @param eval a way to evaluate the location property (e.g. {@link #getStandardPropertyEvaluator})
773
     * @param targetName the name of an Ant target which will build the artifact,
733
     * @param targetName the name of an Ant target which will build the artifact,
774
     *                   e.g. <samp>jar</samp>
734
     *                   e.g. <samp>jar</samp>
775
     * @param cleanTargetName the name of an Ant target which will delete the artifact
735
     * @param cleanTargetName the name of an Ant target which will delete the artifact
776
     *                        (and maybe other build products), e.g. <samp>clean</samp>
736
     *                        (and maybe other build products), e.g. <samp>clean</samp>
777
     * @return an artifact
737
     * @return an artifact
778
     */
738
     */
779
    public AntArtifact createSimpleAntArtifact(String type, String locationProperty, String targetName, String cleanTargetName) {
739
    public AntArtifact createSimpleAntArtifact(String type, String locationProperty, PropertyEvaluator eval, String targetName, String cleanTargetName) {
780
        return new SimpleAntArtifact(this, type, locationProperty, targetName, cleanTargetName);
740
        return new SimpleAntArtifact(this, type, locationProperty, eval, targetName, cleanTargetName);
741
    }
742
    
743
    /** @deprecated Use the variant that takes a property evaluator instead. */
744
    public SharabilityQueryImplementation createSharabilityQuery(String[] sourceRoots, String[] buildDirectories) {
745
        return createSharabilityQuery(getStandardPropertyEvaluator(), sourceRoots, buildDirectories);
781
    }
746
    }
782
    
747
    
783
    /**
748
    /**
Lines 816-822 Link Here
816
     * Typical usage would be:
781
     * Typical usage would be:
817
     * </p>
782
     * </p>
818
     * <pre>
783
     * <pre>
819
     * helper.createSharabilityQuery(new String[] {"${src.dir}", "${test.src.dir}"},
784
     * helper.createSharabilityQuery(helper.getStandardPropertyEvaluator(),
785
     *                               new String[] {"${src.dir}", "${test.src.dir}"},
820
     *                               new String[] {"${build.dir}", "${dist.dir}"})
786
     *                               new String[] {"${build.dir}", "${dist.dir}"})
821
     * </pre>
787
     * </pre>
822
     * <p>
788
     * <p>
Lines 837-855 Link Here
837
     * this implementation in your project lookup and may return <code>UNKNOWN</code>.
803
     * this implementation in your project lookup and may return <code>UNKNOWN</code>.
838
     * </p>
804
     * </p>
839
     * </div>
805
     * </div>
806
     * @param eval a property evaluator to interpret paths with
840
     * @param sourceRoots a list of additional paths to treat as sharable
807
     * @param sourceRoots a list of additional paths to treat as sharable
841
     * @param buildDirectories a list of paths to treat as not sharable
808
     * @param buildDirectories a list of paths to treat as not sharable
842
     * @return a sharability query implementation suitable for the project lookup
809
     * @return a sharability query implementation suitable for the project lookup
843
     * @see Project#getLookup
810
     * @see Project#getLookup
844
     */
811
     */
845
    public SharabilityQueryImplementation createSharabilityQuery(String[] sourceRoots, String[] buildDirectories) {
812
    public SharabilityQueryImplementation createSharabilityQuery(PropertyEvaluator eval, String[] sourceRoots, String[] buildDirectories) {
846
        String[] includes = new String[sourceRoots.length + 1];
813
        String[] includes = new String[sourceRoots.length + 1];
847
        System.arraycopy(sourceRoots, 0, includes, 0, sourceRoots.length);
814
        System.arraycopy(sourceRoots, 0, includes, 0, sourceRoots.length);
848
        includes[sourceRoots.length] = ""; // NOI18N
815
        includes[sourceRoots.length] = ""; // NOI18N
849
        String[] excludes = new String[buildDirectories.length + 1];
816
        String[] excludes = new String[buildDirectories.length + 1];
850
        System.arraycopy(buildDirectories, 0, excludes, 0, buildDirectories.length);
817
        System.arraycopy(buildDirectories, 0, excludes, 0, buildDirectories.length);
851
        excludes[buildDirectories.length] = "nbproject/private"; // NOI18N
818
        excludes[buildDirectories.length] = "nbproject/private"; // NOI18N
852
        return new SharabilityQueryImpl(this, includes, excludes);
819
        return new SharabilityQueryImpl(this, eval, includes, excludes);
853
    }
820
    }
854
        
821
        
855
    /**
822
    /**
Lines 870-879 Link Here
870
     * @see #PRIVATE_PROPERTIES_PATH
837
     * @see #PRIVATE_PROPERTIES_PATH
871
     * @see PropertyUtils#getGlobalProperties
838
     * @see PropertyUtils#getGlobalProperties
872
     * @see #PROJECT_PROPERTIES_PATH
839
     * @see #PROJECT_PROPERTIES_PATH
840
     * @deprecated Please use {@link #getStandardPropertyEvaluator} instead.
873
     */
841
     */
874
    public String evaluate(String prop) {
842
    public String evaluate(String prop) {
875
        // XXX could be cached
843
        return getStandardPropertyEvaluator().getProperty(prop);
876
        return PropertyUtils.evaluate(prop, makeEvalPredefs(), makeEvalDefs());
877
    }
844
    }
878
    
845
    
879
    /**
846
    /**
Lines 885-894 Link Here
885
     * @see #PRIVATE_PROPERTIES_PATH
852
     * @see #PRIVATE_PROPERTIES_PATH
886
     * @see PropertyUtils#getGlobalProperties
853
     * @see PropertyUtils#getGlobalProperties
887
     * @see #PROJECT_PROPERTIES_PATH
854
     * @see #PROJECT_PROPERTIES_PATH
855
     * @deprecated Please use {@link #getStandardPropertyEvaluator} instead.
888
     */
856
     */
889
    public Map/*<String,String>*/ evaluateAll() {
857
    public Map/*<String,String>*/ evaluateAll() {
890
        // XXX could be cached
858
        return getStandardPropertyEvaluator().getProperties();
891
        return PropertyUtils.evaluateAll(makeEvalPredefs(), makeEvalDefs());
892
    }
859
    }
893
    
860
    
894
    /**
861
    /**
Lines 901-955 Link Here
901
     * @see #PRIVATE_PROPERTIES_PATH
868
     * @see #PRIVATE_PROPERTIES_PATH
902
     * @see PropertyUtils#getGlobalProperties
869
     * @see PropertyUtils#getGlobalProperties
903
     * @see #PROJECT_PROPERTIES_PATH
870
     * @see #PROJECT_PROPERTIES_PATH
871
     * @deprecated Please use {@link #getStandardPropertyEvaluator} instead.
904
     */
872
     */
905
    public String evaluateString(String text) {
873
    public String evaluateString(String text) {
906
        return PropertyUtils.evaluateString(text, makeEvalPredefs(), makeEvalDefs());
874
        return getStandardPropertyEvaluator().evaluate(text);
907
    }
875
    }
908
    
876
    
877
    private PropertyProvider stockPropertyPreprovider = null;
878
    
909
    /**
879
    /**
910
     * Create stock predefs: ${basedir} and system properties.
880
     * Get a property provider which defines <code>basedir</code> according to
881
     * the project directory and also copies all system properties in the current VM.
882
     * @return a stock property provider for initial Ant-related definitions
883
     * @see PropertyUtils#sequentialPropertyEvaluator
911
     */
884
     */
912
    private Map/*<String,String>*/ makeEvalPredefs() {
885
    public PropertyProvider getStockPropertyPreprovider() {
913
        Map/*<String,String>*/ m = new HashMap();
886
        if (stockPropertyPreprovider == null) {
914
        Properties p = System.getProperties();
887
            Map/*<String,String>*/ m = new HashMap();
915
        synchronized (p) {
888
            Properties p = System.getProperties();
916
            m.putAll(p);
889
            synchronized (p) {
890
                m.putAll(p);
891
            }
892
            m.put("basedir", FileUtil.toFile(dir).getAbsolutePath()); // NOI18N
893
            stockPropertyPreprovider = PropertyUtils.fixedPropertyProvider(m);
917
        }
894
        }
918
        m.put("basedir", FileUtil.toFile(dir).getAbsolutePath()); // NOI18N
895
        return stockPropertyPreprovider;
919
        return m;
920
    }
896
    }
921
    
897
    
898
    private PropertyEvaluator standardPropertyEvaluator = null;
899
    
922
    /**
900
    /**
923
     * Create stock defs: private project props, global user build props, shared project props.
901
     * Get a property evaluator that can evaluate properties according to the default
902
     * file layout for Ant-based projects.
903
     * First, {@link #getStockPropertyPreprovider stock properties} are predefined.
904
     * Then {@link #PRIVATE_PROPERTIES_PATH} is loaded via {@link #getPropertyProvider},
905
     * then global definitions from {@link PropertyUtils#globalPropertyProvider}
906
     * (though these may be overridden using the property <code>user.properties.file</code>
907
     * in <code>private.properties</code>), then {@link #PROJECT_PROPERTIES_PATH}.
908
     * @return a standard property evaluator
924
     */
909
     */
925
    private List/*<Map<String,String>>*/ makeEvalDefs() {
910
    public PropertyEvaluator getStandardPropertyEvaluator() {
926
        Map/*<String,String>*/ privprops = getProperties(PRIVATE_PROPERTIES_PATH);
911
        if (standardPropertyEvaluator == null) {
927
        // XXX not very efficient...
912
            PropertyEvaluator findUserPropertiesFile = PropertyUtils.sequentialPropertyEvaluator(
928
        String userPropsFile = PropertyUtils.evaluate("user.properties.file", makeEvalPredefs(), Collections.singletonList(privprops));
913
                getStockPropertyPreprovider(),
929
        Map/*<String,String>*/ globprops;
914
                new PropertyProvider[] {
930
        if (userPropsFile != null) {
915
                    getPropertyProvider(PRIVATE_PROPERTIES_PATH),
931
            globprops = new Properties();
916
                }
932
            File f = resolveFile(userPropsFile);
917
            );
933
            if (f.isFile() && f.canRead()) {
918
            String userPropertiesFile = findUserPropertiesFile.getProperty("user.properties.file"); // NOI18N
934
                try {
919
            PropertyProvider globalProperties;
935
                    InputStream is = new FileInputStream(f);
920
            if (userPropertiesFile != null) {
921
                // XXX listen to changes in this, maybe...
922
                // (both in findUserPropertiesFile and in this file on disk)
923
                Properties globprops = new Properties();
924
                File f = resolveFile(userPropertiesFile);
925
                if (f.isFile() && f.canRead()) {
936
                    try {
926
                    try {
937
                        ((Properties)globprops).load(is);
927
                        InputStream is = new FileInputStream(f);
938
                    } finally {
928
                        try {
939
                        is.close();
929
                            globprops.load(is);
930
                        } finally {
931
                            is.close();
932
                        }
933
                    } catch (IOException e) {
934
                        ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
940
                    }
935
                    }
941
                } catch (IOException e) {
942
                    ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
943
                }
936
                }
937
                globalProperties = PropertyUtils.fixedPropertyProvider(globprops);
938
            } else {
939
                globalProperties = PropertyUtils.globalPropertyProvider();
944
            }
940
            }
945
        } else {
941
            standardPropertyEvaluator = PropertyUtils.sequentialPropertyEvaluator(
946
            globprops = PropertyUtils.getGlobalProperties();
942
                getStockPropertyPreprovider(),
943
                new PropertyProvider[] {
944
                    getPropertyProvider(PRIVATE_PROPERTIES_PATH),
945
                    globalProperties,
946
                    getPropertyProvider(PROJECT_PROPERTIES_PATH),
947
                }
948
            );
947
        }
949
        }
948
        return Arrays.asList(new Map/*<String,String>*/[] {
950
        return standardPropertyEvaluator;
949
            privprops,
950
            globprops,
951
            getProperties(PROJECT_PROPERTIES_PATH),
952
        });
953
    }
951
    }
954
    
952
    
955
    /**
953
    /**
(-)ant/project/src/org/netbeans/spi/project/support/ant/GlobFileBuiltQuery.java (-6 / +8 lines)
Lines 48-53 Link Here
48
final class GlobFileBuiltQuery implements FileBuiltQueryImplementation {
48
final class GlobFileBuiltQuery implements FileBuiltQueryImplementation {
49
    
49
    
50
    private final AntProjectHelper helper;
50
    private final AntProjectHelper helper;
51
    private final PropertyEvaluator eval;
51
    private final FileObject projectDir;
52
    private final FileObject projectDir;
52
    private final File projectDirF;
53
    private final File projectDirF;
53
    private final String[] fromPrefixes;
54
    private final String[] fromPrefixes;
Lines 63-70 Link Here
63
     * Create a new query implementation based on an Ant-based project.
64
     * Create a new query implementation based on an Ant-based project.
64
     * @see AntProjectHelper#createGlobFileBuiltQuery
65
     * @see AntProjectHelper#createGlobFileBuiltQuery
65
     */
66
     */
66
    public GlobFileBuiltQuery(AntProjectHelper helper, String[] from, String[] to) throws IllegalArgumentException {
67
    public GlobFileBuiltQuery(AntProjectHelper helper, PropertyEvaluator eval, String[] from, String[] to) throws IllegalArgumentException {
67
        this.helper = helper;
68
        this.helper = helper;
69
        this.eval = eval;
68
        projectDir = helper.getProjectDirectory();
70
        projectDir = helper.getProjectDirectory();
69
        projectDirF = FileUtil.toFile(projectDir);
71
        projectDirF = FileUtil.toFile(projectDir);
70
        assert projectDirF != null;
72
        assert projectDirF != null;
Lines 97-103 Link Here
97
        projectDir.addFileChangeListener(FileUtil.weakFileChangeListener(fileL, projectDir));
99
        projectDir.addFileChangeListener(FileUtil.weakFileChangeListener(fileL, projectDir));
98
         */
100
         */
99
        weakFileL = FileUtil.weakFileChangeListener(fileL, null);
101
        weakFileL = FileUtil.weakFileChangeListener(fileL, null);
100
        // XXX add properties listener to helper... if anything changes, refresh all
102
        // XXX add properties listener to evaluator... if anything changes, refresh all
101
        // status objects and clear the stati cache; can then also keep a cache of
103
        // status objects and clear the stati cache; can then also keep a cache of
102
        // evaluated path prefixes & suffixes
104
        // evaluated path prefixes & suffixes
103
    }
105
    }
Lines 154-160 Link Here
154
            throw new IllegalArgumentException("Cannot check for status on file " + file + " outside of " + projectDir); // NOI18N
156
            throw new IllegalArgumentException("Cannot check for status on file " + file + " outside of " + projectDir); // NOI18N
155
        }
157
        }
156
        for (int i = 0; i < fromPrefixes.length; i++) {
158
        for (int i = 0; i < fromPrefixes.length; i++) {
157
            String prefixEval = helper.evaluateString(fromPrefixes[i]);
159
            String prefixEval = eval.evaluate(fromPrefixes[i]);
158
            if (prefixEval == null) {
160
            if (prefixEval == null) {
159
                return null;
161
                return null;
160
            }
162
            }
Lines 162-168 Link Here
162
                continue;
164
                continue;
163
            }
165
            }
164
            String remainder = path.substring(prefixEval.length());
166
            String remainder = path.substring(prefixEval.length());
165
            String suffixEval = helper.evaluateString(fromSuffixes[i]);
167
            String suffixEval = eval.evaluate(fromSuffixes[i]);
166
            if (suffixEval == null) {
168
            if (suffixEval == null) {
167
                continue;
169
                continue;
168
            }
170
            }
Lines 170-180 Link Here
170
                continue;
172
                continue;
171
            }
173
            }
172
            String particular = remainder.substring(0, remainder.length() - suffixEval.length());
174
            String particular = remainder.substring(0, remainder.length() - suffixEval.length());
173
            String toPrefixEval = helper.evaluateString(toPrefixes[i]);
175
            String toPrefixEval = eval.evaluate(toPrefixes[i]);
174
            if (toPrefixEval == null) {
176
            if (toPrefixEval == null) {
175
                continue;
177
                continue;
176
            }
178
            }
177
            String toSuffixEval = helper.evaluateString(toSuffixes[i]);
179
            String toSuffixEval = eval.evaluate(toSuffixes[i]);
178
            if (toSuffixEval == null) {
180
            if (toSuffixEval == null) {
179
                continue;
181
                continue;
180
            }
182
            }
(-)ant/project/src/org/netbeans/spi/project/support/ant/ProjectProperties.java (+212 lines)
Added Link Here
1
/*
2
 *                 Sun Public License Notice
3
 *
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 *
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.netbeans.spi.project.support.ant;
15
16
import java.io.IOException;
17
import java.io.InputStream;
18
import java.io.OutputStream;
19
import java.util.ArrayList;
20
import java.util.HashMap;
21
import java.util.List;
22
import java.util.Map;
23
import javax.swing.event.ChangeEvent;
24
import javax.swing.event.ChangeListener;
25
import org.openide.ErrorManager;
26
import org.openide.filesystems.FileLock;
27
import org.openide.filesystems.FileObject;
28
import org.openide.filesystems.FileUtil;
29
import org.openide.util.Utilities;
30
31
/**
32
 * Manages the loaded property files for {@link AntProjectHelper}.
33
 * @author Jesse Glick
34
 */
35
final class ProjectProperties {
36
    
37
    private final FileObject dir;
38
    
39
    /**
40
     * Properties loaded from metadata files on disk.
41
     * Keys are project-relative paths such as {@link #PROJECT_PROPERTIES_PATH}.
42
     * Values are loaded property providers.
43
     */
44
    private final Map/*<String,PP>*/ properties = new HashMap();
45
    
46
    /**
47
     * Create a project properties helper object.
48
     * @param dir the project directory
49
     */
50
    public ProjectProperties(FileObject dir) {
51
        this.dir = dir;
52
    }
53
54
    /**
55
     * Get properties from a given path.
56
     * @param path the project-relative path
57
     * @return the applicable properties (created if empty; never null)
58
     */
59
    public EditableProperties getProperties(String path) {
60
        return getPP(path).getEditableProperties();
61
    }
62
    
63
    /**
64
     * Store properties in memory.
65
     * @param path the project-relative path
66
     * @param props the new properties, or null to remove the properties file
67
     * @return true if an actual change was made
68
     */
69
    public boolean putProperties(String path, EditableProperties props) {
70
        return getPP(path).put(props);
71
    }
72
    
73
    /**
74
     * Write cached properties to disk.
75
     * @param the project-relative path
76
     * @throws IOException if the file could not be written
77
     */
78
    public void write(String path) throws IOException {
79
        assert properties.containsKey(path);
80
        getPP(path).write();
81
    }
82
    
83
    /**
84
     * Make a property provider that loads from this file
85
     * and fires changes when it is written to (even in memory).
86
     */
87
    public PropertyProvider getPropertyProvider(String path) {
88
        return getPP(path);
89
    }
90
    
91
    private PP getPP(String path) {
92
        PP pp = (PP)properties.get(path);
93
        if (pp == null) {
94
            pp = new PP(path, dir);
95
            properties.put(path, pp);
96
        }
97
        return pp;
98
    }
99
    
100
    private static final class PP implements PropertyProvider {
101
        
102
        // XXX lock any loaded property files while the project is modified, to prevent manual editing,
103
        // and reload any modified files if the project is unmodified
104
105
        private final String path;
106
        private final FileObject dir;
107
        private EditableProperties properties = null;
108
        private boolean loaded = false;
109
        private final List/*<ChangeListener>*/ listeners = new ArrayList();
110
        
111
        public PP(String path, FileObject dir) {
112
            this.path = path;
113
            this.dir = dir;
114
        }
115
        
116
        public EditableProperties getEditableProperties() {
117
            if (!loaded) {
118
                FileObject fo = dir.getFileObject(path);
119
                if (fo != null) {
120
                    try {
121
                        EditableProperties p;
122
                        InputStream is = fo.getInputStream();
123
                        try {
124
                            p = new EditableProperties(true);
125
                            p.load(is);
126
                        } finally {
127
                            is.close();
128
                        }
129
                        properties = p;
130
                    } catch (IOException e) {
131
                        ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
132
                    }
133
                }
134
                loaded = true;
135
            }
136
            if (properties != null) {
137
                return properties.cloneProperties();
138
            } else {
139
                return new EditableProperties(true);
140
            }
141
        }
142
        
143
        public boolean put(EditableProperties nue) {
144
            loaded = true;
145
            boolean modifying = !Utilities.compareObjects(nue, properties);
146
            if (modifying) {
147
                if (nue != null) {
148
                    properties = nue.cloneProperties();
149
                } else {
150
                    properties = null;
151
                }
152
                fireChange();
153
            }
154
            return modifying;
155
        }
156
        
157
        public void write() throws IOException {
158
            assert loaded;
159
            FileObject f = dir.getFileObject(path);
160
            if (properties != null) {
161
                // Supposed to create/modify the file.
162
                if (f == null) {
163
                    f = FileUtil.createData(dir, path);
164
                }
165
                FileLock lock = f.lock();
166
                try {
167
                    OutputStream os = f.getOutputStream(lock);
168
                    try {
169
                        properties.store(os);
170
                    } finally {
171
                        os.close();
172
                    }
173
                } finally {
174
                    lock.releaseLock();
175
                }
176
            } else {
177
                // We are supposed to remove any existing file.
178
                if (f != null) {
179
                    f.delete();
180
                }
181
            }
182
        }
183
        
184
        public Map getProperties() {
185
            return getEditableProperties();
186
        }
187
        
188
        public synchronized void addChangeListener(ChangeListener l) {
189
            listeners.add(l);
190
        }
191
        
192
        public synchronized void removeChangeListener(ChangeListener l) {
193
            listeners.remove(l);
194
        }
195
        
196
        private void fireChange() {
197
            ChangeListener[] ls;
198
            synchronized (this) {
199
                if (listeners.isEmpty()) {
200
                    return;
201
                }
202
                ls = (ChangeListener[])listeners.toArray(new ChangeListener[listeners.size()]);
203
            }
204
            ChangeEvent ev = new ChangeEvent(this);
205
            for (int i = 0; i < ls.length; i++) {
206
                ls[i].stateChanged(ev);
207
            }
208
        }
209
        
210
    }
211
    
212
}
(-)ant/project/src/org/netbeans/spi/project/support/ant/PropertyEvaluator.java (-1 / +3 lines)
Lines 23-30 Link Here
23
 * it will be used with the project manager mutex. Changes should be fired
23
 * it will be used with the project manager mutex. Changes should be fired
24
 * synchronously.
24
 * synchronously.
25
 * @author Jesse Glick
25
 * @author Jesse Glick
26
 * @see PropertyUtils#sequentialPropertyEvaluator
27
 * @see AntProjectHelper#getStandardPropertyEvaluator
26
 */
28
 */
27
/*XXX: public*/ interface PropertyEvaluator {
29
public interface PropertyEvaluator {
28
    
30
    
29
    /**
31
    /**
30
     * Evaluate a single property.
32
     * Evaluate a single property.
(-)ant/project/src/org/netbeans/spi/project/support/ant/PropertyProvider.java (-1 / +1 lines)
Lines 25-31 Link Here
25
 * synchronously.
25
 * synchronously.
26
 * @author Jesse Glick
26
 * @author Jesse Glick
27
 */
27
 */
28
/*XXX public*/ interface PropertyProvider {
28
public interface PropertyProvider {
29
    
29
    
30
    /**
30
    /**
31
     * Get all defined properties.
31
     * Get all defined properties.
(-)ant/project/src/org/netbeans/spi/project/support/ant/PropertyUtils.java (-3 / +6 lines)
Lines 151-157 Link Here
151
     * is changed.
151
     * is changed.
152
     * @return a property producer
152
     * @return a property producer
153
     */
153
     */
154
    /*XXX public*/ static synchronized PropertyProvider globalPropertyProvider() {
154
    public static synchronized PropertyProvider globalPropertyProvider() {
155
        if (globalPropertyProvider != null) {
155
        if (globalPropertyProvider != null) {
156
            PropertyProvider pp = (PropertyProvider)globalPropertyProvider.get();
156
            PropertyProvider pp = (PropertyProvider)globalPropertyProvider.get();
157
            if (pp != null) {
157
            if (pp != null) {
Lines 234-239 Link Here
234
     * @param predefs an unevaluated set of initial definitions
234
     * @param predefs an unevaluated set of initial definitions
235
     * @param defs an ordered list of property mappings, e.g. {@link EditableProperties} instances
235
     * @param defs an ordered list of property mappings, e.g. {@link EditableProperties} instances
236
     * @return a value for the property, or null if it was not defined or a circularity error was detected
236
     * @return a value for the property, or null if it was not defined or a circularity error was detected
237
     * @deprecated Please use {@link #fixedPropertyProvider} and {@link #sequentialPropertyEvaluator} instead.
237
     */
238
     */
238
    public static String evaluate(String prop, Map/*<String,String>*/ predefs, List/*<Map<String,String>>*/ defs) {
239
    public static String evaluate(String prop, Map/*<String,String>*/ predefs, List/*<Map<String,String>>*/ defs) {
239
        // XXX could be faster for large mappings by using reverse analysis
240
        // XXX could be faster for large mappings by using reverse analysis
Lines 256-261 Link Here
256
     * @param defs an ordered list of property mappings, e.g. {@link EditableProperties} instances
257
     * @param defs an ordered list of property mappings, e.g. {@link EditableProperties} instances
257
     * @param predefs an unevaluated set of initial definitions
258
     * @param predefs an unevaluated set of initial definitions
258
     * @return values for all defined properties, or null if a circularity error was detected
259
     * @return values for all defined properties, or null if a circularity error was detected
260
     * @deprecated Please use {@link #fixedPropertyProvider} and {@link #sequentialPropertyEvaluator} instead.
259
     */
261
     */
260
    public static Map/*<String,String>*/ evaluateAll(Map/*<String,String>*/ predefs, List/*<Map<String,String>>*/ defs) {
262
    public static Map/*<String,String>*/ evaluateAll(Map/*<String,String>*/ predefs, List/*<Map<String,String>>*/ defs) {
261
        Map/*<String,String>*/ m = new HashMap(predefs);
263
        Map/*<String,String>*/ m = new HashMap(predefs);
Lines 311-316 Link Here
311
     * @param predefs an unevaluated set of initial definitions
313
     * @param predefs an unevaluated set of initial definitions
312
     * @param defs an ordered list of property mappings, e.g. {@link EditableProperties} instances
314
     * @param defs an ordered list of property mappings, e.g. {@link EditableProperties} instances
313
     * @return a value for the text, or null if a circularity error was detected
315
     * @return a value for the text, or null if a circularity error was detected
316
     * @deprecated Please use {@link #fixedPropertyProvider} and {@link #sequentialPropertyEvaluator} instead.
314
     */
317
     */
315
    public static String evaluateString(String text, Map/*<String,String>*/ predefs, List/*<Map<String,String>>*/ defs) {
318
    public static String evaluateString(String text, Map/*<String,String>*/ predefs, List/*<Map<String,String>>*/ defs) {
316
        // XXX could be faster for large mappings; see evaluate(...)
319
        // XXX could be faster for large mappings; see evaluate(...)
Lines 541-547 Link Here
541
     *             after passing it to this method)
544
     *             after passing it to this method)
542
     * @return a matching property producer
545
     * @return a matching property producer
543
     */
546
     */
544
    /*XXX public?*/ static PropertyProvider fixedPropertyProvider(Map/*<String,String>*/ defs) {
547
    public static PropertyProvider fixedPropertyProvider(Map/*<String,String>*/ defs) {
545
        return new FixedPropertyProvider(defs);
548
        return new FixedPropertyProvider(defs);
546
    }
549
    }
547
    
550
    
Lines 572-578 Link Here
572
     * @param providers a sequential list of property groups
575
     * @param providers a sequential list of property groups
573
     * @return an evaluator
576
     * @return an evaluator
574
     */
577
     */
575
    /*XXX public*/ static PropertyEvaluator sequentialPropertyEvaluator(PropertyProvider preprovider, PropertyProvider[] providers) {
578
    public static PropertyEvaluator sequentialPropertyEvaluator(PropertyProvider preprovider, PropertyProvider[] providers) {
576
        return new SequentialPropertyEvaluator(preprovider, providers);
579
        return new SequentialPropertyEvaluator(preprovider, providers);
577
    }
580
    }
578
    
581
    
(-)ant/project/src/org/netbeans/spi/project/support/ant/ReferenceHelper.java (-2 / +20 lines)
Lines 83-102 Link Here
83
    static final String REFS_NS = "http://www.netbeans.org/ns/ant-project-references/1"; // NOI18N
83
    static final String REFS_NS = "http://www.netbeans.org/ns/ant-project-references/1"; // NOI18N
84
    
84
    
85
    private final AntProjectHelper h;
85
    private final AntProjectHelper h;
86
    final PropertyEvaluator eval;
86
    private final AuxiliaryConfiguration aux;
87
    private final AuxiliaryConfiguration aux;
87
88
89
    /** @deprecated Use the constructor that takes a property evaluator instead. */
90
    public ReferenceHelper(AntProjectHelper helper, AuxiliaryConfiguration aux) {
91
        this(helper, aux, helper.getStandardPropertyEvaluator());
92
    }
93
    
88
    /**
94
    /**
89
     * Create a new reference helper.
95
     * Create a new reference helper.
90
     * It needs an {@link AntProjectHelper} object in order to update references
96
     * It needs an {@link AntProjectHelper} object in order to update references
91
     * in <code>project.xml</code>,
97
     * in <code>project.xml</code>,
92
     * as well as set project or private properties referring to the locations
98
     * as well as set project or private properties referring to the locations
93
     * of foreign projects on disk.
99
     * of foreign projects on disk.
100
     * <p>
101
     * The property evaluator may be used in {@link #getForeignFileReferenceAsArtifact},
102
     * {@link ReferenceHelper.RawReference#toAntArtifact}, or
103
     * {@link #createSubprojectProvider}. Typically this would
104
     * be {@link AntProjectHelper#getStandardPropertyEvaluator}. You can substitute
105
     * a custom evaluator but be warned that this helper class assumes that
106
     * {@link AntProjectHelper#PROJECT_PROPERTIES_PATH} and {@link AntProjectHelper#PRIVATE_PROPERTIES_PATH}
107
     * have their customary meanings; specifically that they are both used when evaluating
108
     * properties (such as the location of a foreign project) and that private properties
109
     * can override public properties.
94
     * @param helper an Ant project helper object representing this project's configuration
110
     * @param helper an Ant project helper object representing this project's configuration
95
     * @param aux an auxiliary configuration provider needed to store references
111
     * @param aux an auxiliary configuration provider needed to store references
112
     * @param eval a property evaluator
96
     */
113
     */
97
    public ReferenceHelper(AntProjectHelper helper, AuxiliaryConfiguration aux) {
114
    public ReferenceHelper(AntProjectHelper helper, AuxiliaryConfiguration aux, PropertyEvaluator eval) {
98
        h = helper;
115
        h = helper;
99
        this.aux = aux;
116
        this.aux = aux;
117
        this.eval = eval;
100
    }
118
    }
101
119
102
    /**
120
    /**
Lines 827-833 Link Here
827
            return (AntArtifact)ProjectManager.mutex().readAccess(new Mutex.Action() {
845
            return (AntArtifact)ProjectManager.mutex().readAccess(new Mutex.Action() {
828
                public Object run() {
846
                public Object run() {
829
                    AntProjectHelper h = helper.h;
847
                    AntProjectHelper h = helper.h;
830
                    String path = h.evaluate("project." + foreignProjectName); // NOI18N
848
                    String path = helper.eval.getProperty("project." + foreignProjectName); // NOI18N
831
                    if (path == null) {
849
                    if (path == null) {
832
                        // Undefined foreign project.
850
                        // Undefined foreign project.
833
                        return null;
851
                        return null;
(-)ant/project/src/org/netbeans/spi/project/support/ant/SharabilityQueryImpl.java (-9 / +9 lines)
Lines 13-18 Link Here
13
13
14
package org.netbeans.spi.project.support.ant;
14
package org.netbeans.spi.project.support.ant;
15
15
16
import java.beans.PropertyChangeEvent;
17
import java.beans.PropertyChangeListener;
16
import java.io.File;
18
import java.io.File;
17
import java.util.ArrayList;
19
import java.util.ArrayList;
18
import java.util.List;
20
import java.util.List;
Lines 24-32 Link Here
24
 * Standard impl of {@link SharabilityQueryImplementation}.
26
 * Standard impl of {@link SharabilityQueryImplementation}.
25
 * @author Jesse Glick
27
 * @author Jesse Glick
26
 */
28
 */
27
final class SharabilityQueryImpl implements SharabilityQueryImplementation, AntProjectListener {
29
final class SharabilityQueryImpl implements SharabilityQueryImplementation, PropertyChangeListener {
28
    
30
    
29
    private final AntProjectHelper h;
31
    private final AntProjectHelper h;
32
    private final PropertyEvaluator eval;
30
    private final String[] includes;
33
    private final String[] includes;
31
    private final String[] excludes;
34
    private final String[] excludes;
32
    /** Absolute paths of directories or files to treat as sharable (except for the excludes). */
35
    /** Absolute paths of directories or files to treat as sharable (except for the excludes). */
Lines 34-45 Link Here
34
    /** Absolute paths of directories or files to treat as not sharable. */
37
    /** Absolute paths of directories or files to treat as not sharable. */
35
    private String[] excludePaths;
38
    private String[] excludePaths;
36
    
39
    
37
    SharabilityQueryImpl(AntProjectHelper h, String[] includes, String[] excludes) {
40
    SharabilityQueryImpl(AntProjectHelper h, PropertyEvaluator eval, String[] includes, String[] excludes) {
38
        this.h = h;
41
        this.h = h;
42
        this.eval = eval;
39
        this.includes = includes;
43
        this.includes = includes;
40
        this.excludes = excludes;
44
        this.excludes = excludes;
41
        computeFiles();
45
        computeFiles();
42
        h.addAntProjectListener((AntProjectListener)WeakListeners.create(AntProjectListener.class, this, h));
46
        eval.addPropertyChangeListener(WeakListeners.propertyChange(this, eval));
43
    }
47
    }
44
    
48
    
45
    /** Compute the absolute paths which are and are not sharable. */
49
    /** Compute the absolute paths which are and are not sharable. */
Lines 56-62 Link Here
56
    private String[] computeFrom(String[] list) {
60
    private String[] computeFrom(String[] list) {
57
        List/*<String>*/ result = new ArrayList(list.length);
61
        List/*<String>*/ result = new ArrayList(list.length);
58
        for (int i = 0; i < list.length; i++) {
62
        for (int i = 0; i < list.length; i++) {
59
            String val = h.evaluateString(list[i]);
63
            String val = eval.evaluate(list[i]);
60
            if (val != null) {
64
            if (val != null) {
61
                File f = h.resolveFile(val);
65
                File f = h.resolveFile(val);
62
                result.add(f.getAbsolutePath());
66
                result.add(f.getAbsolutePath());
Lines 97-108 Link Here
97
        return false;
101
        return false;
98
    }
102
    }
99
    
103
    
100
    public void propertiesChanged(AntProjectEvent ev) {
104
    public void propertyChange(PropertyChangeEvent evt) {
101
        computeFiles();
105
        computeFiles();
102
    }
103
    
104
    public void configurationXmlChanged(AntProjectEvent ev) {
105
        // ignore
106
    }
106
    }
107
    
107
    
108
}
108
}
(-)ant/project/src/org/netbeans/spi/project/support/ant/SimpleAntArtifact.java (-2 / +4 lines)
Lines 32-53 Link Here
32
    private final AntProjectHelper h;
32
    private final AntProjectHelper h;
33
    private final String type;
33
    private final String type;
34
    private final String locationProperty;
34
    private final String locationProperty;
35
    private final PropertyEvaluator eval;
35
    private final String targetName;
36
    private final String targetName;
36
    private final String cleanTargetName;
37
    private final String cleanTargetName;
37
    
38
    
38
    /**
39
    /**
39
     * @see AntProjectHelper#createSimpleAntArtifact
40
     * @see AntProjectHelper#createSimpleAntArtifact
40
     */
41
     */
41
    public SimpleAntArtifact(AntProjectHelper helper, String type, String locationProperty, String targetName, String cleanTargetName) {
42
    public SimpleAntArtifact(AntProjectHelper helper, String type, String locationProperty, PropertyEvaluator eval, String targetName, String cleanTargetName) {
42
        this.h = helper;
43
        this.h = helper;
43
        this.type = type;
44
        this.type = type;
44
        this.locationProperty = locationProperty;
45
        this.locationProperty = locationProperty;
46
        this.eval = eval;
45
        this.targetName = targetName;
47
        this.targetName = targetName;
46
        this.cleanTargetName = cleanTargetName;
48
        this.cleanTargetName = cleanTargetName;
47
    }
49
    }
48
    
50
    
49
    public URI getArtifactLocation() {
51
    public URI getArtifactLocation() {
50
        String locationResolved = h.evaluate(locationProperty);
52
        String locationResolved = eval.getProperty(locationProperty);
51
        if (locationResolved == null) {
53
        if (locationResolved == null) {
52
            return URI.create("file:/UNDEFINED"); // NOI18N
54
            return URI.create("file:/UNDEFINED"); // NOI18N
53
        }
55
        }
(-)ant/project/src/org/netbeans/spi/project/support/ant/SubprojectProviderImpl.java (-1 / +1 lines)
Lines 52-58 Link Here
52
                    String foreignProjectName = (String)it.next();
52
                    String foreignProjectName = (String)it.next();
53
                    String prop = "project." + foreignProjectName; // NOI18N
53
                    String prop = "project." + foreignProjectName; // NOI18N
54
                    AntProjectHelper h = helper.getAntProjectHelper();
54
                    AntProjectHelper h = helper.getAntProjectHelper();
55
                    String foreignProjectDirS = h.evaluate(prop);
55
                    String foreignProjectDirS = helper.eval.getProperty(prop);
56
                    if (foreignProjectDirS == null) {
56
                    if (foreignProjectDirS == null) {
57
                        // Missing for some reason. Skip it.
57
                        // Missing for some reason. Skip it.
58
                        continue;
58
                        continue;
(-)ant/project/test/unit/src/org/netbeans/spi/project/support/ant/AntProjectHelperTest.java (+56 lines)
Lines 544-548 Link Here
544
        // or other general fixed metadata
544
        // or other general fixed metadata
545
        // XXX try overwriting data
545
        // XXX try overwriting data
546
    }
546
    }
547
    
548
    public void testCreatePropertyProvider() throws Exception {
549
        PropertyProvider pp = h.getPropertyProvider(AntProjectHelper.PROJECT_PROPERTIES_PATH);
550
        Map/*<String,String>*/ defs = pp.getProperties();
551
        assertEquals("correct number of defs", 3, defs.size());
552
        assertEquals("correct value", "value1", defs.get("shared.prop"));
553
        // Test changes.
554
        PropertyUtilsTest.TestCL l = new PropertyUtilsTest.TestCL();
555
        pp.addChangeListener(l);
556
        EditableProperties p = h.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
557
        p.setProperty("foo", "bar");
558
        assertFalse("no events from uncommitted changes", l.changed);
559
        h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, p);
560
        assertTrue("got a change from setting a property", l.changed);
561
        l.changed = false;
562
        defs = pp.getProperties();
563
        assertEquals("correct new size", 4, defs.size());
564
        assertEquals("correct new value", "bar", defs.get("foo"));
565
        // No-op changes.
566
        p = p.cloneProperties();
567
        p.setProperty("foo", "bar2");
568
        p.setProperty("foo", "bar");
569
        h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, p);
570
        assertFalse("no events from no-op changes", l.changed);
571
        // Deleting a property file.
572
        h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, null);
573
        assertTrue("got a change from removing a property file", l.changed);
574
        l.changed = false;
575
        assertEquals("now have no definitions", Collections.EMPTY_MAP, pp.getProperties());
576
        // Start off with no file, then create it.
577
        String path = "foo.properties";
578
        pp = h.getPropertyProvider(path);
579
        pp.addChangeListener(l);
580
        assertEquals("no defs initially", Collections.EMPTY_MAP, pp.getProperties());
581
        assertNull("no file made yet", h.getProjectDirectory().getFileObject(path));
582
        p = new EditableProperties();
583
        p.setProperty("one", "1");
584
        p.setProperty("two", "2");
585
        h.putProperties(path, p);
586
        assertTrue("making the file fired a change", l.changed);
587
        l.changed = false;
588
        defs = pp.getProperties();
589
        assertEquals("two defs", 2, defs.size());
590
        assertEquals("right value #1", "1", defs.get("one"));
591
        assertEquals("right value #2", "2", defs.get("two"));
592
        assertNull("no file yet saved to disk", h.getProjectDirectory().getFileObject(path));
593
        p.setProperty("three", "3");
594
        assertFalse("no events from uncomm. change", l.changed);
595
        h.putProperties(path, p);
596
        assertTrue("now have changed new file", l.changed);
597
        l.changed = false;
598
        defs = pp.getProperties();
599
        assertEquals("three defs", 3, defs.size());
600
        // XXX test that saving the project fires no additional changes
601
        // XXX test changes fired if file modified (or created or removed) on disk
602
    }
547
603
548
}
604
}
(-)ant/project/test/unit/src/org/netbeans/spi/project/support/ant/PropertyUtilsTest.java (-1 / +1 lines)
Lines 438-444 Link Here
438
        
438
        
439
    }
439
    }
440
    
440
    
441
    private static final class TestCL implements ChangeListener {
441
    static final class TestCL implements ChangeListener {
442
        
442
        
443
        public boolean changed = false;
443
        public boolean changed = false;
444
        
444
        
(-)ant/project/test/unit/src/org/netbeans/spi/project/support/ant/ReferenceHelperTest.java (-8 / +8 lines)
Lines 312-318 Link Here
312
    public void testAddRemoveArtifact() throws Exception {
312
    public void testAddRemoveArtifact() throws Exception {
313
        // Add one artifact. Check that the raw reference is there.
313
        // Add one artifact. Check that the raw reference is there.
314
        assertFalse("project not initially modified", pm.isModified(p));
314
        assertFalse("project not initially modified", pm.isModified(p));
315
        AntArtifact art = new SimpleAntArtifact(sisterh, "jar", "build.jar", "dojar", "clean");
315
        AntArtifact art = sisterh.createSimpleAntArtifact("jar", "build.jar", "dojar", "clean");
316
        assertTrue("added a ref to proj2.dojar", r.addReference(art));
316
        assertTrue("added a ref to proj2.dojar", r.addReference(art));
317
        assertTrue("project now modified", pm.isModified(p));
317
        assertTrue("project now modified", pm.isModified(p));
318
        ReferenceHelper.RawReference[] refs = r.getRawReferences();
318
        ReferenceHelper.RawReference[] refs = r.getRawReferences();
Lines 340-346 Link Here
340
        assertFalse("no-op add", r.addReference(art));
340
        assertFalse("no-op add", r.addReference(art));
341
        assertFalse("project not modified by no-op add", pm.isModified(p));
341
        assertFalse("project not modified by no-op add", pm.isModified(p));
342
        // Try another artifact from the same project.
342
        // Try another artifact from the same project.
343
        art = new SimpleAntArtifact(sisterh, "javadoc", "build.javadoc", "dojavadoc", "clean");
343
        art = sisterh.createSimpleAntArtifact("javadoc", "build.javadoc", "dojavadoc", "clean");
344
        assertTrue("added a ref to proj2.dojavadoc", r.addReference(art));
344
        assertTrue("added a ref to proj2.dojavadoc", r.addReference(art));
345
        assertTrue("project now modified", pm.isModified(p));
345
        assertTrue("project now modified", pm.isModified(p));
346
        refs = r.getRawReferences();
346
        refs = r.getRawReferences();
Lines 370-376 Link Here
370
        assertFalse("project not modified by no-op add", pm.isModified(p));
370
        assertFalse("project not modified by no-op add", pm.isModified(p));
371
        // Try modifying the second artifact in some way.
371
        // Try modifying the second artifact in some way.
372
        // Note that only changes in the type, clean target, and artifact path count as modifications.
372
        // Note that only changes in the type, clean target, and artifact path count as modifications.
373
        art = new SimpleAntArtifact(sisterh, "javadoc.html", "build.javadoc", "dojavadoc", "clean");
373
        art = sisterh.createSimpleAntArtifact("javadoc.html", "build.javadoc", "dojavadoc", "clean");
374
        assertTrue("successful modification of proj2.dojavadoc by type", r.addReference(art));
374
        assertTrue("successful modification of proj2.dojavadoc by type", r.addReference(art));
375
        assertTrue("project modified by ref mod", pm.isModified(p));
375
        assertTrue("project modified by ref mod", pm.isModified(p));
376
        refs = r.getRawReferences();
376
        refs = r.getRawReferences();
Lines 381-390 Link Here
381
        assertEquals("correct script location", URI.create("build.xml"), ref.getScriptLocation());
381
        assertEquals("correct script location", URI.create("build.xml"), ref.getScriptLocation());
382
        assertEquals("correct target name", "dojavadoc", ref.getTargetName());
382
        assertEquals("correct target name", "dojavadoc", ref.getTargetName());
383
        assertEquals("correct clean target name", "clean", ref.getCleanTargetName());
383
        assertEquals("correct clean target name", "clean", ref.getCleanTargetName());
384
        art = new SimpleAntArtifact(sisterh, "javadoc.html", "build.javadoc", "dojavadoc", "realclean");
384
        art = sisterh.createSimpleAntArtifact("javadoc.html", "build.javadoc", "dojavadoc", "realclean");
385
        assertTrue("successful modification of proj2.dojavadoc by clean target", r.addReference(art));
385
        assertTrue("successful modification of proj2.dojavadoc by clean target", r.addReference(art));
386
        pm.saveProject(p);
386
        pm.saveProject(p);
387
        art = new SimpleAntArtifact(sisterh, "javadoc.html", "build.javadoc.complete", "dojavadoc", "realclean");
387
        art = sisterh.createSimpleAntArtifact("javadoc.html", "build.javadoc.complete", "dojavadoc", "realclean");
388
        assertTrue("successful modification of proj2.dojavadoc by artifact location property", r.addReference(art));
388
        assertTrue("successful modification of proj2.dojavadoc by artifact location property", r.addReference(art));
389
        assertTrue("project modified by ref mod", pm.isModified(p));
389
        assertTrue("project modified by ref mod", pm.isModified(p));
390
        refs = r.getRawReferences();
390
        refs = r.getRawReferences();
Lines 467-477 Link Here
467
     * @throws Exception in case of unexpected failures
467
     * @throws Exception in case of unexpected failures
468
     */
468
     */
469
    public void testSubprojectProviderImpl() throws Exception {
469
    public void testSubprojectProviderImpl() throws Exception {
470
        AntArtifact art = new SimpleAntArtifact(sisterh, "jar", "build.jar", "dojar", "clean");
470
        AntArtifact art = sisterh.createSimpleAntArtifact("jar", "build.jar", "dojar", "clean");
471
        assertTrue("added a ref to proj2.dojar", r.addReference(art));
471
        assertTrue("added a ref to proj2.dojar", r.addReference(art));
472
        art = new SimpleAntArtifact(sisterh, "javadoc", "build.javadoc", "dojavadoc", "clean");
472
        art = sisterh.createSimpleAntArtifact("javadoc", "build.javadoc", "dojavadoc", "clean");
473
        assertTrue("added a ref to proj2.dojavadoc", r.addReference(art));
473
        assertTrue("added a ref to proj2.dojavadoc", r.addReference(art));
474
        art = new SimpleAntArtifact(seph, "jar", "build.jar", "dojar", "clean");
474
        art = seph.createSimpleAntArtifact("jar", "build.jar", "dojar", "clean");
475
        assertTrue("added a ref to proj3.dojar", r.addReference(art));
475
        assertTrue("added a ref to proj3.dojar", r.addReference(art));
476
        SubprojectProvider sp = r.createSubprojectProvider();
476
        SubprojectProvider sp = r.createSubprojectProvider();
477
        Set/*<Project>*/ subprojs = sp.getSubProjects();
477
        Set/*<Project>*/ subprojs = sp.getSubProjects();

Return to bug 42306