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 44035
Collapse All | Expand All

(-)a/project.ant/apichanges.xml (-3 / +39 lines)
Lines 40-47 Link Here
40
Version 2 license, then the option applies only if the new code is
40
Version 2 license, then the option applies only if the new code is
41
made subject to such option by the copyright holder.
41
made subject to such option by the copyright holder.
42
-->
42
-->
43
<?xml-stylesheet type="text/xml" href="../../nbbuild/javadoctools/apichanges.xsl"?>
43
<?xml-stylesheet type="text/xml" href="../nbbuild/javadoctools/apichanges.xsl"?>
44
<!DOCTYPE apichanges PUBLIC "-//NetBeans//DTD API changes list 1.0//EN" "../../nbbuild/javadoctools/apichanges.dtd">
44
<!DOCTYPE apichanges PUBLIC "-//NetBeans//DTD API changes list 1.0//EN" "../nbbuild/javadoctools/apichanges.dtd">
45
45
46
<!--
46
<!--
47
47
Lines 104-110 Link Here
104
    <!-- ACTUAL CHANGES BEGIN HERE: -->
104
    <!-- ACTUAL CHANGES BEGIN HERE: -->
105
105
106
    <changes>
106
    <changes>
107
        
107
108
        <change id="ant-project-libraries">
109
            <api name="general"/>
110
            <summary>Support for project-specific libraries</summary>
111
            <version major="1" minor="19"/>
112
            <date day="22" month="1" year="2008"/>
113
            <author login="jglick"/>
114
            <compatibility addition="yes"/>
115
            <description>
116
                <p>
117
                    A new XML schema
118
                    (<a href="http://www.netbeans.org/ns/ant-project-libraries/1.xsd"><code>http://www.netbeans.org/ns/ant-project-libraries/1</code></a>),
119
                    several new API methods
120
                    (<code>AntProjectHelper.getProjectLibrariesPropertyProvider</code>,
121
                    <code>AntProjectHelper.isSharableProject</code>,
122
                    <code>AntProjectHelper.getLibrariesLocation</code>,
123
                    <code>AntProjectHelper.setLibrariesLocation</code>,
124
                    <code>ProjectGenerator.createProject(FileObject, String, String)</code>,
125
                    <code>ReferenceHelper.createForeignFileReferenceAsIs</code>,
126
                    <code>ReferenceHelper.createExtraForeignFileReferenceAsIs</code>,
127
                    <code>ReferenceHelper.copyLibrary</code>,
128
                    <code>ReferenceHelper.getLibraryChooserImportHandler</code>,
129
                    <code>ReferenceHelper.createLibraryReference</code>,
130
                    <code>ReferenceHelper.getProjectLibraryManager</code>,
131
                    <code>ReferenceHelper.findLibrary</code>) and
132
                    custom file chooser (<code>FileChooser</code>)
133
                    provide support for collocated library definitions
134
                    referred to from Ant-based projects.
135
                </p>
136
            </description>
137
            <class package="org.netbeans.spi.project.support.ant" name="AntProjectHelper"/>
138
            <class package="org.netbeans.spi.project.support.ant" name="ReferenceHelper"/>
139
            <class package="org.netbeans.spi.project.support.ant" name="ProjectGenerator"/>
140
            <class package="org.netbeans.api.project.ant" name="FileChooser"/>
141
            <issue number="44035"/>
142
        </change>
143
108
        <change id="owned-files">
144
        <change id="owned-files">
109
            <api name="general"/>
145
            <api name="general"/>
110
            <summary>Support for adding external files owned by project</summary>
146
            <summary>Support for adding external files owned by project</summary>
(-)ffef4cca2ff4 (+162 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
42
package org.netbeans.api.project.ant;
43
44
import java.awt.Dialog;
45
import java.io.File;
46
import java.io.IOException;
47
import java.net.URI;
48
import java.net.URL;
49
import javax.swing.JFileChooser;
50
import org.netbeans.api.project.FileOwnerQuery;
51
import org.netbeans.api.project.Project;
52
import org.netbeans.api.project.libraries.LibraryManager;
53
import org.netbeans.modules.project.ant.FileChooserAccessory;
54
import org.netbeans.modules.project.ant.RelativizeFilePathCustomizer;
55
import org.netbeans.modules.project.ant.ProjectLibraryProvider;
56
import org.netbeans.spi.project.AuxiliaryConfiguration;
57
import org.netbeans.spi.project.support.ant.AntProjectHelper;
58
import org.openide.DialogDescriptor;
59
import org.openide.DialogDisplayer;
60
import org.openide.filesystems.FileObject;
61
import org.openide.filesystems.FileUtil;
62
import org.openide.util.NbBundle;
63
64
65
/**
66
 * Custom file chooser allowing user to choose how a file will be referenced 
67
 * from a project - via absolute path, or relative path. Make sure you call
68
 * {@link #getSelectedPaths} instead of {@link #getSelectedFiles} as it returns relative
69
 * files and performs file copying if necessary.
70
 * 
71
 * @author David Konecny
72
 * @since org.netbeans.modules.project.ant/1 1.19
73
 */
74
public final class FileChooser extends JFileChooser {
75
76
    private FileChooserAccessory accessory;
77
78
    /**
79
     * Create chooser for given AntProjectHelper. Standard file chooser is shown
80
     * if project is not sharable.
81
     * 
82
     * @param helper ant project helper; cannot be null
83
     * @param copyAllowed is file copying allowed
84
     */
85
    public FileChooser(AntProjectHelper helper, boolean copyAllowed) {
86
        super();
87
        LibraryManager lm = ProjectLibraryProvider.getProjectLibraryManager(helper);
88
        if (lm != null) {
89
            URL u = lm.getLocation();
90
            if (u != null) {
91
                File libBase = new File(URI.create(u.toExternalForm())).getParentFile();
92
                accessory = new FileChooserAccessory(this, FileUtil.toFile(helper.getProjectDirectory()), 
93
                    libBase, copyAllowed);
94
                setAccessory(accessory);
95
            }
96
        }
97
    }
98
99
    /**
100
     * Create chooser for given base folder and shared libraries folder. 
101
     * 
102
     * @param baseFolder base folder to which all selected files will be relativized;
103
     *  can be null in which case regular file chooser is shown
104
     * @param sharedLibrariesFolder providing shared libraries folder enables option
105
     *  of copying selected files there; can be null in which case copying option
106
     *  is disabled
107
     */
108
    public FileChooser(File baseFolder, File sharedLibrariesFolder) {
109
        super();
110
        if (baseFolder != null) {
111
            accessory = new FileChooserAccessory(this, baseFolder, sharedLibrariesFolder, sharedLibrariesFolder != null);
112
            setAccessory(accessory);
113
        }
114
    }
115
    
116
    /**
117
     * Returns array of paths selected. The difference from 
118
     * {@link #getSelectedFiles} is that depends on user's choice the files
119
     * may be relative and they may have been copied to different location.
120
     * 
121
     * @return array of files which may be relative to base folder this chooser
122
     *  was created for; e.g. project folder in case of AntProjectHelper 
123
     *  constructor; never null; can be empty array
124
     * @throws java.io.IOException any IO problem; for example during 
125
     *  file copying
126
     */
127
    public String[] getSelectedPaths() throws IOException {
128
        if (accessory != null) {
129
            accessory.copyFilesIfNecessary();
130
            if (accessory.isRelative()) {
131
                return accessory.getFiles();
132
            }
133
        }
134
        if (isMultiSelectionEnabled()) {
135
            File[] sels = getSelectedFiles();
136
            String[] toRet = new String[sels.length];
137
            int index = 0;
138
            for (File fil : sels) {
139
                toRet[index] = fil.getAbsolutePath();
140
                index++;
141
            }
142
            return toRet;
143
        } else {
144
            if (getSelectedFile() != null) {
145
                return new String[]{ getSelectedFile().getAbsolutePath() };
146
            } else {
147
                return new String[0];
148
            }
149
        }
150
    }
151
152
    @Override
153
    public void approveSelection() {
154
        if (accessory != null && !accessory.canApprove()) {
155
            return;
156
        }
157
        super.approveSelection();
158
    }
159
160
161
162
}
(-)a/project.ant/src/org/netbeans/spi/project/support/ant/AntProjectHelper.java (-1 / +59 lines)
Lines 60-65 Link Here
60
import org.netbeans.modules.project.ant.FileChangeSupport;
60
import org.netbeans.modules.project.ant.FileChangeSupport;
61
import org.netbeans.modules.project.ant.FileChangeSupportEvent;
61
import org.netbeans.modules.project.ant.FileChangeSupportEvent;
62
import org.netbeans.modules.project.ant.FileChangeSupportListener;
62
import org.netbeans.modules.project.ant.FileChangeSupportListener;
63
import org.netbeans.modules.project.ant.ProjectLibraryProvider;
63
import org.netbeans.modules.project.ant.UserQuestionHandler;
64
import org.netbeans.modules.project.ant.UserQuestionHandler;
64
import org.netbeans.modules.project.ant.Util;
65
import org.netbeans.modules.project.ant.Util;
65
import org.netbeans.spi.project.AuxiliaryConfiguration;
66
import org.netbeans.spi.project.AuxiliaryConfiguration;
Lines 429-435 Link Here
429
                return null;
430
                return null;
430
            }
431
            }
431
        };
432
        };
432
        if (ProjectManager.mutex().isWriteAccess()) {
433
        if (ProjectManager.mutex().isWriteAccess() || ProjectLibraryProvider.FIRE_CHANGES_SYNCH) {
433
            // Run it right now. postReadRequest would be too late.
434
            // Run it right now. postReadRequest would be too late.
434
            ProjectManager.mutex().readAccess(action);
435
            ProjectManager.mutex().readAccess(action);
435
        } else if (ProjectManager.mutex().isReadAccess()) {
436
        } else if (ProjectManager.mutex().isReadAccess()) {
Lines 542-547 Link Here
542
     */
543
     */
543
    private void save() throws IOException {
544
    private void save() throws IOException {
544
        assert ProjectManager.mutex().isWriteAccess();
545
        assert ProjectManager.mutex().isWriteAccess();
546
        if (!getProjectDirectory().isValid()) {
547
            //ProjectManager.saveProject() is called when project is deleted externally..
548
            return;
549
        }
545
        Set<FileLock> locks = new HashSet<FileLock>();
550
        Set<FileLock> locks = new HashSet<FileLock>();
546
        try {
551
        try {
547
            synchronized (modifiedMetadataPaths) {
552
            synchronized (modifiedMetadataPaths) {
Lines 1019-1024 Link Here
1019
     * It is permitted, and harmless, to include items that overlap others. For example,
1024
     * It is permitted, and harmless, to include items that overlap others. For example,
1020
     * you can have both a directory and one of its children in the include list.
1025
     * you can have both a directory and one of its children in the include list.
1021
     * </p>
1026
     * </p>
1027
     * <p>
1028
     * Whether or not you use this method, all files named <code>*-private.properties</code>
1029
     * outside the project are marked unsharable, as are such files inside the project if currently referenced
1030
     * as project libraries. (See {@link #getProjectLibrariesPropertyProvider}.)
1031
     * </p>
1022
     * <div class="nonnormative">
1032
     * <div class="nonnormative">
1023
     * <p>
1033
     * <p>
1024
     * Typical usage would be:
1034
     * Typical usage would be:
Lines 1072-1083 Link Here
1072
    public PropertyProvider getStockPropertyPreprovider() {
1082
    public PropertyProvider getStockPropertyPreprovider() {
1073
        return properties.getStockPropertyPreprovider();
1083
        return properties.getStockPropertyPreprovider();
1074
    }
1084
    }
1085
1086
    /**
1087
     * Creates a property provider which can load definitions of project libraries.
1088
     * If this project refers to any project library definition files, they will
1089
     * be included, with <code>${base}</code> replaced by the appropriate value.
1090
     * @return a property provider
1091
     * @since org.netbeans.modules.project.ant/1 1.19
1092
     * @see <a href="http://www.netbeans.org/ns/ant-project-libraries/1.xsd">Schema for project library references</a>
1093
     */
1094
    public PropertyProvider getProjectLibrariesPropertyProvider() {
1095
        return ProjectLibraryProvider.createPropertyProvider(this);
1096
    }
1097
    
1098
    /**
1099
     * Is this project shared with other or not, that is is it using shrared 
1100
     * libraries or not.
1101
     * @return <code>true</code> for shared project
1102
     * @since org.netbeans.modules.project.ant/1 1.19
1103
     */
1104
    public boolean isSharableProject()
1105
    {
1106
        return getLibrariesLocation() != null;
1107
    }
1108
1109
    /**
1110
     * Returns location of shared libraries associated with this project or null.
1111
     * @return relative or absolute OS path or null
1112
     * @since org.netbeans.modules.project.ant/1 1.19
1113
     */
1114
    public String getLibrariesLocation()
1115
    {
1116
        return ProjectLibraryProvider.getLibrariesLocationText(this.createAuxiliaryConfiguration());
1117
    }
1118
    
1119
    /**
1120
     * Change project's associated shared libraries location. If location is 
1121
     * <code>null</code> then project will not have shared libraries and will
1122
     * be considered as not being shared.
1123
     * 
1124
     * @param location project relative or absolute OS path or null
1125
     * @since org.netbeans.modules.project.ant/1 1.18
1126
     */
1127
    public void setLibrariesLocation(String location)
1128
    {
1129
        ProjectLibraryProvider.setLibrariesLocation(this, location);
1130
    }
1075
    
1131
    
1076
    /**
1132
    /**
1077
     * Get a property evaluator that can evaluate properties according to the default
1133
     * Get a property evaluator that can evaluate properties according to the default
1078
     * file layout for Ant-based projects.
1134
     * file layout for Ant-based projects.
1079
     * First, {@link #getStockPropertyPreprovider stock properties} are predefined.
1135
     * First, {@link #getStockPropertyPreprovider stock properties} are predefined.
1080
     * Then {@link #PRIVATE_PROPERTIES_PATH} is loaded via {@link #getPropertyProvider},
1136
     * Then {@link #PRIVATE_PROPERTIES_PATH} is loaded via {@link #getPropertyProvider},
1137
     * then {@link #getProjectLibrariesPropertyProvider},
1081
     * then global definitions from {@link PropertyUtils#globalPropertyProvider}
1138
     * then global definitions from {@link PropertyUtils#globalPropertyProvider}
1082
     * (though these may be overridden using the property <code>user.properties.file</code>
1139
     * (though these may be overridden using the property <code>user.properties.file</code>
1083
     * in <code>private.properties</code>), then {@link #PROJECT_PROPERTIES_PATH}.
1140
     * in <code>private.properties</code>), then {@link #PROJECT_PROPERTIES_PATH}.
Lines 1127-1132 Link Here
1127
        return PropertyUtils.resolvePath(FileUtil.toFile(dir), path);
1184
        return PropertyUtils.resolvePath(FileUtil.toFile(dir), path);
1128
    }
1185
    }
1129
    
1186
    
1187
    @Override
1130
    public String toString() {
1188
    public String toString() {
1131
        return "AntProjectHelper[" + getProjectDirectory() + "]"; // NOI18N
1189
        return "AntProjectHelper[" + getProjectDirectory() + "]"; // NOI18N
1132
    }
1190
    }
(-)a/project.ant/src/org/netbeans/spi/project/support/ant/ProjectGenerator.java (-2 / +30 lines)
Lines 41-52 Link Here
41
41
42
package org.netbeans.spi.project.support.ant;
42
package org.netbeans.spi.project.support.ant;
43
43
44
import java.io.File;
44
import java.io.IOException;
45
import java.io.IOException;
45
import java.io.OutputStream;
46
import java.io.OutputStream;
46
import java.util.Iterator;
47
import java.util.Iterator;
47
import org.netbeans.api.project.Project;
48
import org.netbeans.api.project.Project;
48
import org.netbeans.api.project.ProjectManager;
49
import org.netbeans.api.project.ProjectManager;
49
import org.netbeans.modules.project.ant.AntBasedProjectFactorySingleton;
50
import org.netbeans.modules.project.ant.AntBasedProjectFactorySingleton;
51
import org.netbeans.modules.project.ant.ProjectLibraryProvider;
50
import org.openide.filesystems.FileLock;
52
import org.openide.filesystems.FileLock;
51
import org.openide.filesystems.FileObject;
53
import org.openide.filesystems.FileObject;
52
import org.openide.filesystems.FileUtil;
54
import org.openide.filesystems.FileUtil;
Lines 90-99 Link Here
90
     *                                  new project on disk is recognized by some other factory
92
     *                                  new project on disk is recognized by some other factory
91
     */
93
     */
92
    public static AntProjectHelper createProject(final FileObject directory, final String type) throws IOException, IllegalArgumentException {
94
    public static AntProjectHelper createProject(final FileObject directory, final String type) throws IOException, IllegalArgumentException {
93
        return createProject0(directory, type, null);
95
        return createProject0(directory, type, null, null);
94
    }
96
    }
95
    
97
    
96
    private static AntProjectHelper createProject0(final FileObject directory, final String type, final String name) throws IOException, IllegalArgumentException {
98
    /**
99
     * See {@link #createProject(FileObject, String)} for more datails. This 
100
     * method in addition allows to setup shared libraries location
101
     * @param directory the main project directory to create it in
102
     *                  (see {@link AntProjectHelper#getProjectDirectory})
103
     * @param type a unique project type identifier (see {@link AntBasedProjectType#getType})
104
     * @param librariesDefinition relative or absolute OS path; can be null
105
     */
106
    public static AntProjectHelper createProject(final FileObject directory, final String type, 
107
            final String librariesDefinition) throws IOException, IllegalArgumentException {
108
        return createProject0(directory, type, null, librariesDefinition);
109
    }
110
    
111
    private static AntProjectHelper createProject0(final FileObject directory, final String type, 
112
            final String name, final String librariesDefinition) throws IOException, IllegalArgumentException {
97
        try {
113
        try {
98
            return ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<AntProjectHelper>() {
114
            return ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<AntProjectHelper>() {
99
                public AntProjectHelper run() throws IOException {
115
                public AntProjectHelper run() throws IOException {
Lines 116-121 Link Here
116
                    }
132
                    }
117
                    el = doc.createElementNS(AntProjectHelper.PROJECT_NS, "configuration"); // NOI18N
133
                    el = doc.createElementNS(AntProjectHelper.PROJECT_NS, "configuration"); // NOI18N
118
                    doc.getDocumentElement().appendChild(el);
134
                    doc.getDocumentElement().appendChild(el);
135
                    if (librariesDefinition != null) {
136
                        el.appendChild(ProjectLibraryProvider.createLibrariesElement(doc, librariesDefinition));
137
                        // create libraries property file if it does not exist:
138
                        File f = new File(librariesDefinition);
139
                        if (!f.isAbsolute()) {
140
                            f = new File(FileUtil.toFile(directory), librariesDefinition);
141
                        }
142
                        f = FileUtil.normalizeFile(f);
143
                        if (!f.exists()) {
144
                            FileUtil.createData(f);
145
                        }
146
                    }
119
                    FileLock lock = projectXml.lock();
147
                    FileLock lock = projectXml.lock();
120
                    try {
148
                    try {
121
                        OutputStream os = projectXml.getOutputStream(lock);
149
                        OutputStream os = projectXml.getOutputStream(lock);
(-)a/project.ant/src/org/netbeans/spi/project/support/ant/ProjectProperties.java (+1 lines)
Lines 409-414 Link Here
409
            standardPropertyEvaluator = PropertyUtils.sequentialPropertyEvaluator(
409
            standardPropertyEvaluator = PropertyUtils.sequentialPropertyEvaluator(
410
                getStockPropertyPreprovider(),
410
                getStockPropertyPreprovider(),
411
                getPropertyProvider(AntProjectHelper.PRIVATE_PROPERTIES_PATH),
411
                getPropertyProvider(AntProjectHelper.PRIVATE_PROPERTIES_PATH),
412
                helper.getProjectLibrariesPropertyProvider(),
412
                globalProperties,
413
                globalProperties,
413
                getPropertyProvider(AntProjectHelper.PROJECT_PROPERTIES_PATH));
414
                getPropertyProvider(AntProjectHelper.PROJECT_PROPERTIES_PATH));
414
        }
415
        }
(-)a/project.ant/src/org/netbeans/spi/project/support/ant/ReferenceHelper.java (-14 / +242 lines)
Lines 43-48 Link Here
43
43
44
import java.io.File;
44
import java.io.File;
45
import java.io.IOException;
45
import java.io.IOException;
46
import java.net.MalformedURLException;
46
import java.net.URI;
47
import java.net.URI;
47
import java.net.URISyntaxException;
48
import java.net.URISyntaxException;
48
import java.util.ArrayList;
49
import java.util.ArrayList;
Lines 55-60 Link Here
55
import java.util.Properties;
56
import java.util.Properties;
56
import java.util.Set;
57
import java.util.Set;
57
import java.util.TreeSet;
58
import java.util.TreeSet;
59
import java.util.logging.Logger;
58
import java.util.regex.Matcher;
60
import java.util.regex.Matcher;
59
import java.util.regex.Pattern;
61
import java.util.regex.Pattern;
60
import org.netbeans.api.project.Project;
62
import org.netbeans.api.project.Project;
Lines 62-69 Link Here
62
import org.netbeans.api.project.ProjectUtils;
64
import org.netbeans.api.project.ProjectUtils;
63
import org.netbeans.api.project.ant.AntArtifact;
65
import org.netbeans.api.project.ant.AntArtifact;
64
import org.netbeans.api.project.ant.AntArtifactQuery;
66
import org.netbeans.api.project.ant.AntArtifactQuery;
67
import org.netbeans.api.project.libraries.Library;
68
import org.netbeans.api.project.libraries.LibraryChooser;
69
import org.netbeans.api.project.libraries.LibraryManager;
65
import org.netbeans.api.queries.CollocationQuery;
70
import org.netbeans.api.queries.CollocationQuery;
66
import org.netbeans.modules.project.ant.AntBasedProjectFactorySingleton;
71
import org.netbeans.modules.project.ant.AntBasedProjectFactorySingleton;
72
import org.netbeans.modules.project.ant.ProjectLibraryProvider;
67
import org.netbeans.modules.project.ant.Util;
73
import org.netbeans.modules.project.ant.Util;
68
import org.netbeans.spi.project.AuxiliaryConfiguration;
74
import org.netbeans.spi.project.AuxiliaryConfiguration;
69
import org.netbeans.spi.project.SubprojectProvider;
75
import org.netbeans.spi.project.SubprojectProvider;
Lines 72-77 Link Here
72
import org.openide.filesystems.FileUtil;
78
import org.openide.filesystems.FileUtil;
73
import org.openide.util.Mutex;
79
import org.openide.util.Mutex;
74
import org.openide.util.NbCollections;
80
import org.openide.util.NbCollections;
81
import org.openide.util.Parameters;
75
import org.openide.xml.XMLUtil;
82
import org.openide.xml.XMLUtil;
76
import org.w3c.dom.Document;
83
import org.w3c.dom.Document;
77
import org.w3c.dom.Element;
84
import org.w3c.dom.Element;
Lines 332-338 Link Here
332
                relativePath
339
                relativePath
333
            };
340
            };
334
        }        
341
        }        
335
        else if (CollocationQuery.areCollocated(base, path)) {
342
        else if (PropertyUtils.relativizeFile(base, path) != null) {
343
        //mkleint: removed CollocationQuery.areCollocated() reference
344
        // when AlwaysRelativeCQI gets removed the condition resolves to false more frequently.
345
        // that might not be desirable.
346
            
336
            // Fine, using a relative path to subproject.
347
            // Fine, using a relative path to subproject.
337
            relativePath = PropertyUtils.relativizeFile(base, path);
348
            relativePath = PropertyUtils.relativizeFile(base, path);
338
            assert relativePath != null : "These dirs are not really collocated: " + base + " & " + path;
349
            assert relativePath != null : "These dirs are not really collocated: " + base + " & " + path;
Lines 352-357 Link Here
352
            };            
363
            };            
353
        }
364
        }
354
        assert !Arrays.asList(values).contains(null) : "values=" + Arrays.toString(values) + " base=" + base + " path=" + path; // #119847
365
        assert !Arrays.asList(values).contains(null) : "values=" + Arrays.toString(values) + " base=" + base + " path=" + path; // #119847
366
        return setPathPropertyImpl(propertyName, values, propertiesFiles);
367
    }
368
    
369
    /**
370
     * Helper method which in project properties file sets up property with
371
     * the given name and with (possibly relative) path value.
372
     * @return was there any change or not
373
     */
374
    private boolean setPathProperty(String path, String propertyName) {
375
        String[] propertiesFiles = new String[] {
376
            AntProjectHelper.PROJECT_PROPERTIES_PATH
377
        };
378
        String[] values = new String[] {
379
            path
380
        };
381
        return setPathPropertyImpl(propertyName, values, propertiesFiles);
382
    }
383
    
384
    private boolean setPathPropertyImpl(String propertyName, String[] values, String[] propertiesFiles) {
355
        
385
        
356
        boolean metadataChanged = false;
386
        boolean metadataChanged = false;
357
        for (int i=0; i<propertiesFiles.length; i++) {
387
        for (int i=0; i<propertiesFiles.length; i++) {
Lines 917-925 Link Here
917
            throw new IllegalArgumentException("Parameter file was not "+  // NOI18N
947
            throw new IllegalArgumentException("Parameter file was not "+  // NOI18N
918
                "normalized. Was "+file+" instead of "+FileUtil.normalizeFile(file));  // NOI18N
948
                "normalized. Was "+file+" instead of "+FileUtil.normalizeFile(file));  // NOI18N
919
        }
949
        }
950
        return createForeignFileReferenceImpl(file.getAbsolutePath(), expectedArtifactType, true);
951
    }
952
    
953
    /**
954
     * Create an Ant-interpretable string referring to a file on disk. Compared
955
     * to {@link #createForeignFileReference} the filepath does not have to be 
956
     * normalized (ie. it can be relative path to project base folder), no 
957
     * relativization or absolutization of path is done and
958
     * reference to file is always stored in project properties.
959
     * If the file refers to a known Ant artifact according to
960
     * {@link AntArtifactQuery#findArtifactFromFile}, of the expected type
961
     * and associated with a particular project,
962
     * the behavior is identical to {@link #createForeignFileReference(AntArtifact)}.
963
     * <p>
964
     * Acquires write access.
965
     * @param path a file path to refer to (need not currently exist)
966
     * @param expectedArtifactType the required {@link AntArtifact#getType}
967
     * @return a string which can refer to that file somehow
968
     *
969
     * @since org.netbeans.modules.project.ant/1 1.19
970
     */
971
    public String createForeignFileReferenceAsIs(final String filepath, final String expectedArtifactType) {
972
        return createForeignFileReferenceImpl(filepath, expectedArtifactType, false);
973
    }
974
975
    private String createForeignFileReferenceImpl(final String path, final String expectedArtifactType, final boolean performHeuristics) {
976
        FileObject myProjDirFO = h.getProjectDirectory();
977
        File myProjDir = FileUtil.toFile(myProjDirFO);
978
        final File normalizedFile = FileUtil.normalizeFile(PropertyUtils.resolveFile(myProjDir, path));
920
        return ProjectManager.mutex().writeAccess(new Mutex.Action<String>() {
979
        return ProjectManager.mutex().writeAccess(new Mutex.Action<String>() {
921
            public String run() {
980
            public String run() {
922
                AntArtifact art = AntArtifactQuery.findArtifactFromFile(file);
981
                AntArtifact art = AntArtifactQuery.findArtifactFromFile(normalizedFile);
923
                if (art != null && art.getType().equals(expectedArtifactType) && art.getProject() != null) {
982
                if (art != null && art.getType().equals(expectedArtifactType) && art.getProject() != null) {
924
                    try {
983
                    try {
925
                        return createForeignFileReference(art);
984
                        return createForeignFileReference(art);
Lines 927-952 Link Here
927
                        throw new AssertionError(iae);
986
                        throw new AssertionError(iae);
928
                    }
987
                    }
929
                } else {
988
                } else {
930
                    String propertiesFile;
931
                    String path;
932
                    File myProjDir = FileUtil.toFile(AntBasedProjectFactorySingleton.getProjectFor(h).getProjectDirectory());
989
                    File myProjDir = FileUtil.toFile(AntBasedProjectFactorySingleton.getProjectFor(h).getProjectDirectory());
933
                    String fileID = file.getName();
990
                    String fileID = normalizedFile.getName();
934
                    // if the file is folder then add to ID string also parent folder name,
991
                    // if the file is folder then add to ID string also parent folder name,
935
                    // i.e. if external source folder name is "src" the ID will
992
                    // i.e. if external source folder name is "src" the ID will
936
                    // be a bit more selfdescribing, e.g. project-src in case
993
                    // be a bit more selfdescribing, e.g. project-src in case
937
                    // of ID for ant/project/src directory.
994
                    // of ID for ant/project/src directory.
938
                    if (file.isDirectory() && file.getParentFile() != null) {
995
                    if (normalizedFile.isDirectory() && normalizedFile.getParentFile() != null) {
939
                        fileID = file.getParentFile().getName()+"-"+file.getName();
996
                        fileID = normalizedFile.getParentFile().getName()+"-"+normalizedFile.getName();
940
                    }
997
                    }
941
                    fileID = PropertyUtils.getUsablePropertyName(fileID);
998
                    fileID = PropertyUtils.getUsablePropertyName(fileID);
942
                    String prop = findReferenceID(fileID, "file.reference.", file.getAbsolutePath()); // NOI18N
999
                    String prop = findReferenceID(fileID, "file.reference.", normalizedFile.getAbsolutePath()); // NOI18N
943
                    if (prop == null) {
1000
                    if (prop == null) {
944
                        prop = generateUniqueID(fileID, "file.reference.", file.getAbsolutePath()); // NOI18N
1001
                        prop = generateUniqueID(fileID, "file.reference.", normalizedFile.getAbsolutePath()); // NOI18N
945
                    }
1002
                    }
946
                    setPathProperty(myProjDir, file, "file.reference." + prop);
1003
                    if (performHeuristics) {
1004
                        setPathProperty(myProjDir, normalizedFile, "file.reference." + prop);
1005
                    } else {
1006
                        setPathProperty(path, "file.reference." + prop);
1007
                    }
947
                    return "${file.reference." + prop + '}'; // NOI18N
1008
                    return "${file.reference." + prop + '}'; // NOI18N
948
                }
1009
                }
949
            }
1010
            }
1011
        });
1012
    }
1013
    
1014
    /**
1015
     * Create an Ant-interpretable string referring to a file on disk. Compared
1016
     * to {@link #createForeignFileReference} the file path does not have to be 
1017
     * normalized (ie. it can be relative path to project base folder), no 
1018
     * relativization or absolutization of path is done and
1019
     * reference to file is always stored in project properties.
1020
     * <p>
1021
     * Acquires write access.
1022
     * @param path a file path to refer to (need not currently exist)
1023
     * @param property name of the property
1024
     * @return a string which can refer to that file somehow
1025
     *
1026
     * @since org.netbeans.modules.project.ant/1 1.19
1027
     */
1028
    public String createExtraForeignFileReferenceAsIs(final String path, final String property) {
1029
        return ProjectManager.mutex().writeAccess(new Mutex.Action<String>() {
1030
            public String run() {
1031
                    setPathProperty(path, property);
1032
                    return "${" + property + '}'; // NOI18N
1033
                }
950
        });
1034
        });
951
    }
1035
    }
952
    
1036
    
Lines 1127-1132 Link Here
1127
    private static final Pattern FOREIGN_FILE_REFERENCE = Pattern.compile("\\$\\{reference\\.([^.${}]+)\\.([^.${}]+)\\.([\\d&&[^.${}]]+)\\}"); // NOI18N
1211
    private static final Pattern FOREIGN_FILE_REFERENCE = Pattern.compile("\\$\\{reference\\.([^.${}]+)\\.([^.${}]+)\\.([\\d&&[^.${}]]+)\\}"); // NOI18N
1128
    private static final Pattern FOREIGN_FILE_REFERENCE_OLD = Pattern.compile("\\$\\{reference\\.([^.${}]+)\\.([^.${}]+)\\}"); // NOI18N
1212
    private static final Pattern FOREIGN_FILE_REFERENCE_OLD = Pattern.compile("\\$\\{reference\\.([^.${}]+)\\.([^.${}]+)\\}"); // NOI18N
1129
    private static final Pattern FOREIGN_PLAIN_FILE_REFERENCE = Pattern.compile("\\$\\{file\\.reference\\.([^${}]+)\\}"); // NOI18N
1213
    private static final Pattern FOREIGN_PLAIN_FILE_REFERENCE = Pattern.compile("\\$\\{file\\.reference\\.([^${}]+)\\}"); // NOI18N
1214
    private static final Pattern LIBRARY_REFERENCE = Pattern.compile("\\$\\{libs\\.([^${}]+)\\.[^${}]+\\}"); // NOI18N
1130
    
1215
    
1131
    /**
1216
    /**
1132
     * Try to find an <code>AntArtifact</code> object corresponding to a given
1217
     * Try to find an <code>AntArtifact</code> object corresponding to a given
Lines 1304-1310 Link Here
1304
            File absolutePath = FileUtil.normalizeFile(PropertyUtils.resolveFile(originalPath, value));
1389
            File absolutePath = FileUtil.normalizeFile(PropertyUtils.resolveFile(originalPath, value));
1305
            
1390
            
1306
            //TODO: extra base dir relativization:
1391
            //TODO: extra base dir relativization:
1307
            if (!CollocationQuery.areCollocated(absolutePath, projectDir)) {
1392
            
1393
        //mkleint: removed CollocationQuery.areCollocated() reference
1394
        // when AlwaysRelativeCQI gets removed the condition resolves to false more frequently.
1395
        // that might not be desirable.
1396
            String rel = PropertyUtils.relativizeFile(projectDir, absolutePath);
1397
            if (rel == null) {
1308
                pubRemove.add(key);
1398
                pubRemove.add(key);
1309
                privAdd.put(key, absolutePath.getAbsolutePath());
1399
                privAdd.put(key, absolutePath.getAbsolutePath());
1310
            }
1400
            }
Lines 1338-1345 Link Here
1338
	    }
1428
	    }
1339
	    
1429
	    
1340
            //TODO: extra base dir relativization:
1430
            //TODO: extra base dir relativization:
1341
            if (CollocationQuery.areCollocated(absolutePath, projectDir)) {
1431
            
1342
                pubAdd.put(key, PropertyUtils.relativizeFile(projectDir, absolutePath));
1432
        //mkleint: removed CollocationQuery.areCollocated() reference
1433
        // when AlwaysRelativeCQI gets removed the condition resolves to false more frequently.
1434
        // that might not be desirable.            
1435
            String rel = PropertyUtils.relativizeFile(projectDir, absolutePath);
1436
            if (rel != null) {
1437
                pubAdd.put(key, rel);
1343
            }
1438
            }
1344
        }
1439
        }
1345
        
1440
        
Lines 1357-1363 Link Here
1357
        h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, pub);
1452
        h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, pub);
1358
        h.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH, priv);
1453
        h.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH, priv);
1359
    }
1454
    }
1455
1456
    /**
1457
     * Create a reference to one volume of a library.
1458
     * @param library a library
1459
     * @param volumeType a legal volume type for that library
1460
     * @return substitutable Ant text suitable for inclusion in a properties file when also loading {@link AntProjectHelper#getProjectLibrariesPropertyProvider}
1461
     * @see #findLibrary
1462
     * @since org.netbeans.modules.project.ant/1 1.19
1463
     */
1464
    public String createLibraryReference(Library library, String volumeType) {
1465
        if (library.getManager() == LibraryManager.getDefault()) {
1466
            if (h.isSharableProject()) {
1467
                throw new IllegalArgumentException("Project ["+ // NOI18N
1468
                    h.getProjectDirectory()+
1469
                    "] is sharable and cannot reference global library "+library.getName()); // NOI18N
1470
            }
1471
        } else {
1472
            if (!ProjectLibraryProvider.isReachableLibrary(library, h)) {
1473
                throw new IllegalArgumentException("Project ["+ // NOI18N
1474
                    h.getProjectDirectory()+
1475
                    "] cannot reference a library from "+library.getManager().getLocation()); // NOI18N
1476
            }
1477
        }
1478
        return "${libs." + library.getName() + "." + volumeType + "}"; // NOI18N
1479
    }
1480
1481
    /**
1482
     * Gets a library manager corresponding to library definition file referred to from this project.
1483
     * There is no guarantee that the manager is the same object from call to call
1484
     * even if the location remain the same; in particular, it is <em>not</em> guaranteed that
1485
     * the manager match that returned from {@link Library#getManager} for libraries added
1486
     * from {@link #createLibraryReference}.
1487
     * @return a library manager associated with project's libraries or null if project is 
1488
     *  not shared (will not include {@link LibraryManager#getDefault})
1489
     * @see #createLibraryReference
1490
     * @see #findLibrary
1491
     * @since org.netbeans.modules.project.ant/1 1.19
1492
     */
1493
    public LibraryManager getProjectLibraryManager() {
1494
        return ProjectLibraryProvider.getProjectLibraryManager(h);
1495
    }
1496
1497
    /**
1498
     * Gets a library manager of the given project.
1499
     * There is no guarantee that the manager is the same object from call to call
1500
     * even if the project is the same; in particular, it is <em>not</em> guaranteed that
1501
     * the manager match that returned from {@link Library#getManager} for libraries added
1502
     * from {@link #createLibraryReference}.
1503
     * @return a library manager associated with project's libraries or null if project is 
1504
     *  not shared (will not include {@link LibraryManager#getDefault})
1505
     *  {@link LibraryManager#getDefault})
1506
     * @since org.netbeans.modules.project.ant/1 1.19
1507
     */
1508
    public static LibraryManager getProjectLibraryManager(Project p) {
1509
        AuxiliaryConfiguration aux = p.getLookup().lookup(AuxiliaryConfiguration.class);
1510
        if (aux != null) {
1511
            File libFile = ProjectLibraryProvider.getLibrariesLocation(aux, 
1512
                    FileUtil.toFile(p.getProjectDirectory()));
1513
            if (libFile != null) {
1514
                try {
1515
                    return LibraryManager.forLocation(libFile.toURI().toURL());
1516
                } catch (MalformedURLException e) {
1517
                    // ok, no project manager
1518
                    Logger.getLogger(ReferenceHelper.class.getName()).info(
1519
                        "library manager cannot be found for "+libFile+". "+e.toString()); //NOI18N
1520
                }
1521
            }
1522
        }
1523
        return null;
1524
    }
1525
1526
    /**
1527
     * Copy global IDE library to sharable libraries definition associated with
1528
     * this project. Does nothing if project is not sharable. 
1529
     * When a library with same name already exists in sharable location, the new one 
1530
     * is copied with generated unique name.
1531
     * 
1532
     * <p>Library creation is done under write access of ProjectManager.mutex().
1533
     * 
1534
     * @param lib global library; cannot be null
1535
     * @return newly created sharable version of library in case of sharable
1536
     *  project or given global library in case of non-sharable project
1537
     * @throws java.io.IOException if there was problem copying files
1538
     * @since org.netbeans.modules.project.ant/1 1.19
1539
     */
1540
    public Library copyLibrary(Library lib) throws IOException {
1541
        Parameters.notNull("lib", lib);
1542
        if (lib.getManager() != LibraryManager.getDefault()) {
1543
            throw new IllegalArgumentException("cannot copy non-global library "+lib.getManager().getLocation()); // NOI18N
1544
        }
1545
        if (!h.isSharableProject()) {
1546
            return lib;
1547
        }
1548
        File mainPropertiesFile = h.resolveFile(h.getLibrariesLocation());
1549
        return ProjectLibraryProvider.copyLibrary(lib, mainPropertiesFile.toURI().toURL(), true);
1550
    }
1360
    
1551
    
1552
    /**
1553
     * Returns library import handler which imports global library to sharable
1554
     * one. See {@link LibraryChooser#showDialog} for usage of this handler.
1555
     * @return copy handler
1556
     * @since org.netbeans.modules.project.ant/1 1.19
1557
     */
1558
    public LibraryChooser.LibraryImportHandler getLibraryChooserImportHandler() {
1559
        return new LibraryChooser.LibraryImportHandler() {
1560
            public Library importLibrary(Library library) throws IOException {
1561
                return copyLibrary(library);
1562
            }
1563
        };        
1564
    }
1565
    /**
1566
     * Tries to find a library by name in library manager associated with the project.
1567
     * It is <em>not</em> guaranteed that any returned library is an identical object to one which passed in to {@link #createLibraryReference}.
1568
     * @param name either a bare {@link Library#getName}, or a reference as created by {@link #createLibraryReference}
1569
     * @return the first library to be found matching that name, or null if not found
1570
     * @since org.netbeans.modules.project.ant/1 1.19
1571
     */
1572
    public Library findLibrary(String name) {
1573
        Matcher m = LIBRARY_REFERENCE.matcher(name);
1574
        if (m.matches()) {
1575
            name = m.group(1);
1576
        }
1577
        LibraryManager mgr = getProjectLibraryManager();
1578
        if (mgr == null) {
1579
            return LibraryManager.getDefault().getLibrary(name);
1580
        } else {
1581
            return mgr.getLibrary(name);
1582
        }
1583
    }
1584
1361
    /**
1585
    /**
1362
     * A raw reference descriptor representing a link to a foreign project
1586
     * A raw reference descriptor representing a link to a foreign project
1363
     * and some build artifact used from it.
1587
     * and some build artifact used from it.
Lines 1638-1644 Link Here
1638
        public String getID() {
1862
        public String getID() {
1639
            return artifactID;
1863
            return artifactID;
1640
        }
1864
        }
1641
        
1865
1866
        /**
1867
         * Get an extra properties used for target execution.
1868
         * @return a set of properties (may be empty but not null)
1869
         */
1642
        public Properties getProperties() {
1870
        public Properties getProperties() {
1643
            return props;
1871
            return props;
1644
        }
1872
        }
(-)a/project.ant/src/org/netbeans/spi/project/support/ant/SharabilityQueryImpl.java (-4 / +15 lines)
Lines 47-52 Link Here
47
import java.util.ArrayList;
47
import java.util.ArrayList;
48
import java.util.List;
48
import java.util.List;
49
import org.netbeans.api.queries.SharabilityQuery;
49
import org.netbeans.api.queries.SharabilityQuery;
50
import org.netbeans.modules.project.ant.ProjectLibraryProvider;
50
import org.netbeans.spi.queries.SharabilityQueryImplementation;
51
import org.netbeans.spi.queries.SharabilityQueryImplementation;
51
import org.openide.util.WeakListeners;
52
import org.openide.util.WeakListeners;
52
53
Lines 54-60 Link Here
54
 * Standard impl of {@link SharabilityQueryImplementation}.
55
 * Standard impl of {@link SharabilityQueryImplementation}.
55
 * @author Jesse Glick
56
 * @author Jesse Glick
56
 */
57
 */
57
final class SharabilityQueryImpl implements SharabilityQueryImplementation, PropertyChangeListener {
58
final class SharabilityQueryImpl implements SharabilityQueryImplementation, PropertyChangeListener, AntProjectListener {
58
59
59
    private final AntProjectHelper h;
60
    private final AntProjectHelper h;
60
    private final PropertyEvaluator eval;
61
    private final PropertyEvaluator eval;
Lines 72-83 Link Here
72
        this.excludes = excludes;
73
        this.excludes = excludes;
73
        computeFiles();
74
        computeFiles();
74
        eval.addPropertyChangeListener(WeakListeners.propertyChange(this, eval));
75
        eval.addPropertyChangeListener(WeakListeners.propertyChange(this, eval));
76
        h.addAntProjectListener(this);
75
    }
77
    }
76
    
78
    
77
    /** Compute the absolute paths which are and are not sharable. */
79
    /** Compute the absolute paths which are and are not sharable. */
78
    private void computeFiles() {
80
    private void computeFiles() {
79
        String[] _includePaths = computeFrom(includes);
81
        String[] _includePaths = computeFrom(includes, false);
80
        String[] _excludePaths = computeFrom(excludes);
82
        String[] _excludePaths = computeFrom(excludes, true);
81
        synchronized (this) {
83
        synchronized (this) {
82
            includePaths = _includePaths;
84
            includePaths = _includePaths;
83
            excludePaths = _excludePaths;
85
            excludePaths = _excludePaths;
Lines 85-91 Link Here
85
    }
87
    }
86
    
88
    
87
    /** Compute a list of absolute paths based on some abstract names. */
89
    /** Compute a list of absolute paths based on some abstract names. */
88
    private String[] computeFrom(String[] list) {
90
    private String[] computeFrom(String[] list, boolean excludeProjectLibraryPrivate) {
89
        List<String> result = new ArrayList<String>(list.length);
91
        List<String> result = new ArrayList<String>(list.length);
90
        for (String s : list) {
92
        for (String s : list) {
91
            String val = eval.evaluate(s);
93
            String val = eval.evaluate(s);
Lines 93-98 Link Here
93
                File f = h.resolveFile(val);
95
                File f = h.resolveFile(val);
94
                result.add(f.getAbsolutePath());
96
                result.add(f.getAbsolutePath());
95
            }
97
            }
98
        }
99
        if (excludeProjectLibraryPrivate) {
100
            result.addAll(ProjectLibraryProvider.getUnsharablePathsWithinProject(h));
96
        }
101
        }
97
        // XXX should remove overlaps somehow
102
        // XXX should remove overlaps somehow
98
        return result.toArray(new String[result.size()]);
103
        return result.toArray(new String[result.size()]);
Lines 132-136 Link Here
132
    public void propertyChange(PropertyChangeEvent evt) {
137
    public void propertyChange(PropertyChangeEvent evt) {
133
        computeFiles();
138
        computeFiles();
134
    }
139
    }
140
141
    public void configurationXmlChanged(AntProjectEvent ev) {
142
        computeFiles();
143
    }
144
145
    public void propertiesChanged(AntProjectEvent ev) {}
135
    
146
    
136
}
147
}
(-)a/project.ant/src/org/netbeans/spi/project/support/ant/SourcesHelper.java (-4 / +4 lines)
Lines 193-203 Link Here
193
                    if (owner != null && owner != p) {
193
                    if (owner != null && owner != p) {
194
                        return false;
194
                        return false;
195
                    }
195
                    }
196
                    File f = FileUtil.toFile(file);
197
                    if (f != null && SharabilityQuery.getSharability(f) == SharabilityQuery.NOT_SHARABLE) {
198
                        return false;
199
                    } // else MIXED, UNKNOWN, or SHARABLE; or not a disk file
196
                }
200
                }
197
                File f = FileUtil.toFile(file);
198
                if (f != null && SharabilityQuery.getSharability(f) == SharabilityQuery.NOT_SHARABLE) {
199
                    return false;
200
                } // else MIXED, UNKNOWN, or SHARABLE; or not a disk file
201
                return true;
201
                return true;
202
            }
202
            }
203
203

Return to bug 44035